3#include "PotreeSystem.h"
5#include "Foundation/Logging/Logger.h"
6#include "Foundation/Platform/IO.h"
14 auto * cell = poData->cellStore.create();
15 cell->owningSubtree = subtree;
16 subtree->cells.push(cell);
22 size_t n = data->size / 5;
24 const glm::vec3& tbMinCenter = poData->octtreeFrame.tightBBoxMin;
25 const glm::vec3& tbMaxCenter = poData->octtreeFrame.tightBBoxMax;
26 const glm::vec3& shift = poData->octtreeFrame.toBBoxShift;
27 const glm::vec3& scale = poData->octtreeFrame.fullBBoxSize;
32 auto* root = createCell(poData, subtree);
34 if (subtree->containingCell ==
nullptr) {
35 assert(poData->root ==
nullptr);
42 root->scaleFactor = subtree->containingCell ? subtree->containingCell->scaleFactor : 1;
44 for (
size_t i = 0; i < n; i++) {
50 auto* cell = curr.shift();
58 auto cellSizeAtLevel = std::exp2f(-
float(subtree->l + cell->l));
59 auto pos = cellSizeAtLevel * glm::vec3(
float((subtree->i << cell->l) + cell->i),
60 float((subtree->j << cell->l) + cell->j),
61 float((subtree->k << cell->l) + cell->k));
63 cell->tbmin = glm::max(tbMinCenter, shift + scale * pos);
64 cell->tbmax = glm::min(tbMaxCenter, shift + scale * (pos + glm::vec3(cellSizeAtLevel)));
66 cell->hierarchyNumPoints = ((data->ptr[5 * i + 1] << 0) |
67 (data->ptr[5 * i + 2] << 8) |
68 (data->ptr[5 * i + 3] << 16) |
69 (data->ptr[5 * i + 4] << 24));
71 if (cell->l < poData->hierarchyStepSize) {
75 cell->kind = PotreeCell::Kind::RegularNode;
78 auto mask = data->ptr[5 * i + 0];
79 for (
unsigned b = 0; b < 8; b++) {
80 cell->children[b] =
nullptr;
81 if ((mask >> b) & 1) {
82 auto* child = createCell(poData, subtree);
85 child->i = (cell->i << 1) | ((b >> 2) & 1);
86 child->j = (cell->j << 1) | ((b >> 1) & 1);
87 child->k = (cell->k << 1) | ((b >> 0) & 1);
88 child->l = cell->l + 1;
89 child->prefix = cell->prefix | (b << (3 * cell->l));
91 cell->children[b] = child;
95 else if (cell->l == poData->hierarchyStepSize) {
96 cell->kind = PotreeCell::Kind::SubtreeLink;
97 cell->linkedSubtree =
nullptr;
100 LOG_ERROR(logger,
"[instance=%u,tree=%u] Error in hierarchy file: %s", instanceId, subtreeId, url.c_str());
101 poData->state = PotreeState::Error;
102 subtree->state = PotreeSubtree::State::Failed;
103 if (subtree->containingCell) subtree->containingCell->state = PotreeCell::State::Failed;
107 assert(curr.empty());
108 assert(next.empty());
111 uint32_t getUint32LE(
const uint8_t* ptr)
113 uint32_t rv = ptr[0];
114 for (
size_t i = 1; i < 4; i++) { rv = rv | (
static_cast<uint32_t
>(ptr[i]) << (8 * i)); }
118 uint64_t getUint64LE(
const uint8_t* ptr)
120 uint64_t rv = ptr[0];
121 for (
size_t i = 1; i < 8; i++) { rv = rv | (
static_cast<uint64_t
>(ptr[i]) << (8 * i)); }
127 size_t bytesPerNode = 22;
128 size_t numNodes = data->size / bytesPerNode;
129 if (numNodes * bytesPerNode != data->size) {
130 LOG_ERROR(logger,
"[instance=%u,tree=%u] Hierarchy file part size (%zu) not a multiple of node size (22): %s",
131 instanceId, subtreeId, data->size, url.c_str());
132 poData->state = PotreeState::Error;
133 subtree->state = PotreeSubtree::State::Failed;
134 if (subtree->containingCell) subtree->containingCell->state = PotreeCell::State::Failed;
138 const glm::vec3& tbMinCenter = poData->octtreeFrame.tightBBoxMin;
139 const glm::vec3& tbMaxCenter = poData->octtreeFrame.tightBBoxMax;
140 const glm::vec3& shift = poData->octtreeFrame.toBBoxShift;
141 const glm::vec3& scale = poData->octtreeFrame.fullBBoxSize;
143 std::vector<PotreeCell*> cells(numNodes);
144 for (
auto& ptr : cells) { ptr = createCell(poData, subtree); }
145 if (subtree->containingCell ==
nullptr) {
146 assert(poData->root ==
nullptr);
147 poData->root = cells[0];
153 cells[0]->scaleFactor = subtree->containingCell ? subtree->containingCell->scaleFactor : 1;
155 unsigned childOffset = 1;
156 for (
size_t i = 0; i < numNodes; i++) {
157 const uint8_t* ptr = data->ptr + bytesPerNode * i;
158 uint8_t nodeType = ptr[0];
159 uint8_t childMask = ptr[1];
160 uint32_t numPoints = getUint32LE(ptr + 2);
161 uint64_t byteOffset = getUint64LE(ptr + 6);
162 uint64_t byteCount = getUint64LE(ptr + 14);
165 auto cellSizeAtLevel = std::exp2f(-
float(subtree->l + current->l));
166 auto pos = cellSizeAtLevel * glm::vec3(
float((subtree->i << current->l) + current->i),
167 float((subtree->j << current->l) + current->j),
168 float((subtree->k << current->l) + current->k));
170 current->hierarchyNumPoints = byteCount ? numPoints : 0;
171 current->byteOffset = byteOffset;
172 current->byteCount = byteCount;
173 current->tbmin = glm::max(tbMinCenter, shift + scale * pos);
174 current->tbmax = glm::min(tbMaxCenter, shift + scale * (pos + glm::vec3(cellSizeAtLevel)));
178 current->kind = PotreeCell::Kind::SubtreeLink;
179 current->linkedSubtree =
nullptr;
183 for (
unsigned childIndex = 0; childIndex < 8; childIndex++) {
185 if (((1u << childIndex) & childMask) == 0) {
189 auto* child = cells[childOffset++];
190 child->i = (current->i << 1) | ((childIndex >> 2) & 1);
191 child->j = (current->j << 1) | ((childIndex >> 1) & 1);
192 child->k = (current->k << 1) | ((childIndex >> 0) & 1);
193 child->l = current->l + 1;
194 child->prefix = current->prefix | (childIndex << (3 * current->l));
196 current->children[childIndex] = child;
202 void parseHrcFile(
Context* context, uint32_t instanceId, uint32_t subtreeId,
const std::string& url,
Cogs::FileContents* data)
208 bool ret = PotreeSystem::lookupAndCheckForStaleness(context, potreeSystem, poData, poComp, subtree, instanceId, subtreeId);
209 if(subtree) subtree->fetch_id = DataFetcherManager::NoFetchId;
213 LOG_TRACE(logger,
"[instance=%u,tree=%u] Received stale *.hrc file, ignoring: %.*s", instanceId, subtreeId, StringViewFormat(data->origin()));
218#if defined(COGS_PARANOIA)
219 assert(!subtree->containingCell || subtree->containingCell->state == PotreeCell::State::Issued);
220 assert(subtree->state == PotreeSubtree::State::Issued);
222 if (subtree->containingCell && subtree->containingCell->state != PotreeCell::State::Issued) {
223 LOG_FATAL(logger,
"[instance=%u,tree=%u] Got hierarchy file, but containing cell is not in state Issued(=1) (state=%u), discarding",
224 instanceId, subtreeId,
static_cast<unsigned>(subtree->containingCell->state));
227 if (subtree->state != PotreeSubtree::State::Issued) {
228 LOG_FATAL(logger,
"[instance=%u,tree=%u] Got hierarchy file, but subtree is not in state Issued(=1) (state=%u), discarding.",
229 instanceId, subtreeId,
static_cast<unsigned>(subtree->state));
235 LOG_ERROR(logger,
"[instance=%u,tree=%u] Failed to get hierarchy file: %s", instanceId, subtreeId, url.c_str());
236 poData->state = PotreeState::Error;
237 subtree->state = PotreeSubtree::State::Failed;
238 if (subtree->containingCell) subtree->containingCell->state = PotreeCell::State::Failed;
241 subtree->state = PotreeSubtree::State::Ready;
242 if (subtree->containingCell) subtree->containingCell->state = PotreeCell::State::Ready;
244 if (poData->versionMajor == 1) {
245 parseHrcFile1(poData, subtree, instanceId, subtreeId, url, data);
248 parseHrcFile2(poData, subtree, instanceId, subtreeId, url, data);
259 assert(state == State::None);
260 state = State::Issued;
262 this->containingCell = containingCell;
263 if (containingCell ==
nullptr) {
271 assert(containingCell->kind == PotreeCell::Kind::SubtreeLink);
272 assert(containingCell->state == PotreeCell::State::Issued);
273 i = (containingCell->owningSubtree->i << containingCell->l) + containingCell->i;
274 j = (containingCell->owningSubtree->j << containingCell->l) + containingCell->j;
275 k = (containingCell->owningSubtree->k << containingCell->l) + containingCell->k;
276 l = containingCell->owningSubtree->l + containingCell->l;
277 containingCell->linkedSubtree =
this;
281 uint64_t fileOffset = 0u;
282 uint64_t fileByteSize = 0u;
283 if (poData->versionMajor == 1) {
286 if (containingCell ==
nullptr) {
290 std::string localPrefix;
291 containingCell->appendDescendSteps(localPrefix);
292 prefix = containingCell->owningSubtree->prefix + localPrefix;
293 path = containingCell->owningSubtree->path + localPrefix +
"/";
295 url = poData->
octreeDir + path +
"r" + prefix +
".hrc";
301 if (containingCell ==
nullptr) {
303 fileByteSize = poData->firstChunkSize;
306 fileOffset = containingCell->byteOffset;
307 fileByteSize = containingCell->byteCount;
309 url = poData->
rootPath +
"hierarchy.bin";
314 poSystem->requestsInFlight++;
317 fetch_id = DataFetcherManager::fetchAsync(context, url, [context, url, instanceId = poData->instanceId, treeId = subtreeId](std::unique_ptr<Cogs::FileContents> data)
319 auto task = [context, url, instanceId, treeId, dataPtr = data.release()]() {
320 std::unique_ptr<Cogs::FileContents> data(dataPtr);
321 parseHrcFile(context, instanceId, treeId, url, data.get());
323 PotreeSystem* poSystem = nullptr;
324 PotreeComponent* poComp = nullptr;
325 PotreeData* poData = nullptr;
326 bool ret = PotreeSystem::lookupAndCheckForStaleness(context, poSystem, poData, poComp, instanceId);
327 poSystem->requestsInFlight--;
328 PotreeSystem::endFetch(context, poComp, poData);
332 LOG_DEBUG(logger,
"[instance=%u] Received *.hrc file, instance does not exist anymore, ignoring: %.*s", instanceId, StringViewFormat(data->origin()));
337 context->engine->setDirty();
339 context->
engine->runTaskInMainThread(std::move(task));
340 }, fileOffset, fileByteSize,
true, Cogs::FileContentsHints::None);
345 while (!cells.empty()) {
346 auto* cell = cells.pop();
347 cell->releaseData(context, poData);
348 assert(cell->state == PotreeCell::State::None);
351 poData->cellStore.destroy(cell);
353 if (state == PotreeSubtree::State::Issued) {
354 DataFetcherManager::cancelAsyncFetch(context, fetch_id);
355 fetch_id = DataFetcherManager::NoFetchId;
A Context instance contains all the services, systems and runtime components needed to use Cogs.
std::unique_ptr< class Engine > engine
Engine instance.
Log implementation class.
Contains the Engine, Renderer, resource managers and other systems needed to run Cogs....
bool HandleIsValid(const ResourceHandle_t< T > &handle)
Check if the given resource is valid, that is not equal to NoHandle or InvalidHandle.
constexpr Log getLogger(const char(&name)[LEN]) noexcept
Component for Point Cloud Display.
std::string octreeDir
1.x only: subdir with data
std::string rootPath
URL to folder containing metadata file.
static void startFetch(Context *context, const PotreeComponent *poComp, PotreeData *poData)
Update Component request count and notify client when starting data fetch.
Abstract base class storing data read from a file.