Added head mesh, points/directions for hair that follow the Poisson
[hair] / src / hair.cc
1 #include <gmath/gmath.h>
2 #include <stdlib.h>
3 #include <string>
4
5 #include "kdtree.h"
6 #include "hair.h"
7
8 struct Triangle {
9         Vec3 v[3];
10         Vec3 n[3];
11 };
12
13 Hair::Hair() {}
14 Hair::~Hair() {}
15
16 static Vec3 calc_rand_point(const Triangle &tr, Vec3 *bary)
17 {
18         float u = (float)rand() / (float)RAND_MAX;
19         float v = (float)rand() / (float)RAND_MAX;
20
21         if(u + v > 1) {
22                 u = 1 - u;
23                 v = 1 - v;
24         }
25
26         float c = 1 - (u + v);
27
28         Vec3 rp = u * tr.v[0] + v * tr.v[1] + c * tr.v[3];
29
30         bary->x = u;
31         bary->y = v;
32         bary->z = c;
33
34         return rp;
35 }
36
37 static void get_spawn_triangles(const Mesh *m, float thresh, std::vector<Triangle> *faces)
38 {
39         for(size_t i=0; i<m->indices.size() / 3; i++) {
40                 bool is_spawn = true;
41                 int idx[3];
42                 for(int j=0; j<3; j++) {
43                         idx[j] = i * 3 + j;
44                         float c = (m->colors[idx[j]].x + m->colors[idx[j]].y + m->colors[idx[j]].z) / 3;
45                         if (c >= thresh) {
46                                 is_spawn = false;
47                                 break;
48                         }
49                 }
50
51                 if(is_spawn) {
52                         Triangle t;
53                         for(int j=0; j<3; j++) {
54                                 t.v[j] = m->vertices[idx[j]];
55                                 t.n[j] = m->normals[idx[j]];
56                         }
57                         faces->push_back(t);
58                 }
59         }
60 }
61
62 bool Hair::init(const Mesh *m, int max_num_spawns, float thresh)
63 {
64         std::vector<Triangle> faces;
65         kdtree *kd = kd_create(3);
66         const float min_dist = 0.05;
67
68         get_spawn_triangles(m, thresh, &faces);
69
70         for(int i = 0; i < max_num_spawns; i++) {
71                 // Poisson
72                 int rnum = (float)((float)rand() / (float)RAND_MAX) * faces.size();
73                 Triangle rtriangle = faces[rnum];
74                 Vec3 bary;
75                 Vec3 rpoint = calc_rand_point(rtriangle, &bary);
76
77                 kdres *res = kd_nearest3f(kd, rpoint.x, rpoint.y, rpoint.z);
78                 if (!kd_res_end(res)) {
79                         Vec3 nearest;
80                         kd_res_item3f(res, &nearest.x, &nearest.y, &nearest.z);
81                         if(distance_sq(rpoint, nearest) < min_dist * min_dist)
82                                 continue;
83                 }
84
85                 /* weighted sum of the triangle's vertex normals */
86                 Vec3 spawn_dir = rtriangle.n[0] * bary.x + rtriangle.n[1] * bary.y + rtriangle.n[2] * bary.z;
87                 spawn_directions.push_back(normalize(spawn_dir));
88                 spawn_points.push_back(rpoint);
89                 kd_insert3f(kd, rpoint.x, rpoint.y, rpoint.z, 0);
90         }
91
92         kd_free(kd);
93         return true;
94 }
95
96 void Hair::draw() const
97 {
98 }