38 #ifndef FCL_BVH_MODEL_INL_H
39 #define FCL_BVH_MODEL_INL_H
49 template <
typename BV>
52 if(num_tris && num_vertices)
61 template <
typename BV>
64 prev_vertices(nullptr),
69 bv_fitter(new detail::BVFitter<BV>()),
70 num_tris_allocated(0),
71 num_vertices_allocated(0),
73 num_vertex_updated(0),
74 primitive_indices(nullptr),
82 template <
typename BV>
85 num_tris(other.num_tris),
86 num_vertices(other.num_vertices),
87 build_state(other.build_state),
88 bv_splitter(other.bv_splitter),
89 bv_fitter(other.bv_fitter),
90 num_tris_allocated(other.num_tris),
91 num_vertices_allocated(other.num_vertices)
103 tri_indices =
new Triangle[num_tris];
107 tri_indices =
nullptr;
115 prev_vertices =
nullptr;
119 int num_primitives = 0;
123 num_primitives = num_tris;
126 num_primitives = num_vertices;
132 primitive_indices =
new unsigned int[num_primitives];
136 primitive_indices =
nullptr;
138 num_bvs = num_bvs_allocated = other.
num_bvs;
142 std::copy(other.
bvs, other.
bvs + num_bvs, bvs);
149 template <
typename BV>
153 delete [] tri_indices;
156 delete [] prev_vertices;
157 delete [] primitive_indices;
161 template <
typename BV>
168 template <
typename BV>
175 template <
typename BV>
182 template <
typename BV>
189 template <
typename BV>
199 template <
typename BV>
206 template <
typename BV>
211 delete [] vertices; vertices =
nullptr;
212 delete [] tri_indices; tri_indices =
nullptr;
213 delete [] bvs; bvs =
nullptr;
214 delete [] prev_vertices; prev_vertices =
nullptr;
215 delete [] primitive_indices; primitive_indices =
nullptr;
217 num_vertices_allocated = num_vertices = num_tris_allocated = num_tris = num_bvs_allocated = num_bvs = 0;
220 if(num_tris_ < 0) num_tris_ = 8;
221 if(num_vertices_ <= 0) num_vertices_ = 8;
223 num_vertices_allocated = num_vertices_;
224 num_tris_allocated = num_tris_;
228 tri_indices =
new(std::nothrow)
Triangle[num_tris_allocated];
231 std::cerr <<
"BVH Error! Out of memory for tri_indices array on BeginModel() call!\n";
236 vertices =
new Vector3<S>[num_vertices_allocated];
239 std::cerr <<
"BVH Error! Out of memory for vertices array on BeginModel() call!\n";
245 std::cerr <<
"BVH Warning! Call beginModel() on a BVHModel that is not empty. This model was cleared and previous triangles/vertices were lost.\n";
256 template <
typename BV>
261 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.\n";
265 if(num_vertices >= num_vertices_allocated)
270 std::cerr <<
"BVH Error! Out of memory for vertices array on addVertex() call!\n";
274 std::copy(vertices, vertices + num_vertices, temp);
277 num_vertices_allocated *= 2;
280 vertices[num_vertices] = p;
287 template <
typename BV>
292 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.\n";
296 if(num_vertices + 2 >= num_vertices_allocated)
301 std::cerr <<
"BVH Error! Out of memory for vertices array on addTriangle() call!\n";
305 std::copy(vertices, vertices + num_vertices, temp);
308 num_vertices_allocated = num_vertices_allocated * 2 + 2;
311 int offset = num_vertices;
313 vertices[num_vertices] = p1;
315 vertices[num_vertices] = p2;
317 vertices[num_vertices] = p3;
320 if(num_tris >= num_tris_allocated)
322 if(num_tris_allocated == 0)
324 num_tris_allocated = 1;
329 std::cerr <<
"BVH Error! Out of memory for tri_indices array on addTriangle() call!\n";
333 std::copy(tri_indices, tri_indices + num_tris, temp);
334 delete [] tri_indices;
336 num_tris_allocated *= 2;
339 tri_indices[num_tris].
set(offset, offset + 1, offset + 2);
346 template <
typename BV>
351 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.\n";
355 int num_vertices_to_add = ps.size();
357 if(num_vertices + num_vertices_to_add - 1 >= num_vertices_allocated)
362 std::cerr <<
"BVH Error! Out of memory for vertices array on addSubModel() call!\n";
366 std::copy(vertices, vertices + num_vertices, temp);
369 num_vertices_allocated = num_vertices_allocated * 2 + num_vertices_to_add - 1;
372 for(
int i = 0; i < num_vertices_to_add; ++i)
374 vertices[num_vertices] = ps[i];
382 template <
typename BV>
387 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.\n";
391 int num_vertices_to_add = ps.size();
393 if(num_vertices + num_vertices_to_add - 1 >= num_vertices_allocated)
398 std::cerr <<
"BVH Error! Out of memory for vertices array on addSubModel() call!\n";
402 std::copy(vertices, vertices + num_vertices, temp);
405 num_vertices_allocated = num_vertices_allocated * 2 + num_vertices_to_add - 1;
408 int offset = num_vertices;
410 for(
int i = 0; i < num_vertices_to_add; ++i)
412 vertices[num_vertices] = ps[i];
417 int num_tris_to_add = ts.size();
419 if(num_tris + num_tris_to_add - 1 >= num_tris_allocated)
421 if(num_tris_allocated == 0)
423 num_tris_allocated = 1;
425 Triangle* temp =
new(std::nothrow)
Triangle[num_tris_allocated * 2 + num_tris_to_add - 1];
428 std::cerr <<
"BVH Error! Out of memory for tri_indices array on addSubModel() call!\n";
432 std::copy(tri_indices, tri_indices + num_tris, temp);
433 delete [] tri_indices;
435 num_tris_allocated = num_tris_allocated * 2 + num_tris_to_add - 1;
438 for(
int i = 0; i < num_tris_to_add; ++i)
441 tri_indices[num_tris].
set(t[0] + offset, t[1] + offset, t[2] + offset);
449 template <
typename BV>
454 std::cerr <<
"BVH Warning! Call endModel() in wrong order. endModel() was ignored.\n";
458 if(num_tris == 0 && num_vertices == 0)
460 std::cerr <<
"BVH Error! endModel() called on model with no triangles and vertices.\n";
464 if(num_tris_allocated > num_tris)
469 std::cerr <<
"BVH Error! Out of memory for tri_indices array in endModel() call!\n";
472 std::copy(tri_indices, tri_indices + num_tris, new_tris);
473 delete [] tri_indices;
474 tri_indices = new_tris;
475 num_tris_allocated = num_tris;
478 if(num_vertices_allocated > num_vertices)
483 std::cerr <<
"BVH Error! Out of memory for vertices array in endModel() call!\n";
486 std::copy(vertices, vertices + num_vertices, new_vertices);
488 vertices = new_vertices;
489 num_vertices_allocated = num_vertices;
494 int num_bvs_to_be_allocated = 0;
496 num_bvs_to_be_allocated = 2 * num_vertices - 1;
498 num_bvs_to_be_allocated = 2 * num_tris - 1;
501 bvs =
new(std::nothrow)
BVNode<BV> [num_bvs_to_be_allocated];
502 primitive_indices =
new(std::nothrow)
unsigned int [num_bvs_to_be_allocated];
503 if(!bvs || !primitive_indices)
505 std::cerr <<
"BVH Error! Out of memory for BV array in endModel()!\n";
508 num_bvs_allocated = num_bvs_to_be_allocated;
520 template <
typename BV>
525 std::cerr <<
"BVH Error! Call beginReplaceModel() on a BVHModel that has no previous frame.\n";
531 delete [] prev_vertices;
532 prev_vertices =
nullptr;
535 num_vertex_updated = 0;
543 template <
typename BV>
548 std::cerr <<
"BVH Warning! Call replaceVertex() in a wrong order. replaceVertex() was ignored. Must do a beginReplaceModel() for initialization.\n";
552 vertices[num_vertex_updated] = p;
553 num_vertex_updated++;
559 template <
typename BV>
564 std::cerr <<
"BVH Warning! Call replaceTriangle() in a wrong order. replaceTriangle() was ignored. Must do a beginReplaceModel() for initialization.\n";
568 vertices[num_vertex_updated] = p1; num_vertex_updated++;
569 vertices[num_vertex_updated] = p2; num_vertex_updated++;
570 vertices[num_vertex_updated] = p3; num_vertex_updated++;
575 template <
typename BV>
580 std::cerr <<
"BVH Warning! Call replaceSubModel() in a wrong order. replaceSubModel() was ignored. Must do a beginReplaceModel() for initialization.\n";
584 for(
unsigned int i = 0; i < ps.size(); ++i)
586 vertices[num_vertex_updated] = ps[i];
587 num_vertex_updated++;
593 template <
typename BV>
598 std::cerr <<
"BVH Warning! Call endReplaceModel() in a wrong order. endReplaceModel() was ignored. \n";
602 if(num_vertex_updated != num_vertices)
604 std::cerr <<
"BVH Error! The replaced model should have the same number of vertices as the old model.\n";
623 template <
typename BV>
628 std::cerr <<
"BVH Error! Call beginUpdatemodel() on a BVHModel that has no previous frame.\n";
635 prev_vertices = vertices;
640 prev_vertices = vertices;
644 num_vertex_updated = 0;
652 template <
typename BV>
657 std::cerr <<
"BVH Warning! Call updateVertex() in a wrong order. updateVertex() was ignored. Must do a beginUpdateModel() for initialization.\n";
661 vertices[num_vertex_updated] = p;
662 num_vertex_updated++;
668 template <
typename BV>
673 std::cerr <<
"BVH Warning! Call updateTriangle() in a wrong order. updateTriangle() was ignored. Must do a beginUpdateModel() for initialization.\n";
677 vertices[num_vertex_updated] = p1; num_vertex_updated++;
678 vertices[num_vertex_updated] = p2; num_vertex_updated++;
679 vertices[num_vertex_updated] = p3; num_vertex_updated++;
684 template <
typename BV>
689 std::cerr <<
"BVH Warning! Call updateSubModel() in a wrong order. updateSubModel() was ignored. Must do a beginUpdateModel() for initialization.\n";
693 for(
unsigned int i = 0; i < ps.size(); ++i)
695 vertices[num_vertex_updated] = ps[i];
696 num_vertex_updated++;
702 template <
typename BV>
707 std::cerr <<
"BVH Warning! Call endUpdateModel() in a wrong order. endUpdateModel() was ignored. \n";
711 if(num_vertex_updated != num_vertices)
713 std::cerr <<
"BVH Error! The updated model should have the same number of vertices as the old model.\n";
737 template <
typename BV>
740 int mem_bv_list =
sizeof(BV) * num_bvs;
741 int mem_tri_list =
sizeof(
Triangle) * num_tris;
742 int mem_vertex_list =
sizeof(
Vector3<S>) * num_vertices;
744 int total_mem = mem_bv_list + mem_tri_list + mem_vertex_list +
sizeof(
BVHModel<BV>);
747 std::cerr <<
"Total for model " << total_mem <<
" bytes.\n";
748 std::cerr <<
"BVs: " << num_bvs <<
" allocated.\n";
749 std::cerr <<
"Tris: " << num_tris <<
" allocated.\n";
750 std::cerr <<
"Vertices: " << num_vertices <<
" allocated.\n";
757 template <
typename BV>
760 makeParentRelativeRecurse(
765 template <
typename BV>
770 for(
int i = 0; i < num_tris; ++i)
772 const Triangle& tri = tri_indices[i];
773 S d_six_vol = (vertices[tri[0]].cross(vertices[tri[1]])).dot(vertices[tri[2]]);
775 com.noalias() += (vertices[tri[0]] + vertices[tri[1]] + vertices[tri[2]]) * d_six_vol;
778 return com / (vol * 4);
782 template <
typename BV>
786 for(
int i = 0; i < num_tris; ++i)
788 const Triangle& tri = tri_indices[i];
789 S d_six_vol = (vertices[tri[0]].cross(vertices[tri[1]])).dot(vertices[tri[2]]);
797 template <
typename BV>
803 C_canonical << 1/ 60.0, 1/120.0, 1/120.0,
804 1/120.0, 1/ 60.0, 1/120.0,
805 1/120.0, 1/120.0, 1/ 60.0;
807 for(
int i = 0; i < num_tris; ++i)
809 const Triangle& tri = tri_indices[i];
813 S d_six_vol = (v1.cross(v2)).dot(v3);
818 C.noalias() += A.transpose() * C_canonical * A * d_six_vol;
821 S trace_C = C(0, 0) + C(1, 1) + C(2, 2);
824 m << trace_C - C(0, 0), -C(0, 1), -C(0, 2),
825 -C(1, 0), trace_C - C(1, 1), -C(1, 2),
826 -C(2, 0), -C(2, 1), trace_C - C(2, 2);
832 template <
typename BV>
836 bv_fitter->set(vertices, tri_indices, getModelType());
838 bv_splitter->set(vertices, tri_indices, getModelType());
842 int num_primitives = 0;
843 switch(getModelType())
846 num_primitives = num_tris;
849 num_primitives = num_vertices;
852 std::cerr <<
"BVH Error: Model type not supported!\n";
856 for(
int i = 0; i < num_primitives; ++i)
857 primitive_indices[i] = i;
858 recursiveBuildTree(0, 0, num_primitives);
861 bv_splitter->clear();
867 template <
typename BV>
872 unsigned int* cur_primitive_indices = primitive_indices + first_primitive;
875 BV bv = bv_fitter->fit(cur_primitive_indices, num_primitives);
876 bv_splitter->computeRule(bv, cur_primitive_indices, num_primitives);
882 if(num_primitives == 1)
884 bvnode->
first_child = -((*cur_primitive_indices) + 1);
892 for(
int i = 0; i < num_primitives; ++i)
898 const Triangle& t = tri_indices[cur_primitive_indices[i]];
902 p.noalias() = (p1 + p2 + p3) / 3.0;
906 std::cerr <<
"BVH Error: Model type not supported!\n";
917 if(bv_splitter->apply(p))
923 std::swap(cur_primitive_indices[i], cur_primitive_indices[c1]);
929 if((c1 == 0) || (c1 == num_primitives)) c1 = num_primitives / 2;
931 int num_first_half = c1;
933 recursiveBuildTree(bvnode->
leftChild(), first_primitive, num_first_half);
934 recursiveBuildTree(bvnode->
rightChild(), first_primitive + num_first_half, num_primitives - num_first_half);
941 template <
typename BV>
945 return refitTree_bottomup();
947 return refitTree_topdown();
951 template <
typename BV>
954 int res = recursiveRefitTree_bottomup(0);
960 template <
typename BV>
975 v[0] = prev_vertices[primitive_id];
976 v[1] = vertices[primitive_id];
980 fit(vertices + primitive_id, 1, bv);
987 const Triangle& triangle = tri_indices[primitive_id];
992 for(
int i = 0; i < 3; ++i)
994 v[i] = prev_vertices[triangle[i]];
995 v[i + 3] = vertices[triangle[i]];
1003 for(
int i = 0; i < 3; ++i)
1005 v[i] = vertices[triangle[i]];
1015 std::cerr <<
"BVH Error: Model type not supported!\n";
1021 recursiveRefitTree_bottomup(bvnode->
leftChild());
1022 recursiveRefitTree_bottomup(bvnode->
rightChild());
1030 template <
typename S,
typename BV>
1038 if(!model.
bvs[bv_id].isLeaf())
1041 tmp1(model, model.
bvs[bv_id].first_child, parent_axis, model.
bvs[bv_id].getCenter());
1044 tmp2(model, model.
bvs[bv_id].first_child + 1, parent_axis, model.
bvs[bv_id].getCenter());
1052 template <
typename BV>
1059 *
this, bv_id, parent_axis, parent_c);
1063 template <
typename BV>
1066 bv_fitter->set(vertices, prev_vertices, tri_indices, getModelType());
1067 for(
int i = 0; i < num_bvs; ++i)
1069 BV bv = bv_fitter->fit(primitive_indices + bvs[i].first_primitive, bvs[i].num_primitives);
1079 template <
typename BV>
1083 for(
int i = 0; i < num_vertices; ++i)
1085 aabb_ += vertices[i];
1088 this->aabb_center = aabb_.
center();
1090 this->aabb_radius = 0;
1091 for(
int i = 0; i < num_vertices; ++i)
1093 S r = (this->aabb_center - vertices[i]).squaredNorm();
1094 if(
r > this->aabb_radius) this->aabb_radius =
r;
1097 this->aabb_radius = sqrt(this->aabb_radius);
1099 this->aabb_local = aabb_;
1103 template <
typename S>
1111 OBB<S>& obb = model.bvs[bv_id].bv;
1112 if(!model.bvs[bv_id].isLeaf())
1115 tmp1(model, model.bvs[bv_id].first_child, obb.
axis, obb.
To);
1118 tmp2(model, model.bvs[bv_id].first_child + 1, obb.
axis, obb.
To);
1122 obb.
axis = parent_axis.transpose() * obb.
axis;
1123 obb.
To = (obb.
To - parent_c).transpose() * parent_axis;
1128 template <
typename S>
1136 RSS<S>& rss = model.bvs[bv_id].bv;
1137 if(!model.bvs[bv_id].isLeaf())
1140 tmp1(model, model.bvs[bv_id].first_child, rss.
axis, rss.
To);
1143 tmp2(model, model.bvs[bv_id].first_child + 1, rss.
axis, rss.
To);
1147 rss.
axis = parent_axis.transpose() * rss.
axis;
1148 rss.
To = (rss.
To - parent_c).transpose() * parent_axis;
1153 template <
typename S>
1161 OBB<S>& obb = model.bvs[bv_id].bv.obb;
1162 RSS<S>& rss = model.bvs[bv_id].bv.rss;
1163 if(!model.bvs[bv_id].isLeaf())
1166 tmp1(model, model.bvs[bv_id].first_child, obb.
axis, obb.
To);
1169 tmp2(model, model.bvs[bv_id].first_child + 1, obb.
axis, obb.
To);
1173 obb.
axis = parent_axis.transpose() * obb.
axis;
1176 obb.
To = (obb.
To - parent_c).transpose() * parent_axis;
1182 template <
typename S>
1192 template <
typename S>
1202 template <
typename S>
1212 template <
typename S>
1222 template <
typename S>
1232 template <
typename S>
1242 template <
typename S>
1252 template <
typename S>