00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00037 #include "fcl/BVH/BVH_model.h"
00038 #include "fcl/BV/BV.h"
00039 #include <iostream>
00040 #include <string.h>
00041
00042 namespace fcl
00043 {
00044
00045 template<typename BV>
00046 BVHModel<BV>::BVHModel(const BVHModel<BV>& other) : CollisionGeometry(other),
00047 num_tris(other.num_tris),
00048 num_vertices(other.num_vertices),
00049 build_state(other.build_state),
00050 bv_splitter(other.bv_splitter),
00051 bv_fitter(other.bv_fitter),
00052 num_tris_allocated(other.num_tris),
00053 num_vertices_allocated(other.num_vertices)
00054 {
00055 if(other.vertices)
00056 {
00057 vertices = new Vec3f[num_vertices];
00058 memcpy(vertices, other.vertices, sizeof(Vec3f) * num_vertices);
00059 }
00060 else
00061 vertices = NULL;
00062
00063 if(other.tri_indices)
00064 {
00065 tri_indices = new Triangle[num_tris];
00066 memcpy(tri_indices, other.tri_indices, sizeof(Triangle) * num_tris);
00067 }
00068 else
00069 tri_indices = NULL;
00070
00071 if(other.prev_vertices)
00072 {
00073 prev_vertices = new Vec3f[num_vertices];
00074 memcpy(prev_vertices, other.prev_vertices, sizeof(Vec3f) * num_vertices);
00075 }
00076 else
00077 prev_vertices = NULL;
00078
00079 if(other.primitive_indices)
00080 {
00081 int num_primitives = 0;
00082 switch(other.getModelType())
00083 {
00084 case BVH_MODEL_TRIANGLES:
00085 num_primitives = num_tris;
00086 break;
00087 case BVH_MODEL_POINTCLOUD:
00088 num_primitives = num_vertices;
00089 break;
00090 default:
00091 ;
00092 }
00093
00094 primitive_indices = new unsigned int[num_primitives];
00095 memcpy(primitive_indices, other.primitive_indices, sizeof(unsigned int) * num_primitives);
00096 }
00097 else
00098 primitive_indices = NULL;
00099
00100 num_bvs = num_bvs_allocated = other.num_bvs;
00101 if(other.bvs)
00102 {
00103 bvs = new BVNode<BV>[num_bvs];
00104 memcpy(bvs, other.bvs, sizeof(BVNode<BV>) * num_bvs);
00105 }
00106 else
00107 bvs = NULL;
00108 }
00109
00110
00111 template<typename BV>
00112 int BVHModel<BV>::beginModel(int num_tris_, int num_vertices_)
00113 {
00114 if(build_state != BVH_BUILD_STATE_EMPTY)
00115 {
00116 delete [] vertices; vertices = NULL;
00117 delete [] tri_indices; tri_indices = NULL;
00118 delete [] bvs; bvs = NULL;
00119 delete [] prev_vertices; prev_vertices = NULL;
00120 delete [] primitive_indices; primitive_indices = NULL;
00121
00122 num_vertices_allocated = num_vertices = num_tris_allocated = num_tris = num_bvs_allocated = num_bvs = 0;
00123 }
00124
00125 if(num_tris_ <= 0) num_tris_ = 8;
00126 if(num_vertices_ <= 0) num_vertices_ = 8;
00127
00128 num_vertices_allocated = num_vertices_;
00129 num_tris_allocated = num_tris_;
00130
00131 tri_indices = new Triangle[num_tris_allocated];
00132 vertices = new Vec3f[num_vertices_allocated];
00133
00134 if(!tri_indices)
00135 {
00136 std::cerr << "BVH Error! Out of memory for tri_indices array on BeginModel() call!" << std::endl;
00137 return BVH_ERR_MODEL_OUT_OF_MEMORY;
00138 }
00139 if(!vertices)
00140 {
00141 std::cerr << "BVH Error! Out of memory for vertices array on BeginModel() call!" << std::endl;
00142 return BVH_ERR_MODEL_OUT_OF_MEMORY;
00143 }
00144
00145 if(build_state != BVH_BUILD_STATE_EMPTY)
00146 {
00147 std::cerr << "BVH Warning! Call beginModel() on a BVHModel that is not empty. This model was cleared and previous triangles/vertices were lost." << std::endl;
00148 build_state = BVH_BUILD_STATE_EMPTY;
00149 return BVH_ERR_BUILD_OUT_OF_SEQUENCE;
00150 }
00151
00152 build_state = BVH_BUILD_STATE_BEGUN;
00153
00154 return BVH_OK;
00155 }
00156
00157
00158 template<typename BV>
00159 int BVHModel<BV>::addVertex(const Vec3f& p)
00160 {
00161 if(build_state != BVH_BUILD_STATE_UPDATE_BEGUN)
00162 {
00163 std::cerr << "BVH Warning! Call addVertex() in a wrong order. addVertex() was ignored. Must do a beginModel() to clear the model for addition of new vertices." << std::endl;
00164 return BVH_ERR_BUILD_OUT_OF_SEQUENCE;
00165 }
00166
00167 if(num_vertices >= num_vertices_allocated)
00168 {
00169 Vec3f* temp = new Vec3f[num_vertices_allocated * 2];
00170 if(!temp)
00171 {
00172 std::cerr << "BVH Error! Out of memory for vertices array on addVertex() call!" << std::endl;
00173 return BVH_ERR_MODEL_OUT_OF_MEMORY;
00174 }
00175
00176 memcpy(temp, vertices, sizeof(Vec3f) * num_vertices);
00177 delete [] vertices;
00178 vertices = temp;
00179 num_vertices_allocated *= 2;
00180 }
00181
00182 vertices[num_vertices] = p;
00183 num_vertices += 1;
00184
00185 return BVH_OK;
00186 }
00187
00188 template<typename BV>
00189 int BVHModel<BV>::addTriangle(const Vec3f& p1, const Vec3f& p2, const Vec3f& p3)
00190 {
00191 if(build_state == BVH_BUILD_STATE_PROCESSED)
00192 {
00193 std::cerr << "BVH Warning! Call addTriangle() in a wrong order. addTriangle() was ignored. Must do a beginModel() to clear the model for addition of new triangles." << std::endl;
00194 return BVH_ERR_BUILD_OUT_OF_SEQUENCE;
00195 }
00196
00197 if(num_vertices + 2 >= num_vertices_allocated)
00198 {
00199 Vec3f* temp = new Vec3f[num_vertices_allocated * 2 + 2];
00200 if(!temp)
00201 {
00202 std::cerr << "BVH Error! Out of memory for vertices array on addTriangle() call!" << std::endl;
00203 return BVH_ERR_MODEL_OUT_OF_MEMORY;
00204 }
00205
00206 memcpy(temp, vertices, sizeof(Vec3f) * num_vertices);
00207 delete [] vertices;
00208 vertices = temp;
00209 num_vertices_allocated = num_vertices_allocated * 2 + 2;
00210 }
00211
00212 int offset = num_vertices;
00213
00214 vertices[num_vertices] = p1;
00215 num_vertices++;
00216 vertices[num_vertices] = p2;
00217 num_vertices++;
00218 vertices[num_vertices] = p3;
00219 num_vertices++;
00220
00221 if(num_tris >= num_tris_allocated)
00222 {
00223 Triangle* temp = new Triangle[num_tris_allocated * 2];
00224 if(!temp)
00225 {
00226 std::cerr << "BVH Error! Out of memory for tri_indices array on addTriangle() call!" << std::endl;
00227 return BVH_ERR_MODEL_OUT_OF_MEMORY;
00228 }
00229
00230 memcpy(temp, tri_indices, sizeof(Triangle) * num_tris);
00231 delete [] tri_indices;
00232 tri_indices = temp;
00233 num_tris_allocated *= 2;
00234 }
00235
00236 tri_indices[num_tris].set(offset, offset + 1, offset + 2);
00237 num_tris++;
00238
00239 return BVH_OK;
00240 }
00241
00242 template<typename BV>
00243 int BVHModel<BV>::addSubModel(const std::vector<Vec3f>& ps)
00244 {
00245 if(build_state == BVH_BUILD_STATE_PROCESSED)
00246 {
00247 std::cerr << "BVH Warning! Call addSubModel() in a wrong order. addSubModel() was ignored. Must do a beginModel() to clear the model for addition of new vertices." << std::endl;
00248 return BVH_ERR_BUILD_OUT_OF_SEQUENCE;
00249 }
00250
00251 int num_vertices_to_add = ps.size();
00252
00253 if(num_vertices + num_vertices_to_add - 1 >= num_vertices_allocated)
00254 {
00255 Vec3f* temp = new Vec3f[num_vertices_allocated * 2 + num_vertices_to_add - 1];
00256 if(!temp)
00257 {
00258 std::cerr << "BVH Error! Out of memory for vertices array on addSubModel() call!" << std::endl;
00259 return BVH_ERR_MODEL_OUT_OF_MEMORY;
00260 }
00261
00262 memcpy(temp, vertices, sizeof(Vec3f) * num_vertices);
00263 delete [] vertices;
00264 vertices = temp;
00265 num_vertices_allocated = num_vertices_allocated * 2 + num_vertices_to_add - 1;
00266 }
00267
00268 for(int i = 0; i < num_vertices_to_add; ++i)
00269 {
00270 vertices[num_vertices] = ps[i];
00271 num_vertices++;
00272 }
00273
00274 return BVH_OK;
00275 }
00276
00277 template<typename BV>
00278 int BVHModel<BV>::addSubModel(const std::vector<Vec3f>& ps, const std::vector<Triangle>& ts)
00279 {
00280 if(build_state == BVH_BUILD_STATE_PROCESSED)
00281 {
00282 std::cerr << "BVH Warning! Call addSubModel() in a wrong order. addSubModel() was ignored. Must do a beginModel() to clear the model for addition of new vertices." << std::endl;
00283 return BVH_ERR_BUILD_OUT_OF_SEQUENCE;
00284 }
00285
00286 int num_vertices_to_add = ps.size();
00287
00288 if(num_vertices + num_vertices_to_add - 1 >= num_vertices_allocated)
00289 {
00290 Vec3f* temp = new Vec3f[num_vertices_allocated * 2 + num_vertices_to_add - 1];
00291 if(!temp)
00292 {
00293 std::cerr << "BVH Error! Out of memory for vertices array on addSubModel() call!" << std::endl;
00294 return BVH_ERR_MODEL_OUT_OF_MEMORY;
00295 }
00296
00297 memcpy(temp, vertices, sizeof(Vec3f) * num_vertices);
00298 delete [] vertices;
00299 vertices = temp;
00300 num_vertices_allocated = num_vertices_allocated * 2 + num_vertices_to_add - 1;
00301 }
00302
00303 int offset = num_vertices;
00304
00305 for(int i = 0; i < num_vertices_to_add; ++i)
00306 {
00307 vertices[num_vertices] = ps[i];
00308 num_vertices++;
00309 }
00310
00311
00312 int num_tris_to_add = ts.size();
00313
00314 if(num_tris + num_tris_to_add - 1 >= num_tris_allocated)
00315 {
00316 Triangle* temp = new Triangle[num_tris_allocated * 2 + num_tris_to_add - 1];
00317 if(!temp)
00318 {
00319 std::cerr << "BVH Error! Out of memory for tri_indices array on addSubModel() call!" << std::endl;
00320 return BVH_ERR_MODEL_OUT_OF_MEMORY;
00321 }
00322
00323 memcpy(temp, tri_indices, sizeof(Triangle) * num_tris);
00324 delete [] tri_indices;
00325 tri_indices = temp;
00326 num_tris_allocated = num_tris_allocated * 2 + num_tris_to_add - 1;
00327 }
00328
00329 for(int i = 0; i < num_tris_to_add; ++i)
00330 {
00331 const Triangle& t = ts[i];
00332 tri_indices[num_tris].set(t[0] + offset, t[1] + offset, t[2] + offset);
00333 num_tris++;
00334 }
00335
00336 return BVH_OK;
00337 }
00338
00339 template<typename BV>
00340 int BVHModel<BV>::endModel()
00341 {
00342 if(build_state != BVH_BUILD_STATE_BEGUN)
00343 {
00344 std::cerr << "BVH Warning! Call endModel() in wrong order. endModel() was ignored." << std::endl;
00345 return BVH_ERR_BUILD_OUT_OF_SEQUENCE;
00346 }
00347
00348 if(num_tris == 0 && num_vertices == 0)
00349 {
00350 std::cerr << "BVH Error! endModel() called on model with no triangles and vertices." << std::endl;
00351 return BVH_ERR_BUILD_EMPTY_MODEL;
00352 }
00353
00354 if(num_tris_allocated > num_tris)
00355 {
00356 Triangle* new_tris = new Triangle[num_tris];
00357 if(!new_tris)
00358 {
00359 std::cerr << "BVH Error! Out of memory for tri_indices array in endModel() call!" << std::endl;
00360 return BVH_ERR_MODEL_OUT_OF_MEMORY;
00361 }
00362 memcpy(new_tris, tri_indices, sizeof(Triangle) * num_tris);
00363 delete [] tri_indices;
00364 tri_indices = new_tris;
00365 num_tris_allocated = num_tris;
00366 }
00367
00368 if(num_vertices_allocated > num_vertices)
00369 {
00370 Vec3f* new_vertices = new Vec3f[num_vertices];
00371 if(!new_vertices)
00372 {
00373 std::cerr << "BVH Error! Out of memory for vertices array in endModel() call!" << std::endl;
00374 return BVH_ERR_MODEL_OUT_OF_MEMORY;
00375 }
00376 memcpy(new_vertices, vertices, sizeof(Vec3f) * num_vertices);
00377 delete [] vertices;
00378 vertices = new_vertices;
00379 num_vertices_allocated = num_vertices;
00380 }
00381
00382
00383
00384 int num_bvs_to_be_allocated = 0;
00385 if(num_tris == 0)
00386 num_bvs_to_be_allocated = 2 * num_vertices - 1;
00387 else
00388 num_bvs_to_be_allocated = 2 * num_tris - 1;
00389
00390
00391 bvs = new BVNode<BV> [num_bvs_to_be_allocated];
00392 primitive_indices = new unsigned int [num_bvs_to_be_allocated];
00393 if(!bvs || !primitive_indices)
00394 {
00395 std::cerr << "BVH Error! Out of memory for BV array in endModel()!" << std::endl;
00396 return BVH_ERR_MODEL_OUT_OF_MEMORY;
00397 }
00398 num_bvs_allocated = num_bvs_to_be_allocated;
00399 num_bvs = 0;
00400
00401 buildTree();
00402
00403
00404 build_state = BVH_BUILD_STATE_PROCESSED;
00405
00406 return BVH_OK;
00407 }
00408
00409
00410
00411 template<typename BV>
00412 int BVHModel<BV>::beginReplaceModel()
00413 {
00414 if(build_state != BVH_BUILD_STATE_PROCESSED)
00415 {
00416 std::cerr << "BVH Error! Call beginReplaceModel() on a BVHModel that has no previous frame." << std::endl;
00417 return BVH_ERR_BUILD_EMPTY_PREVIOUS_FRAME;
00418 }
00419
00420 if(prev_vertices) delete [] prev_vertices; prev_vertices = NULL;
00421
00422 num_vertex_updated = 0;
00423
00424 build_state = BVH_BUILD_STATE_REPLACE_BEGUN;
00425
00426 return BVH_OK;
00427 }
00428
00429 template<typename BV>
00430 int BVHModel<BV>::replaceVertex(const Vec3f& p)
00431 {
00432 if(build_state != BVH_BUILD_STATE_REPLACE_BEGUN)
00433 {
00434 std::cerr << "BVH Warning! Call replaceVertex() in a wrong order. replaceVertex() was ignored. Must do a beginReplaceModel() for initialization." << std::endl;
00435 return BVH_ERR_BUILD_OUT_OF_SEQUENCE;
00436 }
00437
00438 vertices[num_vertex_updated] = p;
00439 num_vertex_updated++;
00440
00441 return BVH_OK;
00442 }
00443
00444 template<typename BV>
00445 int BVHModel<BV>::replaceTriangle(const Vec3f& p1, const Vec3f& p2, const Vec3f& p3)
00446 {
00447 if(build_state != BVH_BUILD_STATE_REPLACE_BEGUN)
00448 {
00449 std::cerr << "BVH Warning! Call replaceTriangle() in a wrong order. replaceTriangle() was ignored. Must do a beginReplaceModel() for initialization." << std::endl;
00450 return BVH_ERR_BUILD_OUT_OF_SEQUENCE;
00451 }
00452
00453 vertices[num_vertex_updated] = p1; num_vertex_updated++;
00454 vertices[num_vertex_updated] = p2; num_vertex_updated++;
00455 vertices[num_vertex_updated] = p3; num_vertex_updated++;
00456 return BVH_OK;
00457 }
00458
00459 template<typename BV>
00460 int BVHModel<BV>::replaceSubModel(const std::vector<Vec3f>& ps)
00461 {
00462 if(build_state != BVH_BUILD_STATE_REPLACE_BEGUN)
00463 {
00464 std::cerr << "BVH Warning! Call replaceSubModel() in a wrong order. replaceSubModel() was ignored. Must do a beginReplaceModel() for initialization." << std::endl;
00465 return BVH_ERR_BUILD_OUT_OF_SEQUENCE;
00466 }
00467
00468 for(unsigned int i = 0; i < ps.size(); ++i)
00469 {
00470 vertices[num_vertex_updated] = ps[i];
00471 num_vertex_updated++;
00472 }
00473 return BVH_OK;
00474 }
00475
00476 template<typename BV>
00477 int BVHModel<BV>::endReplaceModel(bool refit, bool bottomup)
00478 {
00479 if(build_state != BVH_BUILD_STATE_REPLACE_BEGUN)
00480 {
00481 std::cerr << "BVH Warning! Call endReplaceModel() in a wrong order. endReplaceModel() was ignored. " << std::endl;
00482 return BVH_ERR_BUILD_OUT_OF_SEQUENCE;
00483 }
00484
00485 if(num_vertex_updated != num_vertices)
00486 {
00487 std::cerr << "BVH Error! The replaced model should have the same number of vertices as the old model." << std::endl;
00488 return BVH_ERR_INCORRECT_DATA;
00489 }
00490
00491 if(refit)
00492 {
00493 refitTree(bottomup);
00494 }
00495 else
00496 {
00497 buildTree();
00498 }
00499
00500 build_state = BVH_BUILD_STATE_PROCESSED;
00501
00502 return BVH_OK;
00503 }
00504
00505
00506
00507
00508
00509 template<typename BV>
00510 int BVHModel<BV>::beginUpdateModel()
00511 {
00512 if(build_state != BVH_BUILD_STATE_PROCESSED && build_state != BVH_BUILD_STATE_UPDATED)
00513 {
00514 std::cerr << "BVH Error! Call beginUpdatemodel() on a BVHModel that has no previous frame." << std::endl;
00515 return BVH_ERR_BUILD_EMPTY_PREVIOUS_FRAME;
00516 }
00517
00518 if(prev_vertices)
00519 {
00520 Vec3f* temp = prev_vertices;
00521 prev_vertices = vertices;
00522 vertices = temp;
00523 }
00524 else
00525 {
00526 prev_vertices = vertices;
00527 vertices = new Vec3f[num_vertices];
00528 }
00529
00530 num_vertex_updated = 0;
00531
00532 build_state = BVH_BUILD_STATE_UPDATE_BEGUN;
00533
00534 return BVH_OK;
00535 }
00536
00537 template<typename BV>
00538 int BVHModel<BV>::updateVertex(const Vec3f& p)
00539 {
00540 if(build_state != BVH_BUILD_STATE_UPDATE_BEGUN)
00541 {
00542 std::cerr << "BVH Warning! Call updateVertex() in a wrong order. updateVertex() was ignored. Must do a beginUpdateModel() for initialization." << std::endl;
00543 return BVH_ERR_BUILD_OUT_OF_SEQUENCE;
00544 }
00545
00546 vertices[num_vertex_updated] = p;
00547 num_vertex_updated++;
00548
00549 return BVH_OK;
00550 }
00551
00552 template<typename BV>
00553 int BVHModel<BV>::updateTriangle(const Vec3f& p1, const Vec3f& p2, const Vec3f& p3)
00554 {
00555 if(build_state != BVH_BUILD_STATE_UPDATE_BEGUN)
00556 {
00557 std::cerr << "BVH Warning! Call updateTriangle() in a wrong order. updateTriangle() was ignored. Must do a beginUpdateModel() for initialization." << std::endl;
00558 return BVH_ERR_BUILD_OUT_OF_SEQUENCE;
00559 }
00560
00561 vertices[num_vertex_updated] = p1; num_vertex_updated++;
00562 vertices[num_vertex_updated] = p2; num_vertex_updated++;
00563 vertices[num_vertex_updated] = p3; num_vertex_updated++;
00564 return BVH_OK;
00565 }
00566
00567 template<typename BV>
00568 int BVHModel<BV>::updateSubModel(const std::vector<Vec3f>& ps)
00569 {
00570 if(build_state != BVH_BUILD_STATE_UPDATE_BEGUN)
00571 {
00572 std::cerr << "BVH Warning! Call updateSubModel() in a wrong order. updateSubModel() was ignored. Must do a beginUpdateModel() for initialization." << std::endl;
00573 return BVH_ERR_BUILD_OUT_OF_SEQUENCE;
00574 }
00575
00576 for(unsigned int i = 0; i < ps.size(); ++i)
00577 {
00578 vertices[num_vertex_updated] = ps[i];
00579 num_vertex_updated++;
00580 }
00581 return BVH_OK;
00582 }
00583
00584 template<typename BV>
00585 int BVHModel<BV>::endUpdateModel(bool refit, bool bottomup)
00586 {
00587 if(build_state != BVH_BUILD_STATE_UPDATE_BEGUN)
00588 {
00589 std::cerr << "BVH Warning! Call endUpdateModel() in a wrong order. endUpdateModel() was ignored. " << std::endl;
00590 return BVH_ERR_BUILD_OUT_OF_SEQUENCE;
00591 }
00592
00593 if(num_vertex_updated != num_vertices)
00594 {
00595 std::cerr << "BVH Error! The updated model should have the same number of vertices as the old model." << std::endl;
00596 return BVH_ERR_INCORRECT_DATA;
00597 }
00598
00599 if(refit)
00600 {
00601 refitTree(bottomup);
00602 }
00603 else
00604 {
00605 buildTree();
00606
00607
00608
00609 refitTree(bottomup);
00610 }
00611
00612
00613 build_state = BVH_BUILD_STATE_UPDATED;
00614
00615 return BVH_OK;
00616 }
00617
00618
00619
00620
00621 template<typename BV>
00622 int BVHModel<BV>::memUsage(int msg) const
00623 {
00624 int mem_bv_list = sizeof(BV) * num_bvs;
00625 int mem_tri_list = sizeof(Triangle) * num_tris;
00626 int mem_vertex_list = sizeof(Vec3f) * num_vertices;
00627
00628 int total_mem = mem_bv_list + mem_tri_list + mem_vertex_list + sizeof(BVHModel<BV>);
00629 if(msg)
00630 {
00631 std::cerr << "Total for model " << total_mem << " bytes." << std::endl;
00632 std::cerr << "BVs: " << num_bvs << " allocated." << std::endl;
00633 std::cerr << "Tris: " << num_tris << " allocated." << std::endl;
00634 std::cerr << "Vertices: " << num_vertices << " allocated." << std::endl;
00635 }
00636
00637 return BVH_OK;
00638 }
00639
00640
00641 template<typename BV>
00642 int BVHModel<BV>::buildTree()
00643 {
00644
00645 bv_fitter->set(vertices, tri_indices, getModelType());
00646
00647 bv_splitter->set(vertices, tri_indices, getModelType());
00648
00649 num_bvs = 1;
00650
00651 int num_primitives = 0;
00652 switch(getModelType())
00653 {
00654 case BVH_MODEL_TRIANGLES:
00655 num_primitives = num_tris;
00656 break;
00657 case BVH_MODEL_POINTCLOUD:
00658 num_primitives = num_vertices;
00659 break;
00660 default:
00661 std::cerr << "BVH Error: Model type not supported!" << std::endl;
00662 return BVH_ERR_UNSUPPORTED_FUNCTION;
00663 }
00664
00665 for(int i = 0; i < num_primitives; ++i)
00666 primitive_indices[i] = i;
00667 recursiveBuildTree(0, 0, num_primitives);
00668
00669 bv_fitter->clear();
00670 bv_splitter->clear();
00671
00672 return BVH_OK;
00673 }
00674
00675 template<typename BV>
00676 int BVHModel<BV>::recursiveBuildTree(int bv_id, int first_primitive, int num_primitives)
00677 {
00678 BVHModelType type = getModelType();
00679 BVNode<BV>* bvnode = bvs + bv_id;
00680 unsigned int* cur_primitive_indices = primitive_indices + first_primitive;
00681
00682
00683 BV bv = bv_fitter->fit(cur_primitive_indices, num_primitives);
00684 bv_splitter->computeRule(bv, cur_primitive_indices, num_primitives);
00685
00686 bvnode->bv = bv;
00687 bvnode->first_primitive = first_primitive;
00688 bvnode->num_primitives = num_primitives;
00689
00690 if(num_primitives == 1)
00691 {
00692 bvnode->first_child = -((*cur_primitive_indices) + 1);
00693 }
00694 else
00695 {
00696 bvnode->first_child = num_bvs;
00697 num_bvs += 2;
00698
00699 int c1 = 0;
00700 for(int i = 0; i < num_primitives; ++i)
00701 {
00702 Vec3f p;
00703 if(type == BVH_MODEL_POINTCLOUD) p = vertices[cur_primitive_indices[i]];
00704 else if(type == BVH_MODEL_TRIANGLES)
00705 {
00706 const Triangle& t = tri_indices[cur_primitive_indices[i]];
00707 const Vec3f& p1 = vertices[t[0]];
00708 const Vec3f& p2 = vertices[t[1]];
00709 const Vec3f& p3 = vertices[t[2]];
00710 FCL_REAL x = (p1[0] + p2[0] + p3[0]) / 3.0;
00711 FCL_REAL y = (p1[1] + p2[1] + p3[1]) / 3.0;
00712 FCL_REAL z = (p1[2] + p2[2] + p3[2]) / 3.0;
00713 p.setValue(x, y, z);
00714 }
00715 else
00716 {
00717 std::cerr << "BVH Error: Model type not supported!" << std::endl;
00718 return BVH_ERR_UNSUPPORTED_FUNCTION;
00719 }
00720
00721
00722
00723
00724
00725
00726
00727
00728 if(bv_splitter->apply(p))
00729 {
00730
00731 }
00732 else
00733 {
00734 unsigned int temp = cur_primitive_indices[i];
00735 cur_primitive_indices[i] = cur_primitive_indices[c1];
00736 cur_primitive_indices[c1] = temp;
00737 c1++;
00738 }
00739 }
00740
00741
00742 if((c1 == 0) || (c1 == num_primitives)) c1 = num_primitives / 2;
00743
00744 int num_first_half = c1;
00745
00746 recursiveBuildTree(bvnode->leftChild(), first_primitive, num_first_half);
00747 recursiveBuildTree(bvnode->rightChild(), first_primitive + num_first_half, num_primitives - num_first_half);
00748 }
00749
00750 return BVH_OK;
00751 }
00752
00753 template<typename BV>
00754 int BVHModel<BV>::refitTree(bool bottomup)
00755 {
00756 if(bottomup)
00757 return refitTree_bottomup();
00758 else
00759 return refitTree_topdown();
00760 }
00761
00762 template<typename BV>
00763 int BVHModel<BV>::refitTree_bottomup()
00764 {
00765 int res = recursiveRefitTree_bottomup(0);
00766
00767 return res;
00768 }
00769
00770
00771 template<typename BV>
00772 int BVHModel<BV>::recursiveRefitTree_bottomup(int bv_id)
00773 {
00774 BVNode<BV>* bvnode = bvs + bv_id;
00775 if(bvnode->isLeaf())
00776 {
00777 BVHModelType type = getModelType();
00778 int primitive_id = -(bvnode->first_child + 1);
00779 if(type == BVH_MODEL_POINTCLOUD)
00780 {
00781 BV bv;
00782
00783 if(prev_vertices)
00784 {
00785 Vec3f v[2];
00786 v[0] = prev_vertices[primitive_id];
00787 v[1] = vertices[primitive_id];
00788 fit(v, 2, bv);
00789 }
00790 else
00791 fit(vertices + primitive_id, 1, bv);
00792
00793 bvnode->bv = bv;
00794 }
00795 else if(type == BVH_MODEL_TRIANGLES)
00796 {
00797 BV bv;
00798 const Triangle& triangle = tri_indices[primitive_id];
00799
00800 if(prev_vertices)
00801 {
00802 Vec3f v[6];
00803 for(int i = 0; i < 3; ++i)
00804 {
00805 v[i] = prev_vertices[triangle[i]];
00806 v[i + 3] = vertices[triangle[i]];
00807 }
00808
00809 fit(v, 6, bv);
00810 }
00811 else
00812 {
00813 Vec3f v[3];
00814 for(int i = 0; i < 3; ++i)
00815 {
00816 v[i] = vertices[triangle[i]];
00817 }
00818
00819 fit(v, 3, bv);
00820 }
00821
00822 bvnode->bv = bv;
00823 }
00824 else
00825 {
00826 std::cerr << "BVH Error: Model type not supported!" << std::endl;
00827 return BVH_ERR_UNSUPPORTED_FUNCTION;
00828 }
00829 }
00830 else
00831 {
00832 recursiveRefitTree_bottomup(bvnode->leftChild());
00833 recursiveRefitTree_bottomup(bvnode->rightChild());
00834 bvnode->bv = bvs[bvnode->leftChild()].bv + bvs[bvnode->rightChild()].bv;
00835 }
00836
00837 return BVH_OK;
00838 }
00839
00840 template<typename BV>
00841 int BVHModel<BV>::refitTree_topdown()
00842 {
00843 bv_fitter->set(vertices, prev_vertices, tri_indices, getModelType());
00844 for(int i = 0; i < num_bvs; ++i)
00845 {
00846 BV bv = bv_fitter->fit(primitive_indices + bvs[i].first_primitive, bvs[i].num_primitives);
00847 bvs[i].bv = bv;
00848 }
00849
00850 bv_fitter->clear();
00851
00852 return BVH_OK;
00853 }
00854
00855 template<typename BV>
00856 void BVHModel<BV>::computeLocalAABB()
00857 {
00858 AABB aabb_;
00859 for(int i = 0; i < num_vertices; ++i)
00860 {
00861 aabb_ += vertices[i];
00862 }
00863
00864 aabb_center = aabb_.center();
00865
00866 aabb_radius = 0;
00867 for(int i = 0; i < num_vertices; ++i)
00868 {
00869 FCL_REAL r = (aabb_center - vertices[i]).sqrLength();
00870 if(r > aabb_radius) aabb_radius = r;
00871 }
00872
00873 aabb_radius = sqrt(aabb_radius);
00874
00875 aabb_local = aabb_;
00876 }
00877
00878
00879 template<>
00880 void BVHModel<OBB>::makeParentRelativeRecurse(int bv_id, Vec3f parent_axis[], const Vec3f& parent_c)
00881 {
00882 OBB& obb = bvs[bv_id].bv;
00883 if(!bvs[bv_id].isLeaf())
00884 {
00885 makeParentRelativeRecurse(bvs[bv_id].first_child, obb.axis, obb.To);
00886
00887 makeParentRelativeRecurse(bvs[bv_id].first_child + 1, obb.axis, obb.To);
00888 }
00889
00890
00891 obb.axis[0] = Vec3f(parent_axis[0].dot(obb.axis[0]), parent_axis[1].dot(obb.axis[0]), parent_axis[2].dot(obb.axis[0]));
00892 obb.axis[1] = Vec3f(parent_axis[0].dot(obb.axis[1]), parent_axis[1].dot(obb.axis[1]), parent_axis[2].dot(obb.axis[1]));
00893 obb.axis[2] = Vec3f(parent_axis[0].dot(obb.axis[2]), parent_axis[1].dot(obb.axis[2]), parent_axis[2].dot(obb.axis[2]));
00894
00895 Vec3f t = obb.To - parent_c;
00896 obb.To = Vec3f(parent_axis[0].dot(t), parent_axis[1].dot(t), parent_axis[2].dot(t));
00897 }
00898
00899 template<>
00900 void BVHModel<RSS>::makeParentRelativeRecurse(int bv_id, Vec3f parent_axis[], const Vec3f& parent_c)
00901 {
00902 RSS& rss = bvs[bv_id].bv;
00903 if(!bvs[bv_id].isLeaf())
00904 {
00905 makeParentRelativeRecurse(bvs[bv_id].first_child, rss.axis, rss.Tr);
00906
00907 makeParentRelativeRecurse(bvs[bv_id].first_child + 1, rss.axis, rss.Tr);
00908 }
00909
00910
00911 rss.axis[0] = Vec3f(parent_axis[0].dot(rss.axis[0]), parent_axis[1].dot(rss.axis[0]), parent_axis[2].dot(rss.axis[0]));
00912 rss.axis[1] = Vec3f(parent_axis[0].dot(rss.axis[1]), parent_axis[1].dot(rss.axis[1]), parent_axis[2].dot(rss.axis[1]));
00913 rss.axis[2] = Vec3f(parent_axis[0].dot(rss.axis[2]), parent_axis[1].dot(rss.axis[2]), parent_axis[2].dot(rss.axis[2]));
00914
00915 Vec3f t = rss.Tr - parent_c;
00916 rss.Tr = Vec3f(parent_axis[0].dot(t), parent_axis[1].dot(t), parent_axis[2].dot(t));
00917 }
00918
00919 template<>
00920 void BVHModel<OBBRSS>::makeParentRelativeRecurse(int bv_id, Vec3f parent_axis[], const Vec3f& parent_c)
00921 {
00922 OBB& obb = bvs[bv_id].bv.obb;
00923 RSS& rss = bvs[bv_id].bv.rss;
00924 if(!bvs[bv_id].isLeaf())
00925 {
00926 makeParentRelativeRecurse(bvs[bv_id].first_child, obb.axis, obb.To);
00927
00928 makeParentRelativeRecurse(bvs[bv_id].first_child + 1, obb.axis, obb.To);
00929 }
00930
00931
00932 obb.axis[0] = Vec3f(parent_axis[0].dot(obb.axis[0]), parent_axis[1].dot(obb.axis[0]), parent_axis[2].dot(obb.axis[0]));
00933 obb.axis[1] = Vec3f(parent_axis[0].dot(obb.axis[1]), parent_axis[1].dot(obb.axis[1]), parent_axis[2].dot(obb.axis[1]));
00934 obb.axis[2] = Vec3f(parent_axis[0].dot(obb.axis[2]), parent_axis[1].dot(obb.axis[2]), parent_axis[2].dot(obb.axis[2]));
00935
00936 rss.axis[0] = obb.axis[0];
00937 rss.axis[1] = obb.axis[1];
00938 rss.axis[2] = obb.axis[2];
00939
00940 Vec3f t = obb.To - parent_c;
00941 obb.To = Vec3f(parent_axis[0].dot(t), parent_axis[1].dot(t), parent_axis[2].dot(t));
00942 rss.Tr = obb.To;
00943 }
00944
00945
00946
00947 template<>
00948 NODE_TYPE BVHModel<AABB>::getNodeType() const
00949 {
00950 return BV_AABB;
00951 }
00952
00953 template<>
00954 NODE_TYPE BVHModel<OBB>::getNodeType() const
00955 {
00956 return BV_OBB;
00957 }
00958
00959 template<>
00960 NODE_TYPE BVHModel<RSS>::getNodeType() const
00961 {
00962 return BV_RSS;
00963 }
00964
00965 template<>
00966 NODE_TYPE BVHModel<kIOS>::getNodeType() const
00967 {
00968 return BV_kIOS;
00969 }
00970
00971 template<>
00972 NODE_TYPE BVHModel<OBBRSS>::getNodeType() const
00973 {
00974 return BV_OBBRSS;
00975 }
00976
00977 template<>
00978 NODE_TYPE BVHModel<KDOP<16> >::getNodeType() const
00979 {
00980 return BV_KDOP16;
00981 }
00982
00983 template<>
00984 NODE_TYPE BVHModel<KDOP<18> >::getNodeType() const
00985 {
00986 return BV_KDOP18;
00987 }
00988
00989 template<>
00990 NODE_TYPE BVHModel<KDOP<24> >::getNodeType() const
00991 {
00992 return BV_KDOP24;
00993 }
00994
00995
00996
00997
00998
00999
01000 template class BVHModel<KDOP<16> >;
01001 template class BVHModel<KDOP<18> >;
01002 template class BVHModel<KDOP<24> >;
01003 template class BVHModel<OBB>;
01004 template class BVHModel<AABB>;
01005 template class BVHModel<RSS>;
01006 template class BVHModel<kIOS>;
01007 template class BVHModel<OBBRSS>;
01008 }