NDEVR
API Documentation
BlockModelRaster.h
1#pragma once
2#include "BlockModel/Headers/CubeTriangulation.h"
3#include "NDEVRSurfacing/Headers/GeometrySurfacing.h"
4#include "Design/Headers/Geometry.h"
5#include "Base/Headers/Vector.hpp"
6#include "Base/Headers/Buffer.hpp"
7#include "Base/Headers/BaseFunctions.hpp"
8namespace NDEVR
9{
13 template<uint04 t_size, class t_index_type>
14 struct BlockLookupNode
15 {
16 static_assert(sizeof(t_index_type) < t_size * t_size * t_size, "Invalid size for indexing");
17 BlockLookupNode()
18 {
19 for (uint04 i = 0; i < t_size * t_size * t_size; i++)
20 indices[i] = Constant<t_index_type>::Invalid;
21 }
22 static constexpr t_index_type ConvertToIndex(Vector<3, t_index_type> location)
23 {
24 if constexpr (t_size == 8)
25 return (location[Z] << 6) + (location[Y] << 3) + location[X];
26 else
27 return t_size * (t_size * location[Z] + location[Y]) + location[X];
28 }
29 static constexpr t_index_type ConvertToIndex(t_index_type x, t_index_type y, t_index_type z)
30 {
31 if constexpr (t_size == 8)
32 return (z << 6) + (y << 3) + x;
33 else
34 return t_size * (t_size * z + y) + x;
35 }
36 static constexpr Vector<3, t_index_type> ConvertFromIndex(t_index_type location)
37 {
38 Vector<3, t_index_type> vec_location;
39 if constexpr (t_size == 8)
40 {
41 vec_location[Z] = location >> 6;
42 vec_location[Y] = (location >> 3) % t_size;
43 vec_location[X] = location % t_size;
44 }
45 else
46 {
47 vec_location[Z] = location / (t_size * t_size);
48 vec_location[Y] = (location / t_size) % t_size;
49 vec_location[X] = location % t_size;
50 }
51 return vec_location;
52 }
53 inline t_index_type get(Vector<3, t_index_type> location) const
54 {
55 return indices[ConvertToIndex(location)];
56 }
57 inline t_index_type set(Vector<3, t_index_type> location, t_index_type index)
58 {
59 return indices[ConvertToIndex(location)] = index;
60 }
61 void clear()
62 {
63 for (uint04 i = 0; i < t_size * t_size * t_size; i++)
64 indices[i] = Constant<t_index_type>::Invalid;
65 }
66 t_index_type indices[t_size * t_size * t_size];
67 };
68
71 template<uint04 t_size, class t_index_type>
72 struct BlockLookupList : public BlockLookupNode<t_size, t_index_type>
73 {
75 };
76 template<uint04 t_size, class t_index_type>
77 struct ObjectInfo<BlockLookupNode<t_size, t_index_type>, false, true>
78 {
79 static const uint01 Dimensions = 0;
80 static const bool Vector = true;
81 static const bool Buffer = true;
82 static const bool Primitive = true;
83 static const bool Pointer = false;
84 static const bool Unsigned = false;
85 static const bool Float = false;
86 static const bool Integer = false;
87 static const bool Number = false;
88 static const bool Enum = false;
89 static const bool String = true;
90 static const bool Color = false;
91 static const bool Boolean = false;
92 static constexpr ObjectInfo<uint01, false, false> VectorSub() { return ObjectInfo<uint01, false, false>(); }
93 };
97 template<class t_point_type, class t_weight_type>
98 struct BlockModelCache
99 {
100 BlockModelCache(uint08 weight_cutoff)
101 : weight_cutoff(weight_cutoff)
102 {}
103 Buffer<Vector<3, uint04>> geo_add_locations;
104 Buffer<t_point_type> geo_add_info;
105 Buffer<t_weight_type> geo_add_weight;
106 Bounds<1, uint04> position_update_bounds = Constant<Bounds<1, uint04>>::Min;
107 Bounds<1, uint04> color_update_bounds = Constant<Bounds<1, uint04>>::Min;
108 Bounds<1, uint04> normal_update_bounds = Constant<Bounds<1, uint04>>::Min;
109 Bounds<1, uint04> weight_update_bounds = Constant<Bounds<1, uint04>>::Min;
110 Bounds<1, uint04> primitive_update_bounds = Constant<Bounds<1, uint04>>::Min;
111 Bounds<1, uint04> flag_update_bounds = Constant<Bounds<1, uint04>>::Min;
112 uint08 weight_cutoff;
113 uint08 weight_max_capacity = Constant<uint08>::Min;
114 };
115
118 template<class t_point_type, class t_weight_type>
119 struct BlockModelGeometryCache : public BlockModelCache<t_point_type, t_weight_type>
120 {
121 BlockModelGeometryCache(Geometry geo, uint08 weight_cutoff, const void* lock_ptr)
122 : BlockModelCache<t_point_type, t_weight_type>(weight_cutoff)
123 , geo(geo)
124 , position_column(geo.column(VertexProperty::Position))
125 , normal_column(t_point_type::HasNormal() ? geo.column(VertexProperty::Normal) : geo.column(VertexProperty::Position))
126 , color_column(t_point_type::HasColor() ? geo.column(VertexProperty::Color) : geo.column(VertexProperty::Position))
127 , flag_column([&geo]()->TableColumn& { geo.ensureFlagColumnExists(); return geo.column(VertexProperty::BitFlag); }())
128 , weight_column(geo.propertyColumn("intensity"))
129 , geo_vertex_offset(geo.vertexOffset())
130 , geo_vertex_add_offset(geo.vertexCount())
131 , lock_ptr(lock_ptr)
132 {}
133
134 Geometry geo;
135 TableColumn& position_column;
136 TableColumn& normal_column;
137 TableColumn& color_column;
138 TableColumn& flag_column;
139 TableColumn& weight_column;
140 uint04 geo_vertex_offset;
141 uint04 geo_vertex_add_offset;
142 const void* lock_ptr;
143 };
144
148 template<class t_point_type, class t_weight_type>
149 class BlockModelFilteringCache
150 {
151 public:
152 BlockModelFilteringCache() {}
153 virtual ~BlockModelFilteringCache() {}
154 virtual bool shouldFilter(const Vertex<3, uint04>& location, const t_point_type& node, t_weight_type weight) const = 0;
155 virtual void onFiltered(const Vertex<3, uint04>& location, const t_point_type& node, t_weight_type weight) const = 0;
156 virtual IntersectionTypes classifyToFilter(const Bounds<3, uint04>& value) const = 0;
157 };
158
162 template<class t_point_type, uint04 t_size, class t_weight_type>
163 class BlockModelRaster : public BlockLookupNode<t_size, uint04>
164 {
165 public:
166 class RasterBuffer
167 {
168 public:
169 inline BlockModelRaster<t_point_type, t_size, t_weight_type>& operator[](uint04 index)
170 {
171 uint04 size = m_safe_rasters.size();
172 if (index < size)
173 return m_safe_rasters[index];
174 else
175 return m_edit_rasters[index - size];
176 }
177 inline const BlockModelRaster<t_point_type, t_size, t_weight_type>& operator[](uint04 index) const
178 {
179 uint04 size = m_safe_rasters.size();
180 if (index < size)
181 return m_safe_rasters[index];
182 else
183 return m_edit_rasters[index - size];
184 }
185
186 inline void init()
187 {
188 m_safe_rasters.ensureCapacity(t_size * t_size * t_size);
189 m_edit_rasters.ensureCapacity(t_size * t_size);
190 }
191 void clear()
192 {
193 m_safe_rasters.clear();
194 m_edit_rasters.clear();
195 }
196 inline void add(const BlockModelRaster<t_point_type, t_size, t_weight_type>& value)
197 {
198 if (m_safe_rasters.capacity() > m_safe_rasters.size())
199 m_safe_rasters.add(value);
200 else
201 m_edit_rasters.add(value);
202 }
203 inline void sync()
204 {
205 if (m_edit_rasters.size() == 0)
206 return;//no new rasters
207
208 m_adding_cache = true;
209 if (!m_using_safe)
210 m_safe_rasters.ensureCapacity(((m_safe_rasters.size() * 3) / 2) + 4U * m_edit_rasters.size());
211 m_adding_cache = false;
212 uint04 safe_initial_size = m_safe_rasters.size();
213 uint04 available_space = m_safe_rasters.capacity() - safe_initial_size;
214 if (available_space == 0)
215 return;//no available memory
216 const uint04 add_size = getMin<uint04>(available_space, m_edit_rasters.size());
217 m_safe_rasters.template addSpace<false>(add_size);
218 for (uint04 i = 0; i < add_size; i++)
219 m_safe_rasters[safe_initial_size + i] = m_edit_rasters[i];
220 m_edit_rasters.removeIndices(0, add_size);
221 }
222 inline uint04 size() const
223 {
224 return m_safe_rasters.size() + m_edit_rasters.size();
225 }
226 inline uint04 safeSize() const
227 {
228 return m_safe_rasters.size();
229 }
230 inline bool requestUsingSafe(bool using_safe)
231 {
232 if (using_safe)
233 {
234 m_using_safe = true;
235 if (m_adding_cache)
236 {
237 m_using_safe = false;
238 return false;
239 }
240 }
241 m_using_safe = using_safe;
242 return true;
243 }
244 inline void forceUsingSafe()
245 {
246 m_using_safe = true;
247 for (;;)
248 {
249 if (!m_adding_cache)
250 break;
251 }
252 }
253 protected:
254 PrimitiveBuffer<BlockModelRaster<t_point_type, t_size, t_weight_type>> m_safe_rasters;
255 PrimitiveBuffer<BlockModelRaster<t_point_type, t_size, t_weight_type>> m_edit_rasters;
256 volatile bool m_adding_cache = false;
257 volatile bool m_using_safe = false;
258 };
259 struct SurfacingCache
260 {
261 SurfacingCache(GeometrySurfacingParameters& parameters, const RasterBuffer& rasters)
262 : grid(t_size, t_size, t_size)
263 , mc33(grid)
264 , parameters(parameters)
265 , rasters(rasters)
266 {}
268 MC33<t_point_type> mc33;
269 GeometrySurfacingParameters& parameters;
270 const RasterBuffer& rasters;
271 t_weight_type weight_cutoff;
272 };
273 struct RasterNode
274 {
275 RasterNode(BlockModelRaster<t_point_type, t_size, t_weight_type>& geo, uint04 initial_reserve_count)
276 : raster(geo)
277 , vertex_index(initial_reserve_count)
278 {}
279 inline void updateColorAverage(const RGBColor color, uint08 weight)
280 {
281 raster.updateColorAverage(vertex_index, color, weight);
282 }
283 BlockModelRaster<t_point_type, t_size, t_weight_type>& raster;
284 uint04 vertex_index;
285 };
286 BlockModelRaster(const Vector<3, uint04>& location)
287 : location(location)
288 {
289 for (uint04 i = 0; i < Size(); i++)
290 weight_information[i] = t_weight_type(0U);
291 }
292 Bounds<3, uint04> bounds() const
293 {
294 return Bounds<3, uint04>(location, location + t_size);
295 }
296 inline void updateColorAverage(uint04 index, const t_point_type color)
297 {
298 if (weight_information[index] == 0)
299 point_count++;
300 else if (weight_information[index] >= (Constant<t_weight_type>::Max >> 8))
301 return;//Buffer full
302 node_information[index] += color;
303 weight_information[index]++;
304 is_dirty = true;
305 }
306 inline void updateColorAverage(uint04 index, const t_point_type color, t_weight_type weight)
307 {
308 if (weight == 0)
309 return;
310 if (weight_information[index] == 0)
311 point_count++;
312 t_weight_type new_weight = weight_information[index] + weight;
313 if (new_weight > (Constant<t_weight_type>::Max >> 8))
314 return;//Buffer full
315 node_information[index] = combine(node_information[index], weight_information[index], color, weight);
316 weight_information[index] = new_weight;
317 is_dirty = true;
318 }
319 inline void addWeight(uint04 index, t_weight_type weight)
320 {
321 if (weight_information[index] == 0)
322 return;//cant add weight to something that doesn't yet exist
323 weight_information[index] += weight;
324 is_dirty = true;
325 }
326 inline void subtractWeight(uint04 index, t_weight_type weight)
327 {
328 if (weight_information[index] == 0)
329 return;
330 weight_information[index] = getMin(weight_information[index], weight);
331 if (weight_information[index] == 0)
332 point_count--;
333 is_dirty = true;
334 }
335 inline void removeIndex(uint04 index)
336 {
337 if (weight_information[index] == 0)
338 return;
339 node_information[index] = t_point_type();
340 weight_information[index] = t_weight_type(0U);
341 point_count--;
342 is_dirty = true;
343 }
344 inline void clearAll()
345 {
346 for (uint04 i = 0; i < Size(); i++)
347 {
348 weight_information[i] = t_weight_type(0U);
349 node_information[i] = t_point_type();
350 }
351 point_count = 0;
352 is_dirty = true;
353 }
354 inline t_point_type colorAt(uint04 index) const
355 {
356 return node_information[index];
357 }
358 template<class t_special_weight_type>
359 inline void getWeightAndColor(uint04 x, uint04 y, uint04 z, const RasterBuffer& rasters, t_point_type& color, t_special_weight_type& value)
360 {
361 const Vector<3, uint04> index_offset(x % t_size, y % t_size, z % t_size);
362 const uint04 index = BlockLookupNode<t_size, uint04>::ConvertToIndex(index_offset);
363 t_weight_type weight(0U);
364 t_point_type point;
365 if (x >= t_size)
366 {
367 if (y >= t_size)
368 {
369 if (z >= t_size)
370 {
371 if (IsValid(corner_tri_neighbor))
372 {
373 weight = rasters[corner_tri_neighbor].weight_information[index];
374 point = rasters[corner_tri_neighbor].node_information[index];
375 }
376 }
377 else
378 {
379 if (IsValid(corner_neighbors[Z]))
380 {
381 weight = rasters[corner_neighbors[Z]].weight_information[index];
382 point = rasters[corner_neighbors[Z]].node_information[index];
383 }
384 }
385 }
386 else if (z >= t_size)
387 {
388 if (IsValid(corner_neighbors[Y]))
389 {
390 weight = rasters[corner_neighbors[Y]].weight_information[index];
391 point = rasters[corner_neighbors[Y]].node_information[index];
392 }
393 }
394 else
395 {
396 if (IsValid(upper_neighbors[X]))
397 {
398 weight = rasters[upper_neighbors[X]].weight_information[index];
399 point = rasters[upper_neighbors[X]].node_information[index];
400 }
401 }
402 }
403 else if (y >= t_size)
404 {
405 if (z >= t_size)
406 {
407 if (IsValid(corner_neighbors[X]))
408 {
409 weight = rasters[corner_neighbors[X]].weight_information[index];
410 point = rasters[corner_neighbors[X]].node_information[index];
411 }
412 }
413 else
414 {
415 if (IsValid(upper_neighbors[Y]))
416 {
417 weight = rasters[upper_neighbors[Y]].weight_information[index];
418 point = rasters[upper_neighbors[Y]].node_information[index];
419 }
420 }
421 }
422 else if (z >= t_size)
423 {
424 if (IsValid(upper_neighbors[Z]))
425 {
426 weight = rasters[upper_neighbors[Z]].weight_information[index];
427 point = rasters[upper_neighbors[Z]].node_information[index];
428 }
429 }
430 else
431 {
432 weight = weight_information[index];
433 point = node_information[index];
434 }
435 if (weight == 0)
436 {
437 color = t_point_type();
438 value = t_special_weight_type(0);
439 }
440 else
441 {
442 color = point;
443 value = t_special_weight_type(weight);
444 }
445 }
446 inline void calculateTriangulation(SurfacingCache& cache)
447 {
448 if (point_count == 0)
449 return;
450 for (uint04 z = 0; z < t_size; z++)
451 {
452 for (uint04 y = 0; y < t_size; y++)
453 {
454 for (uint04 x = 0; x < t_size; x++)
455 {
456 const uint04 index = BlockLookupNode<t_size, uint04>::ConvertToIndex(x, y, z);
457 cache.grid.nodes[x][y][z] = node_information[index];
458 cache.grid.values[x][y][z] = cast<GRD_data_type>(weight_information[index]);
459 }
460
461 getWeightAndColor(t_size, y, z, cache.rasters, cache.grid.nodes[t_size][y][z], cache.grid.values[t_size][y][z]);
462 }
463 for (uint04 x = 0; x < t_size + 1; x++)
464 getWeightAndColor(x, t_size, z, cache.rasters, cache.grid.nodes[x][t_size][z], cache.grid.values[x][t_size][z]);
465 }
466 for (uint04 y = 0; y < t_size + 1; y++)
467 {
468 for (uint04 x = 0; x < t_size + 1; x++)
469 {
470 getWeightAndColor(x, y, t_size, cache.rasters, cache.grid.nodes[x][y][t_size], cache.grid.values[x][y][t_size]);
471 }
472 }
473 for (uint04 i = 0; i < 2; i++)
474 {
475 for (uint04 z = 0; z < t_size + 1; z++)
476 {
477 for (uint04 y = 0; y < t_size + 1; y++)
478 {
479 for (uint04 x = 0; x < t_size + 1; x++)
480 {
481 if (cache.grid.values[x][y][z] == 0)
482 {
483 if (z < t_size && cache.grid.values[x][y][z + 1] != 0)
484 {
485 cache.grid.nodes[x][y][z] = cache.grid.nodes[x][y][z + 1];
486 }
487 else if (y < t_size && cache.grid.values[x][y + 1][z] != 0)
488 {
489 cache.grid.nodes[x][y][z] = cache.grid.nodes[x][y + 1][z];
490 }
491 else if (x < t_size && cache.grid.values[x + 1][y][z] != 0)
492 {
493 cache.grid.nodes[x][y][z] = cache.grid.nodes[x + 1][y][z];
494 }
495 else if (z > 0 && cache.grid.values[x][y][z - 1] != 0)
496 {
497 cache.grid.nodes[x][y][z] = cache.grid.nodes[x][y][z - 1];
498 }
499 else if (y > 0 && cache.grid.values[x][y - 1][z] != 0)
500 {
501 cache.grid.nodes[x][y][z] = cache.grid.nodes[x][y - 1][z];
502 }
503 else if (x > 0 && cache.grid.values[x - 1][y][z] != 0)
504 {
505 cache.grid.nodes[x][y][z] = cache.grid.nodes[x - 1][y][z];
506 }
507 }
508 }
509 }
510 }
511 }
512 //cache.grid.smooth();
513 //cache.grid.smooth();
514 CubeTriangulation::calculate_isosurface(cache.mc33, cast<fltp04>(cache.weight_cutoff) - 0.1f);
515
516 uint04 vertex_offset = cache.parameters.surface_positions.size();
517 cache.parameters.surface_positions.template addSpace<true>(cache.mc33.nV);
518 //cache.parameters.surface_normals.template addSpace<true>(cache.mc33.nV);
519 if constexpr (t_point_type::HasColor())
520 cache.parameters.surface_colors.template addSpace<true>(cache.mc33.nV);
521 Vertex<3, fltp04> location_f = location.as<3, fltp04>();
522
523 for (uint04 i = 0; i < cache.mc33.nV; i++)
524 {
525 Vertex<3, fltp04> location_offset(cache.mc33.V[i][2], cache.mc33.V[i][1], cache.mc33.V[i][0]);
526 if constexpr (t_point_type::HasColor())
527 cache.parameters.surface_colors[i + vertex_offset] = cache.mc33.C[i].color();
528 cache.parameters.surface_positions[i + vertex_offset] = location_f + location_offset;
529 if constexpr (t_point_type::HasOffset())
530 cache.parameters.surface_positions[i + vertex_offset] += cache.mc33.C[i].offset();
531 //cache.parameters.surface_normals[i + vertex_offset] = Ray<3, fltp04>(cache.mc33.N[i][2], cache.mc33.N[i][1], cache.mc33.N[i][0]);
532 }
533 uint04 tri_offset = cache.parameters.surface_triangles.size();
534 cache.parameters.surface_triangles.template addSpace<true>(cache.mc33.nT);
535 for (uint04 i = 0; i < cache.mc33.nT; i++)
536 {
537 Vector<3, uint04> tri(cache.mc33.T[i][0], cache.mc33.T[i][1], cache.mc33.T[i][2]);
538 if (IsValid(tri))
539 tri += vertex_offset;
540 else
541 tri = Constant<Vector<3, uint04>>::Invalid;
542 cache.parameters.surface_triangles[i + tri_offset] = tri;
543 }
544 }
545 inline bool isVertexValid(uint04 x, uint04 y, uint04 z)
546 {
547 BlockLookupNode<t_size, t_weight_type>::indices[BlockLookupNode<t_size, uint04>::ConvertToIndex(x, y, z)] > 0;
548 }
549 template<bool t_set_indices>
550 inline void collectAllPositions(BlockModelCache<t_point_type, t_weight_type>& cache) noexcept
551 {
552 if (point_count == 0)
553 return;
554 if (t_set_indices)
555 is_dirty = false;
556 for (uint04 i = 0; i < Size(); i++)
557 {
558 if (weight_information[i] >= cache.weight_cutoff)
559 {
560 if constexpr (t_set_indices)
561 BlockLookupNode<t_size, t_weight_type>::indices[i] = cache.geo_add_locations.size();
562 cache.geo_add_locations.add((location + BlockLookupNode<t_size, uint04>::ConvertFromIndex(i)));
563 cache.geo_add_info.add(node_information[i]);
564 cache.geo_add_weight.add(weight_information[i]);
565 }
566 }
567 }
568 inline void collectNewPositions(BlockModelGeometryCache<t_point_type, t_weight_type>& cache) noexcept
569 {
570 if (!is_dirty || point_count == 0)
571 return;
572 for (uint04 i = 0; i < Size(); i++)
573 {
574 if (weight_information[i] >= cache.weight_cutoff)
575 {
576 if (IsInvalid(BlockLookupNode<t_size, t_weight_type>::indices[i]))
577 {
578 BlockLookupNode<t_size, t_weight_type>::indices[i] = cache.geo_vertex_add_offset + cache.geo_add_locations.size();
579 cache.geo_add_locations.add((location + BlockLookupNode<t_size, uint04>::ConvertFromIndex(i)));
580 cache.geo_add_info.add(node_information[i]);
581 cache.geo_add_weight.add(weight_information[i]);
582 }
583 }
584 }
585 }
586 inline bool filterGeometries(BlockModelFilteringCache<t_point_type, t_weight_type>& filter) noexcept
587 {
588 if (point_count == 0)
589 return false;
590 switch (filter.classifyToFilter(bounds()))
591 {
592 case IntersectionTypes::e_outside:
593 return false;
594 case IntersectionTypes::e_inside:
595 {
596 //find the points that need to be filtered
597 for (uint04 i = 0; i < Size(); i++)
598 {
599 if (weight_information[i] > 0)
600 {
601 Vector<3, uint04> vertex_location = (BlockLookupNode<t_size, uint04>::ConvertFromIndex(i) + location);
602 filter.onFiltered(vertex_location, node_information[i], weight_information[i]);
603 node_information[i] = t_point_type();
604 weight_information[i] = cast<t_weight_type>(0U);
605 }
606 }
607 point_count = 0;
608 is_dirty = true;
609 return true;
610 } break;
611 case IntersectionTypes::e_mixed:
612 {
613 for (uint04 i = 0; i < Size(); i++)
614 {
615 if (weight_information[i] > 0)
616 {
617 Vector<3, uint04> vertex_location = (BlockLookupNode<t_size, uint04>::ConvertFromIndex(i) + location);
618 if (filter.shouldFilter(vertex_location, node_information[i], weight_information[i]))
619 {
620 filter.onFiltered(vertex_location, node_information[i], weight_information[i]);
621 node_information[i] = t_point_type();
622 weight_information[i] = cast<t_weight_type>(0U);
623 point_count--;
624 is_dirty = true;
625 }
626 }
627 }
628 return is_dirty;
629 } break;
630 }
631 return false;
632 }
633 inline void updateGeometryVertices(BlockModelGeometryCache<t_point_type, t_weight_type>& cache)
634 {
635 if (!is_dirty || IsInvalid(cache.geo_vertex_offset))
636 return;
637 //WLock lock(cache.lock_ptr);
638 is_dirty = false;
639 BitFlag filtered_flag(0);
640 filtered_flag(cast<uint01>(VertexFlags::e_is_filtered), true);
641 filtered_flag(cast<uint01>(VertexFlags::e_is_hidden), true);
642 for (uint04 i = 0; i < Size(); i++)
643 {
644 const uint04 vert_index = BlockLookupNode<t_size, uint04>::indices[i] + cache.geo_vertex_offset;
645 if (weight_information[i] >= cache.weight_cutoff)
646 {
647 if (IsInvalid(vert_index))
648 continue;//Will collect this next round
649
650 if constexpr (t_point_type::HasOffset())
651 {
652 Vector<3, fltp04> position = (location + BlockLookupNode<t_size, uint04>::ConvertFromIndex(i)).template as<3, fltp04>() + node_information[i].offset();
653 if (position != cache.position_column.template get<Vector<3, fltp04>>(vert_index))
654 {
655 cache.position_column.set(vert_index, position);
656 cache.position_update_bounds.addToBounds(vert_index);
657 }
658 }
659 if constexpr (t_point_type::HasColor())
660 {
661 RGBColor color = node_information[i].color();
662 if (color != cache.color_column.template get<RGBColor>(vert_index))
663 {
664 cache.color_column.set(vert_index, color);
665 cache.color_update_bounds.addToBounds(vert_index);
666 }
667 }
668 if constexpr (t_point_type::HasNormal())
669 {
670 Ray<3, fltp04> normal = node_information[i].normal();
671 if (normal != cache.normal_column.template get<Ray<3, fltp04>>(vert_index))
672 {
673 cache.normal_column.set(vert_index, normal);
674 cache.normal_update_bounds.addToBounds(vert_index);
675 }
676 }
677 fltp04 weight = cast<fltp04>(weight_information[i]);
678 if (weight != cache.weight_column.template get<fltp04>(vert_index))
679 {
680 cache.weight_column.set(vert_index, weight);
681 cache.weight_update_bounds.addToBounds(vert_index);
682 }
683 if (0 != cache.flag_column.template get<uint01>(vert_index))
684 {
685 cache.flag_column.set(vert_index, 0U);
686 cache.flag_update_bounds.addToBounds(vert_index);
687 }
688 }
689 else if (IsValid(vert_index))
690 {
691 if (filtered_flag != BitFlag(cache.flag_column.template get<uint01>(vert_index)))
692 {
693 cache.flag_column.set(vert_index, filtered_flag);
694 cache.flag_update_bounds.addToBounds(vert_index);
695 }
696 }
697 }
698 }
699 constexpr static uint04 Size() { return t_size * t_size * t_size; }
700 t_point_type node_information[t_size * t_size * t_size];
701 t_weight_type weight_information[t_size * t_size * t_size];
702 Vector<3, uint04> location;
703
704 Vector<3, uint04> upper_neighbors = Constant<Vector<3, uint04>>::Invalid;
705 Vector<3, uint04> corner_neighbors = Constant<Vector<3, uint04>>::Invalid;
706 uint04 corner_tri_neighbor = Constant<uint04>::Invalid;
707 bool is_dirty = false;
708 uint04 point_count = 0;
709 };
710 template<class t_point_type, uint04 t_size, class t_weight_type>
711 struct ObjectInfo<BlockModelRaster<t_point_type, t_size, t_weight_type>, false, true>
712 {
713 static const uint01 Dimensions = 0;
714 static const bool Vector = true;
715 static const bool Buffer = true;
716 static const bool Primitive = true;
717 static const bool Pointer = false;
718 static const bool Unsigned = false;
719 static const bool Float = false;
720 static const bool Integer = false;
721 static const bool Number = false;
722 static const bool Enum = false;
723 static const bool String = true;
724 static const bool Color = false;
725 static const bool Boolean = false;
726 static constexpr ObjectInfo<uint01, false, false> VectorSub() { return ObjectInfo<uint01, false, false>(); }
727 };
732 constexpr uint04 cipow(uint04 num, uint04 pow)
733 {
734 return (pow >= sizeof(unsigned int) * 8) ? 0 :
735 pow == 0 ? 1 : num * cipow(num, pow - 1);
736 }
737}
A bitset that stores 8 bits (elements with only two possible values: 0 or 1, true or false,...
Definition BitFlag.hpp:55
Abstract cache interface for filtering block model raster data based on spatial criteria.
A single raster tile of a block model, storing point data, weights, and surfacing support.
A specification of upper and lower bounds in N-dimensions.
Definition Bounds.hpp:54
constexpr void addToBounds(const t_vertex &vector)
Definition Bounds.hpp:415
The equivelent of std::vector but with a bit more control.
Definition Buffer.hpp:58
The core Color class in the NDEVR API.
Definition Color.h:42
A core class within the model hierarchy containing vertex-based data (Usually 3D data) within a set c...
Definition Geometry.h:143
Provides shared ownership of a dynamically allocated object.
Definition Pointer.hpp:71
Represents a color in the RGB space with optional alpha transparency.
Definition RGBColor.h:57
The core String class for the NDEVR API.
Definition String.h:95
A virtual storage type that is used with Table class to store data where the actual mechanism for sto...
Definition TableColumn.h:86
std::enable_if<!ObjectInfo< t_class >::Enum >::type set(uint04 index, const t_class &value)
Sets the value at the given row index from a non-enum type.
A fixed-size array with N dimensions used as the basis for geometric and mathematical types.
Definition Vector.hpp:62
A point in N-dimensional space, used primarily for spatial location information.
Definition Vertex.hpp:44
The primary namespace for the NDEVR SDK.
@ Position
XYZ position of the vertex.
@ Normal
Surface normal vector at the vertex.
@ BitFlag
Per-vertex bit flags (selected, hidden, etc.).
@ Color
Per-vertex RGBA color.
constexpr t_type getMin(const t_type &left, const t_type &right)
Finds the minimum of the given arguments based on the < operator Author: Tyler Parke Date: 2017-11-05...
float fltp04
Defines an alias representing a 4 byte floating-point number Bit layout is as follows: -Sign: 1 bit a...
static constexpr bool IsValid(const Angle< t_type > &value)
Checks whether the given Angle holds a valid value.
Definition Angle.h:398
uint64_t uint08
-Defines an alias representing an 8 byte, unsigned integer
uint32_t uint04
-Defines an alias representing a 4 byte, unsigned integer -Can represent exact integer values 0 throu...
uint8_t uint01
-Defines an alias representing a 1 byte, unsigned integer -Can represent exact integer values 0 throu...
static constexpr bool IsInvalid(const Angle< t_type > &value)
Checks whether the given Angle holds an invalid value.
Definition Angle.h:388
IntersectionTypes
Used for classifying shape intersections.
constexpr uint04 cipow(uint04 num, uint04 pow)
Compile-time integer power function.
@ e_is_filtered
Vertex is excluded by a filter.
@ e_is_hidden
Vertex is hidden from display.
constexpr t_to cast(const Angle< t_from > &value)
Casts an Angle from one backing type to another.
Definition Angle.h:408
Extends BlockLookupNode with a list of child nodes for hierarchical block model lookup.
A fixed-size 3D lookup table mapping spatial indices to flat array positions in a block model.
Cache for collecting block model vertex positions, colors, and weights during batch updates.
Extended cache that links block model data to actual Geometry columns for GPU upload.
Defines for a given type (such as sint04, fltp08, UUID, etc) a maximum, minimum, and reserved 'invali...
Information about the object.
Definition ObjectInfo.h:55
3D grid data structure holding scalar field values and node data for marching cubes isosurface extrac...