BVH_model.cpp
Go to the documentation of this file.
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 "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   // construct BVH tree
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   // finish constructing
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)  // refit, do not change BVH structure
00492   {
00493     refitTree(bottomup);
00494   }
00495   else // reconstruct bvh tree based on current frame data
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)  // refit, do not change BVH structure
00600   {
00601     refitTree(bottomup);
00602   }
00603   else // reconstruct bvh tree based on current frame data
00604   {
00605     buildTree();
00606 
00607     // then refit
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   // set BVFitter
00645   bv_fitter->set(vertices, tri_indices, getModelType());
00646   // set SplitRule
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   // constructing BV
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       // loop invariant: up to (but not including) index c1 in group 1,
00723       // then up to (but not including) index i in group 2
00724       //
00725       //  [1] [1] [1] [1] [2] [2] [2] [x] [x] ... [x]
00726       //                   c1          i
00727       //
00728       if(bv_splitter->apply(p)) // in the right side
00729       {
00730         // do nothing
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   // make self parent relative
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   // make self parent relative
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   // make self parent relative
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 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines


fcl
Author(s): Jia Pan
autogenerated on Tue Jan 15 2013 16:05:30