1.3.64
 
Loading...
Searching...
No Matches
GeometryHandler.cpp
Go to the documentation of this file.
1
16#include "GeometryHandler.h"
17
18void GeometryHandler::allocateBufferSize(size_t primitive_count, VisualizerGeometryType geometry_type) {
19
20 char vertex_count = getVertexCount(geometry_type);
21
22 face_index_data[geometry_type].reserve(face_index_data[geometry_type].size() + primitive_count);
23 vertex_data[geometry_type].reserve(vertex_data[geometry_type].size() + primitive_count * vertex_count * 3);
24 normal_data[geometry_type].reserve(normal_data[geometry_type].size() + primitive_count * vertex_count * 3);
25 color_data[geometry_type].reserve(color_data[geometry_type].size() + primitive_count * 4);
26 uv_data[geometry_type].reserve(uv_data[geometry_type].size() + primitive_count * vertex_count * 2);
27 texture_flag_data[geometry_type].reserve(texture_flag_data[geometry_type].size() + primitive_count);
28 texture_ID_data[geometry_type].reserve(texture_ID_data[geometry_type].size() + primitive_count);
29 coordinate_flag_data[geometry_type].reserve(coordinate_flag_data[geometry_type].size() + primitive_count);
30 delete_flag_data[geometry_type].reserve(delete_flag_data[geometry_type].size() + primitive_count);
31 context_geometry_flag_data[geometry_type].reserve(context_geometry_flag_data[geometry_type].size() + primitive_count);
32 sky_geometry_flag_data[geometry_type].reserve(sky_geometry_flag_data[geometry_type].size() + primitive_count);
33 size_data[geometry_type].reserve(size_data[geometry_type].size() + primitive_count);
34}
35
36void GeometryHandler::addGeometry(size_t UUID, const VisualizerGeometryType &geometry_type, const std::vector<helios::vec3> &vertices, const helios::RGBAcolor &color, const std::vector<helios::vec2> &uvs, int textureID, bool override_texture_color,
37 bool has_glyph_texture, uint coordinate_system, bool visible_flag, bool iscontextgeometry, bool isskygeometry, float size) {
38
39 char vertex_count = getVertexCount(geometry_type);
40
41#ifdef HELIOS_DEBUG
42 assert(vertices.size() == vertex_count);
43 assert(uvs.empty() || uvs.size() == vertex_count);
44#endif
45
46 std::vector<helios::vec3> vertices_copy = vertices; // make a copy so it can be modified
47
48 bool geometry_is_new = false;
49 if (!doesGeometryExist(UUID)) {
50 registerUUID(UUID, geometry_type);
51 geometry_is_new = true;
52 }
53
54 if (coordinate_system == 0) { // No vertex transformation (i.e., identity matrix)
55
56 // NOTE for vertex positions: OpenGL window coordinates range from -1 to 1, but our rectangle coordinates are from 0 to 1 ---- need to convert
57 for (auto &vertex: vertices_copy) {
58 vertex.x = 2.f * vertex.x - 1.f;
59 vertex.y = 2.f * vertex.y - 1.f;
60 }
61 }
62
63 size_t vertex_index = UUID_map.at(UUID).vertex_index;
64 size_t normal_index = UUID_map.at(UUID).normal_index;
65 size_t uv_index = UUID_map.at(UUID).uv_index;
66 size_t color_index = UUID_map.at(UUID).color_index;
67 size_t texture_flag_index = UUID_map.at(UUID).texture_flag_index;
68 size_t texture_ID_index = UUID_map.at(UUID).texture_ID_index;
69 size_t size_index = UUID_map.at(UUID).size_index;
70
71 for (char i = 0; i < vertex_count; i++) {
72
73 if (geometry_is_new) {
74 face_index_data[geometry_type].push_back(static_cast<int>(visible_flag_data[geometry_type].size()));
75
76 vertex_data[geometry_type].push_back(vertices_copy.at(i).x);
77 vertex_data[geometry_type].push_back(vertices_copy.at(i).y);
78 vertex_data[geometry_type].push_back(vertices_copy.at(i).z);
79 } else {
80 // face index doesn't need to be updated
81
82 vertex_data[geometry_type].at(vertex_index) = vertices_copy.at(i).x;
83 vertex_data[geometry_type].at(vertex_index + 1) = vertices_copy.at(i).y;
84 vertex_data[geometry_type].at(vertex_index + 2) = vertices_copy.at(i).z;
85 vertex_index += 3;
86 }
87
88 if ((geometry_type == GEOMETRY_TYPE_TRIANGLE || geometry_type == GEOMETRY_TYPE_RECTANGLE) && !uvs.empty()) { // if (u, v)'s are provided, color triangle based on texture map image
89
90 if (geometry_is_new) {
91 uv_data[geometry_type].push_back(uvs.at(i).x);
92 uv_data[geometry_type].push_back(1.f - uvs.at(i).y);
93
94 if (i == 0) { // only need to do this one time
95 if (has_glyph_texture) {
96 texture_flag_data[geometry_type].push_back(3); // 3 means use RGB for color and red channel of texture for alpha
97 } else if (override_texture_color) { // if texture color is overridden, color primitive based on RGB color but use texture transparence for alpha mask
98 texture_flag_data[geometry_type].push_back(2); // 2 means use RGB for color and texture transparency for alpha
99 } else {
100 texture_flag_data[geometry_type].push_back(1); // 1 means use texture for color and transparency for alpha
101 }
102 texture_ID_data[geometry_type].push_back(textureID);
103 }
104 } else {
105 uv_data[geometry_type].at(uv_index) = uvs.at(i).x;
106 uv_data[geometry_type].at(uv_index + 1) = 1.f - uvs.at(i).y;
107 uv_index += 2;
108
109 if (i == 0) { // only need to do this one time
110 if (has_glyph_texture) {
111 texture_flag_data[geometry_type].at(texture_flag_index) = 3; // 3 means use RGB for color and red channel of texture for alpha
112 } else if (override_texture_color) { // if texture color is overridden, color primitive based on RGB color but use texture transparence for alpha mask
113 texture_flag_data[geometry_type].at(texture_flag_index) = 2; // 2 means use RGB for color and texture transparency for alpha
114 } else {
115 texture_flag_data[geometry_type].at(texture_flag_index) = 1; // 1 means use texture for color and transparency for alpha
116 }
117 texture_flag_index++;
118 texture_ID_data[geometry_type].at(texture_ID_index) = textureID;
119 texture_ID_index++;
120 }
121 }
122 } else { // if (u,v)'s are not provided, color primitive based on RGB color
123
124 if (geometry_is_new) {
125 uv_data[geometry_type].push_back(0.f);
126 uv_data[geometry_type].push_back(0.f);
127
128 if (i == 0) { // only need to do this one time
129 if (has_glyph_texture) {
130 texture_flag_data[geometry_type].push_back(3); // 3 means use RGB for color and red channel of texture for alpha
131 texture_ID_data[geometry_type].push_back(textureID);
132 } else {
133 texture_flag_data[geometry_type].push_back(0); // 0 means use RGB color
134 texture_ID_data[geometry_type].push_back(0);
135 }
136 }
137 } else {
138 uv_data[geometry_type].at(uv_index) = 0.f;
139 uv_data[geometry_type].at(uv_index + 1) = 0.f;
140 uv_index += 2;
141
142 if (i == 0) { // only need to do this one time
143 if (has_glyph_texture) {
144 texture_flag_data[geometry_type].at(texture_flag_index) = 3; // 3 means use RGB for color and red channel of texture for alpha
145 texture_ID_data[geometry_type].at(texture_ID_index) = textureID;
146 } else {
147 texture_flag_data[geometry_type].at(texture_flag_index) = 0; // 0 means use RGB color
148 texture_ID_data[geometry_type].at(texture_ID_index) = 0;
149 }
150 texture_flag_index++;
151 texture_ID_index++;
152 }
153 }
154 }
155 }
156
157 helios::vec3 normal;
158 if (geometry_type == GEOMETRY_TYPE_TRIANGLE || geometry_type == GEOMETRY_TYPE_RECTANGLE) {
159 normal = normalize(cross(vertices_copy.at(1) - vertices_copy.at(0), vertices_copy.at(2) - vertices_copy.at(0)));
160 }
161 if (geometry_is_new) {
162 normal_data[geometry_type].push_back(normal.x);
163 normal_data[geometry_type].push_back(normal.y);
164 normal_data[geometry_type].push_back(normal.z);
165
166 color_data[geometry_type].push_back(color.r);
167 color_data[geometry_type].push_back(color.g);
168 color_data[geometry_type].push_back(color.b);
169 color_data[geometry_type].push_back(color.a);
170
171 coordinate_flag_data[geometry_type].push_back(coordinate_system);
172
173 visible_flag_data[geometry_type].push_back(visible_flag);
174
175 delete_flag_data[geometry_type].push_back(false);
176
177 context_geometry_flag_data[geometry_type].push_back(iscontextgeometry);
178
179 sky_geometry_flag_data[geometry_type].push_back(isskygeometry ? 1 : 0);
180
181 size_data[geometry_type].push_back(size);
182 } else {
183 normal_data[geometry_type].at(normal_index) = normal.x;
184 normal_data[geometry_type].at(normal_index + 1) = normal.y;
185 normal_data[geometry_type].at(normal_index + 2) = normal.z;
186
187 color_data[geometry_type].at(color_index) = color.r;
188 color_data[geometry_type].at(color_index + 1) = color.g;
189 color_data[geometry_type].at(color_index + 2) = color.b;
190 color_data[geometry_type].at(color_index + 3) = color.a;
191
192 size_data[geometry_type].at(size_index) = size;
193 }
194
195 markDirty(UUID);
196}
197
198bool GeometryHandler::doesGeometryExist(size_t UUID) const {
199 return (UUID_map.find(UUID) != UUID_map.end());
200}
201
202std::vector<size_t> GeometryHandler::getAllGeometryIDs() const {
203 std::vector<size_t> result;
204 result.reserve(UUID_map.size());
205 for (const auto &[UUID, primitivemap]: UUID_map) {
206 if (getDeleteFlag(UUID)) {
207 // Only include non-deleted geometries
208 continue;
209 }
210 result.push_back(UUID);
211 }
212 return result;
213}
214
215size_t GeometryHandler::getPrimitiveCount(bool include_deleted) const {
216 size_t count = 0;
217 if (include_deleted) {
218 for (auto &type: all_geometry_types) {
219 count += delete_flag_data.at(type).size();
220 }
221 return count;
222 }
223
224 for (auto &type: all_geometry_types) {
225 count += std::count(delete_flag_data.at(type).begin(), delete_flag_data.at(type).end(), false);
226 }
227 return count;
228}
229
230[[nodiscard]] size_t GeometryHandler::getRectangleCount(bool include_deleted) const {
231 VisualizerGeometryType type = GEOMETRY_TYPE_RECTANGLE;
232 if (include_deleted) {
233 return delete_flag_data.at(type).size();
234 }
235
236 size_t count = std::count(delete_flag_data.at(type).begin(), delete_flag_data.at(type).end(), false);
237 return count;
238}
239
240[[nodiscard]] size_t GeometryHandler::getTriangleCount(bool include_deleted) const {
241 VisualizerGeometryType type = GEOMETRY_TYPE_TRIANGLE;
242 if (include_deleted) {
243 return delete_flag_data.at(type).size();
244 }
245
246 size_t count = std::count(delete_flag_data.at(type).begin(), delete_flag_data.at(type).end(), false);
247 return count;
248}
249
250[[nodiscard]] size_t GeometryHandler::getPointCount(bool include_deleted) const {
251 VisualizerGeometryType type = GEOMETRY_TYPE_POINT;
252 if (include_deleted) {
253 return delete_flag_data.at(type).size();
254 }
255
256 size_t count = std::count(delete_flag_data.at(type).begin(), delete_flag_data.at(type).end(), false);
257 return count;
258}
259
260[[nodiscard]] size_t GeometryHandler::getLineCount(bool include_deleted) const {
261 VisualizerGeometryType type = GEOMETRY_TYPE_LINE;
262 if (include_deleted) {
263 return delete_flag_data.at(type).size();
264 }
265
266 size_t count = std::count(delete_flag_data.at(type).begin(), delete_flag_data.at(type).end(), false);
267 return count;
268}
269
270const std::vector<int> *GeometryHandler::getFaceIndexData_ptr(VisualizerGeometryType geometry_type) const {
271#ifdef HELIOS_DEBUG
272 assert(face_index_data.find(geometry_type) != face_index_data.end());
273#endif
274 return &face_index_data.at(geometry_type);
275}
276
277void GeometryHandler::setVertices(size_t UUID, const std::vector<helios::vec3> &vertices) {
278
279#ifdef HELIOS_DEBUG
280 assert(UUID_map.find(UUID) != UUID_map.end());
281#endif
282
283 const PrimitiveIndexMap &index_map = UUID_map.at(UUID);
284
285 const char vertex_count = getVertexCount(index_map.geometry_type);
286
287#ifdef HELIOS_DEBUG
288 assert(vertices.size() == vertex_count);
289#endif
290
291 // Apply transformation for window-normalized coordinates (same as addGeometry does)
292 std::vector<helios::vec3> vertices_to_store = vertices;
293 const uint coordinate_system = coordinate_flag_data.at(index_map.geometry_type).at(index_map.coordinate_flag_index);
294 if (coordinate_system == 0) { // COORDINATES_WINDOW_NORMALIZED
295 // Transform: [0,1] → [-1,1]
296 for (auto &vertex: vertices_to_store) {
297 vertex.x = 2.f * vertex.x - 1.f;
298 vertex.y = 2.f * vertex.y - 1.f;
299 }
300 }
301
302 const size_t vertex_ind = index_map.vertex_index;
303
304 int ii = 0;
305 for (int i = 0; i < vertex_count; i++) {
306 vertex_data[index_map.geometry_type].at(vertex_ind + ii + 0) = vertices_to_store.at(i).x;
307 vertex_data[index_map.geometry_type].at(vertex_ind + ii + 1) = vertices_to_store.at(i).y;
308 vertex_data[index_map.geometry_type].at(vertex_ind + ii + 2) = vertices_to_store.at(i).z;
309 ii += 3;
310 }
311
312 const size_t normal_ind = index_map.normal_index;
313
314 const helios::vec3 normal = normalize(cross(vertices_to_store.at(1) - vertices_to_store.at(0), vertices_to_store.at(2) - vertices_to_store.at(0)));
315 normal_data[index_map.geometry_type].at(normal_ind + 0) = normal.x;
316 normal_data[index_map.geometry_type].at(normal_ind + 1) = normal.y;
317 normal_data[index_map.geometry_type].at(normal_ind + 2) = normal.z;
318
319 markDirty(UUID);
320}
321
322std::vector<helios::vec3> GeometryHandler::getVertices(size_t UUID) const {
323
324#ifdef HELIOS_DEBUG
325 assert(UUID_map.find(UUID) != UUID_map.end());
326#endif
327
328 const PrimitiveIndexMap &index_map = UUID_map.at(UUID);
329
330 const size_t vertex_ind = index_map.vertex_index;
331
332 const char vertex_count = getVertexCount(index_map.geometry_type);
333
334 std::vector<helios::vec3> vertices(vertex_count);
335
336 for (int i = 0; i < vertex_count; i++) {
337 vertices.at(i).x = vertex_data.at(index_map.geometry_type).at(vertex_ind + i * 3 + 0);
338 vertices.at(i).y = vertex_data.at(index_map.geometry_type).at(vertex_ind + i * 3 + 1);
339 vertices.at(i).z = vertex_data.at(index_map.geometry_type).at(vertex_ind + i * 3 + 2);
340 }
341
342 // Apply inverse transformation for window-normalized coordinates
343 // Internal storage is in OpenGL space [-1,1], so we need to convert back to [0,1]
344 const uint coordinate_system = coordinate_flag_data.at(index_map.geometry_type).at(index_map.coordinate_flag_index);
345 if (coordinate_system == 0) { // COORDINATES_WINDOW_NORMALIZED
346 // Inverse transform: [-1,1] → [0,1]
347 for (auto &vertex: vertices) {
348 vertex.x = (vertex.x + 1.f) * 0.5f;
349 vertex.y = (vertex.y + 1.f) * 0.5f;
350 }
351 }
352
353 return vertices;
354}
355
356const std::vector<float> *GeometryHandler::getVertexData_ptr(VisualizerGeometryType geometry_type) const {
357#ifdef HELIOS_DEBUG
358 assert(vertex_data.find(geometry_type) != vertex_data.end());
359#endif
360 return &vertex_data.at(geometry_type);
361}
362
364
365#ifdef HELIOS_DEBUG
366 assert(UUID_map.find(UUID) != UUID_map.end());
367#endif
368
369 const PrimitiveIndexMap &index_map = UUID_map.at(UUID);
370
371 const size_t normal_ind = index_map.normal_index;
372
373 helios::vec3 normal;
374
375 normal.x = normal_data.at(index_map.geometry_type).at(normal_ind + 0);
376 normal.y = normal_data.at(index_map.geometry_type).at(normal_ind + 1);
377 normal.z = normal_data.at(index_map.geometry_type).at(normal_ind + 2);
378
379 return normal;
380}
381
382const std::vector<float> *GeometryHandler::getNormalData_ptr(VisualizerGeometryType geometry_type) const {
383#ifdef HELIOS_DEBUG
384 assert(normal_data.find(geometry_type) != normal_data.end());
385#endif
386 return &normal_data.at(geometry_type);
387}
388
389void GeometryHandler::setColor(size_t UUID, const helios::RGBAcolor &color) {
390
391#ifdef HELIOS_DEBUG
392 assert(UUID_map.find(UUID) != UUID_map.end());
393#endif
394
395 const PrimitiveIndexMap &index_map = UUID_map.at(UUID);
396
397 const size_t color_ind = index_map.color_index;
398
399 color_data[index_map.geometry_type].at(color_ind + 0) = color.r;
400 color_data[index_map.geometry_type].at(color_ind + 1) = color.g;
401 color_data[index_map.geometry_type].at(color_ind + 2) = color.b;
402 color_data[index_map.geometry_type].at(color_ind + 3) = color.a;
403
404 markDirty(UUID);
405}
406
408
409#ifdef HELIOS_DEBUG
410 assert(UUID_map.find(UUID) != UUID_map.end());
411#endif
412
413 const PrimitiveIndexMap &index_map = UUID_map.at(UUID);
414
415 const size_t color_ind = index_map.color_index;
416
417 const helios::RGBAcolor color{color_data.at(index_map.geometry_type).at(color_ind), color_data.at(index_map.geometry_type).at(color_ind + 1), color_data.at(index_map.geometry_type).at(color_ind + 2),
418 color_data.at(index_map.geometry_type).at(color_ind + 3)};
419
420 return color;
421}
422
423const std::vector<float> *GeometryHandler::getColorData_ptr(VisualizerGeometryType geometry_type) const {
424#ifdef HELIOS_DEBUG
425 assert(color_data.find(geometry_type) != color_data.end());
426#endif
427 return &color_data.at(geometry_type);
428}
429
430void GeometryHandler::setUVs(size_t UUID, const std::vector<helios::vec2> &uvs) {
431
432#ifdef HELIOS_DEBUG
433 assert(UUID_map.find(UUID) != UUID_map.end());
434#endif
435
436 const PrimitiveIndexMap &index_map = UUID_map.at(UUID);
437
438 if (index_map.geometry_type == GEOMETRY_TYPE_LINE || index_map.geometry_type == GEOMETRY_TYPE_POINT) {
439 // These types do not have texture mapping
440 return;
441 }
442
443 const char vertex_count = getVertexCount(index_map.geometry_type);
444
445#ifdef HELIOS_DEBUG
446 assert(uvs.size() == vertex_count);
447#endif
448
449 const size_t uv_ind = index_map.uv_index;
450
451 int ii = 0;
452 for (int i = 0; i < vertex_count; i++) {
453 uv_data.at(index_map.geometry_type).at(uv_ind + ii) = uvs.at(i).x;
454 uv_data.at(index_map.geometry_type).at(uv_ind + ii + 1) = uvs.at(i).y;
455 ii += 2;
456 }
457
458 markDirty(UUID);
459}
460
461std::vector<helios::vec2> GeometryHandler::getUVs(size_t UUID) const {
462
463#ifdef HELIOS_DEBUG
464 assert(UUID_map.find(UUID) != UUID_map.end());
465#endif
466
467 const PrimitiveIndexMap &index_map = UUID_map.at(UUID);
468
469 const size_t uv_ind = index_map.uv_index;
470
471 const char vertex_count = getVertexCount(index_map.geometry_type);
472
473 std::vector<helios::vec2> uvs(vertex_count);
474
475 for (int i = 0; i < vertex_count; i++) {
476 uvs.at(i).x = uv_data.at(index_map.geometry_type).at(uv_ind + i * 2);
477 uvs.at(i).x = uv_data.at(index_map.geometry_type).at(uv_ind + i * 2 + 1);
478 }
479
480 return uvs;
481}
482
483const std::vector<float> *GeometryHandler::getUVData_ptr(VisualizerGeometryType geometry_type) const {
484#ifdef HELIOS_DEBUG
485 assert(uv_data.find(geometry_type) != uv_data.end());
486#endif
487 return &uv_data.at(geometry_type);
488}
489
490void GeometryHandler::setTextureID(size_t UUID, int textureID) {
491
492#ifdef HELIOS_DEBUG
493 assert(UUID_map.find(UUID) != UUID_map.end());
494#endif
495
496 const PrimitiveIndexMap &index_map = UUID_map.at(UUID);
497
498 if (index_map.geometry_type == GEOMETRY_TYPE_LINE || index_map.geometry_type == GEOMETRY_TYPE_POINT) {
499 // These types do not have texture mapping
500 return;
501 }
502
503 const size_t texture_ind = index_map.texture_ID_index;
504
505 texture_ID_data.at(index_map.geometry_type).at(texture_ind) = textureID;
506
507 markDirty(UUID);
508}
509
510int GeometryHandler::getTextureID(size_t UUID) const {
511
512#ifdef HELIOS_DEBUG
513 assert(UUID_map.find(UUID) != UUID_map.end());
514#endif
515
516 const PrimitiveIndexMap &index_map = UUID_map.at(UUID);
517
518 const size_t texture_ID_ind = index_map.texture_ID_index;
519
520 return texture_ID_data.at(index_map.geometry_type).at(texture_ID_ind);
521}
522
523const std::vector<int> *GeometryHandler::getTextureIDData_ptr(VisualizerGeometryType geometry_type) const {
524#ifdef HELIOS_DEBUG
525 assert(texture_ID_data.find(geometry_type) != texture_ID_data.end());
526#endif
527 return &texture_ID_data.at(geometry_type);
528}
529
531
532#ifdef HELIOS_DEBUG
533 assert(UUID_map.find(UUID) != UUID_map.end());
534#endif
535
536 const PrimitiveIndexMap &index_map = UUID_map.at(UUID);
537
538 if (index_map.geometry_type == GEOMETRY_TYPE_LINE || index_map.geometry_type == GEOMETRY_TYPE_POINT) {
539 // These types do not have texture mapping
540 return;
541 }
542
543 const size_t texture_flag_ind = index_map.texture_flag_index;
544
545 const int current_flag = texture_flag_data.at(index_map.geometry_type).at(texture_flag_ind);
546 if (current_flag == 1) {
547 // \todo This might be a problem in the case that the primitive does not have a texture with a transparency. In that case we would want to set to 0
548 texture_flag_data.at(index_map.geometry_type).at(texture_flag_ind) = 2;
549 }
550
551 markDirty(UUID);
552}
553
555
556#ifdef HELIOS_DEBUG
557 assert(UUID_map.find(UUID) != UUID_map.end());
558#endif
559
560 const PrimitiveIndexMap &index_map = UUID_map.at(UUID);
561
562 if (index_map.geometry_type == GEOMETRY_TYPE_LINE || index_map.geometry_type == GEOMETRY_TYPE_POINT) {
563 // These types do not have texture mapping
564 return;
565 }
566
567 const size_t texture_flag_ind = index_map.texture_flag_index;
568
569 // \todo This might be a problem in the case that the primitive does not have a texture image. In this case, we would want to set to 0.
570 texture_flag_data.at(index_map.geometry_type).at(texture_flag_ind) = 1;
571
572 markDirty(UUID);
573}
574
575const std::vector<int> *GeometryHandler::getTextureFlagData_ptr(VisualizerGeometryType geometry_type) const {
576#ifdef HELIOS_DEBUG
577 assert(texture_flag_data.find(geometry_type) != texture_flag_data.end());
578#endif
579 return &texture_flag_data.at(geometry_type);
580}
581
582void GeometryHandler::setVisibility(size_t UUID, bool isvisible) {
583
584#ifdef HELIOS_DEBUG
585 assert(UUID_map.find(UUID) != UUID_map.end());
586#endif
587
588 const PrimitiveIndexMap &index_map = UUID_map.at(UUID);
589
590 const size_t visibile_ind = index_map.visible_index;
591
592 visible_flag_data.at(index_map.geometry_type).at(visibile_ind) = static_cast<char>(isvisible);
593
594 markDirty(UUID);
595}
596
597bool GeometryHandler::isPrimitiveVisible(size_t UUID) const {
598
599#ifdef HELIOS_DEBUG
600 assert(UUID_map.find(UUID) != UUID_map.end());
601#endif
602
603 const PrimitiveIndexMap &index_map = UUID_map.at(UUID);
604
605 const size_t visible_ind = index_map.visible_index;
606
607 return static_cast<bool>(visible_flag_data.at(index_map.geometry_type).at(visible_ind));
608}
609
610const std::vector<char> *GeometryHandler::getVisibilityFlagData_ptr(VisualizerGeometryType geometry_type) const {
611#ifdef HELIOS_DEBUG
612 assert(visible_flag_data.find(geometry_type) != visible_flag_data.end());
613#endif
614 return &visible_flag_data.at(geometry_type);
615}
616
617const std::vector<int> *GeometryHandler::getCoordinateFlagData_ptr(VisualizerGeometryType geometry_type) const {
618#ifdef HELIOS_DEBUG
619 assert(coordinate_flag_data.find(geometry_type) != coordinate_flag_data.end());
620#endif
621 return &coordinate_flag_data.at(geometry_type);
622}
623
624bool GeometryHandler::isSkyGeometry(size_t UUID) const {
625#ifdef HELIOS_DEBUG
626 assert(UUID_map.find(UUID) != UUID_map.end());
627#endif
628
629 const PrimitiveIndexMap &index_map = UUID_map.at(UUID);
630 const size_t sky_ind = index_map.sky_geometry_flag_index;
631
632 return static_cast<bool>(sky_geometry_flag_data.at(index_map.geometry_type).at(sky_ind));
633}
634
635const std::vector<char> *GeometryHandler::getSkyGeometryFlagData_ptr(VisualizerGeometryType geometry_type) const {
636#ifdef HELIOS_DEBUG
637 assert(sky_geometry_flag_data.find(geometry_type) != sky_geometry_flag_data.end());
638#endif
639 return &sky_geometry_flag_data.at(geometry_type);
640}
641
642void GeometryHandler::setSize(size_t UUID, float size) {
643
644#ifdef HELIOS_DEBUG
645 assert(UUID_map.find(UUID) != UUID_map.end());
646#endif
647
648 const PrimitiveIndexMap &index_map = UUID_map.at(UUID);
649
650 const size_t size_ind = index_map.size_index;
651
652 size_data[index_map.geometry_type].at(size_ind) = size;
653
654 markDirty(UUID);
655}
656
657float GeometryHandler::getSize(size_t UUID) const {
658
659#ifdef HELIOS_DEBUG
660 assert(UUID_map.find(UUID) != UUID_map.end());
661#endif
662
663 const PrimitiveIndexMap &index_map = UUID_map.at(UUID);
664
665 const size_t size_ind = index_map.size_index;
666
667 return size_data.at(index_map.geometry_type).at(size_ind);
668}
669
670const std::vector<float> *GeometryHandler::getSizeData_ptr(VisualizerGeometryType geometry_type) const {
671#ifdef HELIOS_DEBUG
672 assert(size_data.find(geometry_type) != size_data.end());
673#endif
674 return &size_data.at(geometry_type);
675}
676
677bool GeometryHandler::getDeleteFlag(size_t UUID) const {
678#ifdef HELIOS_DEBUG
679 assert(UUID_map.find(UUID) != UUID_map.end());
680#endif
681
682 const PrimitiveIndexMap &index_map = UUID_map.at(UUID);
683
684 const size_t delete_flag_ind = index_map.delete_flag_index;
685
686 return delete_flag_data.at(index_map.geometry_type).at(delete_flag_ind);
687}
688
690
691#ifdef HELIOS_DEBUG
692 assert(UUID_map.find(UUID) != UUID_map.end());
693#endif
694
695 const PrimitiveIndexMap &index_map = UUID_map.at(UUID);
696
697 delete_flag_data.at(index_map.geometry_type).at(index_map.delete_flag_index) = true;
698 visible_flag_data.at(index_map.geometry_type).at(index_map.visible_index) = false;
699
700 markDirty(UUID);
701
702 deleted_primitive_count++;
703
704 if (deleted_primitive_count > 250000) {
705 defragmentBuffers();
706 }
707}
708
709void GeometryHandler::deleteGeometry(const std::vector<size_t> &UUIDs) {
710 for (const auto &UUID: UUIDs) {
711 deleteGeometry(UUID);
712 }
713}
714
716
717 for (const auto &geometry_type: all_geometry_types) {
718 if (vertex_data.find(geometry_type) == vertex_data.end()) {
719 continue;
720 }
721
722 face_index_data.at(geometry_type).clear();
723 vertex_data.at(geometry_type).clear();
724 normal_data.at(geometry_type).clear();
725 uv_data.at(geometry_type).clear();
726 color_data.at(geometry_type).clear();
727 texture_flag_data.at(geometry_type).clear();
728 texture_ID_data.at(geometry_type).clear();
729 coordinate_flag_data.at(geometry_type).clear();
730 visible_flag_data.at(geometry_type).clear();
731 context_geometry_flag_data.at(geometry_type).clear();
732 sky_geometry_flag_data.at(geometry_type).clear();
733 delete_flag_data.at(geometry_type).clear();
734 size_data.at(geometry_type).clear();
735 }
736
737 UUID_map.clear();
738
739 deleted_primitive_count = 0;
740}
741
743
744 for (const auto &geometry_type: all_geometry_types) {
745 if (vertex_data.find(geometry_type) == vertex_data.end()) {
746 continue;
747 }
748
749 for (size_t i = 0; i < context_geometry_flag_data.at(geometry_type).size(); i++) {
750 assert(context_geometry_flag_data.at(geometry_type).size() == delete_flag_data.at(geometry_type).size());
751 if (context_geometry_flag_data.at(geometry_type).at(i)) {
752 delete_flag_data.at(geometry_type).at(i) = true;
753 // visible_flag_data.at(geometry_type).at(i) = false;
754 deleted_primitive_count++;
755 }
756 }
757 }
758
759 defragmentBuffers();
760}
761
763
764 xbounds.x = 1e8;
765 xbounds.y = -1e8;
766 ybounds.x = 1e8;
767 ybounds.y = -1e8;
768 zbounds.x = 1e8;
769 zbounds.y = -1e8;
770
771 for (const auto &[UUID, index_map]: UUID_map) {
772 // Only primitives with Cartesian coordinates should be included in bounding box
773 if (coordinate_flag_data.at(index_map.geometry_type).at(index_map.coordinate_flag_index) == 0) {
774 continue;
775 }
776
777 const auto &vertices = getVertices(UUID);
778
779 for (const auto &vertex: vertices) {
780 if (vertex.x < xbounds.x) {
781 xbounds.x = vertex.x;
782 }
783 if (vertex.x > xbounds.y) {
784 xbounds.y = vertex.x;
785 }
786 if (vertex.y < ybounds.x) {
787 ybounds.x = vertex.y;
788 }
789 if (vertex.y > ybounds.y) {
790 ybounds.y = vertex.y;
791 }
792 if (vertex.z < zbounds.x) {
793 zbounds.x = vertex.z;
794 }
795 if (vertex.z > zbounds.y) {
796 zbounds.y = vertex.z;
797 }
798 }
799 }
800}
801
803
804 helios::vec2 xbounds, ybounds, zbounds;
805 getDomainBoundingBox(xbounds, ybounds, zbounds);
806
807 radius = {0.5f * (xbounds.y - xbounds.x), 0.5f * (ybounds.y - ybounds.x), 0.5f * (zbounds.y - zbounds.x)};
808
809 center = {xbounds.x + radius.x, ybounds.x + radius.y, zbounds.x + radius.z};
810}
811
813 std::uniform_int_distribution<size_t> dist(1, (std::numeric_limits<size_t>::max)());
814 size_t UUID = 0;
815 while (UUID == 0 || UUID_map.find(UUID) != UUID_map.end()) {
816 UUID = dist(random_generator);
817 }
818 return UUID;
819}
820
821const GeometryHandler::PrimitiveIndexMap &GeometryHandler::getIndexMap(size_t UUID) const {
822#ifdef HELIOS_DEBUG
823 assert(UUID_map.find(UUID) != UUID_map.end());
824#endif
825 return UUID_map.at(UUID);
826}
827
828void GeometryHandler::defragmentBuffers() {
829
830 // If no primitives were deleted, nothing to do
831 if (deleted_primitive_count == 0) {
832 return;
833 }
834
835 // Iterate each geometry type
836
837 for (const auto &geometry_type: all_geometry_types) {
838 if (vertex_data.find(geometry_type) == vertex_data.end()) {
839 continue;
840 }
841
842 auto &oldFace = face_index_data.at(geometry_type);
843 auto &oldVertex = vertex_data.at(geometry_type);
844 auto &oldNormal = normal_data.at(geometry_type);
845 auto &oldUV = uv_data.at(geometry_type);
846 auto &oldColor = color_data.at(geometry_type);
847 auto &oldTexFlag = texture_flag_data.at(geometry_type);
848 auto &oldTexID = texture_ID_data.at(geometry_type);
849 auto &oldCoordFlag = coordinate_flag_data.at(geometry_type);
850 auto &oldVisible = visible_flag_data.at(geometry_type);
851 auto &oldContextFlag = context_geometry_flag_data.at(geometry_type);
852 auto &oldSkyFlag = sky_geometry_flag_data.at(geometry_type);
853 auto &oldDeleteFlag = delete_flag_data.at(geometry_type);
854 auto &oldSize = size_data.at(geometry_type);
855
856 // New buffers
857 std::vector<VisualizerGeometryType> newType;
858 std::vector<float> newVertex, newNormal, newUV, newColor, newSize;
859 std::vector<int> newFace, newTexFlag, newTexID, newCoordFlag;
860 std::vector<bool> newDeleteFlag, newContextFlag;
861 std::vector<char> newVisible, newSkyFlag;
862
863 // Collect UUIDs to drop
864 std::vector<size_t> toErase;
865
866 // Walk the UUID_map and rebuild entries
867 for (auto &[UUID, prim]: UUID_map) {
868 if (prim.geometry_type != geometry_type) {
869 continue; // this UUID is another geometry type
870 }
871
872 // If marked deleted => drop
873 if (oldDeleteFlag[prim.delete_flag_index]) {
874 toErase.push_back(UUID);
875 continue;
876 }
877
878 // Otherwise copy its slices into the new buffers
879 const char vcount = getVertexCount(prim.geometry_type);
880 const size_t v3 = static_cast<size_t>(vcount) * 3;
881 const size_t v2 = static_cast<size_t>(vcount) * 2;
882
883 // Record new base indices
884 const size_t fi = newFace.size();
885 const size_t vi = newVertex.size();
886 const size_t ni = newNormal.size();
887 const size_t ui = newUV.size();
888 const size_t ci = newColor.size();
889 const size_t tfi = newTexFlag.size();
890 const size_t tidi = newTexID.size();
891 const size_t cfi = newCoordFlag.size();
892 const size_t vi2 = newVisible.size();
893 const size_t cfi2 = newContextFlag.size();
894 const size_t sfi = newSkyFlag.size();
895 const size_t dfi = newDeleteFlag.size();
896 const size_t si = newSize.size();
897
898 // Copy raw data
899 newFace.insert(newFace.end(), vcount, scast<int>(newVisible.size())); // the new face index should be the new index not just copying the previous value. Note that we take the size of newVisible, but could be any per-face array size.
900
901 newVertex.insert(newVertex.end(), oldVertex.begin() + prim.vertex_index, oldVertex.begin() + prim.vertex_index + v3);
902
903 newNormal.insert(newNormal.end(), oldNormal.begin() + prim.normal_index, oldNormal.begin() + prim.normal_index + 3);
904
905 newUV.insert(newUV.end(), oldUV.begin() + prim.uv_index, oldUV.begin() + prim.uv_index + v2);
906
907 newColor.insert(newColor.end(), oldColor.begin() + prim.color_index, oldColor.begin() + prim.color_index + 4);
908
909 newTexFlag.push_back(oldTexFlag[prim.texture_flag_index]);
910 newTexID.push_back(oldTexID[prim.texture_ID_index]);
911 newCoordFlag.push_back(oldCoordFlag[prim.coordinate_flag_index]);
912 newVisible.push_back(oldVisible[prim.visible_index]);
913 newContextFlag.push_back(oldContextFlag[prim.context_geometry_flag_index]);
914 newSkyFlag.push_back(oldSkyFlag[prim.sky_geometry_flag_index]);
915 newDeleteFlag.push_back(oldDeleteFlag[prim.delete_flag_index]);
916 newSize.push_back(oldSize[prim.size_index]);
917
918 // Update the map entry to point at the new positions
919 prim.face_index_index = fi;
920 prim.vertex_index = vi;
921 prim.normal_index = ni;
922 prim.uv_index = ui;
923 prim.color_index = ci;
924 prim.texture_flag_index = tfi;
925 prim.texture_ID_index = tidi;
926 prim.coordinate_flag_index = cfi;
927 prim.visible_index = vi2;
928 prim.context_geometry_flag_index = cfi2;
929 prim.sky_geometry_flag_index = sfi;
930 prim.delete_flag_index = dfi;
931 prim.size_index = si;
932 }
933
934 // Erase deleted UUIDs
935 for (auto UUID: toErase) {
936 UUID_map.erase(UUID);
937 }
938
939 // Swap into place
940 oldFace.swap(newFace);
941 oldVertex.swap(newVertex);
942 oldNormal.swap(newNormal);
943 oldUV.swap(newUV);
944 oldColor.swap(newColor);
945 oldTexFlag.swap(newTexFlag);
946 oldTexID.swap(newTexID);
947 oldCoordFlag.swap(newCoordFlag);
948 oldVisible.swap(newVisible);
949 oldContextFlag.swap(newContextFlag);
950 oldSkyFlag.swap(newSkyFlag);
951 oldDeleteFlag.swap(newDeleteFlag);
952 oldSize.swap(newSize);
953 }
954
955 // Reset deleted count
956 deleted_primitive_count = 0;
957}
958
959void GeometryHandler::registerUUID(size_t UUID, const VisualizerGeometryType &geometry_type) {
960
961 UUID_map[UUID] = {geometry_type,
962 face_index_data.at(geometry_type).size(),
963 vertex_data.at(geometry_type).size(),
964 normal_data.at(geometry_type).size(),
965 uv_data.at(geometry_type).size(),
966 color_data.at(geometry_type).size(),
967 texture_flag_data.at(geometry_type).size(),
968 texture_ID_data.at(geometry_type).size(),
969 coordinate_flag_data.at(geometry_type).size(),
970 visible_flag_data.at(geometry_type).size(),
971 context_geometry_flag_data.at(geometry_type).size(),
972 sky_geometry_flag_data.at(geometry_type).size(),
973 delete_flag_data.at(geometry_type).size(),
974 size_data.at(geometry_type).size()};
975}
976
978
979 switch (geometry_type) {
980 case GEOMETRY_TYPE_RECTANGLE:
981 return 4;
982 case GEOMETRY_TYPE_TRIANGLE:
983 return 3;
984 case GEOMETRY_TYPE_POINT:
985 return 1;
986 case GEOMETRY_TYPE_LINE:
987 return 2;
988 default:
989 assert(true);
990 return 0;
991 }
992}
993
994void GeometryHandler::markDirty(size_t UUID) {
995 dirty_UUIDs.insert(UUID);
996}
997
998const std::unordered_set<size_t> &GeometryHandler::getDirtyUUIDs() const {
999 return dirty_UUIDs;
1000}
1001
1003 dirty_UUIDs.clear();
1004}