X-Git-Url: http://git.mutantstargoat.com?a=blobdiff_plain;f=src%2Fhair.cc;h=2431f509cf7669331698b5327741f2035d4f6007;hb=2c4aeaa83ca06d604c084f1fe146ee7f51e30f90;hp=e4843fb0c9168a058946e31cb6e1e45c6e68d5ef;hpb=da5cbacf755273da510c37c819a59c7fe9894c4e;p=hair diff --git a/src/hair.cc b/src/hair.cc index e4843fb..2431f50 100644 --- a/src/hair.cc +++ b/src/hair.cc @@ -1,3 +1,6 @@ +#include + +#include #include #include #include @@ -10,8 +13,14 @@ struct Triangle { Vec3 n[3]; }; -Hair::Hair() {} -Hair::~Hair() {} +Hair::Hair() +{ + hair_length = 0.5; +} + +Hair::~Hair() +{ +} static Vec3 calc_rand_point(const Triangle &tr, Vec3 *bary) { @@ -25,7 +34,7 @@ static Vec3 calc_rand_point(const Triangle &tr, Vec3 *bary) float c = 1 - (u + v); - Vec3 rp = u * tr.v[0] + v * tr.v[1] + c * tr.v[3]; + Vec3 rp = u * tr.v[0] + v * tr.v[1] + c * tr.v[2]; bary->x = u; bary->y = v; @@ -36,11 +45,18 @@ static Vec3 calc_rand_point(const Triangle &tr, Vec3 *bary) static void get_spawn_triangles(const Mesh *m, float thresh, std::vector *faces) { + if (!m) { + fprintf(stderr, "Func: %s, invalid mesh.\n", __func__); + exit(1); + } + float min_y = FLT_MAX; + float max_y = -FLT_MAX; + for(size_t i=0; iindices.size() / 3; i++) { bool is_spawn = true; int idx[3]; for(int j=0; j<3; j++) { - idx[j] = i * 3 + j; + idx[j] = m->indices[i * 3 + j]; float c = (m->colors[idx[j]].x + m->colors[idx[j]].y + m->colors[idx[j]].z) / 3; if (c >= thresh) { is_spawn = false; @@ -53,10 +69,15 @@ static void get_spawn_triangles(const Mesh *m, float thresh, std::vectorvertices[idx[j]]; t.n[j] = m->normals[idx[j]]; + if(t.v[j].y < min_y) + min_y = t.v[j].y; + if(t.v[j].y > max_y) + max_y = t.v[j].y; } faces->push_back(t); } } +/* printf("spawn tri AABB: min y: %f max y: %f\n", min_y, max_y);*/ } bool Hair::init(const Mesh *m, int max_num_spawns, float thresh) @@ -65,6 +86,11 @@ bool Hair::init(const Mesh *m, int max_num_spawns, float thresh) kdtree *kd = kd_create(3); const float min_dist = 0.05; + if(!m) { + fprintf(stderr, "Func %s: invalid mesh.\n", __func__); + return false; + } + get_spawn_triangles(m, thresh, &faces); for(int i = 0; i < max_num_spawns; i++) { @@ -75,24 +101,82 @@ bool Hair::init(const Mesh *m, int max_num_spawns, float thresh) Vec3 rpoint = calc_rand_point(rtriangle, &bary); kdres *res = kd_nearest3f(kd, rpoint.x, rpoint.y, rpoint.z); - if (!kd_res_end(res)) { + + if (res && !kd_res_end(res)) { Vec3 nearest; kd_res_item3f(res, &nearest.x, &nearest.y, &nearest.z); if(distance_sq(rpoint, nearest) < min_dist * min_dist) continue; } + HairStrand strand; /* weighted sum of the triangle's vertex normals */ - Vec3 spawn_dir = rtriangle.n[0] * bary.x + rtriangle.n[1] * bary.y + rtriangle.n[2] * bary.z; - spawn_directions.push_back(normalize(spawn_dir)); - spawn_points.push_back(rpoint); + strand.spawn_dir = normalize(rtriangle.n[0] * bary.x + rtriangle.n[1] * bary.y + rtriangle.n[2] * bary.z); + strand.spawn_pt = rpoint; + hair.push_back(strand); + kd_insert3f(kd, rpoint.x, rpoint.y, rpoint.z, 0); } kd_free(kd); + + for(size_t i=0; i 0.99)) { + vi = Vec3(0, -1, 0); + } + Vec3 vj = normalize(cross(vk, vi)); + vi = cross(vj, vk); + + /* identity when the hair points to the z axis */ + Mat4 basis = Mat4(vi, vj, vk); + + for(int j=0; j<3; j++) { + float angle = (float)j / 3.0 * 2 * M_PI; + /* dir of each anchor relative to hair end */ + Vec3 dir = Vec3(cos(angle), sin(angle), 0); + dir = basis * dir; + hair[i].anchor_dirs[j] = hair[i].pos + dir - hair[i].spawn_pt; + } + } return true; } void Hair::draw() const { + glPushAttrib(GL_ENABLE_BIT); +// glDisable(GL_DEPTH_TEST); + glDisable(GL_LIGHTING); + glPointSize(5); + glLineWidth(2); + + glBegin(GL_LINES); + for(size_t i=0; ixform = xform; }