$search
00001 /* 00002 * Software License Agreement (BSD License) 00003 * 00004 * Copyright (c) 2011, Willow Garage, Inc. 00005 * All rights reserved. 00006 * 00007 * Redistribution and use in source and binary forms, with or without 00008 * modification, are permitted provided that the following conditions 00009 * are met: 00010 * 00011 * * Redistributions of source code must retain the above copyright 00012 * notice, this list of conditions and the following disclaimer. 00013 * * Redistributions in binary form must reproduce the above 00014 * copyright notice, this list of conditions and the following 00015 * disclaimer in the documentation and/or other materials provided 00016 * with the distribution. 00017 * * Neither the name of Willow Garage, Inc. nor the names of its 00018 * contributors may be used to endorse or promote products derived 00019 * from this software without specific prior written permission. 00020 * 00021 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 00022 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 00023 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 00024 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 00025 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 00026 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 00027 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 00028 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 00029 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 00030 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 00031 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 00032 * POSSIBILITY OF SUCH DAMAGE. 00033 */ 00034 00037 #include "collision_checking/BVH_model.h" 00038 #include "collision_checking/BV.h" 00039 #include <iostream> 00040 #include <string.h> 00041 00042 namespace collision_checking 00043 { 00044 00045 00046 template<typename BV> 00047 int BVHModel<BV>::beginModel(int num_tris_, int num_vertices_) 00048 { 00049 if(build_state != BVH_BUILD_STATE_EMPTY) 00050 { 00051 delete [] vertices; vertices = NULL; 00052 delete [] tri_indices; tri_indices = NULL; 00053 delete [] bvs; bvs = NULL; 00054 delete [] prev_vertices; prev_vertices = NULL; 00055 delete [] primitive_indices; primitive_indices = NULL; 00056 00057 num_vertices_allocated = num_vertices = num_tris_allocated = num_tris = num_bvs_allocated = num_bvs = 0; 00058 } 00059 00060 if(num_tris_ <= 0) num_tris_ = 8; 00061 if(num_vertices_ <= 0) num_vertices_ = 8; 00062 00063 num_vertices_allocated = num_vertices_; 00064 num_tris_allocated = num_tris_; 00065 00066 tri_indices = new Triangle[num_tris_allocated]; 00067 vertices = new Vec3f[num_vertices_allocated]; 00068 00069 if(!tri_indices) 00070 { 00071 std::cerr << "BVH Error! Out of memory for tri_indices array on BeginModel() call!" << std::endl; 00072 return BVH_ERR_MODEL_OUT_OF_MEMORY; 00073 } 00074 if(!vertices) 00075 { 00076 std::cerr << "BVH Error! Out of memory for vertices array on BeginModel() call!" << std::endl; 00077 return BVH_ERR_MODEL_OUT_OF_MEMORY; 00078 } 00079 00080 if(build_state != BVH_BUILD_STATE_EMPTY) 00081 { 00082 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; 00083 build_state = BVH_BUILD_STATE_EMPTY; 00084 return BVH_ERR_BUILD_OUT_OF_SEQUENCE; 00085 } 00086 00087 build_state = BVH_BUILD_STATE_BEGUN; 00088 00089 return BVH_OK; 00090 } 00091 00092 00093 template<typename BV> 00094 int BVHModel<BV>::addVertex(const Vec3f& p) 00095 { 00096 if(build_state != BVH_BUILD_STATE_UPDATE_BEGUN) 00097 { 00098 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; 00099 return BVH_ERR_BUILD_OUT_OF_SEQUENCE; 00100 } 00101 00102 if(num_vertices >= num_vertices_allocated) 00103 { 00104 Vec3f* temp = new Vec3f[num_vertices_allocated * 2]; 00105 if(!temp) 00106 { 00107 std::cerr << "BVH Error! Out of memory for vertices array on addVertex() call!" << std::endl; 00108 return BVH_ERR_MODEL_OUT_OF_MEMORY; 00109 } 00110 00111 memcpy(temp, vertices, sizeof(Vec3f) * num_vertices); 00112 delete [] vertices; 00113 vertices = temp; 00114 num_vertices_allocated *= 2; 00115 } 00116 00117 vertices[num_vertices] = p; 00118 num_vertices += 1; 00119 00120 return BVH_OK; 00121 } 00122 00123 template<typename BV> 00124 int BVHModel<BV>::addTriangle(const Vec3f& p1, const Vec3f& p2, const Vec3f& p3) 00125 { 00126 if(build_state == BVH_BUILD_STATE_PROCESSED) 00127 { 00128 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; 00129 return BVH_ERR_BUILD_OUT_OF_SEQUENCE; 00130 } 00131 00132 if(num_vertices + 2 >= num_vertices_allocated) 00133 { 00134 Vec3f* temp = new Vec3f[num_vertices_allocated * 2 + 2]; 00135 if(!temp) 00136 { 00137 std::cerr << "BVH Error! Out of memory for vertices array on addTriangle() call!" << std::endl; 00138 return BVH_ERR_MODEL_OUT_OF_MEMORY; 00139 } 00140 00141 memcpy(temp, vertices, sizeof(Vec3f) * num_vertices); 00142 delete [] vertices; 00143 vertices = temp; 00144 num_vertices_allocated = num_vertices_allocated * 2 + 2; 00145 } 00146 00147 int offset = num_vertices; 00148 00149 vertices[num_vertices] = p1; 00150 num_vertices++; 00151 vertices[num_vertices] = p2; 00152 num_vertices++; 00153 vertices[num_vertices] = p3; 00154 num_vertices++; 00155 00156 if(num_tris >= num_tris_allocated) 00157 { 00158 Triangle* temp = new Triangle[num_tris_allocated * 2]; 00159 if(!temp) 00160 { 00161 std::cerr << "BVH Error! Out of memory for tri_indices array on addTriangle() call!" << std::endl; 00162 return BVH_ERR_MODEL_OUT_OF_MEMORY; 00163 } 00164 00165 memcpy(temp, tri_indices, sizeof(Triangle) * num_tris); 00166 delete [] tri_indices; 00167 tri_indices = temp; 00168 num_tris_allocated *= 2; 00169 } 00170 00171 tri_indices[num_tris] = Triangle(offset, offset + 1, offset + 2); 00172 00173 return BVH_OK; 00174 } 00175 00176 template<typename BV> 00177 int BVHModel<BV>::addSubModel(const std::vector<Vec3f>& ps) 00178 { 00179 if(build_state == BVH_BUILD_STATE_PROCESSED) 00180 { 00181 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; 00182 return BVH_ERR_BUILD_OUT_OF_SEQUENCE; 00183 } 00184 00185 int num_vertices_to_add = ps.size(); 00186 00187 if(num_vertices + num_vertices_to_add - 1 >= num_vertices_allocated) 00188 { 00189 Vec3f* temp = new Vec3f[num_vertices_allocated * 2 + num_vertices_to_add - 1]; 00190 if(!temp) 00191 { 00192 std::cerr << "BVH Error! Out of memory for vertices array on addSubModel() call!" << std::endl; 00193 return BVH_ERR_MODEL_OUT_OF_MEMORY; 00194 } 00195 00196 memcpy(temp, vertices, sizeof(Vec3f) * num_vertices); 00197 delete [] vertices; 00198 vertices = temp; 00199 num_vertices_allocated = num_vertices_allocated * 2 + num_vertices_to_add - 1; 00200 } 00201 00202 for(int i = 0; i < num_vertices_to_add; ++i) 00203 { 00204 vertices[num_vertices] = ps[i]; 00205 num_vertices++; 00206 } 00207 00208 return BVH_OK; 00209 } 00210 00211 template<typename BV> 00212 int BVHModel<BV>::addSubModel(const std::vector<Vec3f>& ps, const std::vector<Triangle>& ts) 00213 { 00214 if(build_state == BVH_BUILD_STATE_PROCESSED) 00215 { 00216 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; 00217 return BVH_ERR_BUILD_OUT_OF_SEQUENCE; 00218 } 00219 00220 int num_vertices_to_add = ps.size(); 00221 00222 if(num_vertices + num_vertices_to_add - 1 >= num_vertices_allocated) 00223 { 00224 Vec3f* temp = new Vec3f[num_vertices_allocated * 2 + num_vertices_to_add - 1]; 00225 if(!temp) 00226 { 00227 std::cerr << "BVH Error! Out of memory for vertices array on addSubModel() call!" << std::endl; 00228 return BVH_ERR_MODEL_OUT_OF_MEMORY; 00229 } 00230 00231 memcpy(temp, vertices, sizeof(Vec3f) * num_vertices); 00232 delete [] vertices; 00233 vertices = temp; 00234 num_vertices_allocated = num_vertices_allocated * 2 + num_vertices_to_add - 1; 00235 } 00236 00237 int offset = num_vertices; 00238 00239 for(int i = 0; i < num_vertices_to_add; ++i) 00240 { 00241 vertices[num_vertices] = ps[i]; 00242 num_vertices++; 00243 } 00244 00245 00246 int num_tris_to_add = ts.size(); 00247 00248 if(num_tris + num_tris_to_add - 1 >= num_tris_allocated) 00249 { 00250 Triangle* temp = new Triangle[num_tris_allocated * 2 + num_tris_to_add - 1]; 00251 if(!temp) 00252 { 00253 std::cerr << "BVH Error! Out of memory for tri_indices array on addSubModel() call!" << std::endl; 00254 return BVH_ERR_MODEL_OUT_OF_MEMORY; 00255 } 00256 00257 memcpy(temp, tri_indices, sizeof(Triangle) * num_tris); 00258 delete [] tri_indices; 00259 tri_indices = temp; 00260 num_tris_allocated = num_tris_allocated * 2 + num_tris_to_add - 1; 00261 } 00262 00263 for(int i = 0; i < num_tris_to_add; ++i) 00264 { 00265 const Triangle& t = ts[i]; 00266 tri_indices[num_tris] = Triangle(t[0] + offset, t[1] + offset, t[2] + offset); 00267 num_tris++; 00268 } 00269 00270 return BVH_OK; 00271 } 00272 00273 template<typename BV> 00274 int BVHModel<BV>::endModel() 00275 { 00276 if(build_state != BVH_BUILD_STATE_BEGUN) 00277 { 00278 std::cerr << "BVH Warning! Call endModel() in wrong order. endModel() was ignored." << std::endl; 00279 return BVH_ERR_BUILD_OUT_OF_SEQUENCE; 00280 } 00281 00282 if(num_tris == 0 && num_vertices == 0) 00283 { 00284 std::cerr << "BVH Error! endModel() called on model with no triangles and vertices." << std::endl; 00285 return BVH_ERR_BUILD_EMPTY_MODEL; 00286 } 00287 00288 if(num_tris_allocated > num_tris) 00289 { 00290 Triangle* new_tris = new Triangle[num_tris]; 00291 if(!new_tris) 00292 { 00293 std::cerr << "BVH Error! Out of memory for tri_indices array in endModel() call!" << std::endl; 00294 return BVH_ERR_MODEL_OUT_OF_MEMORY; 00295 } 00296 memcpy(new_tris, tri_indices, sizeof(Triangle) * num_tris); 00297 delete [] tri_indices; 00298 tri_indices = new_tris; 00299 num_tris_allocated = num_tris; 00300 } 00301 00302 if(num_vertices_allocated > num_vertices) 00303 { 00304 Vec3f* new_vertices = new Vec3f[num_vertices]; 00305 if(!new_vertices) 00306 { 00307 std::cerr << "BVH Error! Out of memory for vertices array in endModel() call!" << std::endl; 00308 return BVH_ERR_MODEL_OUT_OF_MEMORY; 00309 } 00310 memcpy(new_vertices, vertices, sizeof(Vec3f) * num_vertices); 00311 delete [] vertices; 00312 vertices = new_vertices; 00313 num_vertices_allocated = num_vertices; 00314 } 00315 00316 // construct BVH tree 00317 int num_bvs_to_be_allocated = 0; 00318 if(num_tris == 0) 00319 num_bvs_to_be_allocated = 2 * num_vertices - 1; 00320 else 00321 num_bvs_to_be_allocated = 2 * num_tris - 1; 00322 00323 00324 bvs = new BVNode<BV> [num_bvs_to_be_allocated]; 00325 primitive_indices = new unsigned int [num_bvs_to_be_allocated]; 00326 if(!bvs || !primitive_indices) 00327 { 00328 std::cerr << "BVH Error! Out of memory for BV array in endModel()!" << std::endl; 00329 return BVH_ERR_MODEL_OUT_OF_MEMORY; 00330 } 00331 num_bvs_allocated = num_bvs_to_be_allocated; 00332 num_bvs = 0; 00333 00334 buildTree(); 00335 00336 // finish constructing 00337 build_state = BVH_BUILD_STATE_PROCESSED; 00338 00339 return BVH_OK; 00340 } 00341 00342 00343 00344 template<typename BV> 00345 int BVHModel<BV>::beginReplaceModel() 00346 { 00347 if(build_state != BVH_BUILD_STATE_PROCESSED) 00348 { 00349 std::cerr << "BVH Error! Call beginReplaceModel() on a BVHModel that has no previous frame." << std::endl; 00350 return BVH_ERR_BUILD_EMPTY_PREVIOUS_FRAME; 00351 } 00352 00353 if(prev_vertices) delete [] prev_vertices; prev_vertices = NULL; 00354 00355 num_vertex_updated = 0; 00356 00357 build_state = BVH_BUILD_STATE_REPLACE_BEGUN; 00358 00359 return BVH_OK; 00360 } 00361 00362 template<typename BV> 00363 int BVHModel<BV>::replaceVertex(const Vec3f& p) 00364 { 00365 if(build_state != BVH_BUILD_STATE_REPLACE_BEGUN) 00366 { 00367 std::cerr << "BVH Warning! Call replaceVertex() in a wrong order. replaceVertex() was ignored. Must do a beginReplaceModel() for initialization." << std::endl; 00368 return BVH_ERR_BUILD_OUT_OF_SEQUENCE; 00369 } 00370 00371 vertices[num_vertex_updated] = p; 00372 num_vertex_updated++; 00373 00374 return BVH_OK; 00375 } 00376 00377 template<typename BV> 00378 int BVHModel<BV>::replaceTriangle(const Vec3f& p1, const Vec3f& p2, const Vec3f& p3) 00379 { 00380 if(build_state != BVH_BUILD_STATE_REPLACE_BEGUN) 00381 { 00382 std::cerr << "BVH Warning! Call replaceTriangle() in a wrong order. replaceTriangle() was ignored. Must do a beginReplaceModel() for initialization." << std::endl; 00383 return BVH_ERR_BUILD_OUT_OF_SEQUENCE; 00384 } 00385 00386 vertices[num_vertex_updated] = p1; num_vertex_updated++; 00387 vertices[num_vertex_updated] = p2; num_vertex_updated++; 00388 vertices[num_vertex_updated] = p3; num_vertex_updated++; 00389 return BVH_OK; 00390 } 00391 00392 template<typename BV> 00393 int BVHModel<BV>::replaceSubModel(const std::vector<Vec3f>& ps) 00394 { 00395 if(build_state != BVH_BUILD_STATE_REPLACE_BEGUN) 00396 { 00397 std::cerr << "BVH Warning! Call replaceSubModel() in a wrong order. replaceSubModel() was ignored. Must do a beginReplaceModel() for initialization." << std::endl; 00398 return BVH_ERR_BUILD_OUT_OF_SEQUENCE; 00399 } 00400 00401 for(unsigned int i = 0; i < ps.size(); ++i) 00402 { 00403 vertices[num_vertex_updated] = ps[i]; 00404 num_vertex_updated++; 00405 } 00406 return BVH_OK; 00407 } 00408 00409 template<typename BV> 00410 int BVHModel<BV>::endReplaceModel(bool refit, bool bottomup) 00411 { 00412 if(build_state != BVH_BUILD_STATE_REPLACE_BEGUN) 00413 { 00414 std::cerr << "BVH Warning! Call endReplaceModel() in a wrong order. endReplaceModel() was ignored. " << std::endl; 00415 return BVH_ERR_BUILD_OUT_OF_SEQUENCE; 00416 } 00417 00418 if(num_vertex_updated != num_vertices) 00419 { 00420 std::cerr << "BVH Error! The replaced model should have the same number of vertices as the old model." << std::endl; 00421 return BVH_ERR_INCORRECT_DATA; 00422 } 00423 00424 if(refit) // refit, do not change BVH structure 00425 { 00426 refitTree(bottomup); 00427 } 00428 else // reconstruct bvh tree based on current frame data 00429 { 00430 buildTree(); 00431 } 00432 00433 build_state = BVH_BUILD_STATE_PROCESSED; 00434 00435 return BVH_OK; 00436 } 00437 00438 00439 00440 00441 00442 template<typename BV> 00443 int BVHModel<BV>::beginUpdateModel() 00444 { 00445 if(build_state != BVH_BUILD_STATE_PROCESSED && build_state != BVH_BUILD_STATE_UPDATED) 00446 { 00447 std::cerr << "BVH Error! Call beginUpdatemodel() on a BVHModel that has no previous frame." << std::endl; 00448 return BVH_ERR_BUILD_EMPTY_PREVIOUS_FRAME; 00449 } 00450 00451 if(prev_vertices) 00452 { 00453 Vec3f* temp = prev_vertices; 00454 prev_vertices = vertices; 00455 vertices = temp; 00456 } 00457 else 00458 { 00459 prev_vertices = vertices; 00460 vertices = new Vec3f[num_vertices]; 00461 } 00462 00463 num_vertex_updated = 0; 00464 00465 build_state = BVH_BUILD_STATE_UPDATE_BEGUN; 00466 00467 return BVH_OK; 00468 } 00469 00470 template<typename BV> 00471 int BVHModel<BV>::updateVertex(const Vec3f& p) 00472 { 00473 if(build_state != BVH_BUILD_STATE_UPDATE_BEGUN) 00474 { 00475 std::cerr << "BVH Warning! Call updateVertex() in a wrong order. updateVertex() was ignored. Must do a beginUpdateModel() for initialization." << std::endl; 00476 return BVH_ERR_BUILD_OUT_OF_SEQUENCE; 00477 } 00478 00479 vertices[num_vertex_updated] = p; 00480 num_vertex_updated++; 00481 00482 return BVH_OK; 00483 } 00484 00485 template<typename BV> 00486 int BVHModel<BV>::updateTriangle(const Vec3f& p1, const Vec3f& p2, const Vec3f& p3) 00487 { 00488 if(build_state != BVH_BUILD_STATE_UPDATE_BEGUN) 00489 { 00490 std::cerr << "BVH Warning! Call updateTriangle() in a wrong order. updateTriangle() was ignored. Must do a beginUpdateModel() for initialization." << std::endl; 00491 return BVH_ERR_BUILD_OUT_OF_SEQUENCE; 00492 } 00493 00494 vertices[num_vertex_updated] = p1; num_vertex_updated++; 00495 vertices[num_vertex_updated] = p2; num_vertex_updated++; 00496 vertices[num_vertex_updated] = p3; num_vertex_updated++; 00497 return BVH_OK; 00498 } 00499 00500 template<typename BV> 00501 int BVHModel<BV>::updateSubModel(const std::vector<Vec3f>& ps) 00502 { 00503 if(build_state != BVH_BUILD_STATE_UPDATE_BEGUN) 00504 { 00505 std::cerr << "BVH Warning! Call updateSubModel() in a wrong order. updateSubModel() was ignored. Must do a beginUpdateModel() for initialization." << std::endl; 00506 return BVH_ERR_BUILD_OUT_OF_SEQUENCE; 00507 } 00508 00509 for(unsigned int i = 0; i < ps.size(); ++i) 00510 { 00511 vertices[num_vertex_updated] = ps[i]; 00512 num_vertex_updated++; 00513 } 00514 return BVH_OK; 00515 } 00516 00517 template<typename BV> 00518 int BVHModel<BV>::endUpdateModel(bool refit, bool bottomup) 00519 { 00520 if(build_state != BVH_BUILD_STATE_UPDATE_BEGUN) 00521 { 00522 std::cerr << "BVH Warning! Call endUpdateModel() in a wrong order. endUpdateModel() was ignored. " << std::endl; 00523 return BVH_ERR_BUILD_OUT_OF_SEQUENCE; 00524 } 00525 00526 if(num_vertex_updated != num_vertices) 00527 { 00528 std::cerr << "BVH Error! The updated model should have the same number of vertices as the old model." << std::endl; 00529 return BVH_ERR_INCORRECT_DATA; 00530 } 00531 00532 if(refit) // refit, do not change BVH structure 00533 { 00534 refitTree(bottomup); 00535 } 00536 else // reconstruct bvh tree based on current frame data 00537 { 00538 buildTree(); 00539 00540 // then refit 00541 00542 refitTree(bottomup); 00543 } 00544 00545 00546 build_state = BVH_BUILD_STATE_UPDATED; 00547 00548 return BVH_OK; 00549 } 00550 00551 00552 00553 00554 template<typename BV> 00555 int BVHModel<BV>::memUsage(int msg) const 00556 { 00557 int mem_bv_list = sizeof(BV) * num_bvs; 00558 int mem_tri_list = sizeof(Triangle) * num_tris; 00559 int mem_vertex_list = sizeof(Vec3f) * num_vertices; 00560 00561 int total_mem = mem_bv_list + mem_tri_list + mem_vertex_list + sizeof(BVHModel<BV>); 00562 if(msg) 00563 { 00564 std::cerr << "Total for model " << total_mem << " bytes." << std::endl; 00565 std::cerr << "BVs: " << num_bvs << " allocated." << std::endl; 00566 std::cerr << "Tris: " << num_tris << " allocated." << std::endl; 00567 std::cerr << "Vertices: " << num_vertices << " allocated." << std::endl; 00568 } 00569 00570 return BVH_OK; 00571 } 00572 00573 00574 template<typename BV> 00575 int BVHModel<BV>::buildTree() 00576 { 00577 // set BVFitter 00578 bv_fitter.set(vertices, tri_indices, getModelType()); 00579 // set SplitRule 00580 bv_splitter.set(vertices, tri_indices, getModelType()); 00581 00582 num_bvs = 1; 00583 00584 int num_primitives = 0; 00585 switch(getModelType()) 00586 { 00587 case BVH_MODEL_TRIANGLES: 00588 num_primitives = num_tris; 00589 break; 00590 case BVH_MODEL_POINTCLOUD: 00591 num_primitives = num_vertices; 00592 break; 00593 default: 00594 std::cerr << "BVH Error: Model type not supported!" << std::endl; 00595 return BVH_ERR_UNSUPPORTED_FUNCTION; 00596 } 00597 00598 for(int i = 0; i < num_primitives; ++i) 00599 primitive_indices[i] = i; 00600 00601 recursiveBuildTree(0, 0, num_primitives); 00602 00603 00604 bv_fitter.clear(); 00605 bv_splitter.clear(); 00606 00607 return BVH_OK; 00608 } 00609 00610 template<typename BV> 00611 int BVHModel<BV>::recursiveBuildTree(int bv_id, int first_primitive, int num_primitives) 00612 { 00613 BVHModelType type = getModelType(); 00614 BVNode<BV>* bvnode = bvs + bv_id; 00615 unsigned int* cur_primitive_indices = primitive_indices + first_primitive; 00616 00617 // constructing BV 00618 BV bv = bv_fitter.fit(cur_primitive_indices, num_primitives); 00619 bv_splitter.computeRule(bv, cur_primitive_indices, num_primitives); 00620 00621 00622 bvnode->bv = bv; 00623 bvnode->first_primitive = first_primitive; 00624 bvnode->num_primitives = num_primitives; 00625 00626 if(num_primitives == 1) 00627 { 00628 bvnode->first_child = -((*cur_primitive_indices) + 1); 00629 } 00630 else 00631 { 00632 bvnode->first_child = num_bvs; 00633 num_bvs += 2; 00634 00635 int c1 = 0; 00636 for(int i = 0; i < num_primitives; ++i) 00637 { 00638 Vec3f p; 00639 if(type == BVH_MODEL_POINTCLOUD) p = vertices[cur_primitive_indices[i]]; 00640 else if(type == BVH_MODEL_TRIANGLES) 00641 { 00642 const Triangle& t = tri_indices[cur_primitive_indices[i]]; 00643 const Vec3f& p1 = vertices[t[0]]; 00644 const Vec3f& p2 = vertices[t[1]]; 00645 const Vec3f& p3 = vertices[t[2]]; 00646 BVH_REAL x = (p1[0] + p2[0] + p3[0]) / 3; 00647 BVH_REAL y = (p1[1] + p2[1] + p3[1]) / 3; 00648 BVH_REAL z = (p1[2] + p2[2] + p3[2]) / 3; 00649 p = Vec3f(x, y, z); 00650 } 00651 else 00652 { 00653 std::cerr << "BVH Error: Model type not supported!" << std::endl; 00654 return BVH_ERR_UNSUPPORTED_FUNCTION; 00655 } 00656 00657 00658 // loop invariant: up to (but not including) index c1 in group 1, 00659 // then up to (but not including) index i in group 2 00660 // 00661 // [1] [1] [1] [1] [2] [2] [2] [x] [x] ... [x] 00662 // c1 i 00663 // 00664 if(bv_splitter(p)) // in the right side 00665 { 00666 // do nothing 00667 } 00668 else 00669 { 00670 unsigned int temp = cur_primitive_indices[i]; 00671 cur_primitive_indices[i] = cur_primitive_indices[c1]; 00672 cur_primitive_indices[c1] = temp; 00673 c1++; 00674 } 00675 } 00676 00677 00678 if((c1 == 0) || (c1 == num_primitives)) c1 = num_primitives / 2; 00679 00680 int num_first_half = c1; 00681 00682 recursiveBuildTree(bvnode->leftChild(), first_primitive, num_first_half); 00683 recursiveBuildTree(bvnode->rightChild(), first_primitive + num_first_half, num_primitives - num_first_half); 00684 } 00685 00686 return BVH_OK; 00687 } 00688 00689 template<typename BV> 00690 int BVHModel<BV>::refitTree(bool bottomup) 00691 { 00692 if(bottomup) 00693 return refitTree_bottomup(); 00694 else 00695 return refitTree_topdown(); 00696 } 00697 00698 template<typename BV> 00699 int BVHModel<BV>::refitTree_bottomup() 00700 { 00701 int res = recursiveRefitTree_bottomup(0); 00702 00703 return res; 00704 } 00705 00706 00707 template<typename BV> 00708 int BVHModel<BV>::recursiveRefitTree_bottomup(int bv_id) 00709 { 00710 BVNode<BV>* bvnode = bvs + bv_id; 00711 if(bvnode->isLeaf()) 00712 { 00713 BVHModelType type = getModelType(); 00714 int primitive_id = -(bvnode->first_child + 1); 00715 if(type == BVH_MODEL_POINTCLOUD) 00716 { 00717 BV bv; 00718 00719 if(prev_vertices) 00720 { 00721 Vec3f v[2]; 00722 v[0] = prev_vertices[primitive_id]; 00723 v[1] = vertices[primitive_id]; 00724 bv = BVFitter<BV>::fit(v, 2); 00725 } 00726 else 00727 { 00728 // Vec3f v = vertices[primitive_id]; 00729 // bv = BVFitter<BV>::fit(&v, 1); 00730 bv = BVFitter<BV>::fit(vertices + primitive_id, 1); 00731 } 00732 00733 bvnode->bv = bv; 00734 } 00735 else if(type == BVH_MODEL_TRIANGLES) 00736 { 00737 BV bv; 00738 const Triangle& triangle = tri_indices[primitive_id]; 00739 00740 if(prev_vertices) 00741 { 00742 Vec3f v[6]; 00743 for(int i = 0; i < 3; ++i) 00744 { 00745 v[i] = prev_vertices[triangle[i]]; 00746 v[i + 3] = vertices[triangle[i]]; 00747 } 00748 00749 bv = BVFitter<BV>::fit(v, 6); 00750 } 00751 else 00752 { 00753 Vec3f v[3]; 00754 for(int i = 0; i < 3; ++i) 00755 { 00756 v[i] = vertices[triangle[i]]; 00757 } 00758 00759 bv = BVFitter<BV>::fit(v, 3); 00760 } 00761 00762 bvnode->bv = bv; 00763 } 00764 else 00765 { 00766 std::cerr << "BVH Error: Model type not supported!" << std::endl; 00767 return BVH_ERR_UNSUPPORTED_FUNCTION; 00768 } 00769 } 00770 else 00771 { 00772 recursiveRefitTree_bottomup(bvnode->leftChild()); 00773 recursiveRefitTree_bottomup(bvnode->rightChild()); 00774 bvnode->bv = bvs[bvnode->leftChild()].bv + bvs[bvnode->rightChild()].bv; 00775 } 00776 00777 return BVH_OK; 00778 } 00779 00780 template<typename BV> 00781 int BVHModel<BV>::refitTree_topdown() 00782 { 00783 bv_fitter.set(vertices, prev_vertices, tri_indices, getModelType()); 00784 for(int i = 0; i < num_bvs; ++i) 00785 { 00786 BV bv = bv_fitter.fit(primitive_indices + bvs[i].first_primitive, bvs[i].num_primitives); 00787 bvs[i].bv = bv; 00788 } 00789 00790 bv_fitter.clear(); 00791 00792 return BVH_OK; 00793 } 00794 00795 00796 template class BVHModel<KDOP<16> >; 00797 template class BVHModel<KDOP<18> >; 00798 template class BVHModel<KDOP<24> >; 00799 template class BVHModel<OBB>; 00800 template class BVHModel<AABB>; 00801 template class BVHModel<RSS>; 00802 00803 }