NDEVR
API Documentation
SegmentedBlockModel.h
1#pragma once
2#include "BlockModel/Headers/BlockModelRaster.h"
3#include "NDEVRSurfacing/Headers/GeometrySurfacing.h"
4#include "Design/Headers/GeometrySelectionOptimizer.h"
5#include "Design/Headers/Material.h"
6#include "Base/Headers/Translator.h"
7#include "Base/Headers/ObjectInfo.h"
8namespace NDEVR
9{
10
14 template<class t_point_type, uint04 t_depth, uint04 t_size, class t_weight_type>
16 {
17 public:
18 void init()
19 {
20 m_rasters.init();
21 m_lookup_nodes.ensureCapacity(t_size * t_size);
22 }
23 static constexpr Vector<3, uint04> Size() noexcept
24 {
25 return Vector<3, uint04>(cipow(t_size, t_depth));
26 }
27 inline uint04 rasterAt(const Vector<3, uint04>& zone) const noexcept
28 {
29 Vector<3, uint04> zone_index = ConvertToZoneIndex(zone, 0);
30 uint04 index = m_root_lookup.get(zone_index);
31 if (IsInvalid(index))
32 return Constant<uint04>::Invalid;
33 for (uint04 i = 1; i < t_depth - 1; i++)
34 {
35 const BlockLookupNode<t_size, uint04>& node = m_lookup_nodes[index];
36 zone_index = ConvertToZoneIndex(zone, i);
37 index = node.get(zone_index);
38 if (IsInvalid(index))
39 return Constant<uint04>::Invalid;
40 }
41 return index;
42 }
43 inline uint04 getRasterIndex(Vector<3, uint04> zone) noexcept
44 {
45 Vector<3, uint04> location = zone;
46 Vector<3, uint04> zone_index = ConvertToZoneIndex(zone, 0);
47 uint04 index = m_root_lookup.get(zone_index);
48 if (IsInvalid(index))
49 {
50 index = m_lookup_nodes.size();
51 m_lookup_nodes.add(BlockLookupNode<t_size, uint04>());
52 m_root_lookup.set(zone_index, index);
53 }
54 for (uint04 i = 1; i < t_depth - 1; i++)
55 {
56 BlockLookupNode<t_size, uint04>& node = m_lookup_nodes[index];
57 zone_index = ConvertToZoneIndex(zone, i);
58 index = node.get(zone_index);
59 if (IsInvalid(index))
60 {
61 if (t_depth - 2 == i)
62 {
63 index = m_rasters.size();
64 node.set(zone_index, index);
65 m_rasters.add(BlockModelRaster<t_point_type, t_size, t_weight_type>(location - (location % t_size)));
66 updateAdjacentList(index, location);
67 }
68 else
69 {
70 index = m_lookup_nodes.size();
71 node.set(zone_index, index);
72 m_lookup_nodes.add(BlockLookupNode<t_size, uint04>());
73 }
74 }
75 }
76 return index;
77 }
78 inline static Vector<3, uint04> ConvertToZoneIndex(Vector<3, uint04> location, uint04 i) noexcept
79 {
80 if constexpr (t_size == 8)
81 {
82 for (uint01 n = 0; n < 3; n++)
83 location[n] = (location[n] >> (3 * ((t_depth - 1) - i))) & (7U);
84 }
85 else
86 {
87 location = (location % (s_factor_table[i + 1]) / s_factor_table[i]);
88 }
89 return location;
90 }
92 {
93 return m_rasters[getRasterIndex(location)];
94 }
95 inline void addPoints(const Buffer<Vertex<3, uint04>>& points, const Buffer<t_point_type>& colors, t_weight_type weight) noexcept
96 {
97 const uint04 size = points.size();
98 Vertex<3, uint04> raster_location = Constant<Vector<3, uint04>>::Invalid;
99 uint04 raster_index = Constant<uint04>::Invalid;
100 switch (weight)
101 {
102 case 0:
103 break;
104 case 1:
105 for (uint04 i = 0; i < size; i++)
106 {
107 Vector<3, uint04> block_location = points[i] - raster_location;
108 if (!(block_location < t_size))
109 {
110 raster_index = getRasterIndex(points[i]);
111 raster_location = m_rasters[raster_index].location;
112 block_location = points[i] - raster_location;
113 }
114 uint04 index = BlockLookupNode<t_size, uint04>::ConvertToIndex(block_location);
115 m_rasters[raster_index].updateColorAverage(index, colors[i]);
116 } break;
117 default:
118 for (uint04 i = 0; i < size; i++)
119 {
120 uint04 raster_index = getRasterIndex(points[i]);
121 uint04 index = BlockLookupNode<t_size, uint04>::ConvertToIndex(points[i] - m_rasters[raster_index].location);
122 m_rasters[raster_index].updateColorAverage(index, colors[i], weight);
123 } break;
124 }
125 }
126 inline void addPoints(const Buffer<Vertex<3, uint04>>& points, const Buffer<t_point_type>& colors, const Buffer<t_weight_type>& weights) noexcept
127 {
128 const uint04 size = points.size();
129 Vertex<3, uint04> raster_location = Constant<Vector<3, uint04>>::Invalid;
130 uint04 raster_index = Constant<uint04>::Invalid;
131 for (uint04 i = 0; i < size; i++)
132 {
133 Vector<3, uint04> block_location = points[i] - raster_location;
134 if (!(block_location < t_size))
135 {
136 raster_index = getRasterIndex(points[i]);
137 raster_location = m_rasters[raster_index].location;
138 block_location = points[i] - raster_location;
139 }
140 uint04 index = BlockLookupNode<t_size, uint04>::ConvertToIndex(block_location);
141 m_rasters[raster_index].updateColorAverage(index, colors[i], weights[i]);
142 }
143 }
144 inline void addPoints(const Buffer<Vertex<3, uint04>>& points, t_weight_type weight) noexcept
145 {
146 const uint04 size = points.size();
147 for (uint04 i = 0; i < size; i++)
148 {
149 uint04 raster_index = getRasterIndex(points[i]);
150 uint04 index = BlockLookupNode<t_size, uint04>::ConvertToIndex(points[i] - m_rasters[raster_index].location);
151 m_rasters[raster_index].addWeight(index, weight);
152 }
153 }
154 inline void addPoint(const Vector<3, uint04>& point, const t_point_type& color, t_weight_type weight) noexcept
155 {
156 uint04 raster_index = getRasterIndex(point);
157 uint04 index = BlockLookupNode<t_size, uint04>::ConvertToIndex(point - m_rasters[raster_index].location);
158 m_rasters[raster_index].updateColorAverage(index, color, weight);
159 }
160 inline void addWeight(const Vector<3, uint04>& point, t_weight_type weight) noexcept
161 {
162 uint04 raster_index = getRasterIndex(point);
163 uint04 index = BlockLookupNode<t_size, uint04>::ConvertToIndex(point - m_rasters[raster_index].location);
164 m_rasters[raster_index].addWeight(index, weight);
165 }
166 inline void subtractWeight(const Vector<3, uint04>& point, t_weight_type weight) noexcept
167 {
168 uint04 raster_index = getRasterIndex(point);
169 uint04 index = BlockLookupNode<t_size, uint04>::ConvertToIndex(point - m_rasters[raster_index].location);
170 m_rasters[raster_index].subtractWeight(index, weight);
171 }
172 void clearAll()
173 {
174 m_rasters.clear();
175 m_lookup_nodes.clear();
176 m_root_lookup.clear();
177 m_clear_geometry = true;
178 }
179 void filterGeometries(BlockModelFilteringCache<t_point_type, t_weight_type>& filter) noexcept
180 {
181 uint04 raster_size = m_rasters.safeSize();
182 for (uint04 i = 0; i < raster_size; i++)
183 {
184 m_is_dirty |= m_rasters[i].filterGeometries(filter);
185 }
186 }
188 {
189 uint04 raster_size = m_rasters.safeSize();
190 for (uint04 i = 0; i < raster_size; i++)
191 m_rasters[i].collectAllPositions<false>(cache);
192 }
193 void updateGeometries(BlockModelGeometryCache<t_point_type, t_weight_type>& cache) noexcept
194 {
195 if (!m_is_dirty)
196 return;
197 if (!m_rasters.requestUsingSafe(true))
198 return;
199 m_is_dirty = false;
200 uint04 raster_size = m_rasters.safeSize();
201 if (m_clear_geometry)
202 {
203 WLock lock(cache.lock_ptr);
204 cache.geo.clearVerticesAndPrimitives();
205 cache.geo_vertex_offset = 0U;
206 cache.geo_vertex_add_offset = 0U;
207 for (uint04 i = 0; i < raster_size; i++)
208 m_rasters[i].template collectAllPositions<true>(cache);
209 }
210 else
211 {
212 for (uint04 i = 0; i < raster_size; i++)
213 m_rasters[i].collectNewPositions(cache);
214 }
215 bool updated = false;
216 if (cache.geo_add_locations.size() > 0)
217 {
218 m_rasters.requestUsingSafe(false);
219 WLock lock(cache.lock_ptr);
220 uint04 old_size = cache.geo.vertexCount();
221 if (old_size == 0 && cache.geo_add_locations.size() == 0)
222 return;
223 cache.geo.addVertices(cache.geo_add_locations.size());
224 cache.geo_vertex_offset = cache.geo.vertexOffset();//might have changed
225 const uint04 vertex_offset = old_size + cache.geo_vertex_offset;
226 for (uint04 i = 0; i < cache.geo_add_locations.size(); i++)
227 {
228 uint04 index = vertex_offset + i;
229 if constexpr (t_point_type::HasOffset())
230 cache.position_column.set(index, cache.geo_add_locations[i].template as<3, fltp04>() + cache.geo_add_info[i].offset());
231 else
232 cache.position_column.set(index, cache.geo_add_locations[i]);
233 if constexpr (t_point_type::HasNormal())
234 cache.normal_column.set(index, cache.geo_add_info[i].normal());
235 if constexpr (t_point_type::HasColor())
236 cache.color_column.set(index, cache.geo_add_info[i].color());
237 cache.flag_column.set(index, 0U);
238 cache.weight_column.set(index, cache.geo_add_weight[i]);
239 }
240 cache.position_column.update(TableChange(TableChange::e_update, vertex_offset, cache.geo_add_locations.size()));
241 if constexpr (t_point_type::HasNormal())
242 cache.normal_column.update(TableChange(TableChange::e_update, vertex_offset, cache.geo_add_locations.size()));
243 if constexpr (t_point_type::HasColor())
244 cache.color_column.update(TableChange(TableChange::e_update, vertex_offset, cache.geo_add_locations.size()));
245 cache.weight_column.update(TableChange(TableChange::e_update, vertex_offset, cache.geo_add_locations.size()));
246 cache.flag_column.update(TableChange(TableChange::e_update, vertex_offset, cache.geo_add_locations.size()));
247 updated = true;
248 m_rasters.forceUsingSafe();
249 }
250 if (m_clear_geometry)
251 {
252 m_clear_geometry = false;
253 return;//nothing more to do
254 }
255 for (uint04 i = 0; i < raster_size; i++)
256 m_rasters[i].updateGeometryVertices(cache);
257 m_rasters.requestUsingSafe(false);
258 updated |= cache.flag_update_bounds.validate();
259 updated |= cache.color_update_bounds.validate();
260 updated |= cache.normal_update_bounds.validate();
261 updated |= cache.position_update_bounds.validate();
262 updated |= cache.weight_update_bounds.validate();
263 if (updated)
264 {
265 WLock lock(cache.lock_ptr);
266 Time update_time = Time::SystemTime();
267 if (cache.position_update_bounds.validate())
268 cache.position_column.update(TableChange(TableChange::e_update, cache.position_update_bounds[MIN], cache.position_update_bounds.span(), update_time));
269 if (cache.flag_update_bounds.validate())
270 cache.flag_column.update(TableChange(TableChange::e_update, cache.flag_update_bounds[MIN], cache.flag_update_bounds.span(), update_time));
271 if (cache.color_update_bounds.validate())
272 cache.color_column.update(TableChange(TableChange::e_update, cache.color_update_bounds[MIN], cache.color_update_bounds.span(), update_time));
273 if (cache.weight_update_bounds.validate())
274 cache.weight_column.update(TableChange(TableChange::e_update, cache.weight_update_bounds[MIN], cache.weight_update_bounds.span(), update_time));
275 if (cache.normal_update_bounds.validate())
276 cache.normal_column.update(TableChange(TableChange::e_update, cache.normal_update_bounds[MIN], cache.normal_update_bounds.span(), update_time));
277 cache.geo.set<NDPO::bounding_box>(Bounds<3, fltp08>(Vector<3, fltp08>(0.0), Size().as<3, fltp08>()));
278 cache.geo.updateModifiedTime(update_time);
279 }
280 }
281 void processSelection(OptimizedSelection&)
282 {
283
284 }
285
286
287 inline void calculateTriangulation(GeometrySurfacingParameters& parameters, uint04 weight_cutoff) noexcept
288 {
289 ProgressInfo progress(_t("Calculating Triangles"), parameters.log, 0.0f);
290 typename BlockModelRaster<t_point_type, t_size, t_weight_type>::SurfacingCache cache(parameters, m_rasters);
291 cache.weight_cutoff = weight_cutoff;
292 for (uint04 i = 0; i < m_rasters.size(); i++)
293 {
294 m_rasters[i].calculateTriangulation(cache);
295 if (i % 10 == 0)
296 progress.setProgress(cast<fltp04>(i) / m_rasters.size());
297 }
298 }
299 inline void syncRasters()
300 {
301 this->m_rasters.sync();
302 this->m_is_dirty = true;
303 }
304 protected:
305 template<bool t_positive>
306 static bool ComputeNeighborZone(Vector<t_depth, Vector<3, uint04>>& zone, uint04 dim) noexcept
307 {
308 if (t_positive)
309 {
310 for (uint04 depth = t_depth - 2; IsValid(depth); depth--)
311 {
312 if (zone[depth][dim] < t_size - 1)
313 {
314 zone[depth][dim]++;
315 return true;
316 }
317 zone[depth][dim] = 0;
318 }
319 }
320 else
321 {
322 for (uint04 depth = t_depth - 2; IsValid(depth); depth--)
323 {
324 if (zone[depth][dim] > 0)
325 {
326 zone[depth][dim]--;
327 return true;
328 }
329 zone[depth][dim] = t_size - 1;
330 }
331 }
332 return false;
333 }
334 inline void updateAdjacentList(uint04 index, const Vector<t_depth, Vector<3, uint04>>& zone) noexcept
335 {
338 for (uint04 dim = 0; dim < 3; dim++)
339 {
340 //calculate positive directions
341 new_zone = zone;
342 ComputeNeighborZone<true>(new_zone, dim);
343 value.upper_neighbors[dim] = rasterAt(new_zone);
344 ComputeNeighborZone<true>(new_zone, (dim + 1) % 3);
345 value.corner_neighbors[(dim + 2) % 3] = rasterAt(new_zone);
346 if (dim == 0)
347 {
348 ComputeNeighborZone<true>(new_zone, (dim + 2) % 3);
349 value.corner_tri_neighbor = rasterAt(new_zone);
350 }
351 //calculate negative directions
352 new_zone = zone;
353 ComputeNeighborZone<false>(new_zone, dim);
354 uint04 neigbor_index = rasterAt(new_zone);
355 if (IsValid(neigbor_index))
356 m_rasters[neigbor_index].upper_neighbors[dim] = index;
357 ComputeNeighborZone<false>(new_zone, (dim + 1) % 3);
358 neigbor_index = rasterAt(new_zone);
359 if (IsValid(neigbor_index))
360 m_rasters[neigbor_index].corner_neighbors[(dim + 2) % 3] = index;
361 if (dim == 0)
362 {
363 ComputeNeighborZone<false>(new_zone, (dim + 2) % 3);
364 neigbor_index = rasterAt(new_zone);
365 if (IsValid(neigbor_index))
366 m_rasters[neigbor_index].corner_tri_neighbor = index;
367 }
368 }
369 }
370 inline void updateAdjacentList(uint04 index, const Vector<3, uint04>& location) noexcept
371 {
373 Vector<3, uint04> new_zone;
374 for (uint01 dim = 0; dim < 3; dim++)
375 {
376 //calculate positive directions
377 new_zone = location;
378 new_zone[dim] += t_size;
379 value.upper_neighbors[dim] = rasterAt(new_zone);
380 new_zone[(dim + 1) % 3] += t_size;
381 value.corner_neighbors[(dim + 2) % 3] = rasterAt(new_zone);
382 if (dim == 0)
383 {
384 new_zone[(dim + 2) % 3] += t_size;
385 value.corner_tri_neighbor = rasterAt(new_zone);
386 }
387 //calculate negative directions
388 new_zone = location;
389 new_zone[dim] -= t_size;
390 uint04 neigbor_index = rasterAt(new_zone);
391 if (IsValid(neigbor_index))
392 m_rasters[neigbor_index].upper_neighbors[dim] = index;
393 new_zone[(dim + 1) % 3] -= t_size;
394 neigbor_index = rasterAt(new_zone);
395 if (IsValid(neigbor_index))
396 m_rasters[neigbor_index].corner_neighbors[(dim + 2) % 3] = index;
397 if (dim == 0)
398 {
399 new_zone[(dim + 2) % 3] -= t_size;
400 neigbor_index = rasterAt(new_zone);
401 if (IsValid(neigbor_index))
402 m_rasters[neigbor_index].corner_tri_neighbor = index;
403 }
404 }
405 }
406 /*void updateAdjacentList()
407 {
408 for (uint04 i = 0; i < m_rasters.size(); i++)
409 {
410 m_rasters[i].location
411 }
412
413 }*/
414 static_assert(t_depth >= 1, "Must have depth");
415 protected:
416 typename BlockModelRaster<t_point_type, t_size, t_weight_type>::RasterBuffer m_rasters;
419
420 static constexpr uint04 s_factor_table[8] =
421 {
422 cipow(t_size, t_depth - 0 - 1)
423 , cipow(t_size, t_depth - 1 - 1)
424 , cipow(t_size, t_depth - 2 - 1)
425 , cipow(t_size, t_depth - 3 - 1)
426 , cipow(t_size, t_depth - 4 - 1)
427 , cipow(t_size, t_depth - 5 - 1)
428 , cipow(t_size, t_depth - 6 - 1)
429 , cipow(t_size, t_depth - 7 - 1)
430 };
431 /*template <auto t_start, auto t_end, auto t_increment, class F>
432 static constexpr void constexpr_for(F&& f)
433 {
434 if constexpr (t_start < t_end)
435 {
436 f(std::integral_constant<decltype(t_start), t_start>());
437 constexpr_for<t_start + t_increment, t_end, t_increment>(f);
438 }
439 }*/
440 bool m_is_dirty = false;
441 bool m_clear_geometry = false;
442 };
443
447 template<class t_point_type>
448 class SegmentedBlockModel : public Model
449 {
450 public:
451 SegmentedBlockModel(fltp04 grid_span, Bounds<3, fltp04> bounds) noexcept
452 : Model()//invalid model
453 , m_grid_span4(grid_span)
454 , m_inverse_grid_span4(1.0f / grid_span)
455 , m_bounds(bounds)
456 {
457 initBlockBackend(bounds);
458 //setProperty<NDPO::transform>(Matrix<fltp08>::OffsetMatrix((Size() / 2).as<3, fltp08>()));
459 }
460 SegmentedBlockModel(const Model& model, fltp04 grid_span, Bounds<3, fltp04> bounds) noexcept
461 : Model(model)
462 , m_grid_span4(grid_span)
463 , m_inverse_grid_span4(1.0f / grid_span)
464 , m_bounds(bounds)
465 {
466 initBlockBackend(bounds);
467 if (Model::isValid())
468 {
469 if (!is<NDPN::type>(TypeName()))
470 initModel();
472 }
473
474 //setProperty<NDPO::transform>(Matrix<fltp08>::OffsetMatrix((Size() / 2).as<3, fltp08>()));
475 }
476
477 ~SegmentedBlockModel() {};
478 static constexpr StringView TypeName() { return "segmented_block_model"; }
479
480 inline void addPoints(const Buffer<Vertex<3, fltp08>>& points, Buffer<t_point_type>& colors, const Buffer<fltp08>& weights) noexcept
481 {
482 const uint04 size = points.size();
483 Buffer<Vertex<3, uint04>> grid_points;
484 Buffer<uint04> grid_weights;
485 grid_points.setSize(size);
486 grid_weights.setSize(size);
487 for (uint04 i = 0; i < size; i++)
488 {
489 grid_points[i] = convertPoint(points[i]);
490 if constexpr (t_point_type::HasOffset())
491 colors[i].setOffset(points[i].as<3, fltp04>() - grid_points[i].as<3, fltp04>());
492 grid_weights[i] = cast<uint04>(weights[i]);
493 }
494 addPoints(grid_points, colors, grid_weights);
495 }
496 inline void addPoints(Buffer<Vertex<3, fltp04>>& points, Buffer<t_point_type>& colors, const Buffer<uint04>& weights) noexcept
497 {
498 const uint04 size = points.size();
499 Buffer<Vertex<3, uint04>> grid_points;
500 grid_points.setSize(size);
501 for (uint04 i = 0; i < size; i++)
502 {
503 if constexpr (!t_point_type::HasOffset())
504 {
505 grid_points[i] = convertPoint(points[i]);
506 }
507 else
508 {
509 grid_points[i] = convertPointAndLeaveOffset(points[i]);
510 colors[i].setOffset(points[i]);
511 }
512 }
513 addPoints(grid_points, colors, weights);
514 }
515 template<class t_other_type>
516 inline void addPoints(const Buffer<Vertex<3, fltp04>>& points, const Buffer<t_other_type>& colors, const Buffer<uint04>& weights) noexcept
517 {
518 const uint04 size = points.size();
519 Buffer<Vertex<3, uint04>> grid_points;
520 grid_points.setSize(size);
521 Buffer<t_point_type> converted_points;
522 converted_points.setSize(colors.size());
523 for (uint04 i = 0; i < size; i++)
524 {
525 converted_points[i] = colors[i].template getAs<t_point_type>();
526 if constexpr (t_point_type::HasOffset())
527 {
528 Vertex<3, fltp04> p0 = points[i];
529 grid_points[i] = convertPointAndLeaveOffset(p0);
530 converted_points[i].setOffset(p0);
531 }
532 else
533 {
534 grid_points[i] = convertPoint(points[i]);
535 }
536 }
537 addPoints(grid_points, converted_points, weights);
538 }
539 inline void addPoints(const Buffer<Vertex<3, fltp04>>& points, Buffer<t_point_type>& colors, const fltp04 weight) noexcept
540 {
541 const uint04 size = points.size();
542 Buffer<Vertex<3, uint04>> grid_points;
543 grid_points.setSize(size);
544 for (uint04 i = 0; i < size; i++)
545 {
546 if constexpr (t_point_type::HasOffset())
547 {
548 grid_points[i] = convertPointAndLeaveOffset(points[i]);
549 colors[i].setOffset(points[i]);
550 }
551 else
552 {
553 grid_points[i] = convertPoint(points[i]);
554 }
555 }
556 addPoints(grid_points, colors, cast<uint04>(weight));
557 }
558 inline void addPoints(Buffer<Vertex<3, fltp08>>& points, Buffer<t_point_type>& colors, const fltp08 weight) noexcept
559 {
560 const uint04 size = points.size();
561 Buffer<Vertex<3, uint04>> grid_points;
562 grid_points.setSize(size);
563 for (uint04 i = 0; i < size; i++)
564 {
565 if constexpr (t_point_type::HasOffset())
566 {
567 grid_points[i] = convertPointAndLeaveOffset(points[i]);
568 colors[i].setOffset(points[i]);
569 }
570 else
571 {
572 grid_points[i] = convertPoint(points[i]);
573 }
574 }
575 addPoints(grid_points, colors, cast<uint04>(weight));
576 }
577 template<class t_other_type>
578 inline void addPoints(Buffer<Vertex<3, fltp08>>& points, Buffer<t_other_type>& colors, const fltp08 weight) noexcept
579 {
580 const uint04 size = points.size();
581 Buffer<Vertex<3, uint04>> grid_points;
582 grid_points.setSize(size);
583 Buffer<t_point_type> converted_points;
584 converted_points.setSize(colors.size());
585 for (uint04 i = 0; i < size; i++)
586 {
587 t_point_type mio;
588 for (uint01 n = 0; n < 6; n++)
589 converted_points[i][n] = colors[i][n];
590 if constexpr (!t_point_type::HasOffset())
591 {
592 grid_points[i] = convertPointAndLeaveOffset(points[i]);
593 converted_points[i].setOffset(points[i]);
594 }
595 else
596 {
597 grid_points[i] = convertPoint(points[i]);
598 }
599 }
600 addPoints(grid_points, converted_points, cast<uint04>(weight));
601 }
602 void addPoints(const Buffer<Vertex<3, uint04>>& points, const Buffer<t_point_type>& colors, uint04 weight) noexcept
603 {
604 switch (b_index)
605 {
606 case 2: b2.addPoints(points, colors, weight); break;
607 case 3: b3.addPoints(points, colors, weight); break;
608 case 4: b4.addPoints(points, colors, weight); break;
609 case 5: b5.addPoints(points, colors, weight); break;
610 case 6: b6.addPoints(points, colors, weight); break;
611 }
612 }
613 void addPoints(const Buffer<Vertex<3, uint04>>& points, const Buffer<t_point_type>& colors, const Buffer<uint04>& weights) noexcept
614 {
615 switch (b_index)
616 {
617 case 2: b2.addPoints(points, colors, weights); break;
618 case 3: b3.addPoints(points, colors, weights); break;
619 case 4: b4.addPoints(points, colors, weights); break;
620 case 5: b5.addPoints(points, colors, weights); break;
621 case 6: b6.addPoints(points, colors, weights); break;
622 }
623 }
624 void addPoints(const Buffer<Vertex<3, uint04>>& points, uint04 weight) noexcept
625 {
626 switch (b_index)
627 {
628 case 2: b2.addPoints(points, weight); break;
629 case 3: b3.addPoints(points, weight); break;
630 case 4: b4.addPoints(points, weight); break;
631 case 5: b5.addPoints(points, weight); break;
632 case 6: b6.addPoints(points, weight); break;
633 }
634 }
635 void addPoint(const Vertex<3, uint04>& point, uint04 weight) noexcept
636 {
637 switch (b_index)
638 {
639 case 2: b2.addWeight(point, weight); break;
640 case 3: b3.addWeight(point, weight); break;
641 case 4: b4.addWeight(point, weight); break;
642 case 5: b5.addWeight(point, weight); break;
643 case 6: b6.addWeight(point, weight); break;
644 }
645 }
646 void filterGeometries(BlockModelFilteringCache<t_point_type, uint04>& filter) noexcept
647 {
648 switch (b_index)
649 {
650 case 2: b2.filterGeometries(filter); break;
651 case 3: b3.filterGeometries(filter); break;
652 case 4: b4.filterGeometries(filter); break;
653 case 5: b5.filterGeometries(filter); break;
654 case 6: b6.filterGeometries(filter); break;
655 }
656 }
657 void clearAll()
658 {
659 switch (b_index)
660 {
661 case 2: b2.clearAll(); break;
662 case 3: b3.clearAll(); break;
663 case 4: b4.clearAll(); break;
664 case 5: b5.clearAll(); break;
665 case 6: b6.clearAll(); break;
666 }
667 }
668 void addPoint(const Vertex<3, fltp04>& point, t_point_type& color, uint04 weight) noexcept
669 {
670 addPoint(convertPoint(point), color, weight);
671 }
672 void addPoint(const Vertex<3, fltp04>& point, uint04 weight) noexcept
673 {
674 addPoint(convertPoint(point), weight);
675 }
676 Vertex<3, uint04> convertPoint(const Vertex<3, fltp04>& point) const noexcept
677 {
678 return ((point * m_inverse_grid_span4) + m_point_offset4).as<3, uint04>();
679 }
680 Vertex<3, fltp04> convertPointF(const Vertex<3, fltp04>& point) const noexcept
681 {
682 return ((point * m_inverse_grid_span4) + m_point_offset4).as<3, fltp04>();
683 }
684 Vertex<3, uint04> convertPointAndLeaveOffset(Vertex<3, fltp04>& point) const noexcept
685 {
686 Vector<3, fltp04> loc((point * m_inverse_grid_span4) + m_point_offset4);
687 Vector<3, uint04> loc_a = loc.as<3, uint04>();
688 point = loc - loc_a.as<3, fltp04>();
689 return loc_a;
690 }
691 Vertex<3, uint04> convertPointAndLeaveOffset(Vertex<3, fltp08>& point) const noexcept
692 {
693 Vector<3, fltp08> loc((point * m_inverse_grid_span8) + m_point_offset8);
694 Vector<3, uint04> loc_a = loc.as<3, uint04>();
695 point = loc - loc_a.as<3, fltp08>();
696 return loc_a;
697 }
698 Vertex<3, uint04> convertPoint(const Vertex<3, fltp08>& point) const noexcept
699 {
700 return ((point * m_inverse_grid_span8) + m_point_offset8).as<3, uint04>();
701 }
702 Matrix<fltp08> blockTransform() const
703 {
704 return Matrix<fltp08>::ScalerMatrix(m_grid_span8).offset(-m_point_offset8);
705 }
706 fltp08 gridSpan() const
707 {
708 return m_grid_span8;
709 }
710 void addPoint(const Vector<3, uint04>& point, t_point_type& color, uint04 weight) noexcept
711 {
712 switch (b_index)
713 {
714 case 2: b2.addPoint(point, color, weight); break;
715 case 3: b3.addPoint(point, color, weight); break;
716 case 4: b4.addPoint(point, color, weight); break;
717 case 5: b5.addPoint(point, color, weight); break;
718 case 6: b6.addPoint(point, color, weight); break;
719 }
720 }
721 void syncRasters()
722 {
723 switch (b_index)
724 {
725 case 2: this->b2.syncRasters(); break;
726 case 3: this->b3.syncRasters(); break;
727 case 4: this->b4.syncRasters(); break;
728 case 5: this->b5.syncRasters(); break;
729 case 6: this->b6.syncRasters(); break;
730 }
731 }
732 const Bounds<3, fltp04>& bounds() const
733 {
734 return m_bounds;
735 }
736 void calculateTriangulation(GeometrySurfacingParameters& parameters, uint04 weight_cutoff) noexcept
737 {
738 switch (b_index)
739 {
740 case 2: b2.calculateTriangulation(parameters, weight_cutoff); break;
741 case 3: b3.calculateTriangulation(parameters, weight_cutoff); break;
742 case 4: b4.calculateTriangulation(parameters, weight_cutoff); break;
743 case 5: b5.calculateTriangulation(parameters, weight_cutoff); break;
744 case 6: b6.calculateTriangulation(parameters, weight_cutoff); break;
745 }
746 for (Vertex<3, fltp04>& position : parameters.surface_positions)
747 {
748 position = (position - m_point_offset4) * m_grid_span4;
749 }
750 }
751 BlockModelCache<t_point_type, uint04> getCache(uint08 weight_cuttoff, uint08 max_alpha_cutoff = 0)
752 {
753 BlockModelCache<t_point_type, uint04> cache(weight_cuttoff);
754 cache.weight_max_capacity = max_alpha_cutoff;
755 switch (b_index)
756 {
757 case 2: b2.getCache(cache); break;
758 case 3: b3.getCache(cache); break;
759 case 4: b4.getCache(cache); break;
760 case 5: b5.getCache(cache); break;
761 case 6: b6.getCache(cache); break;
762 }
763 return cache;
764 }
765 void updateCloudGeometries(uint04 weight_cuttoff, uint04 max_alpha_cutoff, const void* lock_ptr) noexcept
766 {
767 Buffer<Model> new_models;
768 Geometry geo = getGeometry();
769 BlockModelGeometryCache<t_point_type, uint04> cache(geo, weight_cuttoff, lock_ptr);
770 cache.weight_max_capacity = max_alpha_cutoff;
771 switch (b_index)
772 {
773 case 2: b2.updateGeometries(cache); break;
774 case 3: b3.updateGeometries(cache); break;
775 case 4: b4.updateGeometries(cache); break;
776 case 5: b5.updateGeometries(cache); break;
777 case 6: b6.updateGeometries(cache); break;
778 }
779 }
780 void updateSurfaceGeometries(uint04 weight_cutoff, bool merge_vertices, const void* lock_ptr) noexcept
781 {
782 GeometrySurfacingParameters parameters;
783 parameters.include_colors = true;
784 switch (b_index)
785 {
786 case 2: b2.calculateTriangulation(parameters, weight_cutoff); break;
787 case 3: b3.calculateTriangulation(parameters, weight_cutoff); break;
788 case 4: b4.calculateTriangulation(parameters, weight_cutoff); break;
789 case 5: b5.calculateTriangulation(parameters, weight_cutoff); break;
790 case 6: b6.calculateTriangulation(parameters, weight_cutoff); break;
791 }
792 WLock lock(lock_ptr);
793 Model child = getChild(1);
794 Geometry geo = child.getGeometry();
795 if (!geo.isValid())
796 {
797 geo = child.createChildGeometry();
799 geo.createVertexProperty<fltp04>("intensity");//weight
800 }
802 geo.setupVertexTable(parameters.surface_positions.size(), Geometry::VertexMode::e_cartesian_3F
805 geo.setVertices(VertexProperty::Position, parameters.surface_positions);
806 geo.setVertices(VertexProperty::Normal, parameters.surface_normals);
807 geo.setVertices(VertexProperty::Color, parameters.surface_colors);
808
809 geo.setPrimitiveRange(PrimitiveProperty::Outline, 0, parameters.surface_triangles.size());
810 for (uint04 i = 0; i < parameters.surface_triangles.size(); i++)
811 {
812 geo.setPrimitive(PrimitiveProperty::Outline, i, parameters.surface_triangles[i]);
813 }
814 if(merge_vertices)
815 geo.removeDuplicateVertices(0.5, nullptr);
816
818 geo.updateVertexColumns(false, false);
820
821 geo.updateModifiedTime();
822 child.updateModifiedTime();
824
825 }
826 void initMaterial()
827 {
830 mat.set<NDPOC::name>(_t("Block Material"));
831 mat.set<NDPM::two_sided>(false);
832 mat.set<NDPM::smooth_normals>(true);
833 mat.set<NDPM::pixel_thickness>(1.0);
834 //if (false)
835 {
837 }
838 /*else
839 {
840 mat.setUVMode(UVType::e_KD, Material::UVMode::e_scaled_channel);
841 //setUVMode(UVType::e_KA, Material::UVMode::e_scaled_channel);
842 //setUVMode(UVType::e_KS, Material::UVMode::e_scaled_channel);
843 mat.set<NDPM::draw_by_property_channel>("intensity");
844 mat.set<NDPM::extra_property_value_max>(20.0);
845 mat.set<NDPM::extra_property_value_mid>(10.0);
846 mat.set<NDPM::extra_property_value_min>(1.0);
847 }*/
848 setMaterial(mat);
849 mat.updateModifiedTime();
850 }
851 void finishUpdatingModel(const void* lock_ptr)
852 {
853 if (Geometry geo = getGeometry())
854 {
855 WLock lock(lock_ptr);
856 geo.set(NDPG::e_no_auto_tree_creation, false);
857 geo.updateModifiedTime();
858 geo.invalidateBounds();
859 }
861 {
862 mat.update(NDPM::two_sided, true, lock_ptr);
863 }
866 }
867 protected:
868 void initBlockBackend(const Bounds<3, fltp04> bounds)
869 {
870 fltp04 max = bounds.span().dimensionalValue<MAX>();
871 Vector<3, fltp04> bm_center;
872 uint08 grid_node_count = cast<uint08>(max / m_grid_span4) + 1U;
873 if (grid_node_count < 8 * 8)
874 {
875 b_index = 2;
876 bm_center = (SegmentedBlockModelBase<t_point_type, 2, s_node_size, uint02>::Size() / 2U).template as<3, fltp04>();
877 b2.init();
878 }
879 else if (grid_node_count < 8 * 8 * 8)
880 {
881 b_index = 3;
882 bm_center = (SegmentedBlockModelBase<t_point_type, 3, s_node_size, uint02>::Size() / 2U).template as<3, fltp04>();
883 b3.init();
884 }
885 else if (grid_node_count < 8 * 8 * 8 * 8)
886 {
887 b_index = 4;
888 bm_center = (SegmentedBlockModelBase<t_point_type, 4, s_node_size, uint02>::Size() / 2U).template as<3, fltp04>();
889 b4.init();
890 }
891 else if (grid_node_count < 8 * 8 * 8 * 8 * 8)
892 {
893 b_index = 5;
894 bm_center = (SegmentedBlockModelBase<t_point_type, 5, s_node_size, uint02>::Size() / 2U).template as<3, fltp04>();
895 b5.init();
896 }
897 else if (grid_node_count < 8 * 8 * 8 * 8 * 8 * 8)
898 {
899 b_index = 6;
900 bm_center = (SegmentedBlockModelBase<t_point_type, 6, s_node_size, uint02>::Size() / 2U).template as<3, fltp04>();
901 b6.init();
902 }
903 m_point_offset4 = (bm_center - (bounds.center() * m_inverse_grid_span4));
904 m_point_offset8 = m_point_offset4.as<3, fltp08>();
905 m_grid_span8 = cast<fltp08>(m_grid_span4);
906 m_inverse_grid_span8 = cast<fltp08>(m_inverse_grid_span4);
907 }
908 void initModel()
909 {
910 set<NDPN::type>(TypeName());
911 initMaterial();
912
914 //if (t_point_type::HasNormal())
915 //geo.set(GeometryProperty::e_normal_mode, NormalMode::e_smooth_normals);
916 geo.set<NDPO::transform>(Matrix<fltp08>::ScalerMatrix(m_grid_span8).offset(-m_point_offset8));
921 geo.setVertexCount(0);
923 geo.createVertexProperty<fltp04>("intensity");//weight
924
925 }
926 protected:
927 uint04 b_index;
928
929 static constexpr uint04 s_node_size = 8;
930 //union
931 // {
937 //};
938 Vector<3, fltp04> m_point_offset4;
939 Vector<3, fltp08> m_point_offset8;
940 fltp04 m_grid_span4;
941 fltp04 m_inverse_grid_span4;
942 fltp08 m_grid_span8;
943 fltp08 m_inverse_grid_span8;
944 Bounds<3, fltp04> m_bounds;
945 };
946
947
948 class ColorNode : public Vector<3, uint01>
949 {
950 public:
951 ColorNode()
952 {}
953 ColorNode(RGBColor color)
954 : Vector<3, uint01>(color[X], color[Y], color[Z])
955 {}
956 ColorNode(Vector<3, uint01> color)
957 : Vector<3, uint01>(color[X], color[Y], color[Z])
958 {}
959 RGBColor color() const
960 {
961 return RGBColor((*this)[X], (*this)[Y], (*this)[Z]);
962 }
963 Vector<3, fltp04> normal() const
964 {
965 return Constant<Vector<3, fltp04>>::Invalid;
966 }
967 Vector<3, fltp04> offset() const
968 {
969 return Constant< Vector<3, fltp04>>::Invalid;
970 }
971 void setNormal(Vector<3, fltp04> normal)
972 {
973 UNUSED(normal);
974 }
975 void setColor(const RGBColor& color)
976 {
977 (*this)[X] = color[X];
978 (*this)[Y] = color[Y];
979 (*this)[Z] = color[Z];
980 }
981 void setOffset(Vector<3, fltp04> offset)
982 {
983 UNUSED(offset);
984 }
985 static constexpr bool HasColor() { return true; }
986 static constexpr bool HasNormal() { return false; }
987 static constexpr bool HasOffset() { return false; }
988 };
989 template<class t_weight_type>
990 ColorNode combine(const ColorNode& a, const t_weight_type& a_weight, const ColorNode& b, const t_weight_type& b_weight)
991 {
992 Vector<3, t_weight_type> new_type =
993 a.as<3, t_weight_type>() * a_weight
994 + b.as<3, t_weight_type>() * b_weight;
995 return ColorNode((new_type / (a_weight + b_weight)).template as<3, uint01>());
996 }
997 template<>
998 struct ObjectInfo<ColorNode, false, true>
999 {
1000 static const uint01 Dimensions = 0;
1001 static const bool Vector = true;
1002 static const bool Buffer = true;
1003 static const bool Primitive = true;
1004 static const bool Pointer = false;
1005 static const bool Unsigned = false;
1006 static const bool Float = false;
1007 static const bool Integer = false;
1008 static const bool Number = false;
1009 static const bool Enum = false;
1010 static const bool String = true;
1011 static const bool Color = false;
1012 static const bool Boolean = false;
1013 static constexpr ObjectInfo<uint01, false, false> VectorSub() { return ObjectInfo<uint01, false, false>(); }
1014 };
1015 class ColorNormalNode : public Vector<6, uint01>
1016 {
1017 public:
1018 ColorNormalNode()
1019 {}
1020 ColorNormalNode(Vector<3, fltp04> normal, RGBColor color)
1021 : Vector<6, uint01>(color[X], color[Y], color[Z], cast<uint01>(127.0f + normal[X] * 127.0f), cast<uint01>(127.0f + normal[Y] * 127.0f), cast<uint01>(127.0f + normal[Z] * 127.0f))
1022 {}
1023 ColorNormalNode(Vector<6, uint01> value)
1024 : Vector<6, uint01>(value)
1025 {}
1026 RGBColor color() const
1027 {
1028 return RGBColor((*this)[X], (*this)[Y], (*this)[Z]);
1029 }
1030 Vector<3, fltp04> normal() const
1031 {
1032 return (Vector<3, fltp04>(cast<fltp04>((*this)[3]), cast<fltp04>((*this)[4]), cast<fltp04>((*this)[5])) - 127.0f) / 127.0f;
1033 }
1034 Vector<3, fltp04> offset() const { return Constant< Vector<3, fltp04>>::Invalid; }
1035 void setNormal(Vector<3, fltp04> normal)
1036 {
1037 (*this)[3] = cast<uint01>(127.0f + normal[X] * 127.0f);
1038 (*this)[4] = cast<uint01>(127.0f + normal[Y] * 127.0f);
1039 (*this)[5] = cast<uint01>(127.0f + normal[Z] * 127.0f);
1040 }
1041 void setColor(const RGBColor& color)
1042 {
1043 (*this)[X] = color[X];
1044 (*this)[Y] = color[Y];
1045 (*this)[Z] = color[Z];
1046 }
1047 void setOffset(Vector<3, fltp04> offset)
1048 {
1049 UNUSED(offset);
1050 }
1051 template<class t_other_type>
1052 t_other_type getAs() const
1053 {
1054 t_other_type node;
1055 memcpy(&node, this, sizeof(t_other_type));
1056 return node;
1057 }
1058
1059 static constexpr bool HasColor() { return true; }
1060 static constexpr bool HasNormal() { return true; }
1061 static constexpr bool HasOffset() { return false; }
1062 };
1063 template<class t_weight_type>
1064 ColorNormalNode combine(const ColorNormalNode& a, const t_weight_type& a_weight, const ColorNormalNode& b, const t_weight_type& b_weight)
1065 {
1066 Vector<6, t_weight_type> new_type =
1067 a.as<6, t_weight_type>() * a_weight
1068 + b.as<6, t_weight_type>() * b_weight;
1069 return ColorNormalNode((new_type / (a_weight + b_weight)).template as<6, uint01>());
1070 }
1071 template<>
1072 struct ObjectInfo<ColorNormalNode, false, true>
1073 {
1074 static const uint01 Dimensions = 6;
1075 static const bool Vector = true;
1076 static const bool Buffer = true;
1077 static const bool Primitive = true;
1078 static const bool Pointer = false;
1079 static const bool Unsigned = false;
1080 static const bool Float = false;
1081 static const bool Integer = false;
1082 static const bool Number = false;
1083 static const bool Enum = false;
1084 static const bool String = true;
1085 static const bool Color = false;
1086 static const bool Boolean = false;
1087 static constexpr ObjectInfo<uint01, false, false> VectorSub() { return ObjectInfo<uint01, false, false>(); }
1088 };
1089
1090 class ColorNormalOffsetNode : public Vector<9, uint01>
1091 {
1092 public:
1093 ColorNormalOffsetNode()
1094 {}
1095 ColorNormalOffsetNode(Vector<3, fltp04> offset, ColorNormalNode node)
1096 {
1097 for (uint01 i = 0; i < 6; i++)
1098 (*this)[i] = node[i];
1099 setOffset(offset);
1100 }
1101 ColorNormalOffsetNode(Vector<3, fltp04> offset, Vector<3, fltp04> normal, RGBColor color)
1102 {
1103 (*this)[0] = color[X];
1104 (*this)[1] = color[Y];
1105 (*this)[2] = color[Z];
1106 setNormal(normal);
1107 setOffset(offset);
1108 }
1109 ColorNormalOffsetNode(Vector<9, uint01> value)
1110 : Vector<9, uint01>(value)
1111 {}
1112 ColorNormalOffsetNode(Vector<9, fltp04> value)
1113 {
1114 for(uint01 i = 0; i < 3; i++)
1115 value[i] = clip(value[i], 0.0f, 255.0f);
1116 for (uint01 i = 3; i < 6; i++)
1117 value[i] = clip(value[i], 0.0f, 254.0f);
1118 for (uint01 i = 6; i < 9; i++)
1119 value[i] = clip(value[i], 0.0f, 255.0f);
1120 (*this) = value.as<uint01>();
1121 }
1122 ColorNormalOffsetNode(Vector<9, uint04> value)
1123 {
1124 for (uint01 i = 0; i < 3; i++)
1125 value[i] = clip(value[i], 0U, 255U);
1126 for (uint01 i = 3; i < 6; i++)
1127 value[i] = clip(value[i], 0U, 254U);
1128 for (uint01 i = 6; i < 9; i++)
1129 value[i] = clip(value[i], 0U, 255U);
1130 (*this) = value.as<uint01>();
1131 }
1132 template<class t_other_type>
1133 t_other_type getAs() const
1134 {
1135 return t_other_type();
1136 }
1137 template<>
1138 ColorNormalNode getAs() const
1139 {
1140 return ColorNormalNode(this->as<6, uint01>());
1141 }
1142 RGBColor color() const
1143 {
1144 return RGBColor((*this)[X], (*this)[Y], (*this)[Z]);
1145 }
1146 Vector<3, fltp04> normal() const
1147 {
1148 return (Vector<3, fltp04>(cast<fltp04>((*this)[3]), cast<fltp04>((*this)[4]), cast<fltp04>((*this)[5])) - 127.0f) / 127.0f;
1149 }
1150 Vector<3, fltp04> offset() const
1151 {
1152 return (Vector<3, fltp04>(cast<fltp04>((*this)[6]), cast<fltp04>((*this)[7]), cast<fltp04>((*this)[8]))) / 256.0f;
1153 }
1154 void setNormal(Vector<3, fltp04> normal)
1155 {
1156 (*this)[3] = cast<uint01>(127.0f + normal[X] * 127.0f);
1157 (*this)[4] = cast<uint01>(127.0f + normal[Y] * 127.0f);
1158 (*this)[5] = cast<uint01>(127.0f + normal[Z] * 127.0f);
1159 }
1160 void setOffset(Vector<3, fltp04> offset)
1161 {
1162 (*this)[6] = cast<uint01>(offset[X] * 256.0f);
1163 (*this)[7] = cast<uint01>(offset[Y] * 256.0f);
1164 (*this)[8] = cast<uint01>(offset[Z] * 256.0f);
1165 }
1166 void setColor(RGBColor color)
1167 {
1168 (*this)[X] = color[X];
1169 (*this)[Y] = color[Y];
1170 (*this)[Z] = color[Z];
1171 }
1172 static constexpr bool HasColor() { return true; }
1173 static constexpr bool HasNormal() { return true; }
1174 static constexpr bool HasOffset() { return true; }
1175 };
1176 template<class t_weight_type>
1177 ColorNormalOffsetNode combine(const ColorNormalOffsetNode& a, const t_weight_type& a_weight, const ColorNormalOffsetNode& b, const t_weight_type& b_weight)
1178 {
1179 Vector<9, t_weight_type> new_type =
1180 a.as<t_weight_type>() * a_weight
1181 + b.as<t_weight_type>() * b_weight;
1182 return ColorNormalOffsetNode((new_type / (a_weight + b_weight)));
1183 }
1184 template<>
1185 struct ObjectInfo<ColorNormalOffsetNode, false, true>
1186 {
1187 static const uint01 Dimensions = 9;
1188 static const bool Vector = true;
1189 static const bool Buffer = true;
1190 static const bool Primitive = true;
1191 static const bool Pointer = false;
1192 static const bool Unsigned = false;
1193 static const bool Float = false;
1194 static const bool Integer = false;
1195 static const bool Number = false;
1196 static const bool Enum = false;
1197 static const bool String = true;
1198 static const bool Color = false;
1199 static const bool Boolean = false;
1200 static constexpr ObjectInfo<uint01, false, false> VectorSub() { return ObjectInfo<uint01, false, false>(); }
1201 };
1202
1203 class ColorOffsetNode : public Vector<6, uint01>
1204 {
1205 public:
1206 ColorOffsetNode()
1207 {}
1208 ColorOffsetNode(Vector<3, fltp04> offset, ColorNormalNode node)
1209 {
1210 for (uint01 i = 0; i < 6; i++)
1211 (*this)[i] = node[i];
1212 setOffset(offset);
1213 }
1214 ColorOffsetNode(Vector<3, fltp04> offset, RGBColor color)
1215 {
1216 (*this)[0] = color[X];
1217 (*this)[1] = color[Y];
1218 (*this)[2] = color[Z];
1219 setOffset(offset);
1220 }
1221 ColorOffsetNode(Vector<6, uint01> value)
1222 : Vector<6, uint01>(value)
1223 {}
1224 ColorOffsetNode(Vector<6, fltp04> value)
1225 {
1226 for (uint01 i = 0; i < 3; i++)
1227 value[i] = clip(value[i], 0.0f, 255.0f);
1228 for (uint01 i = 3; i < 6; i++)
1229 value[i] = clip(value[i], 0.0f, 255.0f);
1230 (*this) = value.as<uint01>();
1231 }
1232 ColorOffsetNode(Vector<6, uint04> value)
1233 {
1234 for (uint01 i = 0; i < 3; i++)
1235 value[i] = clip(value[i], 0U, 255U);
1236 for (uint01 i = 3; i < 6; i++)
1237 value[i] = clip(value[i], 0U, 255U);
1238 (*this) = value.as<uint01>();
1239 }
1240 RGBColor color() const
1241 {
1242 return RGBColor((*this)[X], (*this)[Y], (*this)[Z]);
1243 }
1244 Vector<3, fltp04> normal() const
1245 {
1246 return Constant<Vector<3, fltp04>>::Invalid;
1247 }
1248 Vector<3, fltp04> offset() const
1249 {
1250 return (Vector<3, fltp04>(cast<fltp04>((*this)[3]), cast<fltp04>((*this)[4]), cast<fltp04>((*this)[5]))) / 256.0f;
1251 }
1252 void setNormal(Vector<3, fltp04> normal)
1253 {
1254 UNUSED(normal);
1255 }
1256 void setOffset(Vector<3, fltp04> offset)
1257 {
1258 (*this)[3] = cast<uint01>(offset[X] * 256.0f);
1259 (*this)[4] = cast<uint01>(offset[Y] * 256.0f);
1260 (*this)[5] = cast<uint01>(offset[Z] * 256.0f);
1261 }
1262 static constexpr bool HasColor() { return true; }
1263 static constexpr bool HasNormal() { return false; }
1264 static constexpr bool HasOffset() { return true; }
1265 };
1266 template<class t_weight_type>
1267 ColorOffsetNode combine(const ColorOffsetNode& a, const t_weight_type& a_weight, const ColorOffsetNode& b, const t_weight_type& b_weight)
1268 {
1269 Vector<6, t_weight_type> new_type =
1270 a.as<t_weight_type>() * a_weight
1271 + b.as<t_weight_type>() * b_weight;
1272 return ColorOffsetNode((new_type / (a_weight + b_weight)));
1273 }
1274 template<>
1275 struct ObjectInfo<ColorOffsetNode, false, true>
1276 {
1277 static const uint01 Dimensions = 6;
1278 static const bool Vector = true;
1279 static const bool Buffer = true;
1280 static const bool Primitive = true;
1281 static const bool Pointer = false;
1282 static const bool Unsigned = false;
1283 static const bool Float = false;
1284 static const bool Integer = false;
1285 static const bool Number = false;
1286 static const bool Enum = false;
1287 static const bool String = true;
1288 static const bool Color = false;
1289 static const bool Boolean = false;
1290 static constexpr ObjectInfo<uint01, false, false> VectorSub() { return ObjectInfo<uint01, false, false>(); }
1291 };
1292}
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 bool validate() const
Validates this object.
Definition Bounds.hpp:704
constexpr Ray< t_dims, t_type > span() const
The side lengths of these bounds.
Definition Bounds.hpp:113
The equivelent of std::vector but with a bit more control.
Definition Buffer.hpp:58
void set(t_property_type property, const t_type &value)
Sets a property value in the database.
bool isValid() const
Checks whether this design object has a valid index into the database.
bool is(t_property_type property, const StringView &value) const
Checks whether a string property matches the given StringView value.
A core class within the model hierarchy containing vertex-based data (Usually 3D data) within a set c...
Definition Geometry.h:143
void updateVertexColumns(bool invalidate_bounds=true, bool erase_kd_tree=true)
Notifies the system that all vertex columns have been modified.
@ e_cartesian_3F
3D Cartesian coordinates, single-precision float.
Definition Geometry.h:156
@ e_color_rgb
RGB color data.
Definition Geometry.h:171
@ e_no_vertex
No vertex data present.
Definition Geometry.h:151
void updateModifiedTime(Time time=Time::SystemTime())
Updates the modified timestamp for this geometry.
void updatePrimitiveColumns(bool remove_tree=true)
Notifies the system that all primitive columns have been modified.
void setupVertexTable(uint04 vertex_size, VertexMode position, VertexMode normal=VertexMode::e_no_vertex, VertexMode color=VertexMode::e_no_vertex, VertexMode texture=VertexMode::e_no_vertex, VertexMode tangent=VertexMode::e_no_vertex, VertexMode bitangent=VertexMode::e_no_vertex, VertexMode bones=VertexMode::e_no_vertex)
Configures the vertex table with the specified modes for standard properties.
void autoCalculateIndices(PrimitiveProperty property, const void *lock=nullptr, const Matrix< fltp08 > &transform=Matrix< fltp08 >(1.0), LogPtr log=LogPtr())
Automatically calculates primitive indices (e.g.
void setPrimitive(PrimitiveProperty property, uint04 index, t_type index_value)
Sets a single primitive index value.
Definition Geometry.h:712
void clearVerticesAndPrimitives()
Removes all vertex and primitive data from this geometry.
void setVertices(VertexProperty property, const Buffer< t_type > &vertices, uint04 offset=0)
Sets a standard vertex property for multiple vertices from a buffer.
Definition Geometry.h:1677
uint04 createVertexProperty(const StringView &property_name)
Creates a new custom vertex property column with a compile-time type.
Definition Geometry.h:1348
void removeDuplicateVertices(fltp08 epsilon, const void *lock, LogPtr log=LogPtr())
Removes vertices that are within epsilon distance of each other.
void setGeometryType(GeometryType geometry_type)
Sets the geometry type identifier.
void setPrimitiveRange(PrimitiveProperty mode, uint04 start, uint04 primitive_count)
Sets the start offset and count for a primitive property range.
void setVertexCount(uint04 size, bool deallocate_if_possible=true)
Sets the total vertex count, resizing vertex data columns.
Container responsible for storing and setting the appearance of a Model or Geometry within the NDEVR ...
Definition Material.h:153
@ e_flat
Flat shading. Shading is done on per-face base, diffuse only. Also known as 'faceted shading'.
Definition Material.h:163
void updateModifiedTime(const Time &time=Time::SystemTime())
Updates the material's modification timestamp.
@ e_color_channel
Color is taken from the per-vertex color channel.
Definition Material.h:188
void setUVMode(UVType uv_index, const UVMode &type)
Sets the UV mapping mode for the specified UV channel.
Templated logic for doing matrix multiplication.
Definition Matrix.hpp:182
void updateModifiedTime(Time time=Time::SystemTime())
Updates the modified timestamp for this model.
Vector< 3, fltp08 > size() const
Returns the size (extents) of the model's bounding box.
Geometry getGeometry() const
Returns the geometry attached to this model.
void invalidateBounds()
Invalidates all cached bounding boxes, forcing recalculation on next access.
Geometry createChildGeometry()
Creates a new child geometry for this model.
void setMaterial(const Material &material)
Assigns a material to this model.
Model()
Default constructor. Creates an uninitialized Model.
Definition Model.h:365
Material getMaterial() const
Returns the material assigned to this model.
Model getChild(uint04 child) const
Returns the child model at the given child slot index.
Material createChildMaterial(bool copy_child=false)
Creates a new child material for this model.
Used with InfoPipe to signal that the system will be using progress.
Hierarchical spatial index for block model rasters using a multi-level lookup tree.
The core String View class for the NDEVR API.
Definition StringView.h:58
Represents a timestamp with utilities for manipulation and conversion.
Definition Time.h:62
static Time SystemTime()
Retrieves the current system time which is a combination of std::chrono::steady_clock to ensure smoot...
A fixed-size array with N dimensions used as the basis for geometric and mathematical types.
Definition Vector.hpp:62
constexpr decltype(auto) as() const
Returns the vector as a new time of vector.
Definition Vector.hpp:301
A point in N-dimensional space, used primarily for spatial location information.
Definition Vertex.hpp:44
Used to lock a particular variable for writing.
Definition RWLock.h:272
The primary namespace for the NDEVR SDK.
@ smooth_normals
Whether vertex normals are smoothed across faces.
Definition Material.h:61
@ pixel_thickness
Thickness in pixels for line and point rendering.
Definition Material.h:62
@ shading_model
The shading model index used for rendering (see Material::ShadingModel).
Definition Material.h:55
@ two_sided
Whether the material is rendered on both sides of a face.
Definition Material.h:54
@ fixed_bounding_box
A user-defined fixed bounding box override for this model.
Definition Model.h:59
@ Position
XYZ position of the vertex.
@ Normal
Surface normal vector at the vertex.
@ Color
Per-vertex RGBA color.
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
constexpr HSLColor Constant< HSLColor >::Invalid
The invalid HSLColor constant with all components set to invalid.
Definition HSLColor.h:264
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...
@ e_points
Point cloud or discrete points.
@ e_triangles
Triangle meshes.
double fltp08
Defines an alias representing an 8 byte floating-point number.
@ name
The calculated/translated display name.
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
@ bounding_box
The axis-aligned bounding box of the object in local space.
@ transform
A 4x4 transform matrix that maps local coordinates into global space.
@ Outline
Line-based outline rendering of primitives.
@ Solid
Solid filled rendering of primitives.
constexpr uint04 cipow(uint04 num, uint04 pow)
Compile-time integer power function.
@ e_KD
Diffuse texture/color channel.
@ no_auto_tree_creation
Whether automatic spatial tree creation is disabled.
Definition Geometry.h:77
constexpr t_type clip(const t_type &value, const t_type &lower_bound, const t_type &upper_bound)
Clips the value given so that that the returned value falls between upper and lower bound.
constexpr t_to cast(const Angle< t_from > &value)
Casts an Angle from one backing type to another.
Definition Angle.h:408
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
Stores the state and results of an indexed geometry selection operation.
Records changes to a table or column noting the bounds of the data adjusted.
Definition TableColumn.h:54
@ e_update
An existing row range was modified in place.
Definition TableColumn.h:58