Cogs.Core
PotreeSystem.h
1#pragma once
2
3#include "Scene/RayPick.h"
4#include "Scene/GetBounds.h"
5#include "Resources/DataFetcherManager.h"
6#include "Resources/Resources.h"
7#include "Systems/ComponentSystem.h"
8
9#include "PotreeComponent.h"
10#include "List.h"
11
12#include "Rendering/Common.h"
13#include "Rendering/VertexFormat.h"
14#include "Resources/MeshStreamsLayout.h"
15
16#include "Foundation/Collections/Pool.h"
17#include "Foundation/Collections/SmallVector.h"
18#include "Foundation/Memory/MemoryBuffer.h"
19
20#include <glm/glm.hpp>
21
22namespace Cogs::Core
23{
24 struct CameraData;
25}
26
27namespace Cogs::Core
28{
29 struct PotreeRenderer;
30 struct PotreeSystem;
31
32 enum struct PotreeState {
33 Uninitialized,
34 Error,
35 RequestedCloudJS,
36 ParsedCloudJs,
37 Running
38 };
39
40 enum struct PotreeeType
41 {
42 None,
43 Double,
44 Float,
45 Int8,
46 UInt8,
47 Int16,
48 UInt16,
49 Int32,
50 UInt32,
51 Int64,
52 UInt64,
53 };
54
55 enum struct PotreeEnconding
56 {
57 Default,
58 ZStd,
59 Brotli,
60 };
61
62 enum struct PotreeAttributes {
63 POSITION_CARTESIAN = 0, // 3 x uint32 : x, y, z
64 RGBA_PACKED, // 4 x uint8 : r, g, b, a
65 RGB_U8_PACKED, // 3 x uint8 : r, g, b
66 RGB_U16_PACKED, // 3 x uint16
67 NORMAL, // 3 x float32 : x, y, z
68 NORMAL_SPHEREMAPPED, // 2 x uint8
69 NORMAL_OCT16, // 2 x uint8
70 INTENSITY_U16, // 1 x uint16
71 CLASSIFICATION, // 1 x uint8
72 FILLER_1B, // 1 x uint8
73 COUNT // Number of known attributes.
74 };
75
76 enum struct PotreeVertexLayout {
77 POSITION,
78 POSITION_COLOR,
79 POSITION_NORMAL,
80 POSITION_COLOR_NORMAL,
81 POSITION_INTENSITY,
82 POSITION_COLOR_INTENSITY,
83 POSITION_NORMAL_INTENSITY,
84 POSITION_COLOR_NORMAL_INTENSITY,
85 POSITION_CLASSIFICATION,
86 POSITION_COLOR_CLASSIFICATION,
87 POSITION_NORMAL_CLASSIFICATION,
88 POSITION_COLOR_NORMAL_CLASSIFICATION,
89 POSITION_INTENSITY_CLASSIFICATION,
90 POSITION_COLOR_INTENSITY_CLASSIFICATION,
91 POSITION_NORMAL_INTENSITY_CLASSIFICATION,
92 POSITION_COLOR_NORMAL_INTENSITY_CLASSIFICATION,
93 COUNT
94 };
95
97 unsigned positionOffset;
98 unsigned colorOffset;
99 unsigned normalOffset;
100 unsigned intensityOffset;
101 unsigned classOffset;
102 unsigned stride;
103 std::vector<Cogs::VertexElement> elements;
104 };
105
106 struct PotreeSubtree;
107 struct PotreeData;
108
110 {
111 uint64_t byteOffset = 0;
112 uint64_t byteCount = 0;
113 ListNode subtreeNode; // List node used for membership in subtree.
114 ListNode activeNode; // List node used for membership in list of active nodes.
115 ListNode tmpNode; // List node used temporarily within a function.
116 PotreeSubtree* owningSubtree = nullptr; // Pointer to subtree that owns the node.
117 union {
118 PotreeCell* children[8]; // Regular node: Child node.
119 PotreeSubtree* linkedSubtree; // Subtree link node: Pointer to subtree.
120 };
121
122 Cogs::BufferHandle boxParametersBuffer;
123 VertexBufferHandle pointData; // VBO with position and attribute data, see PotreeData for layout.
124 Memory::TypedBuffer<glm::vec3> points; // CPU side copy of point positions, used for picking.
125
126 glm::vec3 tbmin, tbmax; // Tight bounding box for the points inside this cell. Origin is poData->tbCenter.
127
128 uint32_t hierarchyNumPoints = 0; // Number from hrc files, is _not_ number of points in cell, maybe in hierarchy below.
129 uint32_t pointCount = 0; // Number of points in pointData
130 uint32_t prefix = 0; // Path to this node within this subtree.
131 uint16_t texOffset = static_cast<uint16_t>(~0u); // Current position in texture.
132 uint8_t i = 0; // Cell position within this subtree.
133 uint8_t j = 0; // Cell position within this subtree.
134 uint8_t k = 0; // Cell position within this subtree.
135 uint8_t l = 0; // Cell level within this subtree.
136 uint8_t scaleFactor = 100; // pointsize is scaled with exp2(10.0 - (25.5 * data_.w + level)),
137 // 100 implies just level scale: exp2(10 - 25.5(100.0/255.0)) = exp2(10 - 10) = exp2(0) = 1.
138
139 enum struct Kind : uint8_t
140 {
141 RegularNode,
142 SubtreeLink
143 } kind = Kind::RegularNode;
144 enum struct State : uint8_t
145 {
146 None,
147 Issued,
148 Ready,
149 Failed
150 } state = State::None;
151 enum struct Flags : uint8_t
152 {
153 None = 0,
154 Active = 1 << 0,
155 } flags = Flags::None;
156 DataFetcherManager::FetchId fetch_id = DataFetcherManager::NoFetchId;
157
158 inline bool isRootNode() const; // declared further down, needs subtree defined
159 bool isActive() const { return unsigned(flags) & unsigned(Flags::Active); }
160 void setActive() { flags = Flags(unsigned(flags) | unsigned(Flags::Active)); }
161 void setInactive() { flags = Flags(unsigned(flags) & ~unsigned(Flags::Active)); }
162
163 void appendDescendSteps(std::string& path) const;
164
165 void fetchData(Context* context, PotreeSystem* poSystem, const PotreeComponent* poComp, PotreeData* poData);
166
167 void releaseData(Context* context, PotreeData* poData);
168
169 };
170 ENABLE_ENUM_FLAGS(PotreeCell::Flags);
171
173 {
174 enum struct State {
175 None,
176 Issued,
177 Ready,
178 Failed
179 } state = State::None;
180 DataFetcherManager::FetchId fetch_id = DataFetcherManager::NoFetchId;
181
182 ListNode member;
183 PotreeCell* containingCell = nullptr; // Pointer to PoNode that links to this subtree.
184 std::string path; // URL prefix of this subtree.
185 std::string prefix;
186 List<PotreeCell, offsetof(PotreeCell, subtreeNode)> cells;
187 uint32_t subtreeId = 0;
188 uint32_t i = 0; // Global position of subtree node.
189 uint32_t j = 0; // Global position of subtree node.
190 uint32_t k = 0; // Global position of subtree node.
191 uint32_t l = 0; // Global position of subtree node.
192
193 void fetchLayoutAndInitialize(Context* context, PotreeSystem* poSystem, const PotreeComponent* poComp, PotreeData* poData, PotreeCell* containingCell);
194
195 void release(Context* context, PotreeData* poData);
196 };
197
198 bool PotreeCell::isRootNode() const { return l == 0 && owningSubtree->containingCell == nullptr; }
199
201 {
202 PotreeCell* cell = nullptr;
203 float priority = 0.f;
204 };
205
206 struct PotreeData {
207 PotreeCell* root = nullptr;
208
209 std::vector<PotreeNodeHeapItem> lodHeap;
210
211 std::string jsonPath;
212 std::string rootPath;
213 std::string octreeDir;
214 std::string suffix = ".bin";
216 static constexpr size_t MaxClipPlanes = 6u;
217 glm::vec4 clipPlanes[MaxClipPlanes];
218 size_t clipPlaneCount = 0;
219
221 PotreeNotification potreeNotificationState = PotreeNotification::None;
222
224 uint32_t requestsInFlight = 0U;
225
226 struct {
227 float val = 1.f;
228 float min = 1.f;
229 float max = 1.f;
230 } pointSize;
231
232 // Transforms from octtree native frame
233 struct {
234 glm::dvec3 positionInEntityFrame; // Position of octtree frame in entity frame (defined by transformcomponent)
235 glm::vec3 currentPositionInEntityFrame; // current position in entity frame (adjusted by originPolicy)
236
237 glm::vec3 toBBoxShift; // Shifts a point from octtree frame to frame where bounding box min corner is origin
238 glm::vec3 fullBBoxSize; // Size of full bounding box
239 float fullBBoxDiagonal;
240
241 glm::vec3 fullBBoxMin; // Full bounding box min corner in octtree frame
242 glm::vec3 fullBBoxMax; // Full bounding box max corner in octtree frame
243
244 glm::vec3 tightBBoxMin; // Tight bounding box min corner in octtree frame
245 glm::vec3 tightBBoxMax; // Tight bounding box max corner in octtree frame
246 } octtreeFrame;
247
248 // Transform from encoded point positions to octtree Frame.
249 struct {
250 glm::vec3 scale;
251 glm::vec3 shift;
252 } positionDecode;
253
254 // Original extents as given in metadata.json or cloud.js
255 struct {
256 glm::dvec3 bbmin, bbmax; // Octree extent
257
258 // Actual bounding box for points (might be smaller than octree extent)
259 // v1.x: Taken from cloud.js:tightBoundingBox.
260 // v2.x: Taken from metadata.json:attrobutes.position.min|max.
261 glm::dvec3 tbmin = glm::vec3(0.f);
262 glm::dvec3 tbmax = glm::vec3(0.f);
263
264 // v1.x: Taken from cloud.js:scale (scalar)
265 // v2.x: Taken from cloud.js:scale (vec3)
266 glm::vec3 scale = glm::vec3(1.f);
267
268 // v2.x: Taken from metadata.offset
269 glm::dvec3 offset = glm::vec3(0.f);
270
271 } metadata;
272
273 // controls behaviour of density-based scaling
274 struct {
275 float scale = 25.5f; // scale for density value
276 float bias = 10.f; // offset before density and level takes hold on sizing
277 float levelScale = 1.f; // Strength of hierarchy depth on scaling
278 } densitySized;
279
281 PotreeEnconding encoding = PotreeEnconding::Default;
282 uint32_t firstChunkSize = 0; // v2: Size of root node hierarchy data.
283 uint32_t hierarchyStepSize = 0;
284 uint32_t hierarchyDepth = 0; // v2: Max depth of octtree.
285
286 float spacing = 1.f; // Minimum distance between point at root level.
287
288 float modelSpaceRadius = 1.f;
289 float tolerance = std::numeric_limits<float>::infinity(); // Maximum cell screen diagonal in pixels before refinement.
290 float rootTolerance = std::numeric_limits<float>::infinity(); // Maximum root cell screen diagonal in pixels before refinement.
291
292 unsigned versionMajor = 0;
293 unsigned versionMinor = 0;
294
295 bool hasColor = false;
296 bool hasNormal = false;
297 bool hasIntensity = false;
298 bool hasClassification = false;
299
300 bool supportPicking = true;
301
302 PotreeState state = PotreeState::Uninitialized;
303 DataFetcherManager::FetchId fetch_id = DataFetcherManager::NoFetchId;
304 PotreeVertexLayout layout = PotreeVertexLayout::COUNT;
305
306 MeshStreamsLayout streamsLayout;
307
308 Cogs::BufferHandle pointParametersBuffer;
309
310 Cogs::TextureHandle octtreeTexture;
311 Memory::TypedBuffer<glm::u8vec4> octtreeTextureData;
312
313 uint32_t instanceId = 0;
315
316 glm::mat4 worldFromOcttreeFrame;
317
318 // List of loaded subtrees. Root is always the first subtree.
319 List<PotreeSubtree, offsetof(PotreeSubtree, member)> subtrees;
320
321 // List of cells flagged as active.
322 List<PotreeCell, offsetof(PotreeCell, activeNode)> activeCells;
323
324 Memory::MemoryBuffer tmpVertexData;
325 Memory::TypedBuffer<PotreeCell*> tmpCellPointers;
326
327 static constexpr size_t occupancyGridDim = 32;
328 std::vector<uint8_t> occupancyTmpData;
329
330 Collections::Pool<PotreeCell> cellStore;
331 Collections::Pool<PotreeSubtree> subtreeStore;
332
333 struct {
334 MaterialInstanceHandle instance;
335 VariableKey scale = NoProperty;
336 VariableKey offset = NoProperty;
337 } boxMaterial;
338
339 struct {
340 MaterialInstanceHandle instance;
341 VariableKey pointSize = NoProperty;
342 VariableKey shadingIntensity = NoProperty;
343 VariableKey octTexScale = NoProperty;
344 VariableKey minPointSize = NoProperty;
345 VariableKey maxPointSize = NoProperty;
346 VariableKey baseColor = NoProperty;
347 VariableKey outlineColor = NoProperty;
348 VariableKey outlineSize = NoProperty;
349 VariableKey invShift = NoProperty;
350 VariableKey invScale = NoProperty;
351 VariableKey gradient = NoProperty;
352 } pointMaterial;
353
354 glm::mat4 frustum; // transform unit cube to frustum used when updating lod, used for debug viz.
355
356 glm::dvec3 boundsMin = glm::dvec3(std::numeric_limits<double>::max());
357 glm::dvec3 boundsMax = glm::dvec3(-std::numeric_limits<double>::max());
358 };
359
360 // PoData contains lists that don't support to be memmoved, and component data
361 // might be memmoved, so we keep them in a separate block.
363 {
364 std::unique_ptr<PotreeData> poData;
365 };
366
368 glm::vec4 pointControl[2];
369 glm::vec4 passControl[1+PotreeData::MaxClipPlanes];
370 };
371
373 glm::vec4 boxControl[3];
374 };
375
376 struct PotreeSystem;
377
378
380 {
381 Memory::MemoryBuffer vertexData;
382 size_t pointCount = 0;
383
384 size_t nonEmptyCells = 0;
385 glm::vec3 lo = glm::vec3(std::numeric_limits<float>::max());
386 glm::vec3 hi = glm::vec3(-std::numeric_limits<float>::max());
387
388 Memory::TypedBuffer<uint8_t> occupancyTmpData;
390
391 enum struct State {
392 NoData,
393 DecodingFailed,
394 Success
395 } state = State::Success;
396 };
397
399 {
400 const PotreeVertexLayoutInfo& layoutInfo;
402 glm::uvec4 cellPos;
403 glm::vec3 posScale;
404 glm::vec3 posShift;
405 PotreeEnconding encoding;
406 size_t occGridDim;
407 glm::vec3 fullBBoxMin;
408 glm::vec3 fullBBoxSize;
409 };
410
411 void decodePotreeBin(PotreeDecodeOutData& out, const PotreeDecodeInData& in, const Cogs::FileContents& inData);
412
414 {
415 PotreePicker(PotreeSystem* poSystem) : poSystem(poSystem) {}
416
417 bool pickCamera(Context* context,
418 const CameraComponent& camera,
419 const glm::vec2& normPosition,
420 float /*rayLength*/,
421 float radius,
422 PickingFlags pickingFlags,
423 PicksReturned returnFlag,
424 const RayPicking::RayPickFilter& filter,
425 std::vector<RayPicking::RayPickHit>& hits) override;
426
427 bool pickRay(Context* /*context*/,
428 const glm::vec3& startPos,
429 const glm::quat& rot,
430 float rayLength,
431 float radius,
432 PickingFlags pickingFlags,
433 PicksReturned returnFlag,
434 const RayPicking::RayPickFilter& filter,
435 std::vector<RayPicking::RayPickHit>& hits) override;
436
437 PotreeSystem* poSystem = nullptr;
438 };
439
440 class PotreeBounds final : public IGetBounds {
441 public:
442 explicit PotreeBounds(PotreeSystem* poSystem) : poSystem(poSystem) {}
443
444 void getBounds(Context* context, Cogs::Geometry::BoundingBox& bounds) override;
445
446 bool getBounds(Context* context, const ComponentModel::Entity* entity, Cogs::Geometry::BoundingBox& bounds, bool ignoreVisibility) const override;
447
448 private:
449 bool getBounds(Context* context, const PotreeComponent& poComp, Cogs::Geometry::BoundingBox& bounds, bool ignoreVisibility) const;
450
451 private:
452 PotreeSystem* poSystem = nullptr;
453 };
454
455 struct PotreeSystem : public ComponentSystemWithDataPool<PotreeComponent, PotreeDataHolder>
456 {
457 PotreeSystem(Memory::Allocator* allocator, SizeType capacity) : ComponentSystemWithDataPool(allocator, capacity) {}
458
459 void initialize(Context* context) override;
460 void cleanup(Context* context) override;
461
462 void preUpdate(Context* context) override;
463
464 void update(Context* context) override;
465
467 void destroyComponent(ComponentHandle component) override;
468
469 // Make sure that poComp hasn't died or changed significantly since request was issued
470 static bool lookupAndCheckForStaleness(Context* context, PotreeSystem*& potreeSystem, PotreeData*& poData, PotreeComponent*& poComp, const uint32_t componentId);
471
472 static bool lookupAndCheckForStaleness(Context* context, PotreeSystem*& potreeSystem, PotreeData*& poData, PotreeComponent*& poComp, PotreeSubtree*& subtree, const uint32_t componentId, const uint32_t subtreeId);
473
474 void issueSubtreeFetch(Context* context, const PotreeComponent* poComp, PotreeData* poData, PotreeCell* parent);
475
476 // Implementation in ManageLodLevels.cpp
477 void updateLodLevels(Context* context);
478
479 void updateOcttreeFrame(Context* context, PotreeData& poData, const PotreeComponent& poComp);
480
482 static void startFetch(Context* context, const PotreeComponent* poComp, PotreeData* poData);
483
487 static void endFetch(Context* context, const PotreeComponent* poComp, PotreeData* poData);
488
489 public:
490 unsigned requestsInFlight = 0;
491 bool materialLoaded = false;
492
493 MaterialHandle defaultBoxMaterial;
494 MaterialHandle defaultPointMaterial;
495
496
497 PotreeRenderer* renderer = nullptr;
498 TextureHandle defaultGradient;
499
500 PotreeBounds* bounds = nullptr;
501 PotreePicker* picker = nullptr;
502
503
504 static PotreeVertexLayoutInfo vertexLayoutInfo[static_cast<size_t>(PotreeVertexLayout::COUNT)];
505
506 };
507
508}
Container for components, providing composition of dynamic entities.
Definition: Entity.h:18
Context * context
Pointer to the Context instance the system lives in.
void update()
Updates the system state to that of the current frame.
void preUpdate()
Run the pre-update method of the system.
Component system with parallel data per component stored in a pool similar to how the components them...
A Context instance contains all the services, systems and runtime components needed to use Cogs.
Definition: Context.h:83
Interface for modules implementing custom picking.
Definition: RayPick.h:140
void getBounds(Context *context, Cogs::Geometry::BoundingBox &bounds) override
Expand bounds including bounds of all entities in this system in world coordinates.
Base allocator implementation.
Definition: Allocator.h:30
Contains the Engine, Renderer, resource managers and other systems needed to run Cogs....
@ Success
Resource activated successfully.
PicksReturned
  * Options for returning picking hits.
Definition: PickingFlags.h:40
PickingFlags
Options for COGS picking.
Definition: PickingFlags.h:12
@ None
No debug node outlines.
@ Ready
All 6 baselayers are fully loaded, instance will begin rendering.
@ None
Just use scale and offset as is.
uint16_t VariableKey
Used to lookup material properties.
Definition: Resources.h:46
ComponentIndex SizeType
Type used to track the size of pools.
Definition: Component.h:19
Handle to a Component instance.
Definition: Component.h:67
Component for Point Cloud Display.
uint32_t requestsInFlight
Number of outstanding data fetch requests.
Definition: PotreeSystem.h:224
std::vector< PotreeNodeHeapItem > lodHeap
heap used while calculating lod levels
Definition: PotreeSystem.h:209
float val
Current dpi-scaled and min-max clamped point-size.
Definition: PotreeSystem.h:227
float min
Current dpi-scaled minimum point-size.
Definition: PotreeSystem.h:228
float max
Current dpi-scaled maximum point-size.
Definition: PotreeSystem.h:229
static constexpr size_t MaxClipPlanes
Max available in shader.
Definition: PotreeSystem.h:216
std::string jsonPath
URL to metadata file.
Definition: PotreeSystem.h:211
PotreeNotification potreeNotificationState
Current notification state for this PoTree Component.
Definition: PotreeSystem.h:221
std::string octreeDir
1.x only: subdir with data
Definition: PotreeSystem.h:213
std::string rootPath
URL to folder containing metadata file.
Definition: PotreeSystem.h:212
bool pickRay(Context *, const glm::vec3 &startPos, const glm::quat &rot, float rayLength, float radius, PickingFlags pickingFlags, PicksReturned returnFlag, const RayPicking::RayPickFilter &filter, std::vector< RayPicking::RayPickHit > &hits) override
Do a ray pick from a position and orientation in world space and return all hits.
bool pickCamera(Context *context, const CameraComponent &camera, const glm::vec2 &normPosition, float, float radius, PickingFlags pickingFlags, PicksReturned returnFlag, const RayPicking::RayPickFilter &filter, std::vector< RayPicking::RayPickHit > &hits) override
Do a ray pick from a normalized screen space position in the camera direction and return all hits.
ComponentHandle createComponent() override
static void startFetch(Context *context, const PotreeComponent *poComp, PotreeData *poData)
Update Component request count and notify client when starting data fetch.
void destroyComponent(ComponentHandle component) override
void cleanup(Context *context) override
Provided for custom cleanup logic in derived systems.
void initialize(Context *context) override
Initialize the system.
static void endFetch(Context *context, const PotreeComponent *poComp, PotreeData *poData)
Abstract base class storing data read from a file.
Definition: FileContents.h:20