1.3.64
 
Loading...
Searching...
No Matches
VoxelIntersection.cpp
Go to the documentation of this file.
1
16#include "VoxelIntersection.h"
17
18using namespace helios;
19
21
22 context = __context;
23
24 printmessages = true;
25
26 // Deprecation warning
27 std::cerr << "\n";
28 std::cerr << "********************************************************************************\n";
29 std::cerr << "*** DEPRECATION WARNING: VoxelIntersection plugin ***\n";
30 std::cerr << "********************************************************************************\n";
31 std::cerr << "The VoxelIntersection plugin is DEPRECATED and has been merged into the\n";
32 std::cerr << "CollisionDetection plugin. Please migrate your code:\n\n";
33 std::cerr << " Replace: VoxelIntersection voxelintersection(&context);\n";
34 std::cerr << " With: CollisionDetection collisiondetection(&context);\n\n";
35 std::cerr << " Replace: #include \"VoxelIntersection.h\"\n";
36 std::cerr << " With: #include \"CollisionDetection.h\"\n\n";
37 std::cerr << "All method names remain the same (no API changes).\n";
38 std::cerr << "See CollisionDetection documentation for details.\n\n";
39 std::cerr << "This plugin will be REMOVED in a future release.\n";
40 std::cerr << "********************************************************************************\n";
41 std::cerr << "\n";
42}
43
44
45// find the intersection point of two lines
46helios::vec3 VoxelIntersection::linesIntersection(helios::vec3 line1_point, helios::vec3 line1_direction, helios::vec3 line2_point, helios::vec3 line2_direction) {
47
48 helios::vec3 g = line2_point - line1_point;
49 helios::vec3 h = cross(line2_direction, g);
50 helios::vec3 k = cross(line2_direction, line1_direction);
51 helios::vec3 rht;
52 helios::vec3 out;
53
54 float h_mag = sqrt(pow(h.x, 2) + pow(h.y, 2) + pow(h.z, 2));
55 float k_mag = sqrt(pow(k.x, 2) + pow(k.y, 2) + pow(k.z, 2));
56
57 // in the same direction
58 if (((h.x >= 0 && k.x >= 0) || (h.x < 0 && k.x < 0)) && ((h.y >= 0 && k.y >= 0) || (h.y < 0 && k.y < 0)) && ((h.z >= 0 && k.z >= 0) || (h.z < 0 && k.z < 0))) {
59 rht = (h_mag / k_mag) * line1_direction;
60 return line1_point + rht;
61 } else { // different direction
62 rht = (h_mag / k_mag) * line1_direction;
63 return line1_point - rht;
64 }
65}
66
67std::vector<uint> VoxelIntersection::slicePrimitive(uint UUID, std::vector<helios::vec3> voxel_face_vertices, helios::WarningAggregator &warnings) {
68
69 // vector of UUIDs that will be output
70 std::vector<uint> resulting_UUIDs;
71
72 if (voxel_face_vertices.size() < 3) {
73 helios_runtime_error("ERROR (VoxelIntersection::slicePrimitive): voxel_face_vertices must contain at least three points.");
74 }
75
76 helios::vec3 face_normal = cross(voxel_face_vertices.at(1) - voxel_face_vertices.at(0), voxel_face_vertices.at(2) - voxel_face_vertices.at(1));
77 face_normal.normalize();
78
79 std::vector<helios::vec3> primitive_vertices = context->getPrimitiveVertices(UUID);
80 helios::vec3 primitive_normal = context->getPrimitiveNormal(UUID);
81 primitive_normal.normalize();
82
83 helios::RGBAcolor primitive_color = context->getPrimitiveColorRGBA(UUID);
84
85 std::string texa;
86 const char *tex;
87 texa = context->getPrimitiveTextureFile(UUID);
88 tex = texa.c_str();
89 bool primitiveHasTexture = !texa.empty();
90
91 // get the area of the original primitive for comparison with the area of the sliced primitives later
92 float original_area = context->getPrimitiveArea(UUID);
93
95 // find the equation of the line where the planes of the patch and voxel face intersect
96
97 // direction of the plane intersection line
98 helios::vec3 direction_vector = cross(face_normal, primitive_normal);
99
100 // find a point on the plane intersection line
101 // based on https://vicrucann.github.io/tutorials/3d-geometry-algorithms/
102 helios::vec3 a = helios::make_vec3(fabs(direction_vector.x), fabs(direction_vector.y), fabs(direction_vector.z));
103 uint maxc;
104 if (a.x > a.y) {
105 if (a.x > a.z) {
106 maxc = 1;
107 } else {
108 maxc = 3;
109 }
110 } else {
111 if (a.y > a.z) {
112 maxc = 2;
113 } else {
114 maxc = 3;
115 }
116 }
117
118 helios::vec3 d1a = helios::make_vec3(-1 * face_normal.x * voxel_face_vertices.at(0).x, -1 * face_normal.y * voxel_face_vertices.at(0).y, -1 * face_normal.z * voxel_face_vertices.at(0).z);
119 helios::vec3 d2a = helios::make_vec3(-1 * primitive_normal.x * primitive_vertices.at(1).x, -1 * primitive_normal.y * primitive_vertices.at(1).y, -1 * primitive_normal.z * primitive_vertices.at(1).z);
120
121 float d1 = d1a.x + d1a.y + d1a.z;
122 float d2 = d2a.x + d2a.y + d2a.z;
123
124 float xi;
125 float yi;
126 float zi;
127
128 if (maxc == 1) {
129 xi = 0;
130 yi = (d2 * face_normal.z - d1 * primitive_normal.z) / direction_vector.x;
131 zi = (d1 * primitive_normal.y - d2 * face_normal.y) / direction_vector.x;
132 } else if (maxc == 2) {
133 xi = (d1 * primitive_normal.z - d2 * face_normal.z) / direction_vector.y;
134 yi = 0;
135 zi = (d2 * face_normal.x - d1 * primitive_normal.x) / direction_vector.y;
136 } else if (maxc == 3) {
137 xi = (d2 * face_normal.y - d1 * primitive_normal.y) / direction_vector.z;
138 yi = (d1 * primitive_normal.x - d2 * face_normal.x) / direction_vector.z;
139 zi = 0;
140 }
141
142 helios::vec3 ipoint = make_vec3(xi, yi, zi);
143
145 // get points of intersection between each edge of the patch and the patch-voxel intersection line
146
147 // vector for points of intersection between edge line and intersection line
148 std::vector<helios::vec3> possible_points;
149 // vector for points that actually touch the patch
150 std::vector<helios::vec3> slice_points;
151 std::vector<uint> slice_points_edge_ID;
152 uint vertex_index; // index for cases where one slice point is on a vertex (used for patch cases only)
153
154 helios::vec3 vi0;
155 helios::vec3 vi1;
156
157 // go through the different edges of the patch and calculate intersection points with line along edge of patch and intersection line
158 if (primitive_vertices.size() == 4) {
159 possible_points.resize(4);
160 possible_points.at(0) = linesIntersection(primitive_vertices.at(1), primitive_vertices.at(1) - primitive_vertices.at(0), ipoint, direction_vector);
161 possible_points.at(1) = linesIntersection(primitive_vertices.at(2), primitive_vertices.at(2) - primitive_vertices.at(1), ipoint, direction_vector);
162 possible_points.at(2) = linesIntersection(primitive_vertices.at(3), primitive_vertices.at(3) - primitive_vertices.at(2), ipoint, direction_vector);
163 possible_points.at(3) = linesIntersection(primitive_vertices.at(0), primitive_vertices.at(0) - primitive_vertices.at(3), ipoint, direction_vector);
164
165 for (uint i = 0; i < 4; i++) {
166 if (i == 0) {
167 vi1 = primitive_vertices.at(1);
168 vi0 = primitive_vertices.at(0);
169 } else if (i == 1) {
170 vi1 = primitive_vertices.at(2);
171 vi0 = primitive_vertices.at(1);
172 } else if (i == 2) {
173 vi1 = primitive_vertices.at(3);
174 vi0 = primitive_vertices.at(2);
175 } else if (i == 3) {
176 vi1 = primitive_vertices.at(0);
177 vi0 = primitive_vertices.at(3);
178 }
179
180 bool test_x = ((possible_points.at(i).x >= vi1.x && possible_points.at(i).x <= vi0.x) || (possible_points.at(i).x >= vi0.x && possible_points.at(i).x <= vi1.x));
181 bool test_y = ((possible_points.at(i).y >= vi1.y && possible_points.at(i).y <= vi0.y) || (possible_points.at(i).y >= vi0.y && possible_points.at(i).y <= vi1.y));
182 bool test_z = ((possible_points.at(i).z >= vi1.z && possible_points.at(i).z <= vi0.z) || (possible_points.at(i).z >= vi0.z && possible_points.at(i).z <= vi1.z));
183
184 if (test_x && test_y && test_z) {
185 slice_points.push_back(possible_points.at(i));
186 slice_points_edge_ID.push_back(i);
187 }
188 }
189
190 } else if (primitive_vertices.size() == 3) {
191
192 possible_points.resize(3);
193 possible_points.at(0) = linesIntersection(primitive_vertices.at(1), primitive_vertices.at(1) - primitive_vertices.at(0), ipoint, direction_vector);
194 possible_points.at(1) = linesIntersection(primitive_vertices.at(2), primitive_vertices.at(2) - primitive_vertices.at(1), ipoint, direction_vector);
195 possible_points.at(2) = linesIntersection(primitive_vertices.at(0), primitive_vertices.at(0) - primitive_vertices.at(2), ipoint, direction_vector);
196
197 for (uint i = 0; i < 3; i++) {
198 if (i == 0) {
199 vi1 = primitive_vertices.at(1);
200 vi0 = primitive_vertices.at(0);
201 } else if (i == 1) {
202 vi1 = primitive_vertices.at(2);
203 vi0 = primitive_vertices.at(1);
204
205 } else if (i == 2) {
206 vi1 = primitive_vertices.at(0);
207 vi0 = primitive_vertices.at(2);
208 }
209
210 bool test_x = ((possible_points.at(i).x >= vi1.x && possible_points.at(i).x <= vi0.x) || (possible_points.at(i).x >= vi0.x && possible_points.at(i).x <= vi1.x));
211 bool test_y = ((possible_points.at(i).y >= vi1.y && possible_points.at(i).y <= vi0.y) || (possible_points.at(i).y >= vi0.y && possible_points.at(i).y <= vi1.y));
212 bool test_z = ((possible_points.at(i).z >= vi1.z && possible_points.at(i).z <= vi0.z) || (possible_points.at(i).z >= vi0.z && possible_points.at(i).z <= vi1.z));
213
214 if (test_x && test_y && test_z) {
215 slice_points.push_back(possible_points.at(i));
216 slice_points_edge_ID.push_back(i);
217 }
218 }
219 }
220
221
222 // can be 0, 1, 2, 3, or 4 (0 and 2 are most common)
223 uint initial_slice_points_size = slice_points.size();
224 // std::cout << "initial_slice_points_size = " << initial_slice_points_size << std::endl;
225
226 float absTol = pow(10, -6);
227 float relTol = pow(10, -20);
228
229
230 // the primitive did not intersect with the voxel face
231 if (initial_slice_points_size == 0) {
232 resulting_UUIDs.push_back(UUID);
233 return resulting_UUIDs;
234
235 } else if (initial_slice_points_size == 1) {
236 // the primitive intersected with the face at a single point (a corner) - no slicing needed
237 resulting_UUIDs.push_back(UUID);
238 if (printmessages) {
239 std::cout << "the primitive intersected with the face at a single point (a corner) - no slicing needed" << std::endl;
240 }
241 return resulting_UUIDs;
242 } else if (initial_slice_points_size == 2) {
243
244 // This is the usual case
245 // just check to see if the two slice points are approximately at two vertices for edge cases here
246
247 // the primitive intersected with the face along an edge - no need to slice
248 if (slice_points_edge_ID.at(0) == slice_points_edge_ID.at(1)) {
249 resulting_UUIDs.push_back(UUID);
250 if (printmessages) {
251 std::cout << "the primitive intersected with the face along an edge - no need to slice" << std::endl;
252 }
253 return resulting_UUIDs;
254 }
255
256 if (primitive_vertices.size() == 4) {
257 if ((approxSame(slice_points.at(0), primitive_vertices.at(0), absTol) && approxSame(slice_points.at(1), primitive_vertices.at(1), absTol)) ||
258 (approxSame(slice_points.at(0), primitive_vertices.at(1), absTol) && approxSame(slice_points.at(1), primitive_vertices.at(0), absTol)) ||
259 (approxSame(slice_points.at(0), primitive_vertices.at(1), absTol) && approxSame(slice_points.at(1), primitive_vertices.at(2), absTol)) ||
260 (approxSame(slice_points.at(0), primitive_vertices.at(2), absTol) && approxSame(slice_points.at(1), primitive_vertices.at(1), absTol)) ||
261 (approxSame(slice_points.at(0), primitive_vertices.at(2), absTol) && approxSame(slice_points.at(1), primitive_vertices.at(3), absTol)) ||
262 (approxSame(slice_points.at(0), primitive_vertices.at(3), absTol) && approxSame(slice_points.at(1), primitive_vertices.at(2), absTol)) ||
263 (approxSame(slice_points.at(0), primitive_vertices.at(3), absTol) && approxSame(slice_points.at(1), primitive_vertices.at(0), absTol)) ||
264 (approxSame(slice_points.at(0), primitive_vertices.at(0), absTol) && approxSame(slice_points.at(1), primitive_vertices.at(3), absTol))) {
265 if (printmessages) {
266 std::cout << "the primitive intersected with the face along an edge - no need to slice" << std::endl;
267 }
268 resulting_UUIDs.push_back(UUID);
269 return resulting_UUIDs;
270 }
271
272 } else if (primitive_vertices.size() == 3) {
273
274 if ((approxSame(slice_points.at(0), primitive_vertices.at(0), absTol) || approxSame(slice_points.at(0), primitive_vertices.at(1), absTol) || approxSame(slice_points.at(0), primitive_vertices.at(2), absTol)) &&
275 (approxSame(slice_points.at(1), primitive_vertices.at(0), absTol) || approxSame(slice_points.at(1), primitive_vertices.at(1), absTol) || approxSame(slice_points.at(1), primitive_vertices.at(2), absTol))) {
276 resulting_UUIDs.push_back(UUID);
277 if (printmessages) {
278 std::cout << "the primitive intersected with the face along an edge - no need to slice" << std::endl;
279 }
280 return resulting_UUIDs;
281 }
282 }
283
284
285 // now that edge cases are taken care of,
286 // for each slice point, if it is approximately the same as a vertex, set it to that vertex
287 for (uint j = 0; j < primitive_vertices.size(); j++) {
288 for (uint i = 0; i < slice_points.size(); i++) {
289 // distance between slice point and primitive vertex
290 float Dxyza = sqrtf(powf(primitive_vertices.at(j).x - slice_points.at(i).x, 2.0) + powf(primitive_vertices.at(j).y - slice_points.at(i).y, 2.0) + powf(primitive_vertices.at(j).z - slice_points.at(i).z, 2.0));
291 if (approxSame(Dxyza, float(0.0), absTol, relTol)) {
292 slice_points.at(i) = primitive_vertices.at(j);
293 }
294 }
295 }
296
297
298 } else if (initial_slice_points_size == 3) {
299
300 // if there are 3 slice points, this probably means that two of the points are very close to each other,
301 // at or approximately at one of the primitive's vertices
302 // in this case, if the primitive is a triangle, then it should be sliced into two triangles, not the usual three
303 // in case the primitive is a patch, then it should be sliced into 3 triangles if this occurs at only one vertex
304
305 vec3 non_vertex_slice_point;
306 uint non_vertex_slice_edge_ID;
307 vec3 vertex_slice_point;
308
309 for (uint bb = 0; bb < slice_points.size(); bb++) {
310 bool this_point_vert_test = false;
311 for (uint cc = 0; cc < primitive_vertices.size(); cc++) {
312 bool vert_test = approxSame(slice_points.at(bb), primitive_vertices.at(cc), absTol);
313 // std::cout << "-- test = " << vert_test <<" -- slice point " << bb << " = " << slice_points.at(bb) << ", primitive_vertex " << cc << " = " << primitive_vertices.at(cc) << std::endl;
314 if (vert_test) {
315 this_point_vert_test = true;
316 vertex_slice_point = primitive_vertices.at(cc);
317 vertex_index = cc;
318 }
319 }
320
321 if (this_point_vert_test == false) {
322 non_vertex_slice_point = slice_points.at(bb);
323 non_vertex_slice_edge_ID = slice_points_edge_ID.at(bb);
324 }
325 }
326 slice_points.resize(2);
327 slice_points.at(0) = non_vertex_slice_point;
328 slice_points_edge_ID.at(0) = non_vertex_slice_edge_ID;
329 slice_points.at(1) = vertex_slice_point;
330
331 // std::cout << "slice_points.at(0) = " << slice_points.at(0) << std::endl;
332 // std::cout << "slice_points.at(1) = " << slice_points.at(1) << std::endl;
333 // std::cout << "slice_points_edge_ID.at(0) = " << slice_points_edge_ID.at(0) << std::endl;
334 // std::cout << "vertex_index = " << vertex_index << std::endl;
335
336 } else if (initial_slice_points_size == 4) {
337 // if the voxel face splits a patch diagonally, then only 2 triangles should be produced instead of the usual four
338 vec3 non_vertex_slice_point;
339 uint non_vertex_slice_edge_ID;
340 vec3 vertex_slice_point;
341 for (uint bb = 0; bb < slice_points.size(); bb++) {
342 bool this_point_vert_test = false;
343 for (uint cc = 0; cc < primitive_vertices.size(); cc++) {
344 bool vert_test = approxSame(slice_points.at(bb), primitive_vertices.at(cc), absTol);
345 // std::cout << "-- test = " << vert_test <<" -- slice point " << bb << " = " << slice_points.at(bb) << ", primitive_vertex " << cc << " = " << primitive_vertices.at(cc) << std::endl;
346 if (vert_test) {
347 this_point_vert_test = true;
348 vertex_index = cc;
349 }
350 }
351 }
352 slice_points.resize(2);
353 } else {
354 helios_runtime_error("ERROR (VoxelIntersection::slicePrimitive): more than 5 slice points detected - invalid geometry.");
355 }
356
357 // determine which side of the plane vertex 0 is on and use that to determine the sign of the buffer to add to the face coordinate
358 // the buffer ensures that the vertices will be categorized into grid cells correctly
359 // note that some of these checks are based on the assumption of a axis aligned grid - would need to be re-worked if implementing rotated grid
360
361 helios::vec3 face_coordinate = make_vec3(fabs(face_normal.x) * voxel_face_vertices.at(0).x, fabs(face_normal.y) * voxel_face_vertices.at(0).y, fabs(face_normal.z) * voxel_face_vertices.at(0).z);
362 // float buffer_value = powf(float(10), float(-6));
363 float buffer_value = powf(float(10), float(-5));
364 helios::vec3 buffer = make_vec3(0, 0, 0);
365 if (fabs(face_normal.x) > 0.5) {
366 if (primitive_vertices.at(0).x < face_coordinate.x) {
367 buffer = make_vec3(float(-1) * buffer_value, 0, 0);
368 } else if (primitive_vertices.at(0).x > face_coordinate.x) {
369 buffer = make_vec3(buffer_value, 0, 0);
370 } else {
371 if (printmessages) {
372 std::cout << "vertex 0 exactly at face" << std::endl;
373 }
374 }
375
376 } else if (fabs(face_normal.y) > 0.5) {
377 if (primitive_vertices.at(0).y < face_coordinate.y) {
378 buffer = make_vec3(0, float(-1) * buffer_value, 0);
379 } else if (primitive_vertices.at(0).y > face_coordinate.y) {
380 buffer = make_vec3(0, buffer_value, 0);
381 } else {
382 if (printmessages) {
383 std::cout << "vertex 0 exactly at face" << std::endl;
384 }
385 }
386
387 } else if (fabs(face_normal.z) > 0.5) {
388 if (primitive_vertices.at(0).z < face_coordinate.z) {
389 buffer = make_vec3(0, 0, float(-1) * buffer_value);
390 } else if (primitive_vertices.at(0).z > face_coordinate.z) {
391 buffer = make_vec3(0, 0, buffer_value);
392 } else {
393 if (printmessages) {
394 std::cout << "vertex 0 exactly at face" << std::endl;
395 }
396 }
397 }
398
399 // UUIDs for triangles to be created below
400 uint t0;
401 uint t1;
402 uint t2;
403 uint t3;
404
405 // if a resulting triangle area is below this value, delete it
406 float minArea = pow(10, -13);
407
408 // use this diagnostic code to locate where a particular triangle is being created
409 // (uncomment the print out far below)
410 uint diag_1 = 0;
411
413 // if the primitive isn't texture masked
414 if (primitiveHasTexture == false) {
415
416 if (primitive_vertices.size() == 3) {
417 // split into three triangles (usual case)
418 if (initial_slice_points_size == 2) {
419 if ((slice_points_edge_ID.at(0) == 0 && slice_points_edge_ID.at(1) == 1)) {
420 diag_1 = 1;
421 t0 = context->addTriangle(slice_points.at(0) - buffer, primitive_vertices.at(1) - buffer, slice_points.at(1) - buffer, primitive_color);
422 t1 = context->addTriangle(slice_points.at(0) + buffer, slice_points.at(1) + buffer, primitive_vertices.at(2) + buffer, primitive_color);
423 t2 = context->addTriangle(slice_points.at(0) + buffer, primitive_vertices.at(2) + buffer, primitive_vertices.at(0) + buffer, primitive_color);
424 } else if ((slice_points_edge_ID.at(0) == 1 && slice_points_edge_ID.at(1) == 0)) {
425 diag_1 = 2;
426 t0 = context->addTriangle(slice_points.at(0) - buffer, slice_points.at(1) - buffer, primitive_vertices.at(1) - buffer, primitive_color);
427 t1 = context->addTriangle(slice_points.at(0) + buffer, primitive_vertices.at(2) + buffer, slice_points.at(1) + buffer, primitive_color);
428 t2 = context->addTriangle(slice_points.at(1) + buffer, primitive_vertices.at(0) + buffer, primitive_vertices.at(2) + buffer, primitive_color);
429 } else if ((slice_points_edge_ID.at(0) == 0 && slice_points_edge_ID.at(1) == 2)) {
430 diag_1 = 3;
431 t0 = context->addTriangle(slice_points.at(0) + buffer, slice_points.at(1) + buffer, primitive_vertices.at(0) + buffer, primitive_color);
432 t1 = context->addTriangle(slice_points.at(0) - buffer, primitive_vertices.at(2) - buffer, slice_points.at(1) - buffer, primitive_color);
433 t2 = context->addTriangle(slice_points.at(0) - buffer, primitive_vertices.at(1) - buffer, primitive_vertices.at(2) - buffer, primitive_color);
434 } else if ((slice_points_edge_ID.at(0) == 2 && slice_points_edge_ID.at(1) == 0)) {
435 diag_1 = 4;
436 t0 = context->addTriangle(slice_points.at(0) + buffer, primitive_vertices.at(0) + buffer, slice_points.at(1) + buffer, primitive_color);
437 t1 = context->addTriangle(slice_points.at(0) - buffer, slice_points.at(1) - buffer, primitive_vertices.at(2) - buffer, primitive_color);
438 t2 = context->addTriangle(slice_points.at(1) - buffer, primitive_vertices.at(1) - buffer, primitive_vertices.at(2) - buffer, primitive_color);
439 } else if ((slice_points_edge_ID.at(0) == 1 && slice_points_edge_ID.at(1) == 2)) {
440 diag_1 = 5;
441 t0 = context->addTriangle(slice_points.at(0) - buffer, primitive_vertices.at(2) - buffer, slice_points.at(1) - buffer, primitive_color); //
442 t1 = context->addTriangle(slice_points.at(0) + buffer, slice_points.at(1) + buffer, primitive_vertices.at(0) + buffer, primitive_color); //
443 t2 = context->addTriangle(slice_points.at(0) + buffer, primitive_vertices.at(0) + buffer, primitive_vertices.at(1) + buffer, primitive_color);
444 } else if ((slice_points_edge_ID.at(0) == 2 && slice_points_edge_ID.at(1) == 1)) {
445 diag_1 = 6;
446 t0 = context->addTriangle(slice_points.at(0) - buffer, slice_points.at(1) - buffer, primitive_vertices.at(2) - buffer, primitive_color); //
447 t1 = context->addTriangle(slice_points.at(0) + buffer, primitive_vertices.at(0) + buffer, slice_points.at(1) + buffer, primitive_color); //
448 t2 = context->addTriangle(slice_points.at(1) + buffer, primitive_vertices.at(0) + buffer, primitive_vertices.at(1) + buffer, primitive_color);
449 }
450
451 // delete triangles with area of zero, otherwise add to resulting_UUIDs vector
452 if (context->getPrimitiveArea(t0) < minArea) {
453 context->deletePrimitive(t0);
454 } else {
455 resulting_UUIDs.push_back(t0);
456 }
457 if (context->getPrimitiveArea(t1) < minArea) {
458 context->deletePrimitive(t1);
459 } else {
460 resulting_UUIDs.push_back(t1);
461 }
462 if (context->getPrimitiveArea(t2) < minArea) {
463 context->deletePrimitive(t2);
464 } else {
465 resulting_UUIDs.push_back(t2);
466 }
467
468
469 } else if (initial_slice_points_size == 3) {
470 // split into two triangles instead of three since a vertex falls on the slicing face
471
472 if (slice_points_edge_ID.at(0) == 0) {
473 diag_1 = 7;
474 t0 = context->addTriangle(slice_points.at(0) + buffer, slice_points.at(1) + buffer, primitive_vertices.at(0) + buffer, primitive_color);
475 t1 = context->addTriangle(slice_points.at(0) - buffer, primitive_vertices.at(1) - buffer, slice_points.at(1) - buffer, primitive_color);
476 } else if (slice_points_edge_ID.at(0) == 1) {
477 diag_1 = 8;
478 t0 = context->addTriangle(slice_points.at(0) + buffer, primitive_vertices.at(2) + buffer, slice_points.at(1) + buffer, primitive_color);
479 t1 = context->addTriangle(slice_points.at(0) - buffer, slice_points.at(1) - buffer, primitive_vertices.at(1) - buffer, primitive_color);
480 } else if (slice_points_edge_ID.at(0) == 2) {
481 diag_1 = 9;
482 t0 = context->addTriangle(slice_points.at(0) + buffer, primitive_vertices.at(0) + buffer, slice_points.at(1) + buffer, primitive_color);
483 t1 = context->addTriangle(slice_points.at(0) - buffer, slice_points.at(1) - buffer, primitive_vertices.at(2) - buffer, primitive_color);
484 }
485
486 // delete triangles with area of zero, otherwise add to resulting_UUIDs vector
487 if (context->getPrimitiveArea(t0) < minArea) {
488 context->deletePrimitive(t0);
489 } else {
490 resulting_UUIDs.push_back(t0);
491 }
492 if (context->getPrimitiveArea(t1) < minArea) {
493 context->deletePrimitive(t1);
494 } else {
495 resulting_UUIDs.push_back(t1);
496 }
497 }
498
499 } else if (primitive_vertices.size() == 4) {
500
501 // split into four triangles (usual case)
502 if (initial_slice_points_size == 2) {
503 // cases where intersection points are on opposite sides
504 if ((slice_points_edge_ID.at(0) == 0 && slice_points_edge_ID.at(1) == 2)) {
505 diag_1 = 10;
506 t0 = context->addTriangle(slice_points.at(0) + buffer, slice_points.at(1) + buffer, primitive_vertices.at(0) + buffer, primitive_color);
507 t1 = context->addTriangle(slice_points.at(0) - buffer, primitive_vertices.at(2) - buffer, slice_points.at(1) - buffer, primitive_color);
508 t2 = context->addTriangle(slice_points.at(1) + buffer, primitive_vertices.at(3) + buffer, primitive_vertices.at(0) + buffer, primitive_color);
509 t3 = context->addTriangle(slice_points.at(0) - buffer, primitive_vertices.at(1) - buffer, primitive_vertices.at(2) - buffer, primitive_color);
510
511
512 } else if ((slice_points_edge_ID.at(0) == 2 && slice_points_edge_ID.at(1) == 0)) {
513 diag_1 = 11;
514 t0 = context->addTriangle(slice_points.at(0) + buffer, primitive_vertices.at(0) + buffer, slice_points.at(1) + buffer, primitive_color);
515 t1 = context->addTriangle(slice_points.at(0) - buffer, slice_points.at(1) - buffer, primitive_vertices.at(2) - buffer, primitive_color);
516 t2 = context->addTriangle(slice_points.at(0) + buffer, primitive_vertices.at(3) + buffer, primitive_vertices.at(0) + buffer, primitive_color);
517 t3 = context->addTriangle(slice_points.at(1) - buffer, primitive_vertices.at(1) - buffer, primitive_vertices.at(2) - buffer, primitive_color);
518
519 } else if ((slice_points_edge_ID.at(0) == 1 && slice_points_edge_ID.at(1) == 3)) {
520 diag_1 = 12;
521 t0 = context->addTriangle(slice_points.at(0) + buffer, slice_points.at(1) + buffer, primitive_vertices.at(1) + buffer, primitive_color);
522 t1 = context->addTriangle(slice_points.at(0) - buffer, primitive_vertices.at(3) - buffer, slice_points.at(1) - buffer, primitive_color);
523 t2 = context->addTriangle(slice_points.at(1) + buffer, primitive_vertices.at(0) + buffer, primitive_vertices.at(1) + buffer, primitive_color);
524 t3 = context->addTriangle(slice_points.at(0) - buffer, primitive_vertices.at(2) - buffer, primitive_vertices.at(3) - buffer, primitive_color);
525
526 } else if ((slice_points_edge_ID.at(0) == 3 && slice_points_edge_ID.at(1) == 1)) {
527 diag_1 = 13;
528 t0 = context->addTriangle(slice_points.at(0) + buffer, primitive_vertices.at(1) + buffer, slice_points.at(1) + buffer, primitive_color);
529 t1 = context->addTriangle(slice_points.at(0) - buffer, slice_points.at(1) - buffer, primitive_vertices.at(3) - buffer, primitive_color);
530 t2 = context->addTriangle(slice_points.at(0) + buffer, primitive_vertices.at(0) + buffer, primitive_vertices.at(1) + buffer, primitive_color);
531 t3 = context->addTriangle(slice_points.at(1) - buffer, primitive_vertices.at(2) - buffer, primitive_vertices.at(3) - buffer, primitive_color);
532
533 // cases where intersection points are on adjacent sides
534 } else if ((slice_points_edge_ID.at(0) == 0 && slice_points_edge_ID.at(1) == 3)) {
535 diag_1 = 14;
536 t0 = context->addTriangle(slice_points.at(0) + buffer, slice_points.at(1) + buffer, primitive_vertices.at(0) + buffer, primitive_color);
537 t1 = context->addTriangle(slice_points.at(0) - buffer, primitive_vertices.at(2) - buffer, slice_points.at(1) - buffer, primitive_color);
538 t2 = context->addTriangle(slice_points.at(0) - buffer, primitive_vertices.at(1) - buffer, primitive_vertices.at(2) - buffer, primitive_color);
539 t3 = context->addTriangle(slice_points.at(1) - buffer, primitive_vertices.at(2) - buffer, primitive_vertices.at(3) - buffer, primitive_color);
540 } else if ((slice_points_edge_ID.at(0) == 3 && slice_points_edge_ID.at(1) == 0)) {
541 diag_1 = 15;
542 t0 = context->addTriangle(slice_points.at(0) + buffer, primitive_vertices.at(0) + buffer, slice_points.at(1) + buffer, primitive_color);
543 t1 = context->addTriangle(slice_points.at(0) - buffer, slice_points.at(1) - buffer, primitive_vertices.at(2) - buffer, primitive_color);
544 t2 = context->addTriangle(slice_points.at(1) - buffer, primitive_vertices.at(1) - buffer, primitive_vertices.at(2) - buffer, primitive_color);
545 t3 = context->addTriangle(slice_points.at(0) - buffer, primitive_vertices.at(2) - buffer, primitive_vertices.at(3) - buffer, primitive_color);
546
547 } else if ((slice_points_edge_ID.at(0) == 0 && slice_points_edge_ID.at(1) == 1)) {
548 diag_1 = 16;
549 t0 = context->addTriangle(slice_points.at(0) - buffer, primitive_vertices.at(1) - buffer, slice_points.at(1) - buffer, primitive_color);
550 t1 = context->addTriangle(slice_points.at(0) + buffer, slice_points.at(1) + buffer, primitive_vertices.at(3) + buffer, primitive_color);
551 t2 = context->addTriangle(slice_points.at(1) + buffer, primitive_vertices.at(2) + buffer, primitive_vertices.at(3) + buffer, primitive_color);
552 t3 = context->addTriangle(slice_points.at(0) + buffer, primitive_vertices.at(3) + buffer, primitive_vertices.at(0) + buffer, primitive_color);
553 } else if ((slice_points_edge_ID.at(0) == 1 && slice_points_edge_ID.at(1) == 0)) {
554 diag_1 = 17;
555 t0 = context->addTriangle(slice_points.at(0) - buffer, slice_points.at(1) - buffer, primitive_vertices.at(1) - buffer, primitive_color);
556 t1 = context->addTriangle(slice_points.at(0) + buffer, primitive_vertices.at(3) + buffer, slice_points.at(1) + buffer, primitive_color);
557 t2 = context->addTriangle(slice_points.at(0) + buffer, primitive_vertices.at(2) + buffer, primitive_vertices.at(3) + buffer, primitive_color);
558 t3 = context->addTriangle(slice_points.at(1) + buffer, primitive_vertices.at(3) + buffer, primitive_vertices.at(0) + buffer, primitive_color);
559 } else if ((slice_points_edge_ID.at(0) == 1 && slice_points_edge_ID.at(1) == 2)) {
560 diag_1 = 18;
561 t0 = context->addTriangle(slice_points.at(0) - buffer, primitive_vertices.at(2) - buffer, slice_points.at(1) - buffer, primitive_color);
562 t1 = context->addTriangle(slice_points.at(0) + buffer, slice_points.at(1) + buffer, primitive_vertices.at(0) + buffer, primitive_color);
563 t2 = context->addTriangle(slice_points.at(1) + buffer, primitive_vertices.at(3) + buffer, primitive_vertices.at(0) + buffer, primitive_color);
564 t3 = context->addTriangle(slice_points.at(0) + buffer, primitive_vertices.at(0) + buffer, primitive_vertices.at(1) + buffer, primitive_color);
565 } else if ((slice_points_edge_ID.at(0) == 2 && slice_points_edge_ID.at(1) == 1)) {
566 diag_1 = 19;
567 t0 = context->addTriangle(slice_points.at(0) - buffer, slice_points.at(1) - buffer, primitive_vertices.at(2) - buffer, primitive_color);
568 t1 = context->addTriangle(slice_points.at(0) + buffer, primitive_vertices.at(0) + buffer, slice_points.at(1) + buffer, primitive_color);
569 t2 = context->addTriangle(slice_points.at(0) + buffer, primitive_vertices.at(3) + buffer, primitive_vertices.at(0) + buffer, primitive_color);
570 t3 = context->addTriangle(slice_points.at(1) + buffer, primitive_vertices.at(0) + buffer, primitive_vertices.at(1) + buffer, primitive_color);
571 } else if ((slice_points_edge_ID.at(0) == 3 && slice_points_edge_ID.at(1) == 2)) {
572 diag_1 = 20;
573 t0 = context->addTriangle(slice_points.at(0) - buffer, slice_points.at(1) - buffer, primitive_vertices.at(3) - buffer, primitive_color);
574 t1 = context->addTriangle(slice_points.at(0) + buffer, primitive_vertices.at(1) + buffer, slice_points.at(1) + buffer, primitive_color);
575 t2 = context->addTriangle(slice_points.at(0) + buffer, primitive_vertices.at(0) + buffer, primitive_vertices.at(1) + buffer, primitive_color);
576 t3 = context->addTriangle(slice_points.at(1) + buffer, primitive_vertices.at(1) + buffer, primitive_vertices.at(2) + buffer, primitive_color);
577 } else if ((slice_points_edge_ID.at(0) == 2 && slice_points_edge_ID.at(1) == 3)) {
578 diag_1 = 21;
579 t0 = context->addTriangle(slice_points.at(0) - buffer, primitive_vertices.at(3) - buffer, slice_points.at(1) - buffer, primitive_color);
580 t1 = context->addTriangle(slice_points.at(0) + buffer, slice_points.at(1) + buffer, primitive_vertices.at(1) + buffer, primitive_color);
581 t2 = context->addTriangle(slice_points.at(1) + buffer, primitive_vertices.at(0) + buffer, primitive_vertices.at(1) + buffer, primitive_color);
582 t3 = context->addTriangle(slice_points.at(0) + buffer, primitive_vertices.at(1) + buffer, primitive_vertices.at(2) + buffer, primitive_color);
583 }
584
585 // delete triangles with area of zero, otherwise add to resulting_UUIDs vector
586 if (context->getPrimitiveArea(t0) < minArea) {
587 context->deletePrimitive(t0);
588 } else {
589 resulting_UUIDs.push_back(t0);
590 }
591 if (context->getPrimitiveArea(t1) < minArea) {
592 context->deletePrimitive(t1);
593 } else {
594 resulting_UUIDs.push_back(t1);
595 }
596 if (context->getPrimitiveArea(t2) < minArea) {
597 context->deletePrimitive(t2);
598 } else {
599 resulting_UUIDs.push_back(t2);
600 }
601 if (context->getPrimitiveArea(t3) < minArea) {
602 context->deletePrimitive(t3);
603 } else {
604 resulting_UUIDs.push_back(t3);
605 }
606
607 } else if (initial_slice_points_size == 3) {
608 // split into three triangles instead of four since one vertex falls on the slicing face
609
610 if (slice_points_edge_ID.at(0) == 0 && vertex_index == 2) {
611 diag_1 = 22;
612 t0 = context->addTriangle(slice_points.at(0) + buffer, slice_points.at(1) + buffer, primitive_vertices.at(0) + buffer, primitive_color);
613 t1 = context->addTriangle(slice_points.at(0) - buffer, primitive_vertices.at(1) - buffer, slice_points.at(1) - buffer, primitive_color);
614 t2 = context->addTriangle(slice_points.at(1) + buffer, primitive_vertices.at(3) + buffer, primitive_vertices.at(0) + buffer, primitive_color);
615 } else if (slice_points_edge_ID.at(0) == 0 && vertex_index == 3) {
616 diag_1 = 23;
617 t0 = context->addTriangle(slice_points.at(0) + buffer, slice_points.at(1) + buffer, primitive_vertices.at(0) + buffer, primitive_color);
618 t1 = context->addTriangle(slice_points.at(0) - buffer, primitive_vertices.at(1) - buffer, slice_points.at(1) - buffer, primitive_color);
619 t2 = context->addTriangle(slice_points.at(1) - buffer, primitive_vertices.at(1) - buffer, primitive_vertices.at(2) - buffer, primitive_color);
620 } else if (slice_points_edge_ID.at(0) == 1 && vertex_index == 3) {
621 diag_1 = 24;
622 t0 = context->addTriangle(slice_points.at(0) + buffer, slice_points.at(1) + buffer, primitive_vertices.at(1) + buffer, primitive_color);
623 t1 = context->addTriangle(slice_points.at(1) + buffer, primitive_vertices.at(0) + buffer, primitive_vertices.at(1) + buffer, primitive_color);
624 t2 = context->addTriangle(slice_points.at(0) - buffer, primitive_vertices.at(2) - buffer, slice_points.at(1) - buffer, primitive_color);
625 } else if (slice_points_edge_ID.at(0) == 1 && vertex_index == 0) {
626 diag_1 = 25;
627 t0 = context->addTriangle(slice_points.at(0) + buffer, slice_points.at(1) + buffer, primitive_vertices.at(1) + buffer, primitive_color);
628 t1 = context->addTriangle(slice_points.at(0) - buffer, primitive_vertices.at(2) - buffer, slice_points.at(1) - buffer, primitive_color);
629 t2 = context->addTriangle(slice_points.at(1) - buffer, primitive_vertices.at(2) - buffer, primitive_vertices.at(3) - buffer, primitive_color);
630 } else if (slice_points_edge_ID.at(0) == 2 && vertex_index == 1) {
631 diag_1 = 26;
632 t0 = context->addTriangle(slice_points.at(0) - buffer, slice_points.at(1) - buffer, primitive_vertices.at(2) - buffer, primitive_color);
633 t1 = context->addTriangle(slice_points.at(0) + buffer, primitive_vertices.at(3) + buffer, slice_points.at(1) + buffer, primitive_color);
634 t2 = context->addTriangle(slice_points.at(1) + buffer, primitive_vertices.at(3) + buffer, primitive_vertices.at(0) + buffer, primitive_color);
635 } else if (slice_points_edge_ID.at(0) == 2 && vertex_index == 0) {
636 diag_1 = 27;
637 t0 = context->addTriangle(slice_points.at(0) + buffer, primitive_vertices.at(3) + buffer, slice_points.at(1) + buffer, primitive_color);
638 t1 = context->addTriangle(slice_points.at(0) - buffer, slice_points.at(1) - buffer, primitive_vertices.at(2) - buffer, primitive_color);
639 t2 = context->addTriangle(slice_points.at(1) - buffer, primitive_vertices.at(1) - buffer, primitive_vertices.at(2) - buffer, primitive_color);
640 } else if (slice_points_edge_ID.at(0) == 3 && vertex_index == 2) {
641 diag_1 = 28;
642 t0 = context->addTriangle(slice_points.at(0) + buffer, primitive_vertices.at(0) + buffer, slice_points.at(1) + buffer, primitive_color);
643 t1 = context->addTriangle(slice_points.at(1) + buffer, primitive_vertices.at(0) + buffer, primitive_vertices.at(1) + buffer, primitive_color);
644 t2 = context->addTriangle(slice_points.at(0) - buffer, slice_points.at(1) - buffer, primitive_vertices.at(3) - buffer, primitive_color);
645 } else if (slice_points_edge_ID.at(0) == 3 && vertex_index == 1) {
646 diag_1 = 29;
647 t0 = context->addTriangle(slice_points.at(0) + buffer, primitive_vertices.at(0) + buffer, slice_points.at(1) + buffer, primitive_color);
648 t1 = context->addTriangle(slice_points.at(0) - buffer, slice_points.at(1) - buffer, primitive_vertices.at(3) - buffer, primitive_color);
649 t2 = context->addTriangle(slice_points.at(1) - buffer, primitive_vertices.at(2) - buffer, primitive_vertices.at(3) - buffer, primitive_color);
650 }
651
652 // delete triangles with area of zero, otherwise add to resulting_UUIDs vector
653 if (context->getPrimitiveArea(t0) < minArea) {
654 context->deletePrimitive(t0);
655 } else {
656 resulting_UUIDs.push_back(t0);
657 }
658 if (context->getPrimitiveArea(t1) < minArea) {
659 context->deletePrimitive(t1);
660 } else {
661 resulting_UUIDs.push_back(t1);
662 }
663 if (context->getPrimitiveArea(t2) < minArea) {
664 context->deletePrimitive(t2);
665 } else {
666 resulting_UUIDs.push_back(t2);
667 }
668
669 } else if (initial_slice_points_size == 4) {
670 // split into two triangles instead of four since both vertices fall on the slicing face
671 if (vertex_index == 0 || vertex_index == 2) {
672 diag_1 = 30;
673 t0 = context->addTriangle(primitive_vertices.at(0) - buffer, primitive_vertices.at(1) - buffer, primitive_vertices.at(2) - buffer, primitive_color);
674 t1 = context->addTriangle(primitive_vertices.at(0) + buffer, primitive_vertices.at(2) + buffer, primitive_vertices.at(3) + buffer, primitive_color);
675
676 } else if (vertex_index == 1 || vertex_index == 3) {
677 diag_1 = 31;
678 t0 = context->addTriangle(primitive_vertices.at(1) - buffer, primitive_vertices.at(2) - buffer, primitive_vertices.at(3) - buffer, primitive_color);
679 t1 = context->addTriangle(primitive_vertices.at(1) + buffer, primitive_vertices.at(3) + buffer, primitive_vertices.at(0) + buffer, primitive_color);
680 }
681
682 // delete triangles with area of zero, otherwise add to resulting_UUIDs vector
683 if (context->getPrimitiveArea(t0) < minArea) {
684 context->deletePrimitive(t0);
685 } else {
686 resulting_UUIDs.push_back(t0);
687 }
688 if (context->getPrimitiveArea(t1) < minArea) {
689 context->deletePrimitive(t1);
690 } else {
691 resulting_UUIDs.push_back(t1);
692 }
693 }
694 }
695
696 } else if (primitiveHasTexture) {
697
698 // get uv coordinates of the vertices
699 std::vector<helios::vec2> v_uv = context->getPrimitiveTextureUV(UUID);
700
701 // get uv coordinates of the intersection points
702 std::vector<helios::vec2> ip_uv;
703 ip_uv.resize(2);
704
705 if (primitive_vertices.size() == 3) {
706
707 // split into three triangles (usual case)
708 if (initial_slice_points_size == 2) {
709 for (uint i = 0; i < slice_points.size(); i++) {
710 // vectors to hold point coordinates and uv coordinates for the points on the current point's edge
711 helios::vec3 point_0;
712 helios::vec3 point_1;
713 helios::vec2 point_0uv;
714 helios::vec2 point_1uv;
715 helios::vec2 point_uv;
716
717 if (slice_points_edge_ID.at(i) == 0) {
718 point_0 = primitive_vertices.at(0);
719 point_1 = primitive_vertices.at(1);
720 point_0uv = v_uv.at(0);
721 point_1uv = v_uv.at(1);
722 } else if (slice_points_edge_ID.at(i) == 1) {
723 point_0 = primitive_vertices.at(1);
724 point_1 = primitive_vertices.at(2);
725 point_0uv = v_uv.at(1);
726 point_1uv = v_uv.at(2);
727 } else if (slice_points_edge_ID.at(i) == 2) {
728 point_0 = primitive_vertices.at(2);
729 point_1 = primitive_vertices.at(0);
730 point_0uv = v_uv.at(2);
731 point_1uv = v_uv.at(0);
732 }
733
734 ip_uv.at(i) = interpolate_texture_UV_to_slice_point(point_0, point_0uv, point_1, point_1uv, slice_points.at(i));
735
736 if (ip_uv.at(0).x < 0 || ip_uv.at(0).x > 1 || ip_uv.at(0).y < 0 || ip_uv.at(0).y > 1) {
737 helios_runtime_error("ERROR (VoxelIntersection::slicePrimitive): texture UV coordinates for UUID " + std::to_string(UUID) + " are out of valid range [0,1].");
738 }
739 }
740
741 if ((slice_points_edge_ID.at(0) == 0 && slice_points_edge_ID.at(1) == 1)) {
742 diag_1 = 101;
743 t0 = context->addTriangle(slice_points.at(0) - buffer, primitive_vertices.at(1) - buffer, slice_points.at(1) - buffer, tex, ip_uv.at(0), v_uv.at(1), ip_uv.at(1));
744 t1 = context->addTriangle(slice_points.at(0) + buffer, slice_points.at(1) + buffer, primitive_vertices.at(2) + buffer, tex, ip_uv.at(0), ip_uv.at(1), v_uv.at(2));
745 t2 = context->addTriangle(slice_points.at(0) + buffer, primitive_vertices.at(2) + buffer, primitive_vertices.at(0) + buffer, tex, ip_uv.at(0), v_uv.at(2), v_uv.at(0));
746 } else if ((slice_points_edge_ID.at(0) == 1 && slice_points_edge_ID.at(1) == 0)) {
747 diag_1 = 102;
748 t0 = context->addTriangle(slice_points.at(0) - buffer, slice_points.at(1) - buffer, primitive_vertices.at(1) - buffer, tex, ip_uv.at(0), ip_uv.at(1), v_uv.at(1));
749 t1 = context->addTriangle(slice_points.at(0) + buffer, primitive_vertices.at(2) + buffer, slice_points.at(1) + buffer, tex, ip_uv.at(0), v_uv.at(2), ip_uv.at(1));
750 t2 = context->addTriangle(slice_points.at(1) + buffer, primitive_vertices.at(2) + buffer, primitive_vertices.at(0) + buffer, tex, ip_uv.at(1), v_uv.at(2), v_uv.at(0));
751 } else if ((slice_points_edge_ID.at(0) == 0 && slice_points_edge_ID.at(1) == 2)) {
752 diag_1 = 103;
753 t0 = context->addTriangle(slice_points.at(0) + buffer, slice_points.at(1) + buffer, primitive_vertices.at(0) + buffer, tex, ip_uv.at(0), ip_uv.at(1), v_uv.at(0));
754 t1 = context->addTriangle(slice_points.at(0) - buffer, primitive_vertices.at(2) - buffer, slice_points.at(1) - buffer, tex, ip_uv.at(0), v_uv.at(2), ip_uv.at(1));
755 t2 = context->addTriangle(slice_points.at(0) - buffer, primitive_vertices.at(1) - buffer, primitive_vertices.at(2) - buffer, tex, ip_uv.at(0), v_uv.at(1), v_uv.at(2));
756 } else if ((slice_points_edge_ID.at(0) == 2 && slice_points_edge_ID.at(1) == 0)) {
757 diag_1 = 104;
758 t0 = context->addTriangle(slice_points.at(0) + buffer, primitive_vertices.at(0) + buffer, slice_points.at(1) + buffer, tex, ip_uv.at(0), v_uv.at(0), ip_uv.at(1));
759 t1 = context->addTriangle(slice_points.at(0) - buffer, slice_points.at(1) - buffer, primitive_vertices.at(2) - buffer, tex, ip_uv.at(0), ip_uv.at(1), v_uv.at(2));
760 t2 = context->addTriangle(slice_points.at(1) - buffer, primitive_vertices.at(1) - buffer, primitive_vertices.at(2) - buffer, tex, ip_uv.at(1), v_uv.at(1), v_uv.at(2));
761 } else if ((slice_points_edge_ID.at(0) == 1 && slice_points_edge_ID.at(1) == 2)) {
762 diag_1 = 105;
763 t0 = context->addTriangle(slice_points.at(0) - buffer, primitive_vertices.at(2) - buffer, slice_points.at(1) - buffer, tex, ip_uv.at(0), v_uv.at(2), ip_uv.at(1));
764 t1 = context->addTriangle(slice_points.at(0) + buffer, slice_points.at(1) + buffer, primitive_vertices.at(0) + buffer, tex, ip_uv.at(0), ip_uv.at(1), v_uv.at(0));
765 t2 = context->addTriangle(slice_points.at(0) + buffer, primitive_vertices.at(0) + buffer, primitive_vertices.at(1) + buffer, tex, ip_uv.at(0), v_uv.at(0), v_uv.at(1));
766 } else if ((slice_points_edge_ID.at(0) == 2 && slice_points_edge_ID.at(1) == 1)) {
767 diag_1 = 106;
768 t0 = context->addTriangle(slice_points.at(0) - buffer, slice_points.at(1) - buffer, primitive_vertices.at(2) - buffer, tex, ip_uv.at(0), ip_uv.at(1), v_uv.at(2));
769 t1 = context->addTriangle(slice_points.at(0) + buffer, primitive_vertices.at(0) + buffer, slice_points.at(1) + buffer, tex, ip_uv.at(0), v_uv.at(0), ip_uv.at(1));
770 t2 = context->addTriangle(slice_points.at(1) + buffer, primitive_vertices.at(0) + buffer, primitive_vertices.at(1) + buffer, tex, ip_uv.at(1), v_uv.at(0), v_uv.at(1));
771 }
772
773 // delete triangles with area of zero, otherwise add to resulting_UUIDs vector
774 if (context->getPrimitiveArea(t0) < minArea) {
775 context->deletePrimitive(t0);
776 } else {
777 resulting_UUIDs.push_back(t0);
778 }
779 if (context->getPrimitiveArea(t1) < minArea) {
780 context->deletePrimitive(t1);
781 } else {
782 resulting_UUIDs.push_back(t1);
783 }
784 if (context->getPrimitiveArea(t2) < minArea) {
785 context->deletePrimitive(t2);
786 } else {
787 resulting_UUIDs.push_back(t2);
788 }
789
790 // split into two triangles instead of three since a vertex falls on the slicing face
791 // the non-vertex slice point is slice_points.at(0) and the vertex slice point is slice_points.at(1)
792 } else if (initial_slice_points_size == 3) {
793
794 // std::cout << "initial_slice_points_size = " << initial_slice_points_size << std::endl;
795
796 // vectors to hold point coordinates and uv coordinates for the points on the current point's edge for interpolation
797 helios::vec3 point_0;
798 helios::vec3 point_1;
799 helios::vec2 point_0uv;
800 helios::vec2 point_1uv;
801 helios::vec2 point_uv;
802
803 if (slice_points_edge_ID.at(0) == 0) {
804 point_0 = primitive_vertices.at(0);
805 point_1 = primitive_vertices.at(1);
806 point_0uv = v_uv.at(0);
807 point_1uv = v_uv.at(1);
808 ip_uv.at(1) = v_uv.at(2); // this sets the uv coordinate for the vertex slice point
809
810 } else if (slice_points_edge_ID.at(0) == 1) {
811 point_0 = primitive_vertices.at(1);
812 point_1 = primitive_vertices.at(2);
813 point_0uv = v_uv.at(1);
814 point_1uv = v_uv.at(2);
815 ip_uv.at(1) = v_uv.at(0); // this sets the uv coordinate for the vertex slice point
816 } else if (slice_points_edge_ID.at(0) == 2) {
817 point_0 = primitive_vertices.at(2);
818 point_1 = primitive_vertices.at(0);
819 point_0uv = v_uv.at(2);
820 point_1uv = v_uv.at(0);
821 ip_uv.at(1) = v_uv.at(1); // this sets the uv coordinate for the vertex slice point
822 }
823
824 // UV for non-vertex slice point
825 ip_uv.at(0) = interpolate_texture_UV_to_slice_point(point_0, point_0uv, point_1, point_1uv, slice_points.at(0));
826
827 if (ip_uv.at(0).x < 0 || ip_uv.at(0).x > 1 || ip_uv.at(0).y < 0 || ip_uv.at(0).y > 1) {
828 helios_runtime_error("ERROR (VoxelIntersection::slicePrimitive): texture UV coordinates for UUID " + std::to_string(UUID) + " are out of valid range [0,1].");
829 }
830
831 if (slice_points_edge_ID.at(0) == 0) {
832 diag_1 = 107;
833 t0 = context->addTriangle(slice_points.at(0) + buffer, slice_points.at(1) + buffer, primitive_vertices.at(0) + buffer, tex, ip_uv.at(0), ip_uv.at(1), v_uv.at(0));
834 t1 = context->addTriangle(slice_points.at(0) - buffer, primitive_vertices.at(1) - buffer, slice_points.at(1) - buffer, tex, ip_uv.at(0), v_uv.at(1), ip_uv.at(1));
835 } else if (slice_points_edge_ID.at(0) == 1) {
836 diag_1 = 108;
837 t0 = context->addTriangle(slice_points.at(0) + buffer, primitive_vertices.at(2) + buffer, slice_points.at(1) + buffer, tex, ip_uv.at(0), v_uv.at(2), ip_uv.at(1));
838 t1 = context->addTriangle(slice_points.at(0) - buffer, slice_points.at(1) - buffer, primitive_vertices.at(1) - buffer, tex, ip_uv.at(0), ip_uv.at(1), v_uv.at(1));
839 } else if (slice_points_edge_ID.at(0) == 2) {
840 diag_1 = 109;
841 t0 = context->addTriangle(slice_points.at(0) + buffer, primitive_vertices.at(0) + buffer, slice_points.at(1) + buffer, tex, ip_uv.at(0), v_uv.at(0), ip_uv.at(1));
842 t1 = context->addTriangle(slice_points.at(0) - buffer, slice_points.at(1) - buffer, primitive_vertices.at(2) - buffer, tex, ip_uv.at(0), ip_uv.at(1), v_uv.at(2));
843 }
844
845 // delete triangles with area of zero, otherwise add to resulting_UUIDs vector
846 if (context->getPrimitiveArea(t0) < minArea) {
847 context->deletePrimitive(t0);
848 } else {
849 resulting_UUIDs.push_back(t0);
850 }
851 if (context->getPrimitiveArea(t1) < minArea) {
852 context->deletePrimitive(t1);
853 } else {
854 resulting_UUIDs.push_back(t1);
855 }
856 }
857
858
859 } else if (primitive_vertices.size() == 4) {
860
861 // it seems patches that are not explicitly set up with texture UV coordinates just don't have them
862 // so set the default here
863 if (v_uv.size() == 0) {
864 std::vector<helios::vec2> uv{make_vec2(0, 0), make_vec2(1, 0), make_vec2(1, 1), make_vec2(0, 1)};
865 v_uv = uv;
866 }
867
868 // split into four triangles (usual case)
869 if (initial_slice_points_size == 2) {
870 // for each intersection point, choose the patch vertices on the corresponding edge
871 for (uint i = 0; i < 2; i++) {
872 helios::vec3 point_0;
873 helios::vec3 point_1;
874 helios::vec2 point_uv;
875 helios::vec2 point_0uv;
876 helios::vec2 point_1uv;
877
878 if (slice_points_edge_ID.at(i) == 0) {
879 point_0 = primitive_vertices.at(0);
880 point_1 = primitive_vertices.at(1);
881 point_0uv = v_uv.at(0);
882 point_1uv = v_uv.at(1);
883 } else if (slice_points_edge_ID.at(i) == 1) {
884 point_0 = primitive_vertices.at(1);
885 point_1 = primitive_vertices.at(2);
886 point_0uv = v_uv.at(1);
887 point_1uv = v_uv.at(2);
888 } else if (slice_points_edge_ID.at(i) == 2) {
889 point_0 = primitive_vertices.at(2);
890 point_1 = primitive_vertices.at(3);
891 point_0uv = v_uv.at(2);
892 point_1uv = v_uv.at(3);
893 } else if (slice_points_edge_ID.at(i) == 3) {
894 point_0 = primitive_vertices.at(3);
895 point_1 = primitive_vertices.at(0);
896 point_0uv = v_uv.at(3);
897 point_1uv = v_uv.at(0);
898 }
899
900 ip_uv.at(i) = interpolate_texture_UV_to_slice_point(point_0, point_0uv, point_1, point_1uv, slice_points.at(i));
901
902 if (ip_uv.at(i).x < 0 || ip_uv.at(i).x > 1 || ip_uv.at(i).y < 0 || ip_uv.at(i).y > 1) {
903 helios_runtime_error("ERROR (VoxelIntersection::slicePrimitive): texture UV coordinates for UUID " + std::to_string(UUID) + " are out of valid range [0,1].");
904 }
905 }
906
907 // cases where intersection points are on opposite sides
908 if ((slice_points_edge_ID.at(0) == 0 && slice_points_edge_ID.at(1) == 2)) {
909 diag_1 = 110;
910 t0 = context->addTriangle(slice_points.at(0) + buffer, slice_points.at(1) + buffer, primitive_vertices.at(0) + buffer, tex, ip_uv.at(0), ip_uv.at(1), v_uv.at(0));
911 t1 = context->addTriangle(slice_points.at(0) - buffer, primitive_vertices.at(2) - buffer, slice_points.at(1) - buffer, tex, ip_uv.at(0), v_uv.at(2), ip_uv.at(1));
912 t2 = context->addTriangle(slice_points.at(1) + buffer, primitive_vertices.at(3) + buffer, primitive_vertices.at(0) + buffer, tex, ip_uv.at(1), v_uv.at(3), v_uv.at(0));
913 t3 = context->addTriangle(slice_points.at(0) - buffer, primitive_vertices.at(1) - buffer, primitive_vertices.at(2) - buffer, tex, ip_uv.at(0), v_uv.at(1), v_uv.at(2));
914 } else if ((slice_points_edge_ID.at(0) == 2 && slice_points_edge_ID.at(1) == 0)) {
915 diag_1 = 111;
916 t0 = context->addTriangle(slice_points.at(0) + buffer, primitive_vertices.at(0) + buffer, slice_points.at(1) + buffer, tex, ip_uv.at(0), v_uv.at(0), ip_uv.at(1));
917 t1 = context->addTriangle(slice_points.at(0) - buffer, slice_points.at(1) - buffer, primitive_vertices.at(2) - buffer, tex, ip_uv.at(0), ip_uv.at(1), v_uv.at(2));
918 t2 = context->addTriangle(slice_points.at(0) + buffer, primitive_vertices.at(3) + buffer, primitive_vertices.at(0) + buffer, tex, ip_uv.at(0), v_uv.at(3), v_uv.at(0));
919 t3 = context->addTriangle(slice_points.at(1) - buffer, primitive_vertices.at(1) - buffer, primitive_vertices.at(2) - buffer, tex, ip_uv.at(1), v_uv.at(1), v_uv.at(2));
920 } else if ((slice_points_edge_ID.at(0) == 1 && slice_points_edge_ID.at(1) == 3)) {
921 diag_1 = 112;
922 t0 = context->addTriangle(slice_points.at(0) + buffer, slice_points.at(1) + buffer, primitive_vertices.at(1) + buffer, tex, ip_uv.at(0), ip_uv.at(1), v_uv.at(1));
923 t1 = context->addTriangle(slice_points.at(0) - buffer, primitive_vertices.at(3) - buffer, slice_points.at(1) - buffer, tex, ip_uv.at(0), v_uv.at(3), ip_uv.at(1));
924 t2 = context->addTriangle(slice_points.at(1) + buffer, primitive_vertices.at(0) + buffer, primitive_vertices.at(1) + buffer, tex, ip_uv.at(1), v_uv.at(0), v_uv.at(1));
925 t3 = context->addTriangle(slice_points.at(0) - buffer, primitive_vertices.at(2) - buffer, primitive_vertices.at(3) - buffer, tex, ip_uv.at(0), v_uv.at(2), v_uv.at(3));
926 } else if ((slice_points_edge_ID.at(0) == 3 && slice_points_edge_ID.at(1) == 1)) {
927 diag_1 = 113;
928 t0 = context->addTriangle(slice_points.at(0) + buffer, primitive_vertices.at(1) + buffer, slice_points.at(1) + buffer, tex, ip_uv.at(0), v_uv.at(1), ip_uv.at(1));
929 t1 = context->addTriangle(slice_points.at(0) - buffer, slice_points.at(1) - buffer, primitive_vertices.at(3) - buffer, tex, ip_uv.at(0), ip_uv.at(1), v_uv.at(3));
930 t2 = context->addTriangle(slice_points.at(0) + buffer, primitive_vertices.at(0) + buffer, primitive_vertices.at(1) + buffer, tex, ip_uv.at(0), v_uv.at(0), v_uv.at(1));
931 t3 = context->addTriangle(slice_points.at(1) - buffer, primitive_vertices.at(2) - buffer, primitive_vertices.at(3) - buffer, tex, ip_uv.at(1), v_uv.at(2), v_uv.at(3));
932 // cases where intersection points are on adjacent sides
933 } else if ((slice_points_edge_ID.at(0) == 0 && slice_points_edge_ID.at(1) == 3)) {
934 diag_1 = 114;
935 t0 = context->addTriangle(slice_points.at(0) + buffer, slice_points.at(1) + buffer, primitive_vertices.at(0) + buffer, tex, ip_uv.at(0), ip_uv.at(1), v_uv.at(0));
936 t1 = context->addTriangle(slice_points.at(0) - buffer, primitive_vertices.at(2) - buffer, slice_points.at(1) - buffer, tex, ip_uv.at(0), v_uv.at(2), ip_uv.at(1));
937 t2 = context->addTriangle(slice_points.at(0) - buffer, primitive_vertices.at(1) - buffer, primitive_vertices.at(2) - buffer, tex, ip_uv.at(0), v_uv.at(1), v_uv.at(2));
938 t3 = context->addTriangle(slice_points.at(1) - buffer, primitive_vertices.at(2) - buffer, primitive_vertices.at(3) - buffer, tex, ip_uv.at(1), v_uv.at(2), v_uv.at(3));
939 } else if ((slice_points_edge_ID.at(0) == 3 && slice_points_edge_ID.at(1) == 0)) {
940 diag_1 = 115;
941 t0 = context->addTriangle(slice_points.at(0) + buffer, primitive_vertices.at(0) + buffer, slice_points.at(1) + buffer, tex, ip_uv.at(0), v_uv.at(0), ip_uv.at(1));
942 t1 = context->addTriangle(slice_points.at(0) - buffer, slice_points.at(1) - buffer, primitive_vertices.at(2) - buffer, tex, ip_uv.at(0), ip_uv.at(1), v_uv.at(2));
943 t2 = context->addTriangle(slice_points.at(1) - buffer, primitive_vertices.at(1) - buffer, primitive_vertices.at(2) - buffer, tex, ip_uv.at(1), v_uv.at(1), v_uv.at(2));
944 t3 = context->addTriangle(slice_points.at(0) - buffer, primitive_vertices.at(2) - buffer, primitive_vertices.at(3) - buffer, tex, ip_uv.at(0), v_uv.at(2), v_uv.at(3));
945 } else if ((slice_points_edge_ID.at(0) == 0 && slice_points_edge_ID.at(1) == 1)) {
946 diag_1 = 116;
947 t0 = context->addTriangle(slice_points.at(0) - buffer, primitive_vertices.at(1) - buffer, slice_points.at(1) - buffer, tex, ip_uv.at(0), v_uv.at(1), ip_uv.at(1));
948 t1 = context->addTriangle(slice_points.at(0) + buffer, slice_points.at(1) + buffer, primitive_vertices.at(3) + buffer, tex, ip_uv.at(0), ip_uv.at(1), v_uv.at(3));
949 t2 = context->addTriangle(slice_points.at(1) + buffer, primitive_vertices.at(2) + buffer, primitive_vertices.at(3) + buffer, tex, ip_uv.at(1), v_uv.at(2), v_uv.at(3));
950 t3 = context->addTriangle(slice_points.at(0) + buffer, primitive_vertices.at(3) + buffer, primitive_vertices.at(0) + buffer, tex, ip_uv.at(0), v_uv.at(3), v_uv.at(0));
951 } else if ((slice_points_edge_ID.at(0) == 1 && slice_points_edge_ID.at(1) == 0)) {
952 diag_1 = 117;
953 t0 = context->addTriangle(slice_points.at(0) - buffer, slice_points.at(1) - buffer, primitive_vertices.at(1) - buffer, tex, ip_uv.at(0), ip_uv.at(1), v_uv.at(1));
954 t1 = context->addTriangle(slice_points.at(0) + buffer, primitive_vertices.at(3) + buffer, slice_points.at(1) + buffer, tex, ip_uv.at(0), v_uv.at(3), ip_uv.at(1));
955 t2 = context->addTriangle(slice_points.at(0) + buffer, primitive_vertices.at(2) + buffer, primitive_vertices.at(3) + buffer, tex, ip_uv.at(0), v_uv.at(2), v_uv.at(3));
956 t3 = context->addTriangle(slice_points.at(1) + buffer, primitive_vertices.at(3) + buffer, primitive_vertices.at(0) + buffer, tex, ip_uv.at(1), v_uv.at(3), v_uv.at(0));
957 } else if ((slice_points_edge_ID.at(0) == 1 && slice_points_edge_ID.at(1) == 2)) {
958 diag_1 = 118;
959 t0 = context->addTriangle(slice_points.at(0) - buffer, primitive_vertices.at(2) - buffer, slice_points.at(1) - buffer, tex, ip_uv.at(0), v_uv.at(2), ip_uv.at(1));
960 t1 = context->addTriangle(slice_points.at(0) + buffer, slice_points.at(1) + buffer, primitive_vertices.at(0) + buffer, tex, ip_uv.at(0), ip_uv.at(1), v_uv.at(0));
961 t2 = context->addTriangle(slice_points.at(1) + buffer, primitive_vertices.at(3) + buffer, primitive_vertices.at(0) + buffer, tex, ip_uv.at(1), v_uv.at(03), v_uv.at(0));
962 t3 = context->addTriangle(slice_points.at(0) + buffer, primitive_vertices.at(0) + buffer, primitive_vertices.at(1) + buffer, tex, ip_uv.at(0), v_uv.at(0), v_uv.at(1));
963 } else if ((slice_points_edge_ID.at(0) == 2 && slice_points_edge_ID.at(1) == 1)) {
964 diag_1 = 119;
965 t0 = context->addTriangle(slice_points.at(0) - buffer, slice_points.at(1) - buffer, primitive_vertices.at(2) - buffer, tex, ip_uv.at(0), ip_uv.at(1), v_uv.at(2));
966 t1 = context->addTriangle(slice_points.at(0) + buffer, primitive_vertices.at(0) + buffer, slice_points.at(1) + buffer, tex, ip_uv.at(0), v_uv.at(0), ip_uv.at(1));
967 t2 = context->addTriangle(slice_points.at(0) + buffer, primitive_vertices.at(3) + buffer, primitive_vertices.at(0) + buffer, tex, ip_uv.at(0), v_uv.at(3), v_uv.at(0));
968 t3 = context->addTriangle(slice_points.at(1) + buffer, primitive_vertices.at(0) + buffer, primitive_vertices.at(1) + buffer, tex, ip_uv.at(1), v_uv.at(0), v_uv.at(1));
969 } else if ((slice_points_edge_ID.at(0) == 3 && slice_points_edge_ID.at(1) == 2)) {
970 diag_1 = 120;
971 t0 = context->addTriangle(slice_points.at(0) - buffer, slice_points.at(1) - buffer, primitive_vertices.at(3) - buffer, tex, ip_uv.at(0), ip_uv.at(1), v_uv.at(3));
972 t1 = context->addTriangle(slice_points.at(0) + buffer, primitive_vertices.at(1) + buffer, slice_points.at(1) + buffer, tex, ip_uv.at(0), v_uv.at(1), ip_uv.at(1));
973 t2 = context->addTriangle(slice_points.at(0) + buffer, primitive_vertices.at(0) + buffer, primitive_vertices.at(1) + buffer, tex, ip_uv.at(0), v_uv.at(0), v_uv.at(1));
974 t3 = context->addTriangle(slice_points.at(1) + buffer, primitive_vertices.at(1) + buffer, primitive_vertices.at(2) + buffer, tex, ip_uv.at(1), v_uv.at(1), v_uv.at(2));
975 } else if ((slice_points_edge_ID.at(0) == 2 && slice_points_edge_ID.at(1) == 3)) {
976 diag_1 = 121;
977 t0 = context->addTriangle(slice_points.at(0) - buffer, primitive_vertices.at(3) - buffer, slice_points.at(1) - buffer, tex, ip_uv.at(0), v_uv.at(3), ip_uv.at(1));
978 t1 = context->addTriangle(slice_points.at(0) + buffer, slice_points.at(1) + buffer, primitive_vertices.at(1) + buffer, tex, ip_uv.at(0), ip_uv.at(1), v_uv.at(1));
979 t2 = context->addTriangle(slice_points.at(1) + buffer, primitive_vertices.at(0) + buffer, primitive_vertices.at(1) + buffer, tex, ip_uv.at(1), v_uv.at(0), v_uv.at(1));
980 t3 = context->addTriangle(slice_points.at(0) + buffer, primitive_vertices.at(1) + buffer, primitive_vertices.at(2) + buffer, tex, ip_uv.at(0), v_uv.at(1), v_uv.at(2));
981 }
982
983 // delete triangles with area of zero, otherwise add to resulting_UUIDs vector
984 if (context->getPrimitiveArea(t0) < minArea) {
985 context->deletePrimitive(t0);
986 } else {
987 resulting_UUIDs.push_back(t0);
988 }
989 if (context->getPrimitiveArea(t1) < minArea) {
990 context->deletePrimitive(t1);
991 } else {
992 resulting_UUIDs.push_back(t1);
993 }
994 if (context->getPrimitiveArea(t2) < minArea) {
995 context->deletePrimitive(t2);
996 } else {
997 resulting_UUIDs.push_back(t2);
998 }
999 if (context->getPrimitiveArea(t3) < minArea) {
1000 context->deletePrimitive(t3);
1001 } else {
1002 resulting_UUIDs.push_back(t3);
1003 }
1004
1005
1006 } else if (initial_slice_points_size == 3) {
1007
1008 // for the first intersection point (index 0), choose the endpoints of the edge to interpolate UV between
1009 // for this case where the other intersection point is at a primitive vertex, that vertex UV will be used
1010 for (uint i = 0; i < 1; i++) {
1011 helios::vec3 point_0;
1012 helios::vec3 point_1;
1013 helios::vec2 point_uv;
1014 helios::vec2 point_0uv;
1015 helios::vec2 point_1uv;
1016
1017 if (slice_points_edge_ID.at(i) == 0) {
1018 point_0 = primitive_vertices.at(0);
1019 point_1 = primitive_vertices.at(1);
1020 point_0uv = v_uv.at(0);
1021 point_1uv = v_uv.at(1);
1022 } else if (slice_points_edge_ID.at(i) == 1) {
1023 point_0 = primitive_vertices.at(1);
1024 point_1 = primitive_vertices.at(2);
1025 point_0uv = v_uv.at(1);
1026 point_1uv = v_uv.at(2);
1027 } else if (slice_points_edge_ID.at(i) == 2) {
1028 point_0 = primitive_vertices.at(2);
1029 point_1 = primitive_vertices.at(3);
1030 point_0uv = v_uv.at(2);
1031 point_1uv = v_uv.at(3);
1032 } else if (slice_points_edge_ID.at(i) == 3) {
1033 point_0 = primitive_vertices.at(3);
1034 point_1 = primitive_vertices.at(0);
1035 point_0uv = v_uv.at(3);
1036 point_1uv = v_uv.at(0);
1037 }
1038
1039 // std::cout << "point_0 = " << point_0 << std::endl;
1040 // std::cout << "point_0uv = " << point_0uv << std::endl;
1041 // std::cout << "point_1 = " << point_1 << std::endl;
1042 // std::cout << "point_1uv = " << point_1uv << std::endl;
1043 // std::cout << "i = " << i << std::endl;
1044 // std::cout << "slice_points.at(i) = " << slice_points.at(i) << std::endl;
1045 // std::cout << "slice_points.size() = " << slice_points.size() << std::endl;
1046 // std::cout << "slice_points_edge_ID.at(i) = " << slice_points_edge_ID.at(i) << std::endl;
1047
1048 ip_uv.at(i) = interpolate_texture_UV_to_slice_point(point_0, point_0uv, point_1, point_1uv, slice_points.at(i));
1049
1050 if (ip_uv.at(i).x < 0 || ip_uv.at(i).x > 1 || ip_uv.at(i).y < 0 || ip_uv.at(i).y > 1) {
1051 helios_runtime_error("ERROR (VoxelIntersection::slicePrimitive): texture UV coordinates for UUID " + std::to_string(UUID) + " are out of valid range [0,1].");
1052 }
1053
1054
1055 if (slice_points_edge_ID.at(0) == 0 && vertex_index == 2) {
1056 diag_1 = 122;
1057 t0 = context->addTriangle(slice_points.at(0) + buffer, primitive_vertices.at(2) + buffer, primitive_vertices.at(0) + buffer, tex, ip_uv.at(0), v_uv.at(2), v_uv.at(0));
1058 t1 = context->addTriangle(slice_points.at(0) - buffer, primitive_vertices.at(1) - buffer, primitive_vertices.at(2) - buffer, tex, ip_uv.at(0), v_uv.at(1), v_uv.at(2));
1059 t2 = context->addTriangle(primitive_vertices.at(2) + buffer, primitive_vertices.at(3) + buffer, primitive_vertices.at(0) + buffer, tex, v_uv.at(2), v_uv.at(3), v_uv.at(0));
1060 } else if (slice_points_edge_ID.at(0) == 0 && vertex_index == 3) {
1061 diag_1 = 123;
1062 t0 = context->addTriangle(slice_points.at(0) + buffer, primitive_vertices.at(3) + buffer, primitive_vertices.at(0) + buffer, tex, ip_uv.at(0), v_uv.at(3), v_uv.at(0));
1063 t1 = context->addTriangle(slice_points.at(0) - buffer, primitive_vertices.at(1) - buffer, primitive_vertices.at(3) - buffer, tex, ip_uv.at(0), v_uv.at(1), v_uv.at(3));
1064 t2 = context->addTriangle(primitive_vertices.at(3) - buffer, primitive_vertices.at(1) - buffer, primitive_vertices.at(2) - buffer, tex, v_uv.at(3), v_uv.at(1), v_uv.at(2));
1065 } else if (slice_points_edge_ID.at(0) == 1 && vertex_index == 3) {
1066 diag_1 = 124;
1067 t0 = context->addTriangle(slice_points.at(0) + buffer, primitive_vertices.at(3) + buffer, primitive_vertices.at(1) + buffer, tex, ip_uv.at(0), v_uv.at(3), v_uv.at(1));
1068 t1 = context->addTriangle(primitive_vertices.at(3) + buffer, primitive_vertices.at(0) + buffer, primitive_vertices.at(1) + buffer, tex, v_uv.at(3), v_uv.at(0), v_uv.at(1));
1069 t2 = context->addTriangle(slice_points.at(0) - buffer, primitive_vertices.at(2) - buffer, primitive_vertices.at(3) - buffer, tex, ip_uv.at(0), v_uv.at(2), v_uv.at(3));
1070 } else if (slice_points_edge_ID.at(0) == 1 && vertex_index == 0) {
1071 diag_1 = 125;
1072 t0 = context->addTriangle(slice_points.at(0) + buffer, primitive_vertices.at(0) + buffer, primitive_vertices.at(1) + buffer, tex, ip_uv.at(0), v_uv.at(0), v_uv.at(1));
1073 t1 = context->addTriangle(slice_points.at(0) - buffer, primitive_vertices.at(2) - buffer, primitive_vertices.at(0) - buffer, tex, ip_uv.at(0), v_uv.at(2), v_uv.at(0));
1074 t2 = context->addTriangle(primitive_vertices.at(0) - buffer, primitive_vertices.at(2) - buffer, primitive_vertices.at(3) - buffer, tex, v_uv.at(0), v_uv.at(2), v_uv.at(3));
1075 } else if (slice_points_edge_ID.at(0) == 2 && vertex_index == 1) {
1076 diag_1 = 126;
1077 t0 = context->addTriangle(slice_points.at(0) - buffer, primitive_vertices.at(1) - buffer, primitive_vertices.at(2) - buffer, tex, ip_uv.at(0), v_uv.at(1), v_uv.at(2));
1078 t1 = context->addTriangle(slice_points.at(0) + buffer, primitive_vertices.at(3) + buffer, primitive_vertices.at(1) + buffer, tex, ip_uv.at(0), v_uv.at(3), v_uv.at(1));
1079 t2 = context->addTriangle(primitive_vertices.at(1) + buffer, primitive_vertices.at(3) + buffer, primitive_vertices.at(0) + buffer, tex, v_uv.at(1), v_uv.at(3), v_uv.at(0));
1080 } else if (slice_points_edge_ID.at(0) == 2 && vertex_index == 0) {
1081 diag_1 = 127;
1082 t0 = context->addTriangle(slice_points.at(0) + buffer, primitive_vertices.at(3) + buffer, primitive_vertices.at(0) + buffer, tex, ip_uv.at(0), v_uv.at(3), v_uv.at(0));
1083 t1 = context->addTriangle(slice_points.at(0) - buffer, primitive_vertices.at(0) - buffer, primitive_vertices.at(2) - buffer, tex, ip_uv.at(0), v_uv.at(0), v_uv.at(2));
1084 t2 = context->addTriangle(primitive_vertices.at(0) - buffer, primitive_vertices.at(1) - buffer, primitive_vertices.at(2) - buffer, tex, v_uv.at(0), v_uv.at(1), v_uv.at(2));
1085 } else if (slice_points_edge_ID.at(0) == 3 && vertex_index == 2) {
1086 diag_1 = 128;
1087 t0 = context->addTriangle(slice_points.at(0) + buffer, primitive_vertices.at(0) + buffer, primitive_vertices.at(2) + buffer, tex, ip_uv.at(0), v_uv.at(0), v_uv.at(2));
1088 t1 = context->addTriangle(primitive_vertices.at(2) + buffer, primitive_vertices.at(0) + buffer, primitive_vertices.at(1) + buffer, tex, v_uv.at(2), v_uv.at(0), v_uv.at(1));
1089 t2 = context->addTriangle(slice_points.at(0) - buffer, primitive_vertices.at(2) - buffer, primitive_vertices.at(3) - buffer, tex, ip_uv.at(0), v_uv.at(2), v_uv.at(3));
1090 } else if (slice_points_edge_ID.at(0) == 3 && vertex_index == 1) {
1091 diag_1 = 129;
1092 t0 = context->addTriangle(slice_points.at(0) + buffer, primitive_vertices.at(0) + buffer, primitive_vertices.at(1) + buffer, tex, ip_uv.at(0), v_uv.at(0), v_uv.at(1));
1093 t1 = context->addTriangle(slice_points.at(0) - buffer, primitive_vertices.at(1) - buffer, primitive_vertices.at(3) - buffer, tex, ip_uv.at(0), v_uv.at(1), v_uv.at(3));
1094 t2 = context->addTriangle(primitive_vertices.at(1) - buffer, primitive_vertices.at(2) - buffer, primitive_vertices.at(3) - buffer, tex, v_uv.at(1), v_uv.at(2), v_uv.at(3));
1095 }
1096
1097 // delete triangles with area of zero, otherwise add to resulting_UUIDs vector
1098 if (context->getPrimitiveArea(t0) < minArea) {
1099 context->deletePrimitive(t0);
1100 } else {
1101 resulting_UUIDs.push_back(t0);
1102 }
1103 if (context->getPrimitiveArea(t1) < minArea) {
1104 context->deletePrimitive(t1);
1105 } else {
1106 resulting_UUIDs.push_back(t1);
1107 }
1108 if (context->getPrimitiveArea(t2) < minArea) {
1109 context->deletePrimitive(t2);
1110 } else {
1111 resulting_UUIDs.push_back(t2);
1112 }
1113 }
1114
1115 } else if (initial_slice_points_size == 4) {
1116
1117 if (vertex_index == 0 || vertex_index == 2) {
1118 diag_1 = 130;
1119 t0 = context->addTriangle(primitive_vertices.at(0) - buffer, primitive_vertices.at(1) - buffer, primitive_vertices.at(2) - buffer, tex, v_uv.at(0), v_uv.at(1), v_uv.at(2));
1120 t1 = context->addTriangle(primitive_vertices.at(0) + buffer, primitive_vertices.at(2) + buffer, primitive_vertices.at(3) + buffer, tex, v_uv.at(0), v_uv.at(2), v_uv.at(3));
1121
1122 } else if (vertex_index == 1 || vertex_index == 3) {
1123 diag_1 = 131;
1124 t0 = context->addTriangle(primitive_vertices.at(1) - buffer, primitive_vertices.at(2) - buffer, primitive_vertices.at(3) - buffer, tex, v_uv.at(1), v_uv.at(2), v_uv.at(3));
1125 t1 = context->addTriangle(primitive_vertices.at(1) + buffer, primitive_vertices.at(3) + buffer, primitive_vertices.at(0) + buffer, tex, v_uv.at(1), v_uv.at(3), v_uv.at(0));
1126 }
1127
1128 // delete triangles with area of zero, otherwise add to resulting_UUIDs vector
1129 if (context->getPrimitiveArea(t0) < minArea) {
1130 context->deletePrimitive(t0);
1131 } else {
1132 resulting_UUIDs.push_back(t0);
1133 }
1134 if (context->getPrimitiveArea(t1) < minArea) {
1135 context->deletePrimitive(t1);
1136 } else {
1137 resulting_UUIDs.push_back(t1);
1138 }
1139 }
1140 }
1141 }
1142
1143 // print this out to find where a certain triangle is created
1144 // std::cout << "diag_1 = " << diag_1 << std::endl;
1145
1146 // copy over primitive data to the new triangles
1147 for (uint i = 0; i < resulting_UUIDs.size(); i++) {
1148 context->copyPrimitiveData(UUID, resulting_UUIDs.at(i));
1149 uint parentID = context->getPrimitiveParentObjectID(UUID);
1150 if (parentID > 0 && context->getObjectType(parentID) == helios::OBJECT_TYPE_TILE) {
1151 context->setPrimitiveParentObjectID(resulting_UUIDs.at(i), 0);
1152 } else {
1153 context->setPrimitiveParentObjectID(resulting_UUIDs.at(i), parentID);
1154 }
1155 if (context->isPrimitiveTextureColorOverridden(UUID)) {
1156 context->overridePrimitiveTextureColor(resulting_UUIDs.at(i));
1157 }
1158 }
1159
1160 // compare original and resulting primitive areas to make sure they approximately match
1161 float resulting_area = context->sumPrimitiveSurfaceArea(resulting_UUIDs);
1162 float pdiff_area = (resulting_area - original_area) / original_area * 100.0;
1163 float pdiff_area_abs = fabs(pdiff_area);
1164 if (pdiff_area_abs > 1) {
1165 warnings.addWarning("slice_area_mismatch", "Sum of slice areas does not equal area of original primitive (UUID = " + std::to_string(UUID) + ", original area = " + std::to_string(original_area) +
1166 ", resulting area = " + std::to_string(resulting_area) + ", percent difference = " + std::to_string(pdiff_area) + "%)");
1167 }
1168
1169 // compare original and resulting primitive normals to make sure they match
1170 absTol = 0.5;
1171 relTol = 0.4;
1172 for (uint aa = 0; aa < resulting_UUIDs.size(); aa++) {
1173 helios::vec3 this_normal = context->getPrimitiveNormal(resulting_UUIDs.at(aa));
1174 this_normal.normalize();
1175 if (!approxSame(primitive_normal.x, this_normal.x, absTol, relTol) || !approxSame(primitive_normal.y, this_normal.y, absTol, relTol) || !approxSame(primitive_normal.z, this_normal.z, absTol, relTol)) {
1176 warnings.addWarning("slice_normal_mismatch", "UUID " + std::to_string(resulting_UUIDs.at(aa)) + " normal (" + std::to_string(this_normal.x) + ", " + std::to_string(this_normal.y) + ", " + std::to_string(this_normal.z) +
1177 ") does not match original normal (" + std::to_string(primitive_normal.x) + ", " + std::to_string(primitive_normal.y) + ", " + std::to_string(primitive_normal.z) + ")");
1178 }
1179 }
1180
1181 // delete the original primitive
1182 context->deletePrimitive(UUID);
1183
1184 return resulting_UUIDs;
1185}
1186
1187std::vector<uint> VoxelIntersection::slicePrimitivesUsingGrid(std::vector<uint> UUIDs, helios::vec3 grid_center, helios::vec3 grid_size, helios::int3 grid_divisions) {
1188
1189 // Create warning aggregator
1191 warnings.setEnabled(printmessages);
1192
1193 // set up the grid
1194 std::vector<std::vector<helios::vec3>> grid_face_vertices;
1195 helios::vec3 grid_min = make_vec3(grid_center.x - grid_size.x * 0.5, grid_center.y - grid_size.y * 0.5, grid_center.z - grid_size.z * 0.5);
1196 helios::vec3 grid_max = make_vec3(grid_center.x + grid_size.x * 0.5, grid_center.y + grid_size.y * 0.5, grid_center.z + grid_size.z * 0.5);
1197 helios::vec3 grid_spacing = make_vec3(grid_size.x / grid_divisions.x, grid_size.y / grid_divisions.y, grid_size.z / grid_divisions.z);
1198
1199 // faces in the y-z plane (change x)
1200 for (uint k = 0; k < (grid_divisions.x + 1); k++) {
1201 std::vector<helios::vec3> this_face_vertices;
1202 this_face_vertices.push_back(make_vec3(grid_min.x + k * grid_spacing.x, grid_min.y, grid_min.z));
1203 this_face_vertices.push_back(make_vec3(grid_min.x + k * grid_spacing.x, grid_min.y, grid_max.z));
1204 this_face_vertices.push_back(make_vec3(grid_min.x + k * grid_spacing.x, grid_max.y, grid_min.z));
1205 this_face_vertices.push_back(make_vec3(grid_min.x + k * grid_spacing.x, grid_max.y, grid_max.z));
1206 grid_face_vertices.push_back(this_face_vertices);
1207 }
1208
1209 // faces in the x-z plane (change y)
1210 for (uint k = 0; k < (grid_divisions.y + 1); k++) {
1211 std::vector<helios::vec3> this_face_vertices;
1212 this_face_vertices.push_back(make_vec3(grid_min.x, grid_min.y + k * grid_spacing.y, grid_min.z));
1213 this_face_vertices.push_back(make_vec3(grid_min.x, grid_min.y + k * grid_spacing.y, grid_max.z));
1214 this_face_vertices.push_back(make_vec3(grid_max.x, grid_min.y + k * grid_spacing.y, grid_min.z));
1215 this_face_vertices.push_back(make_vec3(grid_max.x, grid_min.y + k * grid_spacing.y, grid_max.z));
1216 grid_face_vertices.push_back(this_face_vertices);
1217 }
1218
1219 // faces in the x-z plane (change y)
1220 for (uint k = 0; k < (grid_divisions.z + 1); k++) {
1221 std::vector<helios::vec3> this_face_vertices;
1222 this_face_vertices.push_back(make_vec3(grid_min.x, grid_min.y, grid_min.z + k * grid_spacing.z));
1223 this_face_vertices.push_back(make_vec3(grid_min.x, grid_max.y, grid_min.z + k * grid_spacing.z));
1224 this_face_vertices.push_back(make_vec3(grid_max.x, grid_min.y, grid_min.z + k * grid_spacing.z));
1225 this_face_vertices.push_back(make_vec3(grid_max.x, grid_max.y, grid_min.z + k * grid_spacing.z));
1226 grid_face_vertices.push_back(this_face_vertices);
1227 }
1228
1229 if (printmessages) {
1230 std::cout << UUIDs.size() << " input primitives" << std::endl;
1231 std::cout << grid_face_vertices.size() << " grid faces used for slicing" << std::endl;
1232 std::cout << grid_divisions.x * grid_divisions.y * grid_divisions.z << " total grid cells" << std::endl;
1233 }
1234
1235
1237 // do an initial classification of primitives into grid cells based on if all their vertices fall into a given voxel
1238
1239 cell_primitives.resize(grid_divisions.x * grid_divisions.y * grid_divisions.z + 1);
1240
1241 // initially set all UUIDs as outside any voxel
1242 context->setPrimitiveData(UUIDs, "cell_ID", int(-1));
1243
1244 // vectors for UUIDs that do and do not need to be sliced
1245 std::vector<uint> UUIDs_to_slice;
1246 std::vector<uint> UUIDs_no_slice;
1247
1248 auto start = std::chrono::high_resolution_clock::now();
1249 for (uint p = 0; p < UUIDs.size(); p++) {
1250 int cell_ID = 0;
1251 bool flag = false;
1252 for (uint k = 0; k < (grid_divisions.z); k++) {
1253 for (uint j = 0; j < (grid_divisions.y); j++) {
1254 for (uint i = 0; i < (grid_divisions.x); i++) {
1255 helios::vec3 cell_min = make_vec3(grid_min.x + float(i) * grid_spacing.x, grid_min.y + float(j) * grid_spacing.y, grid_min.z + float(k) * grid_spacing.z);
1256 helios::vec3 cell_max = make_vec3(grid_min.x + float(i) * grid_spacing.x + grid_spacing.x, grid_min.y + float(j) * grid_spacing.y + grid_spacing.y, grid_min.z + float(k) * grid_spacing.z + grid_spacing.z);
1257 std::vector<helios::vec3> verts = context->getPrimitiveVertices(UUIDs.at(p));
1258
1259 uint v_in = 0;
1260 for (uint v = 0; v < verts.size(); v++) {
1261
1262 bool test2_x = (verts.at(v).x >= cell_min.x) && (verts.at(v).x <= cell_max.x);
1263 bool test2_y = (verts.at(v).y >= cell_min.y) && (verts.at(v).y <= cell_max.y);
1264 bool test2_z = (verts.at(v).z >= cell_min.z) && (verts.at(v).z <= cell_max.z);
1265
1266 if (test2_x && test2_y && test2_z) {
1267 v_in++;
1268 }
1269 }
1270
1271 if (v_in == verts.size()) {
1272 // the UUID doesn't need to be sliced since its vertices all are within a cell
1273 context->setPrimitiveData(UUIDs.at(p), "cell_ID", cell_ID);
1274 cell_primitives.at(cell_ID).push_back(UUIDs.at(p));
1275 UUIDs_no_slice.push_back(UUIDs.at(p));
1276 cell_ID++;
1277 flag = true;
1278 break;
1279 } else if (v_in != 0) {
1280 // some verticies in and some out: UUID needs to be sliced
1281 UUIDs_to_slice.push_back(UUIDs.at(p));
1282 flag = true;
1283 break;
1284 }
1285 cell_ID++;
1286 }
1287 if (flag == true) {
1288 break;
1289 }
1290 }
1291 if (flag == true) {
1292 break;
1293 }
1294 }
1295
1296 // if all vertices fell outside of all grid cells, add it to be sliced just in case (corner cases)
1297 if (flag == false) {
1298 UUIDs_to_slice.push_back(UUIDs.at(p));
1299 }
1300 }
1301
1302 if (printmessages) {
1303
1304 auto stop = std::chrono::high_resolution_clock::now();
1305 auto duration = std::chrono::duration_cast<std::chrono::seconds>(stop - start);
1306 std::cout << duration.count() << " seconds to do initial grid cell classification" << std::endl;
1307 std::cout << UUIDs_no_slice.size() << " input primitives (" << float(UUIDs_no_slice.size()) / float(UUIDs.size()) * 100 << "%) not sliced" << std::endl;
1308 std::cout << UUIDs_to_slice.size() << " input primitives (" << float(UUIDs_to_slice.size()) / float(UUIDs.size()) * 100 << "%) being sliced" << std::endl;
1309 }
1310
1311
1313 // do the slicing
1314
1315 std::vector<uint> primitives_to_remove;
1316 std::vector<uint> primitives_to_add;
1317 uint s1;
1318
1319 auto start2 = std::chrono::high_resolution_clock::now();
1320 // loop through each voxel face
1321 for (uint i = 0; i < grid_face_vertices.size(); i++) {
1322 for (uint j = 0; j < UUIDs_to_slice.size(); j++) {
1323 // slice
1324 std::vector<uint> resulting_UUIDs;
1325 resulting_UUIDs = slicePrimitive(UUIDs_to_slice.at(j), grid_face_vertices.at(i), warnings);
1326
1327 // update the UUIDs_to_slice vector so it doesn't include deleted primitives (the originals that were split)
1328 bool exists = context->doesPrimitiveExist(UUIDs_to_slice.at(j));
1329 if (!exists) {
1330 primitives_to_remove.push_back(j);
1331 primitives_to_add.insert(primitives_to_add.end(), resulting_UUIDs.begin(), resulting_UUIDs.end());
1332 }
1333 }
1334
1335 for (int k = primitives_to_remove.size() - 1; k >= 0; k--) {
1336 UUIDs_to_slice.erase(UUIDs_to_slice.begin() + primitives_to_remove.at(k));
1337 }
1338 primitives_to_remove.clear();
1339
1340 UUIDs_to_slice.insert(UUIDs_to_slice.end(), primitives_to_add.begin(), primitives_to_add.end());
1341 primitives_to_add.clear();
1342 }
1343
1344 if (printmessages) {
1345
1346 auto stop2 = std::chrono::high_resolution_clock::now();
1347 auto duration2 = std::chrono::duration_cast<std::chrono::seconds>(stop2 - start2);
1348 std::cout << duration2.count() << " seconds to do slicing" << std::endl;
1349 }
1350
1352 // now classify the sliced primitives into grid cells
1353 // save the cell_ID as primitive data for the triangle
1354 // save the primitive UUID to a vector of UUIDs that are in a given cell and save that
1355
1356 auto start3 = std::chrono::high_resolution_clock::now();
1357
1358 for (uint p = 0; p < UUIDs_to_slice.size(); p++) {
1359 // std::cout << "UUIDs_to_slice.at(p) = " << UUIDs_to_slice.at(p) << std::endl;
1360 int cell_ID = 0;
1361 bool flag = false;
1362
1363 for (uint k = 0; k < (grid_divisions.z); k++) {
1364 for (uint j = 0; j < (grid_divisions.y); j++) {
1365 for (uint i = 0; i < (grid_divisions.x); i++) {
1366
1367 helios::vec3 cell_min = make_vec3(grid_min.x + i * grid_spacing.x, grid_min.y + j * grid_spacing.y, grid_min.z + k * grid_spacing.z);
1368 helios::vec3 cell_max = make_vec3(grid_min.x + i * grid_spacing.x + grid_spacing.x, grid_min.y + j * grid_spacing.y + grid_spacing.y, grid_min.z + k * grid_spacing.z + grid_spacing.z);
1369
1370 std::vector<helios::vec3> verts = context->getPrimitiveVertices(UUIDs_to_slice.at(p));
1371 uint v_in = 0;
1372 for (uint v = 0; v < verts.size(); v++) {
1373
1374 float absTol = pow(10, -6);
1375 float relTol = pow(10, -20);
1376 bool test2_x = (verts.at(v).x > cell_min.x || approxSame(verts.at(v).x, cell_min.x, absTol, relTol)) && (verts.at(v).x < cell_max.x || approxSame(verts.at(v).x, cell_max.x, absTol, relTol));
1377 bool test2_y = (verts.at(v).y > cell_min.y || approxSame(verts.at(v).y, cell_min.y, absTol, relTol)) && (verts.at(v).y < cell_max.y || approxSame(verts.at(v).y, cell_max.y, absTol, relTol));
1378 bool test2_z = (verts.at(v).z > cell_min.z || approxSame(verts.at(v).z, cell_min.z, absTol, relTol)) && (verts.at(v).z < cell_max.z || approxSame(verts.at(v).z, cell_max.z, absTol, relTol));
1379
1380 if (test2_x && test2_y && test2_z) {
1381 v_in++;
1382 }
1383 }
1384
1385 if (v_in == verts.size()) {
1386 context->setPrimitiveData(UUIDs_to_slice.at(p), "cell_ID", cell_ID);
1387 cell_primitives.at(cell_ID).push_back(UUIDs_to_slice.at(p));
1388 cell_ID++;
1389 flag = true;
1390 break;
1391 }
1392 cell_ID++;
1393 }
1394 if (flag == true) {
1395 break;
1396 }
1397 }
1398 if (flag == true) {
1399 break;
1400 }
1401 }
1402
1403 if (flag == false) {
1404 cell_primitives.at(cell_primitives.size() - 1).push_back(UUIDs_to_slice.at(p));
1405 }
1406 }
1407
1408 if (printmessages) {
1409 auto stop3 = std::chrono::high_resolution_clock::now();
1410 auto duration3 = std::chrono::duration_cast<std::chrono::seconds>(stop3 - start3);
1411 std::cout << duration3.count() << " seconds to do second classification" << std::endl;
1412 }
1414 // Join the unsliced and sliced primitive UUIDs back into a single vector
1415 std::vector<uint> UUIDs_out = UUIDs_no_slice;
1416 UUIDs_out.insert(UUIDs_out.end(), UUIDs_to_slice.begin(), UUIDs_to_slice.end());
1417
1418 if (printmessages) {
1419 std::cout << UUIDs_to_slice.size() << " primitives created from slicing" << std::endl;
1420 std::cout << UUIDs_out.size() << " total output primitives" << std::endl;
1421 }
1422
1423 // Report aggregated warnings
1424 warnings.report(std::cerr);
1425
1426 return UUIDs_out;
1427}
1428
1429
1430std::vector<std::vector<uint>> VoxelIntersection::getCellPrimitives(void) {
1431
1432 return cell_primitives;
1433}
1434
1435bool VoxelIntersection::approxSame(float a, float b, float absTol, float relTol) {
1436
1437 return fabs(a - b) <= absTol || fabs(a - b) <= relTol * (std::max(fabs(a), fabs(b)));
1438}
1439
1441 return fabs(a.x - b.x) <= absTol && fabs(a.y - b.y) <= absTol && fabs(a.z - b.z) <= absTol;
1442}
1443
1445 // uv coordinate that will be output
1446 helios::vec2 uvs;
1447
1448 float Dxyz = sqrtf(powf(p2.x - p1.x, 2.0) + powf(p2.y - p1.y, 2.0) + powf(p2.z - p1.z, 2.0)); // distance between edge vertex xyz coordinates
1449 float Duv = sqrtf(powf(uv2.x - uv1.x, 2.0) + powf(uv2.y - uv1.y, 2.0)); // distance between edge vertex uv coordinates
1450 float Dxyzs = sqrtf(powf(ps.x - p1.x, 2.0) + powf(ps.y - p1.y, 2.0) + powf(ps.z - p1.z, 2.0)); // distance between slice point and first vertex xyz coordinates
1451
1452 // std::cout << "x1 = " << p1.x << " , y1 = " << p1.y << ", z1 = " << p1.z << std::endl;
1453 // std::cout << "x2 = " << p2.x << " , y2 = " << p2.y << ", z2 = " << p2.z << std::endl;
1454 // std::cout << "xs = " << ps.x << " , ys = " << ps.y << ", zs = " << ps.z << std::endl;
1455 // std::cout << "uv1 = " << uv1 << ", uv2 = " << uv2 << std::endl;
1456 // std::cout << "Dxyz = " << Dxyz << ", Duv = " << Duv << ", Dxyzs = " << Dxyzs << std::endl;
1457 // std::cout << "f = " << (Dxyzs/Dxyz) << std::endl;
1458 // std::cout << "f*Duv = " << Duv*(Dxyzs/Dxyz) << std::endl;
1459
1460 float absTol = pow(10, -6);
1461
1462 float F = (Dxyzs / Dxyz);
1463 if (F > 1.0) {
1464 helios_runtime_error("ERROR (VoxelIntersection::interpolate_texture_UV_to_slice_point): slice point is not between the two end points.");
1465 } else if (approxSame(p1, ps, absTol)) {
1466 // then the slice point is the same as the first vertex
1467 uvs = make_vec2(uv1.x, uv1.y);
1468 return uvs;
1469 } else if (approxSame(p2, ps, absTol)) {
1470 // then the slice point is the same as the first vertex
1471 uvs = make_vec2(uv2.x, uv2.y);
1472 return uvs;
1473 }
1474
1475
1476 // if the u coordinates of the two vertices are the same
1477 if (uv2.x == uv1.x) {
1478 std::vector<float> vec_uv;
1479 vec_uv.push_back(uv1.y);
1480 vec_uv.push_back(uv2.y);
1481 uvs = make_vec2(uv1.x, min(vec_uv) + Duv * (Dxyzs / Dxyz));
1482 // std::cout << "uvs* = " << uvs << std::endl;
1483
1484 } else {
1485
1486 // equation for the line between uv coordinates of the two vertices
1487 float slope = (uv2.y - uv1.y) / (uv2.x - uv1.x);
1488 float offset = uv1.y - slope * uv1.x;
1489
1490 // coefficients of the quadratic equation for the u coordinate of the slice point
1491 float a = powf(slope, 2.0) + 1.0;
1492 float b = -2.0 * uv1.x + 2.0 * slope * offset - 2.0 * slope * uv1.y;
1493 float c = (powf(uv1.x, 2.0) + powf(offset, 2.0) - 2.0 * offset * uv1.y + powf(uv1.y, 2.0)) - powf((Dxyzs / Dxyz) * Duv, 2.0);
1494
1495 // solve the quadratic
1496 float us_a = (-1.0 * b + sqrtf(powf(b, 2.0) - 4.0 * a * c)) / (2.0 * a);
1497 float us_b = (-1.0 * b - sqrtf(powf(b, 2.0) - 4.0 * a * c)) / (2.0 * a);
1498 // get the v coordinate
1499 float vs_a = slope * us_a + offset;
1500 float vs_b = slope * us_b + offset;
1501
1502 // determine which of the roots is the right one
1503 if (((us_a >= uv1.x && us_a <= uv2.x) || (us_a <= uv1.x && us_a >= uv2.x)) && ((vs_a >= uv1.y && vs_a <= uv2.y) || (vs_a <= uv1.y && vs_a >= uv2.y))) {
1504 uvs = make_vec2(us_a, vs_a);
1505 // std::cout << "uvs = " << uvs << std::endl;
1506
1507 } else if (((us_b >= uv1.x && us_b <= uv2.x) || (us_b <= uv1.x && us_b >= uv2.x)) && ((vs_b >= uv1.y && vs_b <= uv2.y) || (vs_b <= uv1.y && vs_b >= uv2.y))) {
1508 uvs = make_vec2(us_b, vs_b);
1509 // std::cout << "uvs = " << uvs << std::endl;
1510
1511 } else {
1512 helios_runtime_error("ERROR (VoxelIntersection::interpolate_texture_UV_to_slice_point): could not interpolate UV coordinates.");
1513 }
1514 }
1515
1516
1517 return uvs;
1518}