NDEVR
API Documentation
KeyFramePointRaster.hpp
1#pragma once
2#include "OrbSLAM/Headers/KeyFrame.h"
3#include "OrbSLAM/Headers/Converter.h"
4#include "PointScanner/Headers/PointContainer.h"
5#include "RasterPointScanner/Headers/ViewportPointSmoother.hpp"
6#include "RasterPointScanner/Headers/PointSmootherBlockFilter.hpp"
7#include "BlockModel/Headers/SegmentedBlockModel.h"
8#include "Design/Headers/GeometryRegistration.h"
9#include "Design/Headers/Geometry.h"
10#include "Design/Headers/Model.h"
11#include "Base/Headers/FileResource.h"
12#include "Base/Headers/Dictionary.h"
13#include <NDEVR/Matrix.h>
14namespace NDEVR
15{
16 struct RasterFrameModel : public Model
17 {
18 RasterFrameModel(const KeyFrame* frame, const Model& model)
19 : Model(model)
20 , frame(frame)
21 {
22 if (!is<NDPN::type>(RasterFrameModel::TypeName()))
23 init();
24 updateModel();
25 }
26 template<class t_point_type>
27 RasterFrameModel(const PointContainer<t_point_type>& points, const Matrix<fltp08>& transform, const KeyFrame* frame, const Model& model)
28 : Model(model)
29 , ndv_transform(transform)
30 , frame(frame)
31 {
32 if (!is<NDPN::type>(RasterFrameModel::TypeName()))
33 init();
34 setPoints(points);
35 updateModel();
36 }
37 void init()
38 {
39 set<NDPN::type>(RasterFrameModel::TypeName());
40 }
41 static constexpr StringView TypeName() { return "frame_raster"; }
42 template<class t_block_model_type>
43 void blockFilter(fltp04 resolution, uint04 weight_filter)
44 {
45 PointContainer<t_block_model_type> points = getPoints();
46 SegmentedBlockModel<t_block_model_type> block_model(resolution, getBounds().expand(1.1f));
47 block_model.addPoints(points.locations, points.colors, points.weights);
48 block_model.syncRasters();
49 BlockModelCache<t_block_model_type, uint04> cache = block_model.getCache(weight_filter);
50 Matrix<fltp04> location_transform = block_model.blockTransform().template as<fltp04>();
51 points.setSize(cache.geo_add_locations.size());
52 for (uint04 i = 0; i < cache.geo_add_locations.size(); i++)
53 {
54 if constexpr (t_block_model_type::HasOffset())
55 points.locations[i] = location_transform * Vertex<3, fltp04>(cache.geo_add_locations[i].template as<3, fltp04>() + cache.geo_add_info[i].offset());
56 else
57 points.locations[i] = location_transform * Vertex<3, fltp04>(cache.geo_add_locations[i].template as<3, fltp04>());
58 points.weights[i] = cache.geo_add_weight[i];
59 points.data[i] = cache.geo_add_info[i].template getAs<t_block_model_type>();
60 }
61 setPoints(points);
62 }
63 template<class t_point_type>
64 PointContainer<t_point_type> getPoints() const
65 {
66 PointContainer<t_point_type> points;
67 Geometry geo(getGeometry());
68 VertexIterator<Vertex<3, fltp04>> pos_iter(VertexProperty::Position, geo);
69 //VertexIterator<Vertex<3, fltp04>> normal_iter(t_point_type::HasNormal() ? VertexProperty::Normal : VertexProperty::Position, geo);
70 VertexIterator<RGBColor> color_iter(t_point_type::HasColor() ? VertexProperty::Color : VertexProperty::Position, geo);
71 points.setSize(pos_iter.size());
72 Matrix<fltp04> transform = geo.get<NDPO::transform>().template as<fltp04>();
73 for (uint04 i = 0; i < points.size(); ++i)
74 {
75 points.locations[i] = transform * pos_iter[i];
76 //if constexpr (t_point_type::HasNormal())
77 //points.data[i].setNormal(normal_iter[i].normalized());
78 if constexpr (t_point_type::HasColor())
79 points.data[i].setColor(color_iter[i]);
80 points.weights[i] = 1U;
81 }
82 return points;
83 }
84 template<class t_point_type>
85 void setPoints(const PointContainer<t_point_type>& points)
86 {
87 Geometry geo = getGeometry();
88 if (!geo.isValid())
89 {
90 geo = createChildGeometry();
91 geo.setGeometryType(GeometryType::e_points);
92 geo.setupVertexTable(points.size()
94 //, t_point_type::HasNormal() ? Geometry::e_cartesian_3S : Geometry::e_no_vertex
96 , t_point_type::HasColor() ? Geometry::e_color_rgb : Geometry::e_no_vertex);
97 uint04 valid_idx = 0;
98 VertexIterator<Vertex<3, fltp04>> pos_iter(VertexProperty::Position, geo);
99 //VertexIterator<Vertex<3, fltp04>> normal_iter(t_point_type::HasNormal() ? VertexProperty::Normal : VertexProperty::Position, geo);
100 VertexIterator<RGBColor> color_iter(t_point_type::HasColor() ? VertexProperty::Color : VertexProperty::Position, geo);
101 Bounds<3, fltp04> bounds = Constant<Bounds<3, fltp04>>::Min;
102 for (uint04 i = 0; i < points.size(); ++i)
103 {
104 bounds.addToBounds(points.locations[i]);
105 }
106 Vector<3, fltp08> max_scale(2.0 * cast<fltp08>(Constant<sint02>::Max));
107 Vector<3, fltp04> pos_scale = max_scale.as<3, fltp04>() / bounds.span();
108 //Vector<3, fltp04> normal_scale(cast<fltp04>(Constant<sint02>::Max));
109 Vector<3, fltp04> offset = bounds.center();
110 for (uint04 i = 0; i < points.size(); ++i)
111 {
112 if (points.weights[i] >= 10)
113 {
114 pos_iter.setVertex(valid_idx, pos_scale * (points.locations[i] - offset));
115 //if constexpr (t_point_type::HasNormal())
116 //normal_iter.setVertex(valid_idx, normal_scale * points.data[i].normal());
117 if constexpr (t_point_type::HasColor())
118 color_iter.setVertex(valid_idx, points.data[i].color());
119 ++valid_idx;
120 }
121 }
122 geo.set<NDPO::transform>(Matrix<fltp08>::OffsetMatrix(offset.as<3, fltp08>()).scale(1.0 / pos_scale.as<3, fltp08>()));
123 geo.setVertexCount(valid_idx);
124 geo.updateVertexColumns();
125 geo.updateModifiedTime();
126 geo.setBounds(Bounds<3, fltp08>(Vertex<3,fltp08>(Constant<sint02>::Min), Vertex<3, fltp08>(Constant<sint02>::Max)));
128 }
129 }
130 void updateModel()
131 {
132 if (frame == nullptr)
133 return;
134 TranslatedString name;
135 if (!frame->isBad())
136 {
137 name = _t("Frame [frame_id]").replace("[frame_id]", String(frame->keyframe_id));
138 }
139 else
140 {
141 name = _t("Frame [frame_id] (Bad)").replace("[frame_id]", String(frame->keyframe_id));
142 //updateDesignVisible(false);
143 }
145 update<NDPO::transform>(ndv_transform);
146 }
147 const KeyFrame* frame = nullptr;
148 Matrix<fltp08> ndv_transform;
149 };
150 class FramePointScan : public Model
151 {
152 public:
153 FramePointScan(const Model& model)
154 : Model(model)
155 {
156 if (!is<NDPN::type>(FramePointScan::TypeName()))
157 init();
158 }
159 void init()
160 {
161 set<NDPN::type>(TypeName());
162 Material material = createChildMaterial();
164 material.set<NDPOC::name>(_t("Live Material"));
165 material.set<NDPM::pixel_thickness>(1.0f);
167 }
168 static constexpr StringView TypeName() { return "frame_point_scan"; }
169
170 void setPointStride(uint04 point_stride)
171 {
172 m_point_stride = point_stride;
173 }
174 template<class t_point_type>
175 void add(const KeyFrame* frame, PointContainer<t_point_type>& points)
176 {
177 if (points.locations.size() == 0 || m_last_keyframe == nullptr)
178 return;
179 frame->setDoNotReduce(true);
180 if (m_last_keyframe != nullptr)
181 {
182 if (m_last_keyframe->isBad())
183 {
184 //find the closest valid keyframe to this
185 uint04 original_id = m_last_keyframe->id;
186 m_last_keyframe = frame;
187 while (m_last_keyframe->mPrevKF && m_last_keyframe->mPrevKF->id > original_id)
188 m_last_keyframe = m_last_keyframe->mPrevKF;
189 }
190 Matrix<fltp08> mat = Converter::ToNDVMat(m_last_keyframe->poseInverse().matrix()).as<fltp08>();
191 Matrix<fltp04> inverse_mat = mat.invert().as<fltp04>();
192 for (Vertex<3, fltp04>& p0 : points.locations)
193 p0 = inverse_mat * p0;
194 RasterFrameModel frame_model(points, mat, m_last_keyframe, createChild());
195 m_rasters.add(frame_model);
197 }
198 m_last_keyframe = frame;
199 }
200 bool shouldAddFramePoints(const KeyFrame* frame)
201 {
202 if (frame == nullptr)
203 return false;
204 if (m_last_keyframe == nullptr)
205 {
206 m_last_keyframe = frame;
207 return false;
208 }
209 if (frame == m_last_keyframe)
210 return false;
211 if (!m_last_keyframe->isSet())
212 return false;
213 if (frame->isFirstConnection())
214 return true;
215 if (frame->timestamp() - m_last_keyframe->timestamp() < 0.1)
216 return false;
217 Eigen::Vector3f r1 = frame->GetRotation() * Eigen::Vector3f(1.0, 0.0, 0.0);
218 Eigen::Vector3f r2 = m_last_keyframe->GetRotation() * Eigen::Vector3f(1.0, 0.0, 0.0);
219 Eigen::Vector3f d1 = frame->cameraCenter();
220 Eigen::Vector3f d2 = m_last_keyframe->cameraCenter();
221 if ((d1 - d2).norm() < 0.1f && (r1 - r2).norm() < 0.2f)
222 return false;
223 return true;
224 }
225 template<class t_block_filter_type>
226 void blockFilter(fltp04 resolution, uint04 weight_filter)
227 {
228 for (uint04 i = 0; i < m_rasters.size(); ++i)
229 {
230 m_rasters[i].template blockFilter<t_block_filter_type>(resolution, weight_filter);
231 }
232 }
233 void updateModels()
234 {
235 for (uint04 i = 0; i < m_rasters.size(); i++)
236 m_rasters[i].updateModel();
237 }
238 bool updateRaster()
239 {
240 bool updated = false;
241 for(uint04 i = m_rasters.size() - 1; IsValid(i); --i)
242 {
243 bool needs_update_model = false;
244 const KeyFrame* frame = m_rasters[i].frame;
245 Matrix<fltp08> new_ndv_mat = Converter::ToNDVMat(frame->poseInverse().matrix()).as<fltp08>();
246 if (!equals(m_rasters[i].ndv_transform, new_ndv_mat, 0.000001))
247 needs_update_model = true;
248 m_rasters[i].ndv_transform = new_ndv_mat;
249 if (!needs_update_model)
250 needs_update_model = frame->isBad() && m_rasters[i].isVisible();
251 if (needs_update_model)
252 m_rasters[i].updateModel();
253 updated |= needs_update_model;
254 }
255 return updated;
256 }
257 template<class t_point_type, class t_block_model_type>
258 void addAllToBlockModel(ViewportPointSmoother<t_point_type>& smoother
259 , SegmentedBlockModel<t_block_model_type>& block_model
260 , InfoPipe* log)
261 {
262 if (m_rasters.size() == 0)
263 return;
264 ProgressInfo progress(_t("Optimizing Graph"), log, 0.0f);
265 block_model.update<NDPO::transform>(block_model.getParentTransform().invert() * getCompleteTransform());
266 smoother.setFrameReduction(0U);
267 smoother.setBoundsFilter(false);
268 smoother.setLockWeights(true);
269 for (uint04 i = 0; i < m_rasters.size(); i++)
270 {
271 auto& iter = m_rasters[i];
272 if (iter.frame->isBad())
273 continue;
274 Matrix<fltp04> ref_mat = m_rasters[i].ndv_transform.template as<fltp04>();
275 //filter.transferActiveLocations();
276 auto points = iter.getPoints<t_point_type>();
277 for (auto& point : points.locations)
278 point = ref_mat * point;
279 //smoother.update(ref_mat, points, iter.points.colors, Buffer<Vector<2, uint04>>(), iter.points.weights, 12.0f, 10U);
280 //auto inactive = smoother.inactive();
281 block_model.addPoints(points.locations, points.data, points.weights);
282 //smoother.clearInactiveLocations();
283 //block_model.filterGeometries(filter);
284 //block_model.add
285 progress.setProgress(i, m_rasters.size());
286 }
287 progress.setProgress(1.0f);
288 const auto& active = smoother.active();
289 block_model.addPoints(active.locations, active.data, active.weights);
290 const auto& inactive = smoother.inactive();
291 block_model.addPoints(inactive.locations, inactive.data, inactive.weights);
292 smoother.postClearAll();
293 smoother.setBoundsFilter(false);
294 }
295 template<class t_block_model_type>
296 void registerPoints(SegmentedBlockModel<t_block_model_type>& block_model
297 , GeometryRegistration& reg
298 , InfoPipe* log
299 , const void* lock_ptr)
300 {
301 {
302 WLock lock(lock_ptr);
303 block_model.update<NDPO::transform>(block_model.getParentTransform().invert()
305 updateModels();
306 }
307 ProgressInfo progress(_t("Register"), log);
308 progress.setProgress(0.0f);
309 if (m_rasters.size() < 2)
310 return;
311 {
312 WLock lock(lock_ptr);
314 }
315 GeometryRegistrationParameters params;
316 {
317 Matrix<fltp04> initial_transform = m_rasters[0].ndv_transform.template as<fltp04>();
318 PointContainer<t_block_model_type> points = m_rasters[0].getPoints<t_block_model_type>();
319 for (uint04 i = 0; i < points.locations.size(); i++)
320 points.locations[i] = initial_transform * points.locations[i];
321 block_model.addPoints(points.locations, points.data, points.weights);
322 }
323 uint04 finished_count = 0;
324 params.update_data_callback = [&](uint04 i, uint04 iteration_b, Matrix<fltp08>& mat, bool finished)
325 {
326 //if (m_root && IsValid(mat))
327 {
328 //WLock lock(lock_ptr);
329 //m_root->getChild(i + 1).update<NDPO::transform>(mat);
330 }
331 if (!finished)
332 return;
333 progress.setProgress(++finished_count, m_rasters.size() - 1);
334 if (IsInvalid(mat))
335 return;//Bad registration
336 auto& raster = m_rasters[i + 1];
337 Matrix<fltp04> adjustment = mat.template as<fltp04>();
338 if (IsInvalid(adjustment))
339 return;//Bad registration
340 PointContainer<t_block_model_type> points = raster.getPoints<t_block_model_type>();
341 for (uint04 i = 0; i < points.locations.size(); i++)
342 points.locations[i] = adjustment * points.locations[i];
343 block_model.addPoints(points.locations, points.data, points.weights);
344 block_model.syncRasters();
345 block_model.updateCloudGeometries(10, 0, lock_ptr);
346 };
347 params.registration_points.setSize(m_rasters.size() - 1);
348 for (uint04 i = 0; i < m_rasters.size(); i++)
349 {
350 auto& iter = m_rasters[i];
351 if (!iter.get<NDPO::spacial_visible>())
352 continue;
353 if (params.reference.positions.size() == 0)
354 {
355 PointContainer<t_block_model_type> points = m_rasters[0].getPoints<t_block_model_type>();
356 params.reference_transform = m_rasters[0].ndv_transform;
357 params.reference.positions = points.locations;
358 }
359 else
360 {
361 PointContainer<t_block_model_type> points = iter.getPoints<t_block_model_type>();
362 params.registration_points[i - 1].positions = points.locations;
363 params.original_transforms.add(m_rasters[i].ndv_transform);
364 }
365 }
366 reg.runRegistration(params);
367 progress.setProgress(1.0f);
368 {
369 WLock lock(lock_ptr);
371 }
372 }
373 void setMinResolution(fltp04 min_resolution) { m_min_resolution = min_resolution; }
374 const KeyFrame* lastKeyFrame() const { return m_last_keyframe; };
375 protected:
376 Buffer<RasterFrameModel> m_rasters;
377 const KeyFrame* m_last_keyframe = nullptr;
378 fltp04 m_min_resolution = 0.0f;
379 uint04 m_point_stride = 1U;
380 };
381}
static Matrix< fltp04 > ToNDVMat(const Eigen::Matrix< float, 4, 4 > &m)
Converts a 4x4 float Eigen matrix to an NDEVR Matrix.
Definition Converter.h:105
void set(t_property_type property, const t_type &value)
Sets a property value in the database.
bool is(t_property_type property, const StringView &value) const
Checks whether a string property matches the given StringView value.
bool update(t_property_type property, const t_type &value, const void *lock=nullptr)
Updates a property only if the new value differs from the current value.
@ e_cartesian_3S
3D Cartesian coordinates, short integer.
Definition Geometry.h:177
@ e_color_rgb
RGB color data.
Definition Geometry.h:171
@ e_no_vertex
No vertex data present.
Definition Geometry.h:151
@ e_flat
Flat shading. Shading is done on per-face base, diffuse only. Also known as 'faceted shading'.
Definition Material.h:163
@ e_color_channel
Color is taken from the per-vertex color channel.
Definition Material.h:188
A core class that represents a node on model hierarchy.
Definition Model.h:292
void updateModifiedTime(Time time=Time::SystemTime())
Updates the modified timestamp for this model.
Geometry getGeometry() const
Returns the geometry attached to this model.
Model createChild()
Creates a new child model and appends it to this model's child list.
Geometry createChildGeometry()
Creates a new child geometry for this model.
Matrix< fltp08 > getCompleteTransform() const
Returns the fully composed local-to-global transform matrix for this model.
Bounds< 3, fltp08 > getBounds() const
Returns the local bounding box of this model.
Material createChildMaterial(bool copy_child=false)
Creates a new child material for this model.
The primary namespace for the NDEVR SDK.
@ 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
@ Position
XYZ position of 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
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.
double fltp08
Defines an alias representing an 8 byte floating-point number.
@ name
The calculated/translated display name.
static constexpr bool IsInvalid(const Angle< t_type > &value)
Checks whether the given Angle holds an invalid value.
Definition Angle.h:388
@ name
The display name of the object.
@ transform
A 4x4 transform matrix that maps local coordinates into global space.
@ spacial_visible
Whether the object is visible in the 3D spatial view.
constexpr HSLColor Constant< HSLColor >::Min
The minimum HSLColor constant with saturation, brightness, and alpha at zero.
Definition HSLColor.h:266
constexpr bool equals(const LineSegment< t_dims, t_type, t_vertex > &left, const LineSegment< t_dims, t_type, t_vertex > &right, const t_type &epsilon=cast< t_type >(0))
Tests if objects are considered equal.
Definition Line.hpp:791
@ e_KD
Diffuse texture/color channel.
constexpr t_to cast(const Angle< t_from > &value)
Casts an Angle from one backing type to another.
Definition Angle.h:408