GCC Code Coverage Report


Directory: ./
File: src/BVH/BVH_model.cpp
Date: 2025-06-03 17:15:40
Exec Total Coverage
Lines: 374 669 55.9%
Functions: 91 123 74.0%
Branches: 256 753 34.0%

Line Branch Exec Source
1 /*
2 * Software License Agreement (BSD License)
3 *
4 * Copyright (c) 2011-2014, Willow Garage, Inc.
5 * Copyright (c) 2014-2015, Open Source Robotics Foundation
6 * Copyright (c) 2020, INRIA
7 * All rights reserved.
8 *
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
11 * are met:
12 *
13 * * Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * * Redistributions in binary form must reproduce the above
16 * copyright notice, this list of conditions and the following
17 * disclaimer in the documentation and/or other materials provided
18 * with the distribution.
19 * * Neither the name of Open Source Robotics Foundation nor the names of its
20 * contributors may be used to endorse or promote products derived
21 * from this software without specific prior written permission.
22 *
23 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
24 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
25 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
26 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
27 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
28 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
29 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
31 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
33 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
34 * POSSIBILITY OF SUCH DAMAGE.
35 */
36
37 /** \author Jia Pan */
38
39 #include "coal/BV/BV_node.h"
40 #include "coal/BVH/BVH_model.h"
41
42 #include "coal/BV/BV.h"
43 #include "coal/shape/convex.h"
44
45 #include "coal/internal/BV_splitter.h"
46 #include "coal/internal/BV_fitter.h"
47
48 #include <iostream>
49 #include <string.h>
50
51 namespace coal {
52
53 3114 BVHModelBase::BVHModelBase()
54 3114 : num_tris(0),
55 3114 num_vertices(0),
56 3114 build_state(BVH_BUILD_STATE_EMPTY),
57 3114 num_tris_allocated(0),
58 3114 num_vertices_allocated(0),
59 3114 num_vertex_updated(0) {}
60
61 44 BVHModelBase::BVHModelBase(const BVHModelBase& other)
62 : CollisionGeometry(other),
63 44 num_tris(other.num_tris),
64 44 num_vertices(other.num_vertices),
65 44 build_state(other.build_state),
66 44 num_tris_allocated(other.num_tris),
67 44 num_vertices_allocated(other.num_vertices) {
68
3/6
✓ Branch 1 taken 44 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 44 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 44 times.
✗ Branch 8 not taken.
44 if (other.vertices.get() && other.vertices->size() > 0) {
69
3/8
✓ Branch 1 taken 44 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 44 times.
✗ Branch 6 not taken.
✓ Branch 8 taken 44 times.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
44 vertices.reset(new std::vector<Vec3s>(*(other.vertices)));
70 } else
71 ✗ vertices.reset();
72
73
3/6
✓ Branch 1 taken 44 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 44 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 44 times.
✗ Branch 8 not taken.
44 if (other.tri_indices.get() && other.tri_indices->size() > 0) {
74
3/8
✓ Branch 1 taken 44 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 44 times.
✗ Branch 6 not taken.
✓ Branch 8 taken 44 times.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
44 tri_indices.reset(new std::vector<Triangle32>(*(other.tri_indices)));
75 } else
76 ✗ tri_indices.reset();
77
78
2/6
✗ Branch 1 not taken.
✓ Branch 2 taken 44 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✓ Branch 8 taken 44 times.
44 if (other.prev_vertices.get() && other.prev_vertices->size() > 0) {
79 ✗ prev_vertices.reset(new std::vector<Vec3s>(*(other.prev_vertices)));
80 } else
81 44 prev_vertices.reset();
82 44 }
83
84 21 bool BVHModelBase::isEqual(const CollisionGeometry& _other) const {
85
1/2
✓ Branch 0 taken 21 times.
✗ Branch 1 not taken.
21 const BVHModelBase* other_ptr = dynamic_cast<const BVHModelBase*>(&_other);
86
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 21 times.
21 if (other_ptr == nullptr) return false;
87 21 const BVHModelBase& other = *other_ptr;
88
89 21 bool result =
90
3/4
✓ Branch 0 taken 20 times.
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 20 times.
✗ Branch 3 not taken.
21 num_tris == other.num_tris && num_vertices == other.num_vertices;
91
92
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 20 times.
21 if (!result) return false;
93
94
3/8
✗ Branch 1 not taken.
✓ Branch 2 taken 20 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✓ Branch 6 taken 20 times.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✓ Branch 9 taken 20 times.
60 if ((!(tri_indices.get()) && other.tri_indices.get()) ||
95
1/2
✗ Branch 2 not taken.
✓ Branch 3 taken 20 times.
40 (tri_indices.get() && !(other.tri_indices.get())))
96 ✗ return false;
97
3/6
✓ Branch 1 taken 20 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 20 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 20 times.
✗ Branch 7 not taken.
20 if (tri_indices.get() && other.tri_indices.get()) {
98 20 const std::vector<Triangle32>& tri_indices_ = *(tri_indices);
99 20 const std::vector<Triangle32>& other_tri_indices_ = *(other.tri_indices);
100
2/2
✓ Branch 0 taken 41636 times.
✓ Branch 1 taken 20 times.
41656 for (size_t k = 0; k < static_cast<size_t>(num_tris); ++k)
101
1/2
✗ Branch 3 not taken.
✓ Branch 4 taken 41636 times.
41636 if (tri_indices_[k] != other_tri_indices_[k]) return false;
102 }
103
104
3/8
✗ Branch 1 not taken.
✓ Branch 2 taken 20 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✓ Branch 6 taken 20 times.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✓ Branch 9 taken 20 times.
60 if ((!(vertices.get()) && other.vertices.get()) ||
105
1/2
✗ Branch 2 not taken.
✓ Branch 3 taken 20 times.
40 (vertices.get() && !(other.vertices.get())))
106 ✗ return false;
107
3/6
✓ Branch 1 taken 20 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 20 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 20 times.
✗ Branch 7 not taken.
20 if (vertices.get() && other.vertices.get()) {
108 20 const std::vector<Vec3s>& vertices_ = *(vertices);
109 20 const std::vector<Vec3s>& other_vertices_ = *(other.vertices);
110
2/2
✓ Branch 0 taken 124908 times.
✓ Branch 1 taken 20 times.
124928 for (size_t k = 0; k < static_cast<size_t>(num_vertices); ++k)
111
1/2
✗ Branch 3 not taken.
✓ Branch 4 taken 124908 times.
124908 if (vertices_[k] != other_vertices_[k]) return false;
112 }
113
114
4/8
✓ Branch 1 taken 20 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 20 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 20 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 20 times.
40 if ((!(prev_vertices.get()) && other.prev_vertices.get()) ||
115
0/2
✗ Branch 2 not taken.
✗ Branch 3 not taken.
20 (prev_vertices.get() && !(other.prev_vertices.get())))
116 ✗ return false;
117
2/6
✗ Branch 1 not taken.
✓ Branch 2 taken 20 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 20 times.
20 if (prev_vertices.get() && other.prev_vertices.get()) {
118 ✗ const std::vector<Vec3s>& prev_vertices_ = *(prev_vertices);
119 ✗ const std::vector<Vec3s>& other_prev_vertices_ = *(other.prev_vertices);
120 ✗ for (size_t k = 0; k < static_cast<size_t>(num_vertices); ++k) {
121 ✗ if (prev_vertices_[k] != other_prev_vertices_[k]) return false;
122 }
123 }
124
125 20 return true;
126 }
127
128 3 void BVHModelBase::buildConvexRepresentation(bool share_memory) {
129
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
3 if (!(vertices.get())) {
130 std::cerr << "BVH Error in `buildConvexRepresentation`! The BVHModel has "
131 ✗ "no vertices."
132 ✗ << std::endl;
133 ✗ return;
134 }
135
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
3 if (!(tri_indices.get())) {
136 std::cerr << "BVH Error in `buildConvexRepresentation`! The BVHModel has "
137 ✗ "no triangles."
138 ✗ << std::endl;
139 ✗ return;
140 }
141
142
1/2
✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
3 if (!convex) {
143 3 std::shared_ptr<std::vector<Vec3s>> points = vertices;
144 3 std::shared_ptr<std::vector<Triangle32>> polygons = tri_indices;
145
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 if (!share_memory) {
146
3/8
✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 3 times.
✗ Branch 6 not taken.
✓ Branch 8 taken 3 times.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
3 points.reset(new std::vector<Vec3s>(*(vertices)));
147
3/8
✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 3 times.
✗ Branch 6 not taken.
✓ Branch 8 taken 3 times.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
3 polygons.reset(new std::vector<Triangle32>(*(tri_indices)));
148 }
149
1/4
✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
3 convex.reset(
150
2/4
✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
✓ Branch 6 taken 3 times.
✗ Branch 7 not taken.
6 new ConvexTpl<Triangle32>(points, num_vertices, polygons, num_tris));
151 3 }
152 }
153
154 ✗ bool BVHModelBase::buildConvexHull(bool keepTriangle,
155 const char* qhullCommand) {
156 ✗ convex.reset(BVHModelBase::ConvexType::convexHull(
157 ✗ vertices, num_vertices, keepTriangle, qhullCommand));
158 ✗ return num_vertices == convex->num_points;
159 }
160
161 template <typename BV>
162 88 BVHModel<BV>::BVHModel(const BVHModel<BV>& other)
163 : BVHModelBase(other),
164 88 bv_splitter(other.bv_splitter),
165 88 bv_fitter(other.bv_fitter) {
166
1/2
✓ Branch 1 taken 44 times.
✗ Branch 2 not taken.
88 if (other.primitive_indices.get()) {
167
1/4
✓ Branch 1 taken 44 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
88 primitive_indices.reset(
168
2/4
✓ Branch 1 taken 44 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 44 times.
✗ Branch 6 not taken.
88 new std::vector<unsigned int>(*(other.primitive_indices)));
169 } else
170 ✗ primitive_indices.reset();
171
172 88 num_bvs = num_bvs_allocated = other.num_bvs;
173
1/2
✓ Branch 1 taken 44 times.
✗ Branch 2 not taken.
88 if (other.bvs.get()) {
174
3/8
✓ Branch 1 taken 44 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 44 times.
✗ Branch 6 not taken.
✓ Branch 8 taken 44 times.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
88 bvs.reset(new bv_node_vector_t(*(other.bvs)));
175 } else
176 ✗ bvs.reset();
177 88 }
178
179 3108 int BVHModelBase::beginModel(unsigned int num_tris_,
180 unsigned int num_vertices_) {
181
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 3105 times.
3108 if (build_state != BVH_BUILD_STATE_EMPTY) {
182 3 vertices.reset();
183 3 tri_indices.reset();
184 3 tri_indices.reset();
185 3 prev_vertices.reset();
186
187 3 num_vertices_allocated = num_vertices = num_tris_allocated = num_tris = 0;
188 3 deleteBVs();
189 }
190
191
2/2
✓ Branch 0 taken 3076 times.
✓ Branch 1 taken 32 times.
3108 if (num_tris_ <= 0) num_tris_ = 8;
192
2/2
✓ Branch 0 taken 3076 times.
✓ Branch 1 taken 32 times.
3108 if (num_vertices_ <= 0) num_vertices_ = 8;
193
194 3108 num_vertices_allocated = num_vertices_;
195 3108 num_tris_allocated = num_tris_;
196
197
1/2
✓ Branch 0 taken 3108 times.
✗ Branch 1 not taken.
3108 if (num_tris_allocated > 0) {
198
2/6
✓ Branch 2 taken 3108 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 3108 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
6216 tri_indices.reset(new std::vector<Triangle32>(num_tris_allocated));
199
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 3108 times.
3108 if (!(tri_indices.get())) {
200 std::cerr << "BVH Error! Out of memory for tri_indices array on "
201 ✗ "BeginModel() call!"
202 ✗ << std::endl;
203 ✗ return BVH_ERR_MODEL_OUT_OF_MEMORY;
204 }
205 } else
206 ✗ tri_indices.reset();
207
208
1/2
✓ Branch 0 taken 3108 times.
✗ Branch 1 not taken.
3108 if (num_vertices_allocated > 0) {
209
2/6
✓ Branch 2 taken 3108 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 3108 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
6216 vertices.reset(new std::vector<Vec3s>(num_vertices_allocated));
210
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 3108 times.
3108 if (!(vertices.get())) {
211 std::cerr
212 ✗ << "BVH Error! Out of memory for vertices array on BeginModel() call!"
213 ✗ << std::endl;
214 ✗ return BVH_ERR_MODEL_OUT_OF_MEMORY;
215 }
216 } else {
217 ✗ vertices.reset();
218 ✗ prev_vertices.reset();
219 };
220
221
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 3105 times.
3108 if (build_state != BVH_BUILD_STATE_EMPTY) {
222 std::cerr
223 << "BVH Warning! Calling beginModel() on a BVHModel that is not empty. "
224 3 "This model was cleared and previous triangles/vertices were lost."
225 3 << std::endl;
226 3 build_state = BVH_BUILD_STATE_EMPTY;
227 3 return BVH_ERR_BUILD_OUT_OF_SEQUENCE;
228 }
229
230 3105 build_state = BVH_BUILD_STATE_BEGUN;
231
232 3105 return BVH_OK;
233 }
234
235 32 int BVHModelBase::addVertex(const Vec3s& p) {
236
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 32 times.
32 if (build_state != BVH_BUILD_STATE_BEGUN) {
237 std::cerr << "BVH Warning! Call addVertex() in a wrong order. addVertex() "
238 "was ignored. Must do a beginModel() to clear the model for "
239 ✗ "addition of new vertices."
240 ✗ << std::endl;
241 ✗ return BVH_ERR_BUILD_OUT_OF_SEQUENCE;
242 }
243
244
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 32 times.
32 if (num_vertices >= num_vertices_allocated) {
245 std::shared_ptr<std::vector<Vec3s>> temp(
246 ✗ new std::vector<Vec3s>(num_vertices_allocated * 2));
247 ✗ if (!(temp.get())) {
248 std::cerr
249 ✗ << "BVH Error! Out of memory for vertices array on addVertex() call!"
250 ✗ << std::endl;
251 ✗ return BVH_ERR_MODEL_OUT_OF_MEMORY;
252 }
253
254 ✗ for (size_t i = 0; i < num_vertices; ++i) {
255 ✗ (*temp)[i] = (*vertices)[i];
256 }
257 ✗ vertices = temp;
258 ✗ num_vertices_allocated *= 2;
259 ✗ }
260
261 32 (*vertices)[num_vertices] = p;
262 32 num_vertices += 1;
263
264 32 return BVH_OK;
265 }
266
267 ✗ int BVHModelBase::addTriangles(const Matrixx3i& triangles) {
268 ✗ if (build_state == BVH_BUILD_STATE_PROCESSED) {
269 std::cerr << "BVH Warning! Call addSubModel() in a wrong order. "
270 "addSubModel() was ignored. Must do a beginModel() to clear "
271 ✗ "the model for addition of new vertices."
272 ✗ << std::endl;
273 ✗ return BVH_ERR_BUILD_OUT_OF_SEQUENCE;
274 }
275
276 ✗ const unsigned int num_tris_to_add = (unsigned int)triangles.rows();
277
278 ✗ if (num_tris + num_tris_to_add > num_tris_allocated) {
279 std::shared_ptr<std::vector<Triangle32>> temp(
280 ✗ new std::vector<Triangle32>(num_tris_allocated * 2 + num_tris_to_add));
281 ✗ if (!(temp.get())) {
282 std::cerr << "BVH Error! Out of memory for tri_indices array on "
283 ✗ "addSubModel() call!"
284 ✗ << std::endl;
285 ✗ return BVH_ERR_MODEL_OUT_OF_MEMORY;
286 }
287
288 ✗ for (size_t i = 0; i < num_tris; ++i) {
289 ✗ (*temp)[i] = (*tri_indices)[i];
290 }
291 ✗ tri_indices = temp;
292 ✗ num_tris_allocated = num_tris_allocated * 2 + num_tris_to_add;
293 ✗ }
294
295 ✗ std::vector<Triangle32>& tri_indices_ = *tri_indices;
296 ✗ for (Eigen::DenseIndex i = 0; i < triangles.rows(); ++i) {
297 ✗ const Matrixx3i::ConstRowXpr triangle = triangles.row(i);
298 ✗ tri_indices_[num_tris++].set(
299 ✗ static_cast<Triangle32::IndexType>(triangle[0]),
300 ✗ static_cast<Triangle32::IndexType>(triangle[1]),
301 ✗ static_cast<Triangle32::IndexType>(triangle[2]));
302 }
303
304 ✗ return BVH_OK;
305 }
306
307 4 int BVHModelBase::addVertices(const MatrixX3s& points) {
308
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (build_state != BVH_BUILD_STATE_BEGUN) {
309 std::cerr << "BVH Warning! Call addVertex() in a wrong order. "
310 "addVertices() was ignored. Must do a beginModel() to clear "
311 ✗ "the model for addition of new vertices."
312 ✗ << std::endl;
313 ✗ return BVH_ERR_BUILD_OUT_OF_SEQUENCE;
314 }
315
316
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
4 if (num_vertices + points.rows() > num_vertices_allocated) {
317 ✗ num_vertices_allocated = num_vertices + (unsigned int)points.rows();
318 std::shared_ptr<std::vector<Vec3s>> temp(
319 ✗ new std::vector<Vec3s>(num_vertices_allocated));
320 ✗ if (!(temp.get())) {
321 std::cerr
322 ✗ << "BVH Error! Out of memory for vertices array on addVertex() call!"
323 ✗ << std::endl;
324 ✗ return BVH_ERR_MODEL_OUT_OF_MEMORY;
325 }
326
327 ✗ for (size_t i = 0; i < num_vertices; ++i) {
328 ✗ (*temp)[i] = (*vertices)[i];
329 }
330 ✗ vertices = temp;
331 ✗ }
332
333 4 std::vector<Vec3s>& vertices_ = *vertices;
334
2/2
✓ Branch 1 taken 32 times.
✓ Branch 2 taken 4 times.
36 for (Eigen::DenseIndex id = 0; id < points.rows(); ++id)
335
3/6
✓ Branch 1 taken 32 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 32 times.
✗ Branch 5 not taken.
✓ Branch 8 taken 32 times.
✗ Branch 9 not taken.
32 vertices_[num_vertices++] = points.row(id).transpose();
336
337 4 return BVH_OK;
338 }
339
340 96 int BVHModelBase::addTriangle(const Vec3s& p1, const Vec3s& p2,
341 const Vec3s& p3) {
342
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 96 times.
96 if (build_state == BVH_BUILD_STATE_PROCESSED) {
343 std::cerr << "BVH Warning! Call addTriangle() in a wrong order. "
344 "addTriangle() was ignored. Must do a beginModel() to clear "
345 ✗ "the model for addition of new triangles."
346 ✗ << std::endl;
347 ✗ return BVH_ERR_BUILD_OUT_OF_SEQUENCE;
348 }
349
350
2/2
✓ Branch 0 taken 16 times.
✓ Branch 1 taken 80 times.
96 if (num_vertices + 2 >= num_vertices_allocated) {
351 std::shared_ptr<std::vector<Vec3s>> temp(
352
3/8
✓ Branch 1 taken 16 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 16 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 16 times.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
32 new std::vector<Vec3s>(num_vertices_allocated * 2 + 2));
353
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 16 times.
16 if (!(temp.get())) {
354 std::cerr << "BVH Error! Out of memory for vertices array on "
355 ✗ "addTriangle() call!"
356 ✗ << std::endl;
357 ✗ return BVH_ERR_MODEL_OUT_OF_MEMORY;
358 }
359
360
2/2
✓ Branch 0 taken 192 times.
✓ Branch 1 taken 16 times.
208 for (size_t i = 0; i < num_vertices; ++i) {
361
1/2
✓ Branch 5 taken 192 times.
✗ Branch 6 not taken.
192 (*temp)[i] = (*vertices)[i];
362 }
363 16 vertices = temp;
364 16 num_vertices_allocated = num_vertices_allocated * 2 + 2;
365
1/2
✓ Branch 1 taken 16 times.
✗ Branch 2 not taken.
16 }
366
367 96 const unsigned int offset = num_vertices;
368
369 96 (*vertices)[num_vertices] = p1;
370 96 num_vertices++;
371 96 (*vertices)[num_vertices] = p2;
372 96 num_vertices++;
373 96 (*vertices)[num_vertices] = p3;
374 96 num_vertices++;
375
376
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 88 times.
96 if (num_tris >= num_tris_allocated) {
377 std::shared_ptr<std::vector<Triangle32>> temp(
378
3/8
✓ Branch 1 taken 8 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 8 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 8 times.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
16 new std::vector<Triangle32>(num_tris_allocated * 2));
379
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 8 times.
8 if (!(temp.get())) {
380 std::cerr << "BVH Error! Out of memory for tri_indices array on "
381 ✗ "addTriangle() call!"
382 ✗ << std::endl;
383 ✗ return BVH_ERR_MODEL_OUT_OF_MEMORY;
384 }
385
386
2/2
✓ Branch 0 taken 64 times.
✓ Branch 1 taken 8 times.
72 for (size_t i = 0; i < num_tris; ++i) {
387
1/2
✓ Branch 5 taken 64 times.
✗ Branch 6 not taken.
64 (*temp)[i] = (*tri_indices)[i];
388 }
389 8 tri_indices = temp;
390 8 num_tris_allocated *= 2;
391
1/2
✓ Branch 1 taken 8 times.
✗ Branch 2 not taken.
8 }
392
393 96 (*tri_indices)[num_tris].set(Triangle32::IndexType(offset),
394 96 Triangle32::IndexType((offset + 1)),
395 96 Triangle32::IndexType((offset + 2)));
396 96 num_tris++;
397
398 96 return BVH_OK;
399 }
400
401 ✗ int BVHModelBase::addSubModel(const std::vector<Vec3s>& ps) {
402 ✗ if (build_state == BVH_BUILD_STATE_PROCESSED) {
403 std::cerr << "BVH Warning! Calling addSubModel() in a wrong order. "
404 "addSubModel() was ignored. Must do a beginModel() to clear "
405 ✗ "the model for addition of new vertices."
406 ✗ << std::endl;
407 ✗ return BVH_ERR_BUILD_OUT_OF_SEQUENCE;
408 }
409
410 ✗ const unsigned int num_vertices_to_add = (unsigned int)ps.size();
411
412 ✗ if (num_vertices + num_vertices_to_add - 1 >= num_vertices_allocated) {
413 std::shared_ptr<std::vector<Vec3s>> temp(new std::vector<Vec3s>(
414 ✗ num_vertices_allocated * 2 + num_vertices_to_add - 1));
415 ✗ if (!(temp.get())) {
416 std::cerr << "BVH Error! Out of memory for vertices array on "
417 ✗ "addSubModel() call!"
418 ✗ << std::endl;
419 ✗ return BVH_ERR_MODEL_OUT_OF_MEMORY;
420 }
421
422 ✗ for (size_t i = 0; i < num_vertices; ++i) {
423 ✗ (*temp)[i] = (*vertices)[i];
424 }
425 ✗ vertices = temp;
426 ✗ num_vertices_allocated =
427 ✗ num_vertices_allocated * 2 + num_vertices_to_add - 1;
428 ✗ }
429
430 ✗ std::vector<Vec3s>& vertices_ = *vertices;
431 ✗ for (size_t i = 0; i < (size_t)num_vertices_to_add; ++i) {
432 ✗ vertices_[num_vertices] = ps[i];
433 ✗ num_vertices++;
434 }
435
436 ✗ return BVH_OK;
437 }
438
439 3060 int BVHModelBase::addSubModel(const std::vector<Vec3s>& ps,
440 const std::vector<Triangle32>& ts) {
441
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3060 times.
3060 if (build_state == BVH_BUILD_STATE_PROCESSED) {
442 std::cerr << "BVH Warning! Calling addSubModel() in a wrong order. "
443 "addSubModel() was ignored. Must do a beginModel() to clear "
444 ✗ "the model for addition of new vertices."
445 ✗ << std::endl;
446 ✗ return BVH_ERR_BUILD_OUT_OF_SEQUENCE;
447 }
448
449 3060 const unsigned int num_vertices_to_add = (unsigned int)ps.size();
450
451
2/2
✓ Branch 0 taken 1184 times.
✓ Branch 1 taken 1876 times.
3060 if (num_vertices + num_vertices_to_add - 1 >= num_vertices_allocated) {
452 std::shared_ptr<std::vector<Vec3s>> temp(new std::vector<Vec3s>(
453
3/8
✓ Branch 1 taken 1184 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1184 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 1184 times.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
2368 num_vertices_allocated * 2 + num_vertices_to_add - 1));
454
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 1184 times.
1184 if (!(temp.get())) {
455 std::cerr << "BVH Error! Out of memory for vertices array on "
456 ✗ "addSubModel() call!"
457 ✗ << std::endl;
458 ✗ return BVH_ERR_MODEL_OUT_OF_MEMORY;
459 }
460
461
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1184 times.
1184 for (size_t i = 0; i < num_vertices; ++i) {
462 ✗ (*temp)[i] = (*vertices)[i];
463 }
464 1184 vertices = temp;
465 1184 num_vertices_allocated =
466 1184 num_vertices_allocated * 2 + num_vertices_to_add - 1;
467
1/2
✓ Branch 1 taken 1184 times.
✗ Branch 2 not taken.
1184 }
468
469 3060 const unsigned int offset = num_vertices;
470
471 3060 std::vector<Vec3s>& vertices_ = *vertices;
472
2/2
✓ Branch 0 taken 1435778 times.
✓ Branch 1 taken 3060 times.
1438838 for (size_t i = 0; i < (size_t)num_vertices_to_add; ++i) {
473 1435778 vertices_[num_vertices] = ps[i];
474 1435778 num_vertices++;
475 }
476
477 3060 const unsigned int num_tris_to_add = (unsigned int)ts.size();
478
479
2/2
✓ Branch 0 taken 3058 times.
✓ Branch 1 taken 2 times.
3060 if (num_tris + num_tris_to_add - 1 >= num_tris_allocated) {
480 std::shared_ptr<std::vector<Triangle32>> temp(new std::vector<Triangle32>(
481
3/8
✓ Branch 1 taken 3058 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 3058 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 3058 times.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
6116 num_tris_allocated * 2 + num_tris_to_add - 1));
482
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 3058 times.
3058 if (!(temp.get())) {
483 std::cerr << "BVH Error! Out of memory for tri_indices array on "
484 ✗ "addSubModel() call!"
485 ✗ << std::endl;
486 ✗ return BVH_ERR_MODEL_OUT_OF_MEMORY;
487 }
488
489
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3058 times.
3058 for (size_t i = 0; i < num_tris; ++i) {
490 ✗ (*temp)[i] = (*tri_indices)[i];
491 }
492 3058 tri_indices = temp;
493 3058 num_tris_allocated = num_tris_allocated * 2 + num_tris_to_add - 1;
494
1/2
✓ Branch 1 taken 3058 times.
✗ Branch 2 not taken.
3058 }
495
496 3060 std::vector<Triangle32>& tri_indices_ = *tri_indices;
497
2/2
✓ Branch 0 taken 978283 times.
✓ Branch 1 taken 3060 times.
981343 for (size_t i = 0; i < (size_t)num_tris_to_add; ++i) {
498 978283 const Triangle32& t = ts[i];
499 1956566 tri_indices_[num_tris].set(t[0] + Triangle32::IndexType(offset),
500 978283 t[1] + Triangle32::IndexType(offset),
501 978283 t[2] + Triangle32::IndexType(offset));
502 978283 num_tris++;
503 }
504
505 3060 return BVH_OK;
506 }
507
508 3108 int BVHModelBase::endModel() {
509
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 3105 times.
3108 if (build_state != BVH_BUILD_STATE_BEGUN) {
510 std::cerr << "BVH Warning! Call endModel() in wrong order. endModel() was "
511 3 "ignored."
512 3 << std::endl;
513 3 return BVH_ERR_BUILD_OUT_OF_SEQUENCE;
514 }
515
516
3/4
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 3097 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 8 times.
3105 if (num_tris == 0 && num_vertices == 0) {
517 std::cerr << "BVH Error! endModel() called on model with no triangles and "
518 ✗ "vertices."
519 ✗ << std::endl;
520 ✗ return BVH_ERR_BUILD_EMPTY_MODEL;
521 }
522
523
2/2
✓ Branch 0 taken 3073 times.
✓ Branch 1 taken 32 times.
3105 if (num_tris_allocated > num_tris) {
524
2/2
✓ Branch 0 taken 3065 times.
✓ Branch 1 taken 8 times.
3073 if (num_tris > 0) {
525 std::shared_ptr<std::vector<Triangle32>> new_tris(
526
3/8
✓ Branch 1 taken 3065 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 3065 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 3065 times.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
6130 new std::vector<Triangle32>(num_tris));
527
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 3065 times.
3065 if (!(new_tris.get())) {
528 std::cerr << "BVH Error! Out of memory for tri_indices array in "
529 ✗ "endModel() call!"
530 ✗ << std::endl;
531 ✗ return BVH_ERR_MODEL_OUT_OF_MEMORY;
532 }
533
534
2/2
✓ Branch 0 taken 976629 times.
✓ Branch 1 taken 3065 times.
979694 for (size_t i = 0; i < num_tris; ++i) {
535
1/2
✓ Branch 5 taken 976629 times.
✗ Branch 6 not taken.
976629 (*new_tris)[i] = (*tri_indices)[i];
536 }
537 3065 tri_indices = new_tris;
538 3065 num_tris_allocated = num_tris;
539
1/2
✓ Branch 1 taken 3065 times.
✗ Branch 2 not taken.
3065 } else {
540 8 tri_indices.reset();
541 8 num_tris = num_tris_allocated = 0;
542 }
543 }
544
545
2/2
✓ Branch 0 taken 1191 times.
✓ Branch 1 taken 1914 times.
3105 if (num_vertices_allocated > num_vertices) {
546
1/2
✓ Branch 0 taken 1191 times.
✗ Branch 1 not taken.
1191 if (num_vertices > 0) {
547 std::shared_ptr<std::vector<Vec3s>> new_vertices(
548
3/8
✓ Branch 1 taken 1191 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1191 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 1191 times.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
2382 new std::vector<Vec3s>(num_vertices));
549
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 1191 times.
1191 if (!(new_vertices.get())) {
550 std::cerr
551 ✗ << "BVH Error! Out of memory for vertices array in endModel() call!"
552 ✗ << std::endl;
553 ✗ return BVH_ERR_MODEL_OUT_OF_MEMORY;
554 }
555
556
2/2
✓ Branch 0 taken 1420193 times.
✓ Branch 1 taken 1191 times.
1421384 for (size_t i = 0; i < num_vertices; ++i) {
557
1/2
✓ Branch 5 taken 1420193 times.
✗ Branch 6 not taken.
1420193 (*new_vertices)[i] = (*vertices)[i];
558 }
559 1191 vertices = new_vertices;
560 1191 num_vertices_allocated = num_vertices;
561
1/2
✓ Branch 1 taken 1191 times.
✗ Branch 2 not taken.
1191 } else {
562 ✗ vertices.reset();
563 ✗ num_vertices = num_vertices_allocated = 0;
564 }
565 }
566
567 // construct BVH tree
568
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 3105 times.
3105 if (!allocateBVs()) return BVH_ERR_MODEL_OUT_OF_MEMORY;
569
570 3105 buildTree();
571
572 // finish constructing
573 3105 build_state = BVH_BUILD_STATE_PROCESSED;
574
575 3105 return BVH_OK;
576 }
577
578 159 int BVHModelBase::beginReplaceModel() {
579
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 159 times.
159 if (build_state != BVH_BUILD_STATE_PROCESSED) {
580 std::cerr << "BVH Error! Call beginReplaceModel() on a BVHModel that has "
581 ✗ "no previous frame."
582 ✗ << std::endl;
583 ✗ return BVH_ERR_BUILD_EMPTY_PREVIOUS_FRAME;
584 }
585
586
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 159 times.
159 if (prev_vertices.get()) prev_vertices.reset();
587
588 159 num_vertex_updated = 0;
589
590 159 build_state = BVH_BUILD_STATE_REPLACE_BEGUN;
591
592 159 return BVH_OK;
593 }
594
595 ✗ int BVHModelBase::replaceVertex(const Vec3s& p) {
596 ✗ if (build_state != BVH_BUILD_STATE_REPLACE_BEGUN) {
597 std::cerr << "BVH Warning! Call replaceVertex() in a wrong order. "
598 "replaceVertex() was ignored. Must do a beginReplaceModel() "
599 ✗ "for initialization."
600 ✗ << std::endl;
601 ✗ return BVH_ERR_BUILD_OUT_OF_SEQUENCE;
602 }
603
604 ✗ (*vertices)[num_vertex_updated] = p;
605 ✗ num_vertex_updated++;
606
607 ✗ return BVH_OK;
608 }
609
610 ✗ int BVHModelBase::replaceTriangle(const Vec3s& p1, const Vec3s& p2,
611 const Vec3s& p3) {
612 ✗ if (build_state != BVH_BUILD_STATE_REPLACE_BEGUN) {
613 std::cerr << "BVH Warning! Call replaceTriangle() in a wrong order. "
614 "replaceTriangle() was ignored. Must do a beginReplaceModel() "
615 ✗ "for initialization."
616 ✗ << std::endl;
617 ✗ return BVH_ERR_BUILD_OUT_OF_SEQUENCE;
618 }
619
620 ✗ (*vertices)[num_vertex_updated] = p1;
621 ✗ num_vertex_updated++;
622 ✗ (*vertices)[num_vertex_updated] = p2;
623 ✗ num_vertex_updated++;
624 ✗ (*vertices)[num_vertex_updated] = p3;
625 ✗ num_vertex_updated++;
626 ✗ return BVH_OK;
627 }
628
629 159 int BVHModelBase::replaceSubModel(const std::vector<Vec3s>& ps) {
630
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 159 times.
159 if (build_state != BVH_BUILD_STATE_REPLACE_BEGUN) {
631 std::cerr << "BVH Warning! Call replaceSubModel() in a wrong order. "
632 "replaceSubModel() was ignored. Must do a beginReplaceModel() "
633 ✗ "for initialization."
634 ✗ << std::endl;
635 ✗ return BVH_ERR_BUILD_OUT_OF_SEQUENCE;
636 }
637
638 159 std::vector<Vec3s>& vertices_ = *vertices;
639
2/2
✓ Branch 1 taken 745704 times.
✓ Branch 2 taken 159 times.
745863 for (unsigned int i = 0; i < ps.size(); ++i) {
640 745704 vertices_[num_vertex_updated] = ps[i];
641 745704 num_vertex_updated++;
642 }
643 159 return BVH_OK;
644 }
645
646 159 int BVHModelBase::endReplaceModel(bool refit, bool bottomup) {
647
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 159 times.
159 if (build_state != BVH_BUILD_STATE_REPLACE_BEGUN) {
648 std::cerr << "BVH Warning! Call endReplaceModel() in a wrong order. "
649 ✗ "endReplaceModel() was ignored. "
650 ✗ << std::endl;
651 ✗ return BVH_ERR_BUILD_OUT_OF_SEQUENCE;
652 }
653
654
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 159 times.
159 if (num_vertex_updated != num_vertices) {
655 std::cerr << "BVH Error! The replaced model should have the same number of "
656 ✗ "vertices as the old model."
657 ✗ << std::endl;
658 ✗ return BVH_ERR_INCORRECT_DATA;
659 }
660
661
2/2
✓ Branch 0 taken 89 times.
✓ Branch 1 taken 70 times.
159 if (refit) // refit, do not change BVH structure
662 {
663 89 refitTree(bottomup);
664 } else // reconstruct bvh tree based on current frame data
665 {
666 70 buildTree();
667 }
668
669 159 build_state = BVH_BUILD_STATE_PROCESSED;
670
671 159 return BVH_OK;
672 }
673
674 ✗ int BVHModelBase::beginUpdateModel() {
675 ✗ if (build_state != BVH_BUILD_STATE_PROCESSED &&
676 ✗ build_state != BVH_BUILD_STATE_UPDATED) {
677 std::cerr << "BVH Error! Call beginUpdatemodel() on a BVHModel that has no "
678 ✗ "previous frame."
679 ✗ << std::endl;
680 ✗ return BVH_ERR_BUILD_EMPTY_PREVIOUS_FRAME;
681 }
682
683 ✗ if (prev_vertices.get()) {
684 ✗ std::shared_ptr<std::vector<Vec3s>> temp = prev_vertices;
685 ✗ prev_vertices = vertices;
686 ✗ vertices = temp;
687 ✗ } else {
688 ✗ prev_vertices = vertices;
689 ✗ vertices.reset(new std::vector<Vec3s>(num_vertices));
690 }
691
692 ✗ num_vertex_updated = 0;
693
694 ✗ build_state = BVH_BUILD_STATE_UPDATE_BEGUN;
695
696 ✗ return BVH_OK;
697 }
698
699 ✗ int BVHModelBase::updateVertex(const Vec3s& p) {
700 ✗ if (build_state != BVH_BUILD_STATE_UPDATE_BEGUN) {
701 std::cerr
702 << "BVH Warning! Call updateVertex() in a wrong order. updateVertex() "
703 ✗ "was ignored. Must do a beginUpdateModel() for initialization."
704 ✗ << std::endl;
705 ✗ return BVH_ERR_BUILD_OUT_OF_SEQUENCE;
706 }
707
708 ✗ (*vertices)[num_vertex_updated] = p;
709 ✗ num_vertex_updated++;
710
711 ✗ return BVH_OK;
712 }
713
714 ✗ int BVHModelBase::updateTriangle(const Vec3s& p1, const Vec3s& p2,
715 const Vec3s& p3) {
716 ✗ if (build_state != BVH_BUILD_STATE_UPDATE_BEGUN) {
717 std::cerr << "BVH Warning! Call updateTriangle() in a wrong order. "
718 "updateTriangle() was ignored. Must do a beginUpdateModel() "
719 ✗ "for initialization."
720 ✗ << std::endl;
721 ✗ return BVH_ERR_BUILD_OUT_OF_SEQUENCE;
722 }
723
724 ✗ (*vertices)[num_vertex_updated] = p1;
725 ✗ num_vertex_updated++;
726 ✗ (*vertices)[num_vertex_updated] = p2;
727 ✗ num_vertex_updated++;
728 ✗ (*vertices)[num_vertex_updated] = p3;
729 ✗ num_vertex_updated++;
730 ✗ return BVH_OK;
731 }
732
733 ✗ int BVHModelBase::updateSubModel(const std::vector<Vec3s>& ps) {
734 ✗ if (build_state != BVH_BUILD_STATE_UPDATE_BEGUN) {
735 std::cerr << "BVH Warning! Call updateSubModel() in a wrong order. "
736 "updateSubModel() was ignored. Must do a beginUpdateModel() "
737 ✗ "for initialization."
738 ✗ << std::endl;
739 ✗ return BVH_ERR_BUILD_OUT_OF_SEQUENCE;
740 }
741
742 ✗ std::vector<Vec3s>& vertices_ = *vertices;
743 ✗ for (unsigned int i = 0; i < ps.size(); ++i) {
744 ✗ vertices_[num_vertex_updated] = ps[i];
745 ✗ num_vertex_updated++;
746 }
747 ✗ return BVH_OK;
748 }
749
750 ✗ int BVHModelBase::endUpdateModel(bool refit, bool bottomup) {
751 ✗ if (build_state != BVH_BUILD_STATE_UPDATE_BEGUN) {
752 std::cerr << "BVH Warning! Call endUpdateModel() in a wrong order. "
753 ✗ "endUpdateModel() was ignored. "
754 ✗ << std::endl;
755 ✗ return BVH_ERR_BUILD_OUT_OF_SEQUENCE;
756 }
757
758 ✗ if (num_vertex_updated != num_vertices) {
759 std::cerr << "BVH Error! The updated model should have the same number of "
760 ✗ "vertices as the old model."
761 ✗ << std::endl;
762 ✗ return BVH_ERR_INCORRECT_DATA;
763 }
764
765 ✗ if (refit) // refit, do not change BVH structure
766 {
767 ✗ refitTree(bottomup);
768 } else // reconstruct bvh tree based on current frame data
769 {
770 ✗ buildTree();
771
772 // then refit
773
774 ✗ refitTree(bottomup);
775 }
776
777 ✗ build_state = BVH_BUILD_STATE_UPDATED;
778
779 ✗ return BVH_OK;
780 }
781
782 8628 void BVHModelBase::computeLocalAABB() {
783
1/2
✓ Branch 1 taken 8628 times.
✗ Branch 2 not taken.
8628 AABB aabb_;
784 8628 const std::vector<Vec3s>& vertices_ = *vertices;
785
2/2
✓ Branch 0 taken 4112649 times.
✓ Branch 1 taken 8628 times.
4121277 for (unsigned int i = 0; i < num_vertices; ++i) {
786
1/2
✓ Branch 2 taken 4112649 times.
✗ Branch 3 not taken.
4112649 aabb_ += vertices_[i];
787 }
788
789
1/2
✓ Branch 1 taken 8628 times.
✗ Branch 2 not taken.
8628 aabb_center = aabb_.center();
790
791 8628 aabb_radius = 0;
792
2/2
✓ Branch 0 taken 4112649 times.
✓ Branch 1 taken 8628 times.
4121277 for (unsigned int i = 0; i < num_vertices; ++i) {
793
2/4
✓ Branch 2 taken 4112649 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 4112649 times.
✗ Branch 6 not taken.
4112649 Scalar r = (aabb_center - vertices_[i]).squaredNorm();
794
2/2
✓ Branch 0 taken 10757 times.
✓ Branch 1 taken 4101892 times.
4112649 if (r > aabb_radius) aabb_radius = r;
795 }
796
797 8628 aabb_radius = sqrt(aabb_radius);
798
799
1/2
✓ Branch 1 taken 8628 times.
✗ Branch 2 not taken.
8628 aabb_local = aabb_;
800 8628 }
801
802 /// @brief Constructing an empty BVH
803 template <typename BV>
804 6228 BVHModel<BV>::BVHModel()
805 : BVHModelBase(),
806
2/6
✓ Branch 1 taken 3114 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 3114 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
6228 bv_splitter(new BVSplitter<BV>(SPLIT_METHOD_MEAN)),
807
2/6
✓ Branch 1 taken 3114 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 3114 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
6228 bv_fitter(new BVFitter<BV>()),
808 6228 num_bvs_allocated(0),
809
1/2
✓ Branch 2 taken 3114 times.
✗ Branch 3 not taken.
12456 num_bvs(0) {}
810
811 template <typename BV>
812 6 void BVHModel<BV>::deleteBVs() {
813 6 bvs.reset();
814 6 primitive_indices.reset();
815 6 num_bvs_allocated = num_bvs = 0;
816 6 }
817
818 template <typename BV>
819 6210 bool BVHModel<BV>::allocateBVs() {
820 // construct BVH tree
821 6210 unsigned int num_bvs_to_be_allocated = 0;
822
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 3097 times.
6210 if (num_tris == 0)
823 16 num_bvs_to_be_allocated = 2 * num_vertices - 1;
824 else
825 6194 num_bvs_to_be_allocated = 2 * num_tris - 1;
826
827
2/6
✓ Branch 3 taken 3105 times.
✗ Branch 4 not taken.
✓ Branch 6 taken 3105 times.
✗ Branch 7 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
6210 bvs.reset(new bv_node_vector_t(num_bvs_to_be_allocated));
828
1/4
✓ Branch 1 taken 3105 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
6210 primitive_indices.reset(
829
1/2
✓ Branch 2 taken 3105 times.
✗ Branch 3 not taken.
12420 new std::vector<unsigned int>(num_bvs_to_be_allocated));
830
3/6
✓ Branch 1 taken 3105 times.
✗ Branch 2 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 3105 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 3105 times.
6210 if (!(bvs.get()) || !(primitive_indices.get())) {
831 ✗ std::cerr << "BVH Error! Out of memory for BV array in endModel()!"
832 ✗ << std::endl;
833 ✗ return false;
834 }
835 6210 num_bvs_allocated = num_bvs_to_be_allocated;
836 6210 num_bvs = 0;
837 6210 return true;
838 }
839
840 template <typename BV>
841 8 int BVHModel<BV>::memUsage(const bool msg) const {
842 8 unsigned int mem_bv_list = (unsigned int)sizeof(BV) * num_bvs;
843 8 unsigned int mem_tri_list = (unsigned int)sizeof(Triangle32) * num_tris;
844 8 unsigned int mem_vertex_list = (unsigned int)sizeof(Vec3s) * num_vertices;
845
846 8 unsigned int total_mem = mem_bv_list + mem_tri_list + mem_vertex_list +
847 (unsigned int)sizeof(BVHModel<BV>);
848
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
8 if (msg) {
849 ✗ std::cerr << "Total for model " << total_mem << " bytes." << std::endl;
850 ✗ std::cerr << "BVs: " << num_bvs << " allocated." << std::endl;
851 ✗ std::cerr << "Tris: " << num_tris << " allocated." << std::endl;
852 ✗ std::cerr << "Vertices: " << num_vertices << " allocated." << std::endl;
853 }
854
855 8 return static_cast<int>(total_mem);
856 }
857
858 template <typename BV>
859 6350 int BVHModel<BV>::buildTree() {
860 // set BVFitter
861
1/2
✓ Branch 1 taken 3175 times.
✗ Branch 2 not taken.
6350 Vec3s* vertices_ = vertices.get() ? vertices->data() : NULL;
862
2/2
✓ Branch 1 taken 3167 times.
✓ Branch 2 taken 8 times.
6350 Triangle32* tri_indices_ = tri_indices.get() ? tri_indices->data() : NULL;
863 6350 bv_fitter->set(vertices_, tri_indices_, getModelType());
864 // set SplitRule
865 6350 bv_splitter->set(vertices_, tri_indices_, getModelType());
866
867 6350 num_bvs = 1;
868
869 6350 unsigned int num_primitives = 0;
870
2/3
✓ Branch 1 taken 3167 times.
✓ Branch 2 taken 8 times.
✗ Branch 3 not taken.
6350 switch (getModelType()) {
871 6334 case BVH_MODEL_TRIANGLES:
872 6334 num_primitives = (unsigned int)num_tris;
873 6334 break;
874 16 case BVH_MODEL_POINTCLOUD:
875 16 num_primitives = (unsigned int)num_vertices;
876 16 break;
877 ✗ default:
878 ✗ std::cerr << "BVH Error: Model type not supported!" << std::endl;
879 ✗ return BVH_ERR_UNSUPPORTED_FUNCTION;
880 }
881
882 6350 std::vector<unsigned int>& primitive_indices_ = *primitive_indices;
883
2/2
✓ Branch 1 taken 1129549 times.
✓ Branch 2 taken 3175 times.
2265448 for (unsigned int i = 0; i < num_primitives; ++i) primitive_indices_[i] = i;
884 6350 recursiveBuildTree(0, 0, num_primitives);
885
886 6350 bv_fitter->clear();
887 6350 bv_splitter->clear();
888
889 6350 return BVH_OK;
890 }
891
892 template <typename BV>
893 4511846 int BVHModel<BV>::recursiveBuildTree(int bv_id, unsigned int first_primitive,
894 unsigned int num_primitives) {
895 4511846 BVHModelType type = getModelType();
896 4511846 BVNode<BV>* bvnode = bvs->data() + bv_id;
897 4511846 unsigned int* cur_primitive_indices =
898 4511846 primitive_indices->data() + first_primitive;
899
900 // constructing BV
901
1/2
✓ Branch 2 taken 2255923 times.
✗ Branch 3 not taken.
4511846 BV bv = bv_fitter->fit(cur_primitive_indices, num_primitives);
902
1/2
✓ Branch 2 taken 2255923 times.
✗ Branch 3 not taken.
4511846 bv_splitter->computeRule(bv, cur_primitive_indices, num_primitives);
903
904
1/2
✓ Branch 1 taken 2255923 times.
✗ Branch 2 not taken.
4511846 bvnode->bv = bv;
905 4511846 bvnode->first_primitive = first_primitive;
906 4511846 bvnode->num_primitives = num_primitives;
907
908
2/2
✓ Branch 0 taken 1129549 times.
✓ Branch 1 taken 1126374 times.
4511846 if (num_primitives == 1) {
909 2259098 bvnode->first_child = -((int)(*cur_primitive_indices) + 1);
910 } else {
911 2252748 bvnode->first_child = (int)num_bvs;
912 2252748 num_bvs += 2;
913
914 2252748 unsigned int c1 = 0;
915 2252748 const std::vector<Vec3s>& vertices_ = *vertices;
916 2252748 const std::vector<Triangle32>& tri_indices_ = *tri_indices;
917
2/2
✓ Branch 0 taken 12055007 times.
✓ Branch 1 taken 1126374 times.
26362762 for (unsigned int i = 0; i < num_primitives; ++i) {
918
1/2
✓ Branch 1 taken 12055007 times.
✗ Branch 2 not taken.
24110014 Vec3s p;
919
2/2
✓ Branch 0 taken 192 times.
✓ Branch 1 taken 12054815 times.
24110014 if (type == BVH_MODEL_POINTCLOUD)
920
1/2
✓ Branch 2 taken 192 times.
✗ Branch 3 not taken.
384 p = vertices_[cur_primitive_indices[i]];
921
1/2
✓ Branch 0 taken 12054815 times.
✗ Branch 1 not taken.
24109630 else if (type == BVH_MODEL_TRIANGLES) {
922 24109630 const Triangle32& t = tri_indices_[cur_primitive_indices[i]];
923 24109630 const Vec3s& p1 = vertices_[t[0]];
924 24109630 const Vec3s& p2 = vertices_[t[1]];
925 24109630 const Vec3s& p3 = vertices_[t[2]];
926
927
4/8
✓ Branch 1 taken 12054815 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 12054815 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 12054815 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 12054815 times.
✗ Branch 11 not taken.
24109630 p = (p1 + p2 + p3) / 3.;
928 } else {
929 ✗ std::cerr << "BVH Error: Model type not supported!" << std::endl;
930 ✗ return BVH_ERR_UNSUPPORTED_FUNCTION;
931 }
932
933 // loop invariant: up to (but not including) index c1 in group 1,
934 // then up to (but not including) index i in group 2
935 //
936 // [1] [1] [1] [1] [2] [2] [2] [x] [x] ... [x]
937 // c1 i
938 //
939
3/4
✓ Branch 2 taken 12055007 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 5934216 times.
✓ Branch 5 taken 6120791 times.
24110014 if (bv_splitter->apply(p)) // in the right side
940 {
941 // do nothing
942 } else {
943 11868432 unsigned int temp = cur_primitive_indices[i];
944 11868432 cur_primitive_indices[i] = cur_primitive_indices[c1];
945 11868432 cur_primitive_indices[c1] = temp;
946 11868432 c1++;
947 }
948 }
949
950
4/4
✓ Branch 0 taken 993687 times.
✓ Branch 1 taken 132687 times.
✓ Branch 2 taken 167940 times.
✓ Branch 3 taken 825747 times.
2252748 if ((c1 == 0) || (c1 == num_primitives)) c1 = num_primitives / 2;
951
952 2252748 const unsigned int num_first_half = c1;
953
954
1/2
✓ Branch 2 taken 1126374 times.
✗ Branch 3 not taken.
2252748 recursiveBuildTree(bvnode->leftChild(), first_primitive, num_first_half);
955
1/2
✓ Branch 2 taken 1126374 times.
✗ Branch 3 not taken.
2252748 recursiveBuildTree(bvnode->rightChild(), first_primitive + num_first_half,
956 num_primitives - num_first_half);
957 }
958
959 4511846 return BVH_OK;
960 }
961
962 template <typename BV>
963 178 int BVHModel<BV>::refitTree(bool bottomup) {
964
2/2
✓ Branch 0 taken 21 times.
✓ Branch 1 taken 68 times.
178 if (bottomup)
965 42 return refitTree_bottomup();
966 else
967 136 return refitTree_topdown();
968 }
969
970 template <typename BV>
971 42 int BVHModel<BV>::refitTree_bottomup() {
972 // TODO the recomputation of the BV is done manually, without using
973 // bv_fitter. The manual BV recomputation seems bugged. Using bv_fitter
974 // seems to correct the bug.
975 // bv_fitter->set(vertices, tri_indices, getModelType());
976
977 42 int res = recursiveRefitTree_bottomup(0);
978
979 // bv_fitter->clear();
980 42 return res;
981 }
982
983 template <typename BV>
984 183078 int BVHModel<BV>::recursiveRefitTree_bottomup(int bv_id) {
985 183078 BVNode<BV>* bvnode = bvs->data() + bv_id;
986
2/2
✓ Branch 1 taken 45780 times.
✓ Branch 2 taken 45759 times.
183078 if (bvnode->isLeaf()) {
987 91560 BVHModelType type = getModelType();
988 91560 int primitive_id = -(bvnode->first_child + 1);
989
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 45780 times.
91560 if (type == BVH_MODEL_POINTCLOUD) {
990 ✗ BV bv;
991
992 ✗ if (prev_vertices.get()) {
993 ✗ Vec3s v[2];
994 ✗ v[0] = (*prev_vertices)[static_cast<size_t>(primitive_id)];
995 ✗ v[1] = (*vertices)[static_cast<size_t>(primitive_id)];
996 ✗ fit(v, 2, bv);
997 } else
998 ✗ fit(vertices->data() + primitive_id, 1, bv);
999
1000 ✗ bvnode->bv = bv;
1001
1/2
✓ Branch 0 taken 45780 times.
✗ Branch 1 not taken.
91560 } else if (type == BVH_MODEL_TRIANGLES) {
1002
1/2
✓ Branch 1 taken 45780 times.
✗ Branch 2 not taken.
91560 BV bv;
1003 91560 const Triangle32& triangle =
1004 91560 (*tri_indices)[static_cast<size_t>(primitive_id)];
1005
1006
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 45780 times.
91560 if (prev_vertices.get()) {
1007 ✗ Vec3s v[6];
1008 ✗ for (Triangle32::IndexType i = 0; i < 3; ++i) {
1009 ✗ v[i] = (*prev_vertices)[triangle[i]];
1010 ✗ v[i + 3] = (*vertices)[triangle[i]];
1011 }
1012
1013 ✗ fit(v, 6, bv);
1014 } else {
1015 // TODO use bv_fitter to build BV. See comment in refitTree_bottomup
1016 // unsigned int* cur_primitive_indices = primitive_indices +
1017 // bvnode->first_primitive; bv = bv_fitter->fit(cur_primitive_indices,
1018 // bvnode->num_primitives);
1019
3/4
✓ Branch 1 taken 137340 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 137340 times.
✓ Branch 4 taken 45780 times.
366240 Vec3s v[3];
1020
2/2
✓ Branch 0 taken 137340 times.
✓ Branch 1 taken 45780 times.
366240 for (int i = 0; i < 3; ++i) {
1021
1/2
✓ Branch 4 taken 137340 times.
✗ Branch 5 not taken.
274680 v[i] = (*vertices)[triangle[(Triangle32::IndexType)i]];
1022 }
1023
1024
1/2
✓ Branch 1 taken 45780 times.
✗ Branch 2 not taken.
91560 fit(v, 3, bv);
1025 }
1026
1027
1/2
✓ Branch 1 taken 45780 times.
✗ Branch 2 not taken.
91560 bvnode->bv = bv;
1028 } else {
1029 ✗ std::cerr << "BVH Error: Model type not supported!" << std::endl;
1030 ✗ return BVH_ERR_UNSUPPORTED_FUNCTION;
1031 }
1032 } else {
1033 91518 recursiveRefitTree_bottomup(bvnode->leftChild());
1034 91518 recursiveRefitTree_bottomup(bvnode->rightChild());
1035
1/4
✓ Branch 3 taken 45759 times.
✗ Branch 4 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
91518 bvnode->bv = (*bvs)[static_cast<size_t>(bvnode->leftChild())].bv +
1036 91518 (*bvs)[static_cast<size_t>(bvnode->rightChild())].bv;
1037 // TODO use bv_fitter to build BV. See comment in refitTree_bottomup
1038 // unsigned int* cur_primitive_indices = primitive_indices +
1039 // bvnode->first_primitive; bvnode->bv =
1040 // bv_fitter->fit(cur_primitive_indices, bvnode->num_primitives);
1041 }
1042
1043 183078 return BVH_OK;
1044 }
1045
1046 template <typename BV>
1047 136 int BVHModel<BV>::refitTree_topdown() {
1048
1/2
✓ Branch 1 taken 68 times.
✗ Branch 2 not taken.
136 Vec3s* vertices_ = vertices.get() ? vertices->data() : NULL;
1049
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 68 times.
136 Vec3s* prev_vertices_ = prev_vertices.get() ? prev_vertices->data() : NULL;
1050
1/2
✓ Branch 1 taken 68 times.
✗ Branch 2 not taken.
136 Triangle32* tri_indices_ = tri_indices.get() ? tri_indices->data() : NULL;
1051 136 bv_fitter->set(vertices_, prev_vertices_, tri_indices_, getModelType());
1052 136 BVNode<BV>* bvs_ = bvs->data();
1053 136 unsigned int* primitive_indices_ = primitive_indices->data();
1054
2/2
✓ Branch 0 taken 162860 times.
✓ Branch 1 taken 68 times.
325856 for (unsigned int i = 0; i < num_bvs; ++i) {
1055 325720 BV bv = bv_fitter->fit(primitive_indices_ + bvs_[i].first_primitive,
1056
1/2
✓ Branch 1 taken 162860 times.
✗ Branch 2 not taken.
325720 bvs_[i].num_primitives);
1057
1/2
✓ Branch 1 taken 162860 times.
✗ Branch 2 not taken.
325720 bvs_[i].bv = bv;
1058 }
1059
1060 136 bv_fitter->clear();
1061
1062 136 return BVH_OK;
1063 }
1064
1065 template <>
1066 ✗ void BVHModel<OBB>::makeParentRelativeRecurse(int bv_id, Matrix3s& parent_axes,
1067 const Vec3s& parent_c) {
1068 ✗ bv_node_vector_t& bvs_ = *bvs;
1069 ✗ OBB& obb = bvs_[static_cast<size_t>(bv_id)].bv;
1070 ✗ if (!bvs_[static_cast<size_t>(bv_id)].isLeaf()) {
1071 ✗ makeParentRelativeRecurse(bvs_[static_cast<size_t>(bv_id)].first_child,
1072 ✗ obb.axes, obb.To);
1073
1074 ✗ makeParentRelativeRecurse(bvs_[static_cast<size_t>(bv_id)].first_child + 1,
1075 ✗ obb.axes, obb.To);
1076 }
1077
1078 // make self parent relative
1079 // obb.axes = parent_axes.transpose() * obb.axes;
1080 ✗ obb.axes.applyOnTheLeft(parent_axes.transpose());
1081
1082 ✗ Vec3s t(obb.To - parent_c);
1083 ✗ obb.To.noalias() = parent_axes.transpose() * t;
1084 ✗ }
1085
1086 template <>
1087 ✗ void BVHModel<RSS>::makeParentRelativeRecurse(int bv_id, Matrix3s& parent_axes,
1088 const Vec3s& parent_c) {
1089 ✗ bv_node_vector_t& bvs_ = *bvs;
1090 ✗ RSS& rss = bvs_[static_cast<size_t>(bv_id)].bv;
1091 ✗ if (!bvs_[static_cast<size_t>(bv_id)].isLeaf()) {
1092 ✗ makeParentRelativeRecurse(bvs_[static_cast<size_t>(bv_id)].first_child,
1093 ✗ rss.axes, rss.Tr);
1094
1095 ✗ makeParentRelativeRecurse(bvs_[static_cast<size_t>(bv_id)].first_child + 1,
1096 ✗ rss.axes, rss.Tr);
1097 }
1098
1099 // make self parent relative
1100 // rss.axes = parent_axes.transpose() * rss.axes;
1101 ✗ rss.axes.applyOnTheLeft(parent_axes.transpose());
1102
1103 ✗ Vec3s t(rss.Tr - parent_c);
1104 ✗ rss.Tr.noalias() = parent_axes.transpose() * t;
1105 ✗ }
1106
1107 template <>
1108 ✗ void BVHModel<OBBRSS>::makeParentRelativeRecurse(int bv_id,
1109 Matrix3s& parent_axes,
1110 const Vec3s& parent_c) {
1111 ✗ bv_node_vector_t& bvs_ = *bvs;
1112 ✗ OBB& obb = bvs_[static_cast<size_t>(bv_id)].bv.obb;
1113 ✗ RSS& rss = bvs_[static_cast<size_t>(bv_id)].bv.rss;
1114 ✗ if (!bvs_[static_cast<size_t>(bv_id)].isLeaf()) {
1115 ✗ makeParentRelativeRecurse(bvs_[static_cast<size_t>(bv_id)].first_child,
1116 ✗ obb.axes, obb.To);
1117
1118 ✗ makeParentRelativeRecurse(bvs_[static_cast<size_t>(bv_id)].first_child + 1,
1119 ✗ obb.axes, obb.To);
1120 }
1121
1122 // make self parent relative
1123 ✗ rss.axes.noalias() = parent_axes.transpose() * obb.axes;
1124 ✗ obb.axes = rss.axes;
1125
1126 ✗ Vec3s t(obb.To - parent_c);
1127 ✗ obb.To.noalias() = parent_axes.transpose() * t;
1128 ✗ rss.Tr = obb.To;
1129 ✗ }
1130
1131 template <>
1132 3 NODE_TYPE BVHModel<AABB>::getNodeType() const {
1133 3 return BV_AABB;
1134 }
1135
1136 template <>
1137 43 NODE_TYPE BVHModel<OBB>::getNodeType() const {
1138 43 return BV_OBB;
1139 }
1140
1141 template <>
1142 7 NODE_TYPE BVHModel<RSS>::getNodeType() const {
1143 7 return BV_RSS;
1144 }
1145
1146 template <>
1147 7 NODE_TYPE BVHModel<kIOS>::getNodeType() const {
1148 7 return BV_kIOS;
1149 }
1150
1151 template <>
1152 39067 NODE_TYPE BVHModel<OBBRSS>::getNodeType() const {
1153 39067 return BV_OBBRSS;
1154 }
1155
1156 template <>
1157 5 NODE_TYPE BVHModel<KDOP<16>>::getNodeType() const {
1158 5 return BV_KDOP16;
1159 }
1160
1161 template <>
1162 7 NODE_TYPE BVHModel<KDOP<18>>::getNodeType() const {
1163 7 return BV_KDOP18;
1164 }
1165
1166 template <>
1167 9 NODE_TYPE BVHModel<KDOP<24>>::getNodeType() const {
1168 9 return BV_KDOP24;
1169 }
1170
1171 template class BVHModel<KDOP<16>>;
1172 template class BVHModel<KDOP<18>>;
1173 template class BVHModel<KDOP<24>>;
1174 template class BVHModel<OBB>;
1175 template class BVHModel<AABB>;
1176 template class BVHModel<RSS>;
1177 template class BVHModel<kIOS>;
1178 template class BVHModel<OBBRSS>;
1179
1180 } // namespace coal
1181