rev |
line source |
John@15
|
1 #include <math.h>
|
nuclear@25
|
2 #include <float.h>
|
nuclear@26
|
3 #include <assert.h>
|
nuclear@22
|
4 #include "scene.h"
|
nuclear@27
|
5 #include "ogl.h"
|
nuclear@6
|
6
|
nuclear@26
|
7
|
nuclear@27
|
8 static void draw_kdtree(const KDNode *node, int level = 0);
|
nuclear@27
|
9 static bool build_kdtree(KDNode *kd, int level = 0);
|
nuclear@27
|
10 static float eval_cost(const std::list<const Face*> &faces, const AABBox &aabb, int axis, float par_sarea = 1.0);
|
nuclear@26
|
11 static void free_kdtree(KDNode *node);
|
nuclear@28
|
12 static void kdtree_gpu_flatten(KDNodeGPU *kdbuf, int idx, const KDNode *node, const Face *facebuf);
|
nuclear@27
|
13 static void print_item_counts(const KDNode *node, int level);
|
nuclear@26
|
14
|
nuclear@26
|
15
|
nuclear@26
|
16 static int accel_param[NUM_ACCEL_PARAMS] = {
|
nuclear@28
|
17 40, // max tree depth
|
nuclear@26
|
18 0, // max items per node (0 means ignore limit)
|
nuclear@26
|
19 5, // estimated traversal cost
|
nuclear@26
|
20 15 // estimated interseciton cost
|
nuclear@26
|
21 };
|
nuclear@26
|
22
|
nuclear@26
|
23
|
nuclear@26
|
24 void set_accel_param(int p, int v)
|
nuclear@26
|
25 {
|
nuclear@26
|
26 assert(p >= 0 && p < NUM_ACCEL_PARAMS);
|
nuclear@26
|
27 accel_param[p] = v;
|
nuclear@26
|
28 }
|
nuclear@26
|
29
|
nuclear@26
|
30
|
John@15
|
31 #define FEQ(a, b) (fabs((a) - (b)) < 1e-8)
|
John@15
|
32 bool Face::operator ==(const Face &f) const
|
John@15
|
33 {
|
John@15
|
34 for(int i=0; i<3; i++) {
|
John@15
|
35 for(int j=0; j<3; j++) {
|
John@15
|
36 if(!FEQ(v[i].pos[j], f.v[i].pos[j])) {
|
John@15
|
37 return false;
|
John@15
|
38 }
|
John@15
|
39 if(!FEQ(v[i].normal[j], f.v[i].normal[j])) {
|
John@15
|
40 return false;
|
John@15
|
41 }
|
John@15
|
42 }
|
John@15
|
43 if(!FEQ(normal[i], f.normal[i])) {
|
John@15
|
44 return false;
|
John@15
|
45 }
|
John@15
|
46 }
|
John@15
|
47 return true;
|
John@15
|
48 }
|
John@15
|
49
|
nuclear@25
|
50 float AABBox::calc_surface_area() const
|
nuclear@25
|
51 {
|
nuclear@25
|
52 float area1 = (max[0] - min[0]) * (max[1] - min[1]);
|
nuclear@25
|
53 float area2 = (max[3] - min[3]) * (max[1] - min[1]);
|
nuclear@25
|
54 float area3 = (max[0] - min[0]) * (max[3] - min[3]);
|
nuclear@25
|
55
|
nuclear@25
|
56 return 2.0f * (area1 + area2 + area3);
|
nuclear@25
|
57 }
|
nuclear@25
|
58
|
nuclear@26
|
59 KDNode::KDNode()
|
nuclear@26
|
60 {
|
nuclear@26
|
61 axis = 0;
|
nuclear@26
|
62 pt = 0.0;
|
nuclear@26
|
63 left = right = 0;
|
nuclear@26
|
64 num_faces = 0;
|
nuclear@26
|
65 }
|
nuclear@26
|
66
|
nuclear@25
|
67
|
nuclear@24
|
68 Scene::Scene()
|
nuclear@24
|
69 {
|
nuclear@24
|
70 facebuf = 0;
|
nuclear@24
|
71 num_faces = -1;
|
nuclear@24
|
72 kdtree = 0;
|
nuclear@28
|
73 num_kdnodes = -1;
|
nuclear@28
|
74 kdbuf = 0;
|
nuclear@24
|
75 }
|
nuclear@24
|
76
|
nuclear@24
|
77 Scene::~Scene()
|
nuclear@24
|
78 {
|
nuclear@24
|
79 delete [] facebuf;
|
nuclear@28
|
80 delete [] kdbuf;
|
nuclear@28
|
81 free_kdtree(kdtree);
|
nuclear@24
|
82 }
|
nuclear@24
|
83
|
nuclear@13
|
84 bool Scene::add_mesh(Mesh *m)
|
nuclear@13
|
85 {
|
nuclear@13
|
86 // make sure triangles have material ids
|
nuclear@13
|
87 for(size_t i=0; i<m->faces.size(); i++) {
|
nuclear@13
|
88 m->faces[i].matid = m->matid;
|
nuclear@13
|
89 }
|
nuclear@24
|
90
|
nuclear@24
|
91 try {
|
nuclear@24
|
92 meshes.push_back(m);
|
nuclear@24
|
93 }
|
nuclear@24
|
94 catch(...) {
|
nuclear@24
|
95 return false;
|
nuclear@24
|
96 }
|
nuclear@24
|
97
|
nuclear@24
|
98 // invalidate facebuffer and count
|
nuclear@24
|
99 delete [] facebuf;
|
nuclear@24
|
100 facebuf = 0;
|
nuclear@24
|
101 num_faces = -1;
|
nuclear@24
|
102
|
nuclear@13
|
103 return true;
|
nuclear@13
|
104 }
|
nuclear@13
|
105
|
John@14
|
106 int Scene::get_num_meshes() const
|
John@14
|
107 {
|
John@14
|
108 return (int)meshes.size();
|
John@14
|
109 }
|
John@14
|
110
|
nuclear@13
|
111 int Scene::get_num_faces() const
|
nuclear@13
|
112 {
|
nuclear@24
|
113 if(num_faces >= 0) {
|
nuclear@24
|
114 return num_faces;
|
nuclear@24
|
115 }
|
nuclear@24
|
116
|
nuclear@24
|
117 num_faces = 0;
|
nuclear@13
|
118 for(size_t i=0; i<meshes.size(); i++) {
|
nuclear@13
|
119 num_faces += meshes[i]->faces.size();
|
nuclear@13
|
120 }
|
nuclear@13
|
121 return num_faces;
|
nuclear@13
|
122 }
|
nuclear@13
|
123
|
John@14
|
124 int Scene::get_num_materials() const
|
John@14
|
125 {
|
John@14
|
126 return (int)matlib.size();
|
John@14
|
127 }
|
John@14
|
128
|
John@14
|
129 Material *Scene::get_materials()
|
John@14
|
130 {
|
John@14
|
131 if(matlib.empty()) {
|
John@14
|
132 return 0;
|
John@14
|
133 }
|
John@14
|
134 return &matlib[0];
|
John@14
|
135 }
|
John@14
|
136
|
John@14
|
137 const Material *Scene::get_materials() const
|
John@14
|
138 {
|
John@14
|
139 if(matlib.empty()) {
|
John@14
|
140 return 0;
|
John@14
|
141 }
|
John@14
|
142 return &matlib[0];
|
John@14
|
143 }
|
nuclear@24
|
144
|
nuclear@24
|
145 const Face *Scene::get_face_buffer() const
|
nuclear@24
|
146 {
|
nuclear@24
|
147 if(facebuf) {
|
nuclear@24
|
148 return facebuf;
|
nuclear@24
|
149 }
|
nuclear@24
|
150
|
nuclear@24
|
151 int num_meshes = get_num_meshes();
|
nuclear@24
|
152
|
nuclear@24
|
153 printf("constructing face buffer with %d faces (out of %d meshes)\n", get_num_faces(), num_meshes);
|
nuclear@24
|
154 facebuf = new Face[num_faces];
|
nuclear@24
|
155 Face *fptr = facebuf;
|
nuclear@24
|
156
|
nuclear@24
|
157 for(int i=0; i<num_meshes; i++) {
|
nuclear@24
|
158 for(size_t j=0; j<meshes[i]->faces.size(); j++) {
|
nuclear@24
|
159 *fptr++ = meshes[i]->faces[j];
|
nuclear@24
|
160 }
|
nuclear@24
|
161 }
|
nuclear@24
|
162 return facebuf;
|
nuclear@24
|
163 }
|
nuclear@24
|
164
|
nuclear@28
|
165 const KDNodeGPU *Scene::get_kdtree_buffer() const
|
nuclear@28
|
166 {
|
nuclear@28
|
167 if(kdbuf) {
|
nuclear@28
|
168 return kdbuf;
|
nuclear@28
|
169 }
|
nuclear@28
|
170
|
nuclear@28
|
171 if(!kdtree) {
|
nuclear@28
|
172 ((Scene*)this)->build_kdtree();
|
nuclear@28
|
173 }
|
nuclear@28
|
174
|
nuclear@28
|
175 if(!get_num_kdnodes()) {
|
nuclear@28
|
176 return 0;
|
nuclear@28
|
177 }
|
nuclear@28
|
178
|
nuclear@28
|
179 kdbuf = new KDNodeGPU[num_kdnodes + 1];
|
nuclear@28
|
180 kdtree_gpu_flatten(kdbuf, 1, kdtree, get_face_buffer());
|
nuclear@28
|
181 return kdbuf;
|
nuclear@28
|
182 }
|
nuclear@28
|
183
|
nuclear@28
|
184 int Scene::get_num_kdnodes() const
|
nuclear@28
|
185 {
|
nuclear@28
|
186 if(num_kdnodes >= 0) {
|
nuclear@28
|
187 return num_kdnodes;
|
nuclear@28
|
188 }
|
nuclear@28
|
189
|
nuclear@28
|
190 num_kdnodes = kdtree_nodes(kdtree);
|
nuclear@28
|
191 return num_kdnodes;
|
nuclear@28
|
192 }
|
nuclear@28
|
193
|
nuclear@24
|
194
|
nuclear@27
|
195 void Scene::draw_kdtree() const
|
nuclear@27
|
196 {
|
nuclear@27
|
197 glPushAttrib(GL_ENABLE_BIT);
|
nuclear@27
|
198 glDisable(GL_LIGHTING);
|
nuclear@27
|
199 glDepthMask(0);
|
nuclear@27
|
200
|
nuclear@27
|
201 glBegin(GL_LINES);
|
nuclear@27
|
202 ::draw_kdtree(kdtree, 0);
|
nuclear@27
|
203 glEnd();
|
nuclear@27
|
204
|
nuclear@27
|
205 glDepthMask(1);
|
nuclear@27
|
206 glPopAttrib();
|
nuclear@27
|
207 }
|
nuclear@27
|
208
|
nuclear@27
|
209 static float palette[][3] = {
|
nuclear@27
|
210 {0, 1, 0},
|
nuclear@27
|
211 {1, 0, 0},
|
nuclear@27
|
212 {0, 0, 1},
|
nuclear@27
|
213 {1, 1, 0},
|
nuclear@27
|
214 {0, 0, 1},
|
nuclear@27
|
215 {1, 0, 1}
|
nuclear@27
|
216 };
|
nuclear@27
|
217 static int pal_size = sizeof palette / sizeof *palette;
|
nuclear@27
|
218
|
nuclear@27
|
219 static void draw_kdtree(const KDNode *node, int level)
|
nuclear@27
|
220 {
|
nuclear@27
|
221 if(!node) return;
|
nuclear@27
|
222
|
nuclear@27
|
223 draw_kdtree(node->left, level + 1);
|
nuclear@27
|
224 draw_kdtree(node->right, level + 1);
|
nuclear@27
|
225
|
nuclear@27
|
226 glColor3fv(palette[level % pal_size]);
|
nuclear@27
|
227
|
nuclear@27
|
228 glVertex3fv(node->aabb.min);
|
nuclear@27
|
229 glVertex3f(node->aabb.max[0], node->aabb.min[1], node->aabb.min[2]);
|
nuclear@27
|
230 glVertex3f(node->aabb.max[0], node->aabb.min[1], node->aabb.min[2]);
|
nuclear@27
|
231 glVertex3f(node->aabb.max[0], node->aabb.max[1], node->aabb.min[2]);
|
nuclear@27
|
232 glVertex3f(node->aabb.max[0], node->aabb.max[1], node->aabb.min[2]);
|
nuclear@27
|
233 glVertex3f(node->aabb.min[0], node->aabb.max[1], node->aabb.min[2]);
|
nuclear@27
|
234 glVertex3f(node->aabb.min[0], node->aabb.max[1], node->aabb.min[2]);
|
nuclear@27
|
235 glVertex3fv(node->aabb.min);
|
nuclear@27
|
236
|
nuclear@27
|
237 glVertex3f(node->aabb.min[0], node->aabb.min[1], node->aabb.max[2]);
|
nuclear@27
|
238 glVertex3f(node->aabb.max[0], node->aabb.min[1], node->aabb.max[2]);
|
nuclear@27
|
239 glVertex3f(node->aabb.max[0], node->aabb.min[1], node->aabb.max[2]);
|
nuclear@27
|
240 glVertex3fv(node->aabb.max);
|
nuclear@27
|
241 glVertex3fv(node->aabb.max);
|
nuclear@27
|
242 glVertex3f(node->aabb.min[0], node->aabb.max[1], node->aabb.max[2]);
|
nuclear@27
|
243 glVertex3f(node->aabb.min[0], node->aabb.max[1], node->aabb.max[2]);
|
nuclear@27
|
244 glVertex3f(node->aabb.min[0], node->aabb.min[1], node->aabb.max[2]);
|
nuclear@27
|
245
|
nuclear@27
|
246 glVertex3fv(node->aabb.min);
|
nuclear@27
|
247 glVertex3f(node->aabb.min[0], node->aabb.min[1], node->aabb.max[2]);
|
nuclear@27
|
248 glVertex3f(node->aabb.max[0], node->aabb.min[1], node->aabb.min[2]);
|
nuclear@27
|
249 glVertex3f(node->aabb.max[0], node->aabb.min[1], node->aabb.max[2]);
|
nuclear@27
|
250 glVertex3f(node->aabb.max[0], node->aabb.max[1], node->aabb.min[2]);
|
nuclear@27
|
251 glVertex3fv(node->aabb.max);
|
nuclear@27
|
252 glVertex3f(node->aabb.min[0], node->aabb.max[1], node->aabb.min[2]);
|
nuclear@27
|
253 glVertex3f(node->aabb.min[0], node->aabb.max[1], node->aabb.max[2]);
|
nuclear@27
|
254 }
|
nuclear@27
|
255
|
nuclear@27
|
256 bool Scene::build_kdtree()
|
nuclear@24
|
257 {
|
nuclear@24
|
258 const Face *faces = get_face_buffer();
|
nuclear@24
|
259 int num_faces = get_num_faces();
|
nuclear@24
|
260
|
nuclear@25
|
261 printf("Constructing kd-tree out of %d faces ...\n", num_faces);
|
nuclear@25
|
262
|
nuclear@27
|
263 int icost = accel_param[ACCEL_PARAM_COST_INTERSECT];
|
nuclear@27
|
264 int tcost = accel_param[ACCEL_PARAM_COST_TRAVERSE];
|
nuclear@27
|
265 printf(" max items per leaf: %d\n", accel_param[ACCEL_PARAM_MAX_NODE_ITEMS]);
|
nuclear@27
|
266 printf(" SAH parameters - tcost: %d - icost: %d\n", tcost, icost);
|
nuclear@27
|
267
|
nuclear@25
|
268 free_kdtree(kdtree);
|
nuclear@25
|
269 kdtree = new KDNode;
|
nuclear@25
|
270
|
nuclear@25
|
271 /* Start the construction of the kdtree by adding all faces of the scene
|
nuclear@25
|
272 * to the new root node. At the same time calculate the root's AABB.
|
nuclear@25
|
273 */
|
nuclear@25
|
274 kdtree->aabb.min[0] = kdtree->aabb.min[1] = kdtree->aabb.min[2] = FLT_MAX;
|
nuclear@25
|
275 kdtree->aabb.max[0] = kdtree->aabb.max[1] = kdtree->aabb.max[2] = -FLT_MAX;
|
nuclear@25
|
276
|
nuclear@24
|
277 for(int i=0; i<num_faces; i++) {
|
nuclear@25
|
278 const Face *face = faces + i;
|
nuclear@25
|
279
|
nuclear@25
|
280 // for each vertex of the face ...
|
nuclear@25
|
281 for(int j=0; j<3; j++) {
|
nuclear@25
|
282 const float *pos = face->v[j].pos;
|
nuclear@25
|
283
|
nuclear@25
|
284 // for each element (xyz) of the position vector ...
|
nuclear@25
|
285 for(int k=0; k<3; k++) {
|
nuclear@25
|
286 if(pos[k] < kdtree->aabb.min[k]) {
|
nuclear@25
|
287 kdtree->aabb.min[k] = pos[k];
|
nuclear@25
|
288 }
|
nuclear@25
|
289 if(pos[k] > kdtree->aabb.max[k]) {
|
nuclear@25
|
290 kdtree->aabb.max[k] = pos[k];
|
nuclear@25
|
291 }
|
nuclear@25
|
292 }
|
nuclear@25
|
293 }
|
nuclear@25
|
294
|
nuclear@25
|
295 kdtree->faces.push_back(face); // add the face
|
nuclear@26
|
296 kdtree->num_faces++;
|
nuclear@24
|
297 }
|
nuclear@24
|
298
|
nuclear@26
|
299 // calculate the heuristic for the root
|
nuclear@26
|
300 kdtree->cost = eval_cost(kdtree->faces, kdtree->aabb, kdtree->axis);
|
nuclear@26
|
301
|
nuclear@25
|
302 // now proceed splitting the root recursively
|
nuclear@27
|
303 if(!::build_kdtree(kdtree)) {
|
nuclear@27
|
304 fprintf(stderr, "failed to build kdtree\n");
|
nuclear@27
|
305 return false;
|
nuclear@27
|
306 }
|
nuclear@27
|
307
|
nuclear@27
|
308 printf(" tree depth: %d\n", kdtree_depth(kdtree));
|
nuclear@27
|
309 print_item_counts(kdtree, 0);
|
nuclear@27
|
310 return true;
|
nuclear@24
|
311 }
|
nuclear@24
|
312
|
nuclear@27
|
313 static bool build_kdtree(KDNode *kd, int level)
|
nuclear@24
|
314 {
|
nuclear@28
|
315 int opt_max_depth = accel_param[ACCEL_PARAM_MAX_TREE_DEPTH];
|
nuclear@26
|
316 int opt_max_items = accel_param[ACCEL_PARAM_MAX_NODE_ITEMS];
|
nuclear@27
|
317 int tcost = accel_param[ACCEL_PARAM_COST_TRAVERSE];
|
nuclear@27
|
318
|
nuclear@28
|
319 if(kd->num_faces == 0 || level >= opt_max_depth) {
|
nuclear@27
|
320 return true;
|
nuclear@25
|
321 }
|
nuclear@25
|
322
|
nuclear@27
|
323 int axis = level % 3;
|
nuclear@27
|
324 //float parent_sa = kd->aabb.calc_surface_area();
|
nuclear@26
|
325
|
nuclear@26
|
326 float best_cost[2], best_sum_cost = FLT_MAX;
|
nuclear@26
|
327 float best_split;
|
nuclear@26
|
328
|
nuclear@26
|
329 std::list<const Face*>::iterator it = kd->faces.begin();
|
nuclear@26
|
330 while(it != kd->faces.end()) {
|
nuclear@26
|
331 const Face *face = *it++;
|
nuclear@26
|
332
|
nuclear@26
|
333 for(int i=0; i<3; i++) {
|
nuclear@26
|
334 AABBox aabb_left, aabb_right;
|
nuclear@26
|
335 const float *split = face->v[i].pos;
|
nuclear@26
|
336
|
nuclear@26
|
337 aabb_left = aabb_right = kd->aabb;
|
nuclear@26
|
338 aabb_left.max[axis] = split[axis];
|
nuclear@26
|
339 aabb_right.min[axis] = split[axis];
|
nuclear@26
|
340
|
nuclear@26
|
341 float left_cost = eval_cost(kd->faces, aabb_left, axis);
|
nuclear@26
|
342 float right_cost = eval_cost(kd->faces, aabb_right, axis);
|
nuclear@27
|
343 float sum_cost = left_cost + right_cost - tcost; // tcost is added twice
|
nuclear@26
|
344
|
nuclear@26
|
345 if(sum_cost < best_sum_cost) {
|
nuclear@26
|
346 best_cost[0] = left_cost;
|
nuclear@26
|
347 best_cost[1] = right_cost;
|
nuclear@26
|
348 best_sum_cost = sum_cost;
|
nuclear@26
|
349 best_split = split[axis];
|
nuclear@26
|
350 }
|
nuclear@26
|
351 }
|
nuclear@26
|
352 }
|
nuclear@26
|
353
|
nuclear@27
|
354 printf("current cost: %f, best_cost: %f\n", kd->cost, best_sum_cost);
|
nuclear@27
|
355 if(best_sum_cost > kd->cost && (opt_max_items == 0 || kd->num_faces <= opt_max_items)) {
|
nuclear@27
|
356 return true; // stop splitting if it doesn't reduce the cost
|
nuclear@26
|
357 }
|
nuclear@26
|
358 kd->pt = best_split;
|
nuclear@26
|
359
|
nuclear@26
|
360 // create the two children
|
nuclear@26
|
361 KDNode *kdleft, *kdright;
|
nuclear@26
|
362 kdleft = new KDNode;
|
nuclear@26
|
363 kdright = new KDNode;
|
nuclear@26
|
364
|
nuclear@26
|
365 kdleft->aabb = kdright->aabb = kd->aabb;
|
nuclear@26
|
366
|
nuclear@26
|
367 kdleft->aabb.max[axis] = best_split;
|
nuclear@26
|
368 kdright->aabb.min[axis] = best_split;
|
nuclear@26
|
369
|
nuclear@26
|
370 kdleft->cost = best_cost[0];
|
nuclear@26
|
371 kdright->cost = best_cost[1];
|
nuclear@26
|
372
|
nuclear@27
|
373 //kdleft->axis = kdright->axis = (axis + 1) % 3;
|
nuclear@27
|
374
|
nuclear@26
|
375 it = kd->faces.begin();
|
nuclear@26
|
376 while(it != kd->faces.end()) {
|
nuclear@26
|
377 const Face *face = *it++;
|
nuclear@26
|
378
|
nuclear@26
|
379 if(face->v[0].pos[axis] < best_split ||
|
nuclear@26
|
380 face->v[1].pos[axis] < best_split ||
|
nuclear@26
|
381 face->v[2].pos[axis] < best_split) {
|
nuclear@26
|
382 kdleft->faces.push_back(face);
|
nuclear@26
|
383 kdleft->num_faces++;
|
nuclear@26
|
384 }
|
nuclear@26
|
385 if(face->v[0].pos[axis] >= best_split ||
|
nuclear@26
|
386 face->v[1].pos[axis] >= best_split ||
|
nuclear@26
|
387 face->v[2].pos[axis] >= best_split) {
|
nuclear@26
|
388 kdright->faces.push_back(face);
|
nuclear@26
|
389 kdright->num_faces++;
|
nuclear@26
|
390 }
|
nuclear@26
|
391 }
|
nuclear@27
|
392 kd->faces.clear(); // only leaves have faces
|
nuclear@26
|
393
|
nuclear@26
|
394 kd->left = kdleft;
|
nuclear@26
|
395 kd->right = kdright;
|
nuclear@27
|
396
|
nuclear@27
|
397 return build_kdtree(kd->left, level + 1) && build_kdtree(kd->right, level + 1);
|
nuclear@26
|
398 }
|
nuclear@26
|
399
|
nuclear@27
|
400 static float eval_cost(const std::list<const Face*> &faces, const AABBox &aabb, int axis, float par_sarea)
|
nuclear@26
|
401 {
|
nuclear@26
|
402 int num_inside = 0;
|
nuclear@26
|
403 int tcost = accel_param[ACCEL_PARAM_COST_TRAVERSE];
|
nuclear@26
|
404 int icost = accel_param[ACCEL_PARAM_COST_INTERSECT];
|
nuclear@26
|
405
|
nuclear@26
|
406 std::list<const Face*>::const_iterator it = faces.begin();
|
nuclear@26
|
407 while(it != faces.end()) {
|
nuclear@26
|
408 const Face *face = *it++;
|
nuclear@26
|
409
|
nuclear@26
|
410 for(int i=0; i<3; i++) {
|
nuclear@26
|
411 if(face->v[i].pos[axis] >= aabb.min[axis] && face->v[i].pos[axis] < aabb.max[axis]) {
|
nuclear@26
|
412 num_inside++;
|
nuclear@26
|
413 break;
|
nuclear@26
|
414 }
|
nuclear@26
|
415 }
|
nuclear@26
|
416 }
|
nuclear@26
|
417
|
nuclear@27
|
418 float sarea = aabb.calc_surface_area();
|
nuclear@27
|
419 if(sarea < 1e-8) {
|
nuclear@27
|
420 return FLT_MAX; // heavily penalize 0-area voxels
|
nuclear@27
|
421 }
|
nuclear@27
|
422
|
nuclear@27
|
423 return tcost + (sarea / par_sarea) * num_inside * icost;
|
nuclear@24
|
424 }
|
nuclear@25
|
425
|
nuclear@25
|
426 static void free_kdtree(KDNode *node)
|
nuclear@25
|
427 {
|
nuclear@25
|
428 if(node) {
|
nuclear@25
|
429 free_kdtree(node->left);
|
nuclear@25
|
430 free_kdtree(node->right);
|
nuclear@25
|
431 delete node;
|
nuclear@25
|
432 }
|
nuclear@25
|
433 }
|
nuclear@27
|
434
|
nuclear@28
|
435 int kdtree_depth(const KDNode *node)
|
nuclear@27
|
436 {
|
nuclear@27
|
437 if(!node) return 0;
|
nuclear@27
|
438
|
nuclear@27
|
439 int left = kdtree_depth(node->left);
|
nuclear@27
|
440 int right = kdtree_depth(node->right);
|
nuclear@27
|
441 return (left > right ? left : right) + 1;
|
nuclear@27
|
442 }
|
nuclear@27
|
443
|
nuclear@28
|
444 int kdtree_nodes(const KDNode *node)
|
nuclear@28
|
445 {
|
nuclear@28
|
446 if(!node) return 0;
|
nuclear@28
|
447 return kdtree_nodes(node->left) + kdtree_nodes(node->right) + 1;
|
nuclear@28
|
448 }
|
nuclear@28
|
449
|
nuclear@28
|
450 #define MAX_FACES (sizeof dest->face_idx / sizeof *dest->face_idx)
|
nuclear@28
|
451 static void kdtree_gpu_flatten(KDNodeGPU *kdbuf, int idx, const KDNode *node, const Face *facebuf)
|
nuclear@28
|
452 {
|
nuclear@28
|
453 KDNodeGPU *dest = kdbuf + idx;
|
nuclear@28
|
454
|
nuclear@28
|
455 dest->aabb = node->aabb;
|
nuclear@28
|
456 dest->num_faces = 0;
|
nuclear@28
|
457
|
nuclear@28
|
458 std::list<const Face*>::const_iterator it = node->faces.begin();
|
nuclear@28
|
459 while(it != node->faces.end()) {
|
nuclear@28
|
460 if(dest->num_faces >= (int)MAX_FACES) {
|
nuclear@28
|
461 fprintf(stderr, "kdtree_gpu_flatten WARNING: more than %d faces in node, skipping!\n", (int)MAX_FACES);
|
nuclear@28
|
462 break;
|
nuclear@28
|
463 }
|
nuclear@28
|
464 dest->face_idx[dest->num_faces++] = *it - facebuf;
|
nuclear@28
|
465 }
|
nuclear@28
|
466
|
nuclear@28
|
467 if(node->left) {
|
nuclear@28
|
468 assert(node->right);
|
nuclear@28
|
469 kdtree_gpu_flatten(kdbuf, idx * 2, node->left, facebuf);
|
nuclear@28
|
470 kdtree_gpu_flatten(kdbuf, idx * 2 + 1, node->right, facebuf);
|
nuclear@28
|
471 }
|
nuclear@28
|
472 }
|
nuclear@28
|
473
|
nuclear@27
|
474 static void print_item_counts(const KDNode *node, int level)
|
nuclear@27
|
475 {
|
nuclear@27
|
476 if(!node) return;
|
nuclear@27
|
477
|
nuclear@27
|
478 for(int i=0; i<level; i++) {
|
nuclear@27
|
479 fputs(" ", stdout);
|
nuclear@27
|
480 }
|
nuclear@27
|
481 printf("- %d (cost: %f)\n", node->num_faces, node->cost);
|
nuclear@27
|
482
|
nuclear@27
|
483 print_item_counts(node->left, level + 1);
|
nuclear@27
|
484 print_item_counts(node->right, level + 1);
|
nuclear@27
|
485 }
|