clray

annotate src/scene.cc @ 53:54a96b738afe

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