NDEVR
API Documentation
ViewportPointSmoother.hpp
1#pragma once
2#include <NDEVR/GLComputeShader.h>
3#include "RasterPointScanner/Headers/ViewPortSmoothShaderLogic.h"
4#include "PointScanner/Headers/PointContainer.h"
5#include "Base/Headers/Vertex.hpp"
6#include "Base/Headers/Matrix.hpp"
7#include "Base/Headers/MatrixFunctions.h"
8#include "Base/Headers/Time.h"
9#include "Base/Headers/RGBColor.h"
10#include "Base/Headers/RWLock.h"
11#include "Base/Headers/Line.hpp"
12#include "Base/Headers/TimeSpan.h"
13class QOpenGLShaderProgram;
14namespace NDEVR
15{
16 static constexpr fltp04 FastInvSqrt(fltp04 number)
17 {
18 union { fltp04 f = 0.0f; uint04 i; } conv;
19 const fltp04 threehalfs = 1.5f;
20 fltp04 x2 = number * 0.5f;
21 conv.f = number;
22 conv.i = 0x5f3759df - (conv.i >> 1);
23 conv.f = conv.f * (threehalfs - (x2 * conv.f * conv.f));
24 return conv.f;
25 }
26 static Vertex<3, fltp04> AverageValue(Vertex<3, fltp04> a, fltp04 wa, Vertex<3, fltp04> b, fltp04 wb)
27 {
28 return ((a * wa + b * wb) * (1.0f / (wa + wb)));
29 }
30
31 struct Intrinsics
32 {
33 Vector<2, fltp04> size_f = Constant<Vector<2, fltp04>>::Invalid;
34 Vector<2, fltp04> size_fr = Constant<Vector<2, fltp04>>::Invalid;
35 Vector<2, uint04> center_i = Constant<Vector<2, uint04>>::Invalid;
36 Vector<2, uint04> size_i = Constant<Vector<2, uint04>>::Invalid;
37 Vector<2, fltp04> pp = Constant<Vector<2, fltp04>>::Invalid;
38 Vector<2, fltp04> f = Constant<Vector<2, fltp04>>::Invalid;
39 Vector<2, fltp04> inv_f = Constant<Vector<2, fltp04>>::Invalid;
40 uint04 size_max_distance = Constant<uint04>::Invalid;
41 Vector<5, fltp04> coeffs;
42
43 void setScreenSize(const Vector<2, uint04>& view_size)
44 {
45 size_i = view_size;
46 center_i = view_size / 2U;
47 size_max_distance = view_size[X] * view_size[Y];
48 size_f = size_i.as<2, fltp04>();
49 size_fr = (size_i + 10U).as<2, fltp04>();
50 }
51 void setFx(Vector<2, fltp04> fov)
52 {
53 f = fov;
54 inv_f = 1.0f / fov;
55 }
56 };
57
58 struct ViewPortSmootherInformation
59 {
60 uint04 point_count = 0;
61 fltp08 average_weight = 0.0;
62 fltp08 average_distance = 0.0;
63 };
64
65 static constexpr uint04 s_discard_weight = 8U;
66 static constexpr uint04 s_record_weight = 4096U;
67 static constexpr uint04 s_max_weight = 1073741823U;
68
69 template<class t_point_type>
70 class ViewportPointSmoother
71 {
72 public:
73 ViewportPointSmoother()
74 {}
75
76 static constexpr uint04 RecordWeight() { return s_record_weight; }
77 static constexpr uint04 MaxWeight() { return s_max_weight; }
78 static constexpr uint04 DiscardWeight() { return s_discard_weight; }
79 void setMaxDistance(fltp04 max_distance)
80 {
81 m_max_distance = max_distance;
82 }
83
84 void updateCameraLocationBounds()
85 {
86 m_camera_location_bounds = Constant<Bounds<2, fltp04>>::Min;
87 fltp04 max_dist = m_max_distance;
88 m_camera_location_bounds.addToBounds(pixelToPoint(Vector<3, fltp04>(0.0f, m_intrinsics.size_f[Y] / 2, max_dist)).template as<2, fltp04>());
89 m_camera_location_bounds.addToBounds(pixelToPoint(Vector<3, fltp04>(m_intrinsics.size_f[X] / 2.0f, 0.0f, max_dist)).template as<2, fltp04>());
90 m_camera_location_bounds.addToBounds(pixelToPoint(Vector<3, fltp04>(m_intrinsics.size_f[X] / 2.0f, m_intrinsics.size_f[Y], max_dist)).template as<2, fltp04>());
91 m_camera_location_bounds.addToBounds(pixelToPoint(Vector<3, fltp04>(m_intrinsics.size_f[X], m_intrinsics.size_f[Y] / 2, max_dist)).template as<2, fltp04>());
92 m_camera_location_bounds.addToBounds(Vector<2, fltp04>(0.0f));
93 m_camera_location_bounds = m_camera_location_bounds.scale(1.0 / max_dist);
94 }
95
96 Vertex<3, fltp04> closestPoint(const Vertex<3, fltp04>& point) const
97 {
98 fltp04 min_dist = Constant<fltp04>::Max;
99 Vertex<3, fltp04> closest_point = Constant<Vertex<3, fltp04>>::Invalid;
100 for (uint04 i = 0; i < m_active.locations.size(); i++)
101 {
102 Vertex<3, fltp04> p0 = m_active.locations[i];
103 fltp04 current_dist = distanceSquared(p0, point);
104 if (current_dist < min_dist) { min_dist = current_dist; closest_point = p0; }
105 }
106 return closest_point;
107 }
108 Vertex<3, fltp04> closestPoint(const LineSegment<3, fltp04>& line) const
109 {
110 fltp04 min_dist = Constant<fltp04>::Max;
111 Vertex<3, fltp04> closest_point = Constant<Vertex<3, fltp04>>::Invalid;
112 for (uint04 i = 0; i < m_active.locations.size(); i++)
113 {
114 Vertex<3, fltp04> p0 = m_active.locations[i];
115 fltp04 current_dist = distanceSquared(p0, line);
116 if (current_dist < min_dist) { min_dist = current_dist; closest_point = p0; }
117 }
118 return closest_point;
119 }
120
121 void calcHistoricPixelLocations(uint04 record_weight, uint04 discard_weight, uint04 max_weight, uint04 weight_reduction)
122 {
123 if (m_point_smooth_logic == nullptr)
124 m_point_smooth_logic = new ViewPortSmoothShaderLogic();
125 if (m_point_smooth_logic)
126 {
127 calcHistoricPixelLocationsGL(record_weight, discard_weight, max_weight, weight_reduction);
128 return;
129 }
130 m_pixel_buffer.setSize(m_intrinsics.size_i.product());
131 m_pixel_buffer.setAllToValue(Constant<uint04>::Invalid);
132 uint04 nan_index = m_active.locations.size();
133 for (uint04 i = 0; i < nan_index;)
134 {
135 uint04 pix_idx = Constant<uint04>::Invalid;
136 bool is_filtered = false;
137 if (!m_lock_weights || m_active.weights[i] <= weight_reduction)
138 is_filtered = m_active.weights[i] <= getMax(weight_reduction, discard_weight);
139 if (!is_filtered)
140 {
141 Vector<2, fltp04> location = screenLocation(m_active.locations[i]);
142 bool is_out_of_range = !isInActiveScreen(location);
143 if (is_out_of_range && !isInScreen(location)) is_filtered = true;
144 fltp04 d = 0.0f;
145 if (!is_out_of_range)
146 {
147 Vertex<3, fltp04> value_dir(m_active.locations[i] - m_camera_location);
148 d = value_dir.magnitudeSquared();
149 is_out_of_range = d > m_max_distance;
150 if (is_out_of_range && d > 1.2f * m_max_distance) is_filtered = true;
151 else
152 {
153 if constexpr (t_point_type::HasNormal())
154 {
155 if (!is_out_of_range)
156 {
157 Vector<3, fltp04> normal = m_active.data[i].normal();
158 fltp08 dot_t = dot(normal, value_dir);
159 if (dot_t > 0) is_out_of_range = true;
160 if (dot_t > 0.25f) is_filtered = true;
161 }
162 }
163 }
164 }
165 if (!is_out_of_range)
166 {
167 if (m_active.weights[i] > max_weight) m_active.weights[i] = max_weight;
168 else if (m_active.weights[i] > weight_reduction) m_active.weights[i] -= weight_reduction;
169 else { m_active.weights[i] = 0U; is_out_of_range = true; }
170 }
171 if (!is_out_of_range)
172 {
173 Vector<2, uint04> ipix = location.as<2, uint04>();
174 pix_idx = screenIndex(ipix);
175 uint04 existing_idx = m_pixel_buffer[pix_idx];
176 if (IsValid(existing_idx))
177 {
178 if (m_filter_matching_points)
179 {
180 if (m_active.weights[existing_idx] < record_weight)
181 {
182 updateWeightedAverage(existing_idx, m_active.locations[i], m_active.data[i], m_active.weights[i], m_max_error_percent_sqrd * d);
183 }
184 m_active.weights[i] = 0U;
185 is_filtered = true;
186 }
187 else
188 {
189 m_pixel_buffer[pix_idx] = i;
190 }
191 }
192 else
193 {
194 m_pixel_buffer[pix_idx] = i;
195 }
196 }
197 }
198 if (is_filtered)
199 {
200 if (m_active.weights[i] >= record_weight)
201 {
202 m_inactive.locations.add(m_active.locations[i]);
203 m_inactive.data.add(m_active.data[i]);
204 m_inactive.weights.add(m_active.weights[i]);
205 }
206 --nan_index;
207 m_active.locations.swapIndices(i, nan_index);
208 m_active.data.swapIndices(i, nan_index);
209 m_active.weights.swapIndices(i, nan_index);
210 }
211 else
212 {
213 i++;
214 }
215 }
216 m_active.locations.setSize(nan_index);
217 m_active.data.setSize(nan_index);
218 m_active.weights.setSize(nan_index);
219 }
220 const Intrinsics& intrinsics() const { return m_intrinsics; }
221 void updateAverage(uint04 index, Vertex<3, fltp04> view_point, t_point_type view_color, uint04 weight)
222 {
223 m_active.locations[index] = AverageValue(m_active.locations[index], m_active.weights[index], view_point, weight);
224 m_active.data[index] = combine(m_active.data[index], m_active.weights[index], view_color, weight);
225 m_active.weights[index] += weight;
226 }
227
228 uint08 updateWeightedAverage(uint04 index, Vertex<3, fltp04> view_point, t_point_type view_color, uint04 weight, fltp04 max_slice_distance)
229 {
230 fltp04 d2 = distanceSquared(m_active.locations[index], view_point);
231 if (d2 > max_slice_distance)
232 {
233 if (!m_lock_weights) m_active.weights[index] -= getMin(m_active.weights[index], weight);
234 return s_max_weight;
235 }
236 else
237 {
238 m_active.locations[index] = AverageValue(m_active.locations[index], m_active.weights[index], view_point, weight);
239 m_active.data[index] = combine(m_active.data[index], m_active.weights[index], view_color, weight);
240 m_active.weights[index] += weight;
241 if (m_active.weights[index] < s_max_weight) return s_max_weight - m_active.weights[index];
242 else return 0U;
243 }
244 }
245
246 void setLockWeights(bool lock_weights)
247 {
248 m_lock_weights = lock_weights;
249 }
250
251 fltp04 update(const Matrix<fltp04>& view_matrix, const Buffer<Vertex<3, fltp04>>& view_points, const Buffer<t_point_type>& view_data)
252 {
253 Time current_time = Time::SystemTime();
254 uint04 weight_mult = 10;
255 if (IsValid(m_last_update_time))
256 {
257 TimeSpan span = current_time - m_last_update_time;
258 weight_mult = cast<uint04>(clip(300.0 * span.elapsedSeconds(), 1.0, 300.0));
259 }
260 m_last_update_time = current_time;
261 return update(view_matrix, view_points, view_data, Buffer<uint04>());
262 }
263
264 fltp04 update(const Matrix<fltp04>& view_matrix, const Buffer<Vertex<3, fltp04>>& view_points, const Buffer<t_point_type>& view_data, const Buffer<uint04>& weights)
265 {
266 Vertex<3, fltp04> new_camera_location = view_matrix.decomposeOffset();
267 m_camera_location = new_camera_location;
268 updateCameraLocationBounds();
269 bool too_much_movement = false;
270 if (!m_lock_weights) {}
271
272 if (m_request_clear_all || IsInvalid(m_view_matrix) || m_active.locations.size() == 0 || too_much_movement)
273 {
274 m_last_update_time = Constant<Time>::Invalid;
275 WLock lock(&m_active);
276 m_active.locations = view_points;
277 m_active.data = view_data;
278 m_active.weights = weights;
279 m_view_matrix = view_matrix;
280 m_inactive.clear();
281 m_inverse_view_matrix = view_matrix.invert();
282 if (m_request_clear_all) clearInactiveLocations();
283 m_request_clear_all = false;
284 return 0.0f;
285 }
286
287 uint08 total_variablity = 0;
288 m_view_matrix = view_matrix;
289 m_inverse_view_matrix = view_matrix.invert();
290
291 if (m_point_smooth_logic)
292 m_point_smooth_logic->getInput(m_active, m_inactive, s_record_weight);
293 uint04 original_size = m_active.size();
294 m_active.locations.addAll(view_points);
295 m_active.data.addAll(view_data);
296 m_active.weights.addAll(weights);
297 calcHistoricPixelLocations(s_record_weight, s_discard_weight, s_max_weight, 2 * m_frame_reduction);
298 fltp04 percent = cast<fltp04>(1.0 - (cast<fltp08>(total_variablity) / (cast<fltp08>(view_points.size()) * cast<fltp08>(s_max_weight))));
299 percent = clip(percent, 0.0f, 1.0f);
300 m_active.setSize(original_size);//remove the newly added points. They just were to add to the buffer
301 return percent;
302 }
303
304 uint04 getWeight(fltp04 camera_distance, Vertex<2, uint04> pixel_location)
305 {
306 uint04 distance_sqr = 0U;
307 for (uint01 i = 0; i < 2; i++)
308 {
309 uint04 dt;
310 if (pixel_location[i] > m_intrinsics.center_i[i]) dt = (pixel_location[i] - m_intrinsics.center_i[i]);
311 else dt = (m_intrinsics.center_i[i] - pixel_location[i]);
312 dt += 10U;
313 distance_sqr += dt * dt;
314 }
315 return getMax(1U, cast<uint04>(FastInvSqrt(cast<fltp04>(distance_sqr)) * 65536.0f * camera_distance));
316 }
317 uint04 getWeight(Vertex<3, fltp04> location, Vertex<2, uint04> pixel_location, Vertex<3, fltp04> camera_location)
318 {
319 fltp04 d2 = distanceSquared(location, camera_location);
320 return getWeight(FastInvSqrt(d2), pixel_location);
321 }
322
323 Vector<3, fltp04> locationAt(Vector<2, uint04> location, uint04 min_weight) const
324 {
325 uint04 idx = screenIndex(location);
326 if (idx >= m_pixel_buffer.size()) return Constant<Vector<3, fltp04>>::Invalid;
327 uint04 index = m_pixel_buffer[idx];
328 if (index >= m_active.weights.size()) return Constant<Vector<3, fltp04>>::Invalid;
329 if (m_active.weights[index] < min_weight) return Constant<Vector<3, fltp04>>::Invalid;
330 return m_active.locations[index];
331 }
332
333 Vector<2, fltp04> screenLocation(Vertex<3, fltp04> location) const
334 {
335 location = m_inverse_view_matrix * location;
336 if (location[Z] <= 0.01) return Constant<Vector<2, fltp04>>::Invalid;
337 return pointToPixel(location);
338 }
339
340 uint04 screenIndex(Vector<2, uint04> location) const
341 {
342 return location[X] + location[Y] * m_intrinsics.size_i[X];
343 }
344
345 bool isInActiveScreen(Vertex<2, fltp04> pixel) const
346 {
347 return pixel[X] >= 10.0f && pixel[Y] >= 10.0f && pixel[X] < m_intrinsics.size_fr[X] && pixel[Y] < m_intrinsics.size_fr[Y];
348 }
349 bool isInScreen(Vertex<2, fltp04> pixel) const
350 {
351 return pixel[X] >= 0.0f && pixel[Y] >= 0.0f && pixel[X] < m_intrinsics.size_f[X] && pixel[Y] < m_intrinsics.size_f[Y];
352 }
353
354 template<class t_node_type>
355 bool contains(Vertex<3, fltp04> value, const t_node_type& node) const
356 {
357 value = m_block_mat * value;
358 auto pixel_value = screenLocation(value);
359 if (!isInScreen(pixel_value) || distanceSquared(value, m_camera_location) > m_max_distance * m_max_distance)
360 return false;
361 return true;
362 }
363 bool contains(Vertex<3, fltp04> value) const
364 {
365 if (m_pixel_buffer.size() == 0) return false;
366 value = m_block_mat * value;
367 auto pixel_value = screenLocation(value);
368 if (!isInScreen(pixel_value) || distanceSquared(value, m_camera_location) > m_max_distance * m_max_distance)
369 return false;
370 return true;
371 }
372
373 IntersectionTypes classifyBlock(Bounds<3, fltp04> bounds) const
374 {
375 if ((m_block_mat * bounds).contains(m_camera_location)) return IntersectionTypes::e_mixed;
376 bool has_object = contains({ bounds[MAX][X],bounds[MAX][Y],bounds[MAX][Z] });
377 if (has_object != contains({ bounds[MAX][X],bounds[MAX][Y],bounds[MIN][Z] })) return IntersectionTypes::e_mixed;
378 if (has_object != contains({ bounds[MAX][X],bounds[MIN][Y],bounds[MAX][Z] })) return IntersectionTypes::e_mixed;
379 if (has_object != contains({ bounds[MAX][X],bounds[MIN][Y],bounds[MIN][Z] })) return IntersectionTypes::e_mixed;
380 if (has_object != contains({ bounds[MIN][X],bounds[MAX][Y],bounds[MAX][Z] })) return IntersectionTypes::e_mixed;
381 if (has_object != contains({ bounds[MIN][X],bounds[MAX][Y],bounds[MIN][Z] })) return IntersectionTypes::e_mixed;
382 if (has_object != contains({ bounds[MIN][X],bounds[MIN][Y],bounds[MAX][Z] })) return IntersectionTypes::e_mixed;
383 if (has_object != contains({ bounds[MIN][X],bounds[MIN][Y],bounds[MIN][Z] })) return IntersectionTypes::e_mixed;
384 if (has_object) return IntersectionTypes::e_mixed; else return IntersectionTypes::e_outside;
385 }
386
387 Vector<2, uint04> viewSizeI() const { return m_intrinsics.size_i; }
388 Vector<2, fltp04> viewSizeF() const { return m_intrinsics.size_f; }
389
390 void setBlockTransform(const Matrix<fltp04>& mat)
391 {
392 m_block_mat = mat;
393 m_block_camera_mat = m_inverse_view_matrix * m_block_mat;
394 }
395
396 void finish()
397 {
398 for (uint04 i = 0; i < m_active.weights.size(); i++)
399 {
400 if (m_active.weights[i] >= s_record_weight)
401 {
402 m_inactive.locations.add(m_active.locations[i]);
403 m_inactive.data.add(m_active.data[i]);
404 m_inactive.weights.add(m_active.weights[i]);
405 }
406 }
407 m_active.clear();
408 }
409
410 void setFilterMatchingPoints(bool filter_matching) { m_filter_matching_points = filter_matching; }
411
412 void getActiveLocations(Buffer<Vertex<3, fltp04>>& locations, Buffer<RGBColor>& colors) const
413 {
414 locations.ensureCapacity(locations.size() + m_active.weights.size());
415 colors.ensureCapacity(colors.size() + m_active.weights.size());
416 for (uint04 i = 0; i < m_active.weights.size(); i++)
417 {
418 if (m_active.weights[i] >= s_record_weight)
419 {
420 locations.add(m_active.locations[i]);
421 colors.add(m_active.data[i].color());
422 }
423 }
424 }
425
426 void getInactiveLocations(Buffer<Vertex<3, fltp04>>& locations, Buffer<RGBColor>& colors) const
427 {
428 uint04 offset = locations.size();
429 locations.setSize(offset + m_inactive.size());
430 colors.setSize(offset + m_inactive.size());
431 memcpy(locations.begin(offset), m_inactive.locations.begin(), sizeof(Vertex<3, fltp04>) * m_inactive.size());
432 for (uint04 i = 0; i < m_inactive.size(); i++) colors[i + offset] = m_inactive.data[i].color();
433 }
434
435 void getActiveNodes(Buffer<t_point_type>& nodes) const
436 {
437 nodes.ensureCapacity(m_active.weights.size());
438 for (uint04 i = 0; i < m_active.weights.size(); i++)
439 if (m_active.weights[i] >= s_record_weight) nodes.add(m_active.data[i]);
440 }
441
442 void getActiveWeights(Buffer<uint04>& weights) const
443 {
444 weights.ensureCapacity(m_active.weights.size());
445 for (uint04 i = 0; i < m_active.weights.size(); i++)
446 if (m_active.weights[i] >= s_record_weight) weights.add(m_active.weights[i]);
447 }
448
449 void clearInactiveLocations() { m_inactive.clear(); }
450 void clearInactiveLocations(PointContainer<t_point_type>& points) { points.clear(); std::swap(m_inactive, points); }
451
452 void addBlockPoints(const Buffer<Vertex<3, fltp04>>& locations, const Buffer<t_point_type>& nodes, const Buffer<uint04>& weights)
453 {
454 lib_assert(locations.size() == nodes.size(), "invalid size");
455 lib_assert(nodes.size() == weights.size(), "invalid size");
456 for (uint04 i = 0; i < locations.size(); i++)
457 {
458 if constexpr (t_point_type::HasOffset()) m_active.locations.add(m_block_mat * (locations[i] + nodes[i].offset()));
459 else m_active.locations.add(m_block_mat * locations[i]);
460 m_active.data.add(nodes[i]);
461 m_active.weights.add(weights[i]);
462 }
463 }
464
465 PointContainer<t_point_type>& inactive() { return m_inactive; }
466 PointContainer<t_point_type>& active() { return m_active; }
467
468 void postClearAll() { m_request_clear_all = true; }
469 void setFrameReduction(uint04 frame_reduction) { m_frame_reduction = frame_reduction; }
470 void setViewSize(const Vector<2, uint04>& view_size) { m_intrinsics.setScreenSize(view_size); }
471 const Buffer<uint04>& pixelBuffer() const { return m_pixel_buffer; }
472
473 [[nodiscard]] inline Vertex<3, fltp04> pixelToPoint(Vertex<3, fltp04> pixel) const
474 {
475 const auto& intr = m_intrinsics;
476 const fltp04 invfx = intr.inv_f[X], invfy = intr.inv_f[Y];
477 fltp04 x = (pixel[X] - intr.pp[X]) * invfx;
478 fltp04 y = (pixel[Y] - intr.pp[Y]) * invfy;
479 const fltp04 xo = x, yo = y;
480 const fltp04 k1 = intr.coeffs[0], k2 = intr.coeffs[1], p1 = intr.coeffs[2], p2 = intr.coeffs[3], k3 = intr.coeffs[4];
481 for (int i = 0; i < 3; ++i)
482 {
483 const fltp04 r2 = std::fma(x, x, y * y);
484 const fltp04 icdist = fltp04(1) / (std::fma(std::fma(std::fma(k3, r2, k2), r2, k1), r2, fltp04(1)));
485 const fltp04 xq = x * icdist;
486 const fltp04 yq = y * icdist;
487 const fltp04 xq2 = xq * xq;
488 const fltp04 yq2 = yq * yq;
489 const fltp04 xyq = xq * yq;
490 const fltp04 dx = fltp04(2) * p1 * xyq + p2 * (r2 + fltp04(2) * xq2);
491 const fltp04 dy = fltp04(2) * p2 * xyq + p1 * (r2 + fltp04(2) * yq2);
492 x = (xo - dx) * icdist;
493 y = (yo - dy) * icdist;
494 }
495 return { pixel[Z] * x,pixel[Z] * y,pixel[Z] };
496 }
497
498 Vertex<2, fltp04> pointToPixel(Vertex<3, fltp04> location) const
499 {
500 Vertex<2, fltp04> xy;
501 const fltp04 iz = fltp04(1) / cast<fltp04>(location[Z]);
502 xy[X] = cast<fltp04>(location[X]) * iz;
503 xy[Y] = cast<fltp04>(location[Y]) * iz;
504 if (!m_camera_location_bounds.contains(xy)) return Constant<Vector<2, fltp04>>::Invalid;
505
506 const fltp04 x0 = xy[X];
507 const fltp04 y0 = xy[Y];
508 const fltp04 x2 = x0 * x0;
509 const fltp04 y2 = y0 * y0;
510 const fltp04 r2 = x2 + y2;
511 const fltp04 k1 = m_intrinsics.coeffs[0];
512 const fltp04 k2 = m_intrinsics.coeffs[1];
513 const fltp04 p1 = m_intrinsics.coeffs[2];
514 const fltp04 p2 = m_intrinsics.coeffs[3];
515 const fltp04 k3 = m_intrinsics.coeffs[4];
516
517 const fltp04 f = std::fma(std::fma(std::fma(k3, r2, k2), r2, k1), r2, fltp04(1));
518 const fltp04 xr = x0 * f;
519 const fltp04 yr = y0 * f;
520
521 const fltp04 two_xy = fltp04(2) * x0 * y0;
522 const fltp04 dx = xr + p1 * two_xy + p2 * (r2 + fltp04(2) * x2);
523 const fltp04 dy = yr + p2 * two_xy + p1 * (r2 + fltp04(2) * y2);
524
525 Vertex<2, fltp04> pixel;
526 pixel[0] = std::fma(dx, m_intrinsics.f[X], m_intrinsics.pp[X]);
527 pixel[1] = std::fma(dy, m_intrinsics.f[Y], m_intrinsics.pp[Y]);
528 return pixel;
529 }
530
531 protected:
532 void fillUBO(uint04 record_weight,
533 uint04 discard_weight, uint04 max_weight, uint04 weight_reduction,
534 ViewPortSmoothShaderLogic::UBO& u)
535 {
536 u.inv_view = m_inverse_view_matrix;
537 u.pp = m_intrinsics.pp;
538 u.f = m_intrinsics.f;
539 u.inv_f = m_intrinsics.inv_f;
540 u.size_f = m_intrinsics.size_f;
541 u.size_fr = m_intrinsics.size_fr;
542 u.size_i = m_intrinsics.size_i;
543 u.k12p1p2[0] = m_intrinsics.coeffs[0];
544 u.k12p1p2[1] = m_intrinsics.coeffs[1];
545 u.k12p1p2[2] = m_intrinsics.coeffs[2];
546 u.k12p1p2[3] = m_intrinsics.coeffs[3];
547 u.k3 = m_intrinsics.coeffs[4];
548 u.max_dist2 = m_max_distance * m_max_distance;
549 u.max_dist2_relax = m_max_distance * 1.2f * m_max_distance * 1.2f;
550 //u.filter_matching_points = 0U;// m_filter_matching_points ? 1u : 0u;
551 for (uint01 i = 0; i < 3; i++)
552 u.cam_pos4[i] = m_camera_location[i];
553 u.cam_pos4[3] = 1.0f;
554 u.max_error_percent_sqrd = m_max_error_percent_sqrd;
555
556 u.weightsA[0] = record_weight; // was s_record_weight
557 u.weightsA[1] = discard_weight; // was s_discard_weight
558 u.weightsA[2] = max_weight; // was s_max_weight
559 u.weightsA[3] = weight_reduction; // was m_frame_reduction*32
560 //u.has_normal = 0u;// t_point_type::HasNormal() ? 1u : 0u;
561 //u.lock_weights = m_lock_weights ? 1u : 0u;
562 u.counts[0] = m_active.size();
563 }
564 void calcHistoricPixelLocationsGL(uint04 record_weight, uint04 discard_weight, uint04 max_weight, uint04 weight_reduction)
565 {
566
567 if (m_active.locations.size() == 0)
568 return;
569 m_point_smooth_logic->ensureCurrent();
570 ViewPortSmoothShaderLogic::UBO u;
571 fillUBO(record_weight, discard_weight, max_weight, weight_reduction, u);
572 m_point_smooth_logic->setUBO(u);
573 m_point_smooth_logic->uploadInputs(m_active, m_intrinsics.size_i.product());
574 m_point_smooth_logic->runAll(m_active.size());
575 }
576
577 protected:
578 ViewPortSmoothShaderLogic* m_point_smooth_logic = nullptr;
579 Matrix<fltp04> m_view_matrix = Constant<Matrix<fltp04>>::Invalid;
580 Matrix<fltp04> m_inverse_view_matrix = Constant<Matrix<fltp04>>::Invalid;
581 Matrix<fltp04> m_block_camera_mat = Constant<Matrix<fltp04>>::Invalid;
582 Matrix<fltp04> m_block_mat = Constant<Matrix<fltp04>>::Invalid;
583 PointContainer<t_point_type> m_inactive;
584 PointContainer<t_point_type> m_active;
585 Intrinsics m_intrinsics;
586 Buffer<uint04> m_pixel_buffer;
587 Bounds<2, fltp04> m_camera_location_bounds;
588 Time m_last_update_time = Constant<Time>::Invalid;
589 Vertex<3, fltp04> m_camera_location;
590 fltp04 m_max_distance = 0.0f;
591 uint04 m_frame_reduction = 0U;
592 fltp04 m_max_error_percent_sqrd = 0.20f * 0.20f;
593 bool m_request_clear_all = false;
594 bool m_filter_matching_points = false;
595 bool m_lock_weights = false;
596
597 };
598}
static Time SystemTime()
Retrieves the current system time which is a combination of std::chrono::steady_clock to ensure smoot...
A point in N-dimensional space, used primarily for spatial location information.
Definition Vertex.hpp:44
The primary namespace for the NDEVR SDK.
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...
constexpr t_type getMax(const t_type &left, const t_type &right)
Finds the max of the given arguments using the > operator The only requirement is that t_type have > ...
static constexpr bool IsValid(const Angle< t_type > &value)
Checks whether the given Angle holds a valid value.
Definition Angle.h:398
t_type dot(const Vector< t_dims, t_type > &v1, const Vector< t_dims, t_type > &v2)
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...
double fltp08
Defines an alias representing an 8 byte floating-point number.
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 HSLColor Constant< HSLColor >::Min
The minimum HSLColor constant with saturation, brightness, and alpha at zero.
Definition HSLColor.h:266
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