1#include "DracoMeshDecompressor.h"
4#include "Foundation/Logging/Logger.h"
5#include "Resources/MeshManager.h"
9#pragma warning(disable:4127 4804)
10#elif defined ( __clang__ )
11#pragma clang diagnostic push
12#pragma clang diagnostic ignored "-Wignored-qualifiers"
13#pragma clang diagnostic ignored "-Wdeprecated-this-capture"
14#pragma clang diagnostic ignored "-Wignored-qualifiers"
16#include <draco/compression/decode.h>
17#include <draco/core/decoder_buffer.h>
20#elif defined ( __clang__ )
21#pragma clang diagnostic pop
32DracoMeshDecompressor::DracoMeshDecompressor() =
default;
34DracoMeshDecompressor::~DracoMeshDecompressor() =
default;
37DracoMeshDecompressor::initAttributes(
const GltfLoader::Object& properties)
39 if (properties.HasMember(
"bufferView")) {
40 this->bufferViewIdx = properties[
"bufferView"].GetInt();
43 if (properties.HasMember(
"attributes")) {
44 auto attrSection = properties[
"attributes"].GetObject();
45 this->attrPositionIdx = attrSection[
"POSITION"].GetInt();
47 if (attrSection.HasMember(
"NORMAL")) {
48 this->attrNormalIdx = attrSection[
"NORMAL"].GetInt();
51 if (attrSection.HasMember(
"TANGENT")) {
52 this->attrTangentIdx = attrSection[
"TANGENT"].GetInt();
57 this->attrTexCoordIndices.resize(16);
58 for (n = 0; n < 16; ++n) {
59 std::string key =
"TEXCOORD_" + std::to_string(n);
60 if (attrSection.HasMember(key.c_str())) {
61 this->attrTexCoordIndices[n] = attrSection[key.c_str()].GetInt();
67 this->attrTexCoordIndices.resize(n);
70 this->attrColorIndices.resize(16);
71 for (n=0; n<16; ++n) {
72 std::string key =
"COLOR_" + std::to_string(n);
73 if (attrSection.HasMember(key.c_str())) {
74 this->attrColorIndices[n] = attrSection[key.c_str()].GetInt();
80 this->attrColorIndices.resize(n);
85 assert(
false &&
"The KHR_draco_mesh_compression section does not have an 'attributes' property.");
89 LOG_DEBUG(logger,
"BufferViewIdx=%d, PositionIdx=%d, NormalIdx=%d, TangentIdx=%d",
90 this->bufferViewIdx, this->attrPositionIdx, this->attrNormalIdx, this->attrTangentIdx);
91 if (this->attrTexCoordIndices.size() > 0) {
92 for (
int i = 0; i < this->attrTexCoordIndices.size();++i) {
93 printf(
" TEXCOORD_%d=%d\n", i, this->attrTexCoordIndices[i]);
96 if (this->attrColorIndices.size() > 0) {
97 for (
int i = 0; i < this->attrColorIndices.size(); ++i) {
98 printf(
" COLOR_%d=%d\n", i, this->attrColorIndices[i]);
107 const GltfLoader::Object& attributeObject,
bool skipNormals)
110 const char* buffer =
reinterpret_cast<const char*
>(&(loadData.buffer_data[bufferView.buffer].data())[bufferView.byteOffset]);
112 const size_t bufferSize = bufferView.byteLength;
114 draco::DecoderBuffer decoderBuffer;
115 decoderBuffer.Init(buffer, bufferSize);
118 std::unique_ptr<draco::PointCloud> pointCloud;
119 draco::Mesh* dmesh =
nullptr;
120 draco::Decoder decoder;
122 auto type_statusor = draco::Decoder::GetEncodedGeometryType(&decoderBuffer);
123 if (!type_statusor.ok()) {
124 LOG_ERROR(logger,
"Draco: %s", type_statusor.status().error_msg_string().c_str());
127 const draco::EncodedGeometryType geom_type = type_statusor.value();
129 if (geom_type == draco::TRIANGULAR_MESH) {
130 auto statusor = decoder.DecodeMeshFromBuffer(&decoderBuffer);
131 if (!statusor.ok()) {
132 LOG_ERROR(logger,
"Draco: %s", statusor.status().error_msg_string().c_str());
135 std::unique_ptr<draco::Mesh> in_mesh = std::move(statusor).value();
137 dmesh = in_mesh.get();
138 pointCloud = std::move(in_mesh);
141 else if (geom_type == draco::POINT_CLOUD) {
142 auto statusor = decoder.DecodePointCloudFromBuffer(&decoderBuffer);
143 if (!statusor.ok()) {
144 LOG_ERROR(logger,
"Draco: %s", statusor.status().error_msg_string().c_str());
147 pointCloud = std::move(statusor).value();
150 assert(dmesh &&
"Internal error");
152 if (pointCloud->num_points() > 0 && dmesh->num_points() == 0) {
154 LOG_WARNING(logger,
"Point-cloud decompression not implemented yet.");
160 int numattrs = dmesh->num_attributes();
161 int numPosAttr = dmesh->NumNamedAttributes(draco::GeometryAttribute::POSITION);
162 printf(
"Num draco mesh attributes: %d\n", numPosAttr);
163 for (
int i = 0; i < numattrs; ++i) {
164 auto attr = dmesh->attribute(i);
165 int idx = attr->unique_id();
166 printf(
" %s: idx=%d, datasize=%d items=%d, stride=%d\n",
167 draco::GeometryAttribute::TypeToString(attr->attribute_type()).c_str(),
169 attr->buffer()->data_size(),
171 attr->byte_stride());
180 assert(this->decompressedIndices.size() == 0 &&
"decompressedIndices buffer was reused");
181 this->decompressedIndices.resize(
static_cast<unsigned long long>(dmesh->num_faces()) * 3 *
sizeof(uint32_t));
182 uint32_t* buf =
reinterpret_cast<uint32_t *
>(this->decompressedIndices.data());
184 for (
size_t n=0; n<dmesh->num_faces(); ++n) {
185 const draco::Mesh::Face face = dmesh->face(draco::FaceIndex((uint32_t) n));
186 buf[n * 3] = face[0].value();
187 buf[n * 3 + 1] = face[1].value();
188 buf[n * 3 + 2] = face[2].value();
192 .data =
reinterpret_cast<uint8_t*
>(buf),
193 .stride =
sizeof(uint32_t),
194 .count = dmesh->num_faces() * 3
196 streamsState.indexType = GltfLoader::AccessorComponentType::UnsignedInt;
197 streamsState.indexSize =
sizeof(uint32_t);
202 int32_t attrId = dmesh->GetAttributeIdByUniqueId(this->attrPositionIdx);
203 const draco::PointAttribute* positionAttribute = dmesh->attribute(attrId);
204 assert(positionAttribute->IsValid() &&
"Internal error");
205 assert(positionAttribute->data_type() == draco::DT_FLOAT32 &&
"Only vertices using float32 is supported for now.");
206 assert(positionAttribute->num_components() == 3 &&
"Only 3-component float arrays are supported for vertices.");
209 this->getAttributeData<float>(dmesh, positionAttribute, vertexStream);
210 vertexStream.format = Cogs::DataFormat::R32G32B32_FLOAT;
212 vertexStream.semanticIndex = 0;
213 vertexStreams.push_back(vertexStream);
216 printf(
"INDICES (%d, min=%d, max=%d):\n", numIndices, minIndexValue, maxIndexValue);
217 for (
int i = 0; i < dmesh->num_faces() * 3; ++i) {
218 printf(
"%d, ", indices[i]);
221 if (vertexStream.dataView.count < maxIndexValue) {
222 LOG_ERROR(logger,
"Number of decompressed verices (%d) is less than highest index value (%d)", vertexStream.dataView.count, maxIndexValue);
227 printf(
"POSITION (%d, num items=%d): \n", vertexStream.dataView.count, vertexStream.dataView.count / vertexStream.dataView.stride);
228 int numcomps = positionAttribute->num_components();
229 float* buf = (
float*)vertexStream.dataView.data;
230 for (
int i = 0; i < vertexStream.dataView.count; ++i) {
231 float x = buf[i * numcomps];
232 float y = buf[i * numcomps + 1];
233 float z = buf[i * numcomps + 2];
234 printf(
"<%f, %f, %f>, ", x, y, z);
239 streamsState.positionPresent =
true;
240 streamsState.positionCount = vertexStream.dataView.count;
241 streamsState.positionData = vertexStream.dataView;
245 if (!skipNormals && this->attrNormalIdx != -1) {
246 processNormals(dmesh, vertexStreams, streamsState);
249 if (this->attrTangentIdx != -1) {
250 processTangents(dmesh, vertexStreams, streamsState);
253 processTextureCoords(dmesh, vertexStreams, streamsState);
254 processVertexColors(dmesh, vertexStreams, streamsState);
259 uint32_t modelPositionAttrIdx = attributeObject[
"POSITION"].GetInt();
261 if (positionAccessor.minCount == 3 && positionAccessor.maxCount == 3) {
262 streamsState.bbox.min = glm::make_vec3(positionAccessor.min.s_float);
263 streamsState.bbox.max = glm::make_vec3(positionAccessor.max.s_float);
266 LOG_WARNING(logger,
"%.*s: POSITION attribute has missing or malformed min and max values", StringViewFormat(loadData.path));
267 streamsState.bbox.min = glm::vec3(std::numeric_limits<float>::max());
268 streamsState.bbox.max = -streamsState.bbox.min;
269 for (
size_t i=0; i<streamsState.positionCount; i++) {
270 const glm::vec3 &p = *(
reinterpret_cast<const glm::vec3 *
>((streamsState.positionData.data + streamsState.positionData.stride * i)));
271 if (std::isfinite(p.x) && std::isfinite(p.y) && std::isfinite(p.z)) {
272 streamsState.bbox.min = glm::min(streamsState.bbox.min, p);
273 streamsState.bbox.max = glm::max(streamsState.bbox.max, p);
282DracoMeshDecompressor::processVertexColors(draco::Mesh* dmesh, std::vector<GltfLoader::VertexStream>& vertexStreams,
GltfLoader::VertexStreamsState& streamsState)
284 for (
size_t colorNum = 0; colorNum<this->attrColorIndices.size(); ++colorNum) {
285 uint32_t cAttrId = dmesh->GetAttributeIdByUniqueId(this->attrColorIndices[colorNum]);
286 const draco::PointAttribute* colorAttr = dmesh->attribute(cAttrId);
287 assert(colorAttr->IsValid() &&
"Internal error");
288 assert(colorAttr->data_type() == draco::DT_FLOAT32 &&
"Only texture coords using float32 is supported for now.");
291 this->getAttributeData<float>(dmesh, colorAttr, colorStream);
293 uint32_t numComponents = colorAttr->num_components();
294 assert(numComponents == 3 || numComponents == 4 &&
"Only Vec3 or Vec4 supported for color attributes.");
296 colorStream.format = numComponents == 3 ? Cogs::DataFormat::R32G32B32_FLOAT : Cogs::DataFormat::R32G32B32A32_FLOAT;
298 colorStream.semanticIndex = (uint32_t)colorNum;
301 printf(
"COLOR_%d (%d, num items=%d): \n", colorNum, colorStream.dataView.count, colorStream.dataView.count / colorStream.dataView.stride);
302 float* buf = (
float*)colorStream.dataView.data;
303 for (
int i = 0; i < colorStream.dataView.count; ++i) {
304 float r = buf[i * numComponents];
305 float g = buf[i * numComponents + 1];
306 float b = buf[i * numComponents + 2];
307 if (numComponents == 4) {
308 float a = buf[i * numComponents + 3];
309 printf(
"<%f, %f, %f, %f>, ", r, g, b, a);
312 printf(
"<%f, %f, %f>, ", r, g, b);
318 vertexStreams.push_back(colorStream);
321 streamsState.colorStreamCount =
static_cast<uint32_t
>(this->attrColorIndices.size());
325DracoMeshDecompressor::processTextureCoords(draco::Mesh* dmesh, std::vector<GltfLoader::VertexStream>& vertexStreams,
GltfLoader::VertexStreamsState& streamsState)
327 for (
size_t texNum = 0; texNum<this->attrTexCoordIndices.size(); ++texNum) {
328 uint32_t tcAttrId = dmesh->GetAttributeIdByUniqueId(this->attrTexCoordIndices[texNum]);
329 const draco::PointAttribute* texAttr = dmesh->attribute(tcAttrId);
330 assert(texAttr->IsValid() &&
"Internal error");
331 assert(texAttr->data_type() == draco::DT_FLOAT32 &&
"Only texture coords using float32 is supported for now.");
333 uint32_t numComponents = texAttr->num_components();
334 assert(numComponents == 2 &&
"Only Vec2 is supported for texcoord attributes.");
337 this->getAttributeData<float>(dmesh, texAttr, texStream);
338 texStream.format = Cogs::DataFormat::R32G32_FLOAT;
340 texStream.semanticIndex = (uint32_t)texNum;
343 printf(
"TEX_%d (%d, num items=%d): \n", texNum, texStream.dataView.count, texStream.dataView.count / texStream.dataView.stride);
344 float* buf = (
float*)texStream.dataView.data;
345 for (
int i = 0; i < texStream.dataView.count; ++i) {
346 float x = buf[i * numComponents];
347 float y = buf[i * numComponents + 1];
348 printf(
"<%f, %f>, ", x, y);
353 vertexStreams.push_back(texStream);
358 streamsState.texcoordStreamCount =
static_cast<uint32_t
>(this->attrTexCoordIndices.size());
362DracoMeshDecompressor::processNormals(draco::Mesh* dmesh, std::vector<GltfLoader::VertexStream>& vertexStreams,
GltfLoader::VertexStreamsState& streamsState)
364 uint32_t nAttrId = dmesh->GetAttributeIdByUniqueId(this->attrNormalIdx);
365 const draco::PointAttribute* normalAttribute = dmesh->attribute(nAttrId);
366 assert(normalAttribute->IsValid() &&
"Internal error");
367 assert(normalAttribute->data_type() == draco::DT_FLOAT32 &&
"Only normals using float32 is supported for now.");
368 assert(normalAttribute->num_components() == 3 &&
"Only 3-component float arrays are supported for normals.");
372 this->getAttributeData<float>(dmesh, normalAttribute, normalStream);
373 normalStream.format = Cogs::DataFormat::R32G32B32_FLOAT;
375 normalStream.semanticIndex = 0;
378 printf(
"NORMALS (%d, num items=%d): \n", normalStream.dataView.count, normalStream.dataView.count / normalStream.dataView.stride);
379 int numcomps = normalAttribute->num_components();
380 float* buf = (
float*)normalStream.dataView.data;
381 for (
int i = 0; i < normalStream.dataView.count; ++i) {
382 float x = buf[i * numcomps];
383 float y = buf[i * numcomps + 1];
384 float z = buf[i * numcomps + 2];
385 printf(
"<%f, %f, %f>, ", x, y, z);
390 vertexStreams.push_back(normalStream);
391 streamsState.normalPresent =
true;
392 streamsState.normalData = normalStream.dataView;
396DracoMeshDecompressor::processTangents(draco::Mesh* dmesh, std::vector<GltfLoader::VertexStream>& vertexStreams,
GltfLoader::VertexStreamsState& streamsState)
398 uint32_t tAttrId = dmesh->GetAttributeIdByUniqueId(this->attrTangentIdx);
399 const draco::PointAttribute* tangentAttribute = dmesh->attribute(tAttrId);
400 assert(tangentAttribute->IsValid() &&
"Internal error");
401 assert(tangentAttribute->data_type() == draco::DT_FLOAT32 &&
"Only tangents using float32 is supported for now.");
402 assert(tangentAttribute->num_components() == 4 &&
"Only 4-component generic float arrays are supported for tangents for now.");
406 this->getAttributeData<float>(dmesh, tangentAttribute, tangentStream);
407 tangentStream.format = Cogs::DataFormat::R32G32B32A32_FLOAT;
409 tangentStream.semanticIndex = 0;
412 printf(
"TANGENTS (%d, num items=%d): \n", tangentStream.dataView.count, tangentStream.dataView.count / tangentStream.dataView.stride);
413 int numcomps = tangentAttribute->num_components();
414 float* buf = (
float*)tangentStream.dataView.data;
415 for (
int i = 0; i < tangentStream.dataView.count; ++i) {
416 float x = buf[i * numcomps];
417 float y = buf[i * numcomps + 1];
418 float z = buf[i * numcomps + 2];
419 if (accessor.type == GltfLoader::AccessorType::Vec4) {
420 float a = buf[i * numcomps + 3];
421 printf(
"<%f, %f, %f, %f>, ", x, y, z, a);
424 printf(
"<%f, %f, %f>, ", x, y, z);
430 vertexStreams.push_back(tangentStream);
431 streamsState.tangentPresent =
true;
Log implementation class.
Contains the Engine, Renderer, resource managers and other systems needed to run Cogs....
constexpr Log getLogger(const char(&name)[LEN]) noexcept
@ Position
Position semantic.
@ Tangent
Tangent semantic.
@ TextureCoordinate
Texture coordinate semantic.