1#include "PotreeSystem.h"
6#include "Rendering/IGraphicsDevice.h"
7#include "Rendering/IBuffers.h"
9#include "Foundation/Logging/Logger.h"
10#include "Foundation/Platform/IO.h"
18void Cogs::Core::PotreeCell::appendDescendSteps(std::string& path)
const
21 for (
unsigned i = 0; i < l; i++) {
22 path.push_back(
'0' + (steps & 0x7));
30 assert(state == PotreeCell::State::None);
31 state = PotreeCell::State::Issued;
34 uint64_t fileOffset = 0u;
35 uint64_t fileByteSize = 0u;
36 if (poData->versionMajor == 1) {
38 url.append(owningSubtree->path);
40 url.append(owningSubtree->prefix);
41 appendDescendSteps(url);
42 url.append(poData->suffix);
45 url = poData->
rootPath +
"octree.bin";
46 fileOffset = byteOffset;
47 fileByteSize = byteCount;
52 switch (poData->encoding)
54 case PotreeEnconding::ZStd:
57 case PotreeEnconding::Brotli:
68 .layoutInfo = PotreeSystem::vertexLayoutInfo[
static_cast<size_t>(poData->layout)],
69 .attributes = poData->attributes,
70 .cellPos = glm::uvec4((owningSubtree->i << this->l) + this->i,
71 (owningSubtree->j << this->l) + this->j,
72 (owningSubtree->k << this->l) + this->k,
73 owningSubtree->l + this->l),
74 .posScale = poData->positionDecode.scale,
75 .posShift = poData->positionDecode.shift,
76 .encoding = poData->encoding,
77 .occGridDim = poData->occupancyGridDim,
78 .fullBBoxMin = poData->octtreeFrame.fullBBoxMin,
79 .fullBBoxSize = poData->octtreeFrame.fullBBoxSize
81 if (poData->versionMajor == 1) {
84 const glm::vec3& bbsize = poData->octtreeFrame.fullBBoxSize;
85 float cellSizeAtLevel = std::exp2f(-
float(decodeArgs.cellPos.w));
86 glm::vec3 octCellMinCorner = bbsize * cellSizeAtLevel * glm::vec3(decodeArgs.cellPos);
87 decodeArgs.posShift += octCellMinCorner;
91 poSystem->requestsInFlight++;
92 fetch_id = DataFetcherManager::fetchAsync(context, url, [context, url, decodeArgs, cell =
this, instanceId = poData->instanceId, treeId = owningSubtree->subtreeId](std::unique_ptr<Cogs::FileContents>&& data)
95 std::unique_ptr<PotreeDecodeOutData> decoded = std::make_unique<PotreeDecodeOutData>();
98 decoded->state = PotreeDecodeOutData::State::NoData;
101 decodePotreeBin(*decoded, decodeArgs, *data.get());
104 auto task = [context, decodedPtr = decoded.release(), url, cell, instanceId, treeId]()
107 std::unique_ptr<PotreeDecodeOutData> decoded(decodedPtr);
108 PotreeSystem* poSystem = nullptr;
109 PotreeComponent* poComp = nullptr;
110 PotreeData* poData = nullptr;
111 PotreeSubtree* subtree = nullptr;
112 bool ret = PotreeSystem::lookupAndCheckForStaleness(context, poSystem, poData, poComp, subtree, instanceId, treeId);
113 poSystem->requestsInFlight--;
114 if(subtree) cell->fetch_id = DataFetcherManager::NoFetchId;
115 PotreeSystem::endFetch(context, poComp, poData);
120 else if (cell->state != PotreeCell::State::Issued) {
121 LOG_TRACE(logger,
"[instance=%u,tree=%u] Got data for cell, but cell has been deactivated (state=%u), discarding data: %s", instanceId, treeId, static_cast<uint32_t>(cell->state), url.c_str());
123 else if (decoded->state == PotreeDecodeOutData::State::NoData) {
124 LOG_ERROR(logger,
"[instance=%u,tree=%u] Failed to get .bin-file: %s", instanceId, treeId, url.c_str());
125 cell->state = PotreeCell::State::Failed;
127 else if (decoded->state != PotreeDecodeOutData::State::Success) {
128 LOG_ERROR(logger,
"[instance=%u,tree=%u] Failed to parse .bin-file: %s", instanceId, treeId, url.c_str());
129 cell->state = PotreeCell::State::Failed;
134 switch (poData->encoding) {
135 case PotreeEnconding::Default:
136 case PotreeEnconding::ZStd:
137 if (decoded->pointCount != cell->hierarchyNumPoints) {
143 case PotreeEnconding::Brotli:
144 if (decoded->pointCount != cell->hierarchyNumPoints) {
145 LOG_WARNING(logger,
"Mismatch between number of points in hierarchy (%u) and number of points in data (%zu)", cell->hierarchyNumPoints, decoded->pointCount);
149 assert(false &&
"Invalid encoding enum value");
152 if (decoded->lo.x <= decoded->hi.x) {
153 cell->tbmin = decoded->lo;
154 cell->tbmax = decoded->hi;
157 if (poData->supportPicking) {
158 cell->points.swap(decoded->points);
161 cell->pointCount =
static_cast<uint32_t
>(decoded->pointCount);
162 if (cell->pointCount) {
163 Cogs::IBuffers* buffers = context->device->getBuffers();
164 cell->pointData = buffers->loadVertexBuffer(decoded->vertexData.data(), cell->pointCount, poData->streamsLayout.vertexFormats[0]);
170 float scale = 255.f * std::pow(0.65f,
static_cast<float>(cell->owningSubtree->l + cell->l));
171 scale = scale <= 255.f ? scale : 255.f;
172 scale = 1.f <= scale ? scale : 1.f;
173 cell->scaleFactor =
static_cast<uint8_t
>(scale);
177 float density =
static_cast<float>(decoded->pointCount) /
static_cast<float>(decoded->nonEmptyCells);
178 float offset = 10.f * (std::log2(density) / 2.f + 8.5f);
179 cell->scaleFactor =
static_cast<uint8_t
>(glm::clamp(offset, 0.f, 255.f));
181 for (
auto* child : cell->children) {
182 if (child && child->state != PotreeCell::State::Ready) {
184 child->scaleFactor = cell->scaleFactor;
188 cell->state = PotreeCell::State::Ready;
191 context->
engine->setDirty();
194 context->
engine->runTaskInMainThread(std::move(task));
196 }, fileOffset, fileByteSize,
true, hints);
202 PotreeCell::State old_state = state;
203 state = PotreeCell::State::None;
204 if (old_state == PotreeCell::State::Issued) {
205 LOG_TRACE(logger,
"Deactivating cell with data still in transit.");
206 DataFetcherManager::cancelAsyncFetch(context, fetch_id);
207 fetch_id = DataFetcherManager::NoFetchId;
210 auto* buffers = context->device->getBuffers();
211 buffers->releaseBuffer(boxParametersBuffer);
215 auto* buffers = context->device->getBuffers();
216 buffers->releaseVertexBuffer(pointData);
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
@ BrotliDecompress
A hint that the contents are Brotli (Google) compressed and is allowed to be decompressed during tran...
@ ZStdDecompress
A hint that the contents are Zstandard (Facebook) compressed and is allowed to be decompressed during...
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.
static const Handle_t NoHandle
Represents a handle to nothing.