2020-12-07 15:23:55 +01:00
|
|
|
/*
|
|
|
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
|
|
|
* you may not use this file except in compliance with the License.
|
|
|
|
|
* You may obtain a copy of the License at
|
|
|
|
|
*
|
|
|
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
|
*
|
|
|
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
|
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
|
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
|
|
|
* See the License for the specific language governing permissions and
|
|
|
|
|
* limitations under the License.
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @author Jim Eckerlein <eckerlein@ux3d.io>
|
|
|
|
|
* @date 2020-11-18
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
#include "decoder.h"
|
|
|
|
|
|
|
|
|
|
#include <memory>
|
|
|
|
|
#include <vector>
|
|
|
|
|
#include <cinttypes>
|
|
|
|
|
|
|
|
|
|
#include "draco/mesh/mesh.h"
|
|
|
|
|
#include "draco/core/decoder_buffer.h"
|
|
|
|
|
#include "draco/compression/decode.h"
|
|
|
|
|
|
|
|
|
|
#define LOG_PREFIX "DracoDecoder | "
|
|
|
|
|
|
2022-06-17 18:38:41 +02:00
|
|
|
struct Decoder
|
|
|
|
|
{
|
2020-12-07 15:23:55 +01:00
|
|
|
std::unique_ptr<draco::Mesh> mesh;
|
|
|
|
|
std::vector<uint8_t> indexBuffer;
|
|
|
|
|
std::map<uint32_t, std::vector<uint8_t>> buffers;
|
|
|
|
|
draco::DecoderBuffer decoderBuffer;
|
|
|
|
|
uint32_t vertexCount;
|
|
|
|
|
uint32_t indexCount;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
Decoder *decoderCreate()
|
|
|
|
|
{
|
|
|
|
|
return new Decoder;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void decoderRelease(Decoder *decoder)
|
|
|
|
|
{
|
|
|
|
|
delete decoder;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool decoderDecode(Decoder *decoder, void *data, size_t byteLength)
|
|
|
|
|
{
|
|
|
|
|
draco::Decoder dracoDecoder;
|
|
|
|
|
draco::DecoderBuffer dracoDecoderBuffer;
|
|
|
|
|
dracoDecoderBuffer.Init(reinterpret_cast<char *>(data), byteLength);
|
2022-06-17 18:38:41 +02:00
|
|
|
|
2020-12-07 15:23:55 +01:00
|
|
|
auto decoderStatus = dracoDecoder.DecodeMeshFromBuffer(&dracoDecoderBuffer);
|
|
|
|
|
if (!decoderStatus.ok())
|
|
|
|
|
{
|
|
|
|
|
printf(LOG_PREFIX "Error during Draco decoding: %s\n", decoderStatus.status().error_msg());
|
|
|
|
|
return false;
|
|
|
|
|
}
|
2022-06-17 18:38:41 +02:00
|
|
|
|
2020-12-07 15:23:55 +01:00
|
|
|
decoder->mesh = std::move(decoderStatus).value();
|
|
|
|
|
decoder->vertexCount = decoder->mesh->num_points();
|
|
|
|
|
decoder->indexCount = decoder->mesh->num_faces() * 3;
|
2022-06-17 18:38:41 +02:00
|
|
|
|
2020-12-07 15:23:55 +01:00
|
|
|
printf(LOG_PREFIX "Decoded %" PRIu32 " vertices, %" PRIu32 " indices\n", decoder->vertexCount, decoder->indexCount);
|
2022-06-17 18:38:41 +02:00
|
|
|
|
2020-12-07 15:23:55 +01:00
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
uint32_t decoderGetVertexCount(Decoder *decoder)
|
|
|
|
|
{
|
|
|
|
|
return decoder->vertexCount;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
uint32_t decoderGetIndexCount(Decoder *decoder)
|
|
|
|
|
{
|
|
|
|
|
return decoder->indexCount;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool decoderAttributeIsNormalized(Decoder *decoder, uint32_t id)
|
|
|
|
|
{
|
2022-06-17 18:38:41 +02:00
|
|
|
const draco::PointAttribute *attribute = decoder->mesh->GetAttributeByUniqueId(id);
|
2020-12-07 15:23:55 +01:00
|
|
|
return attribute != nullptr && attribute->normalized();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool decoderReadAttribute(Decoder *decoder, uint32_t id, size_t componentType, char *dataType)
|
|
|
|
|
{
|
2022-06-17 18:38:41 +02:00
|
|
|
const draco::PointAttribute *attribute = decoder->mesh->GetAttributeByUniqueId(id);
|
|
|
|
|
|
2020-12-07 15:23:55 +01:00
|
|
|
if (attribute == nullptr)
|
|
|
|
|
{
|
|
|
|
|
printf(LOG_PREFIX "Attribute with id=%" PRIu32 " does not exist in Draco data\n", id);
|
|
|
|
|
return false;
|
|
|
|
|
}
|
2022-06-17 18:38:41 +02:00
|
|
|
|
2020-12-07 15:23:55 +01:00
|
|
|
size_t stride = getAttributeStride(componentType, dataType);
|
2022-06-17 18:38:41 +02:00
|
|
|
|
2020-12-07 15:23:55 +01:00
|
|
|
std::vector<uint8_t> decodedData;
|
|
|
|
|
decodedData.resize(stride * decoder->vertexCount);
|
2022-06-17 18:38:41 +02:00
|
|
|
|
2020-12-07 15:23:55 +01:00
|
|
|
for (uint32_t i = 0; i < decoder->vertexCount; ++i)
|
|
|
|
|
{
|
|
|
|
|
auto index = attribute->mapped_index(draco::PointIndex(i));
|
|
|
|
|
uint8_t *value = decodedData.data() + i * stride;
|
2022-06-17 18:38:41 +02:00
|
|
|
|
2020-12-07 15:23:55 +01:00
|
|
|
bool converted = false;
|
2022-06-17 18:38:41 +02:00
|
|
|
|
2020-12-07 15:23:55 +01:00
|
|
|
switch (componentType)
|
|
|
|
|
{
|
|
|
|
|
case ComponentType::Byte:
|
|
|
|
|
converted = attribute->ConvertValue(index, reinterpret_cast<int8_t *>(value));
|
|
|
|
|
break;
|
|
|
|
|
case ComponentType::UnsignedByte:
|
|
|
|
|
converted = attribute->ConvertValue(index, reinterpret_cast<uint8_t *>(value));
|
|
|
|
|
break;
|
|
|
|
|
case ComponentType::Short:
|
|
|
|
|
converted = attribute->ConvertValue(index, reinterpret_cast<int16_t *>(value));
|
|
|
|
|
break;
|
|
|
|
|
case ComponentType::UnsignedShort:
|
|
|
|
|
converted = attribute->ConvertValue(index, reinterpret_cast<uint16_t *>(value));
|
|
|
|
|
break;
|
|
|
|
|
case ComponentType::UnsignedInt:
|
|
|
|
|
converted = attribute->ConvertValue(index, reinterpret_cast<uint32_t *>(value));
|
|
|
|
|
break;
|
|
|
|
|
case ComponentType::Float:
|
|
|
|
|
converted = attribute->ConvertValue(index, reinterpret_cast<float *>(value));
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!converted)
|
|
|
|
|
{
|
|
|
|
|
printf(LOG_PREFIX "Failed to convert Draco attribute type to glTF accessor type for attribute with id=%" PRIu32 "\n", id);
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
}
|
2022-06-17 18:38:41 +02:00
|
|
|
|
2020-12-07 15:23:55 +01:00
|
|
|
decoder->buffers[id] = decodedData;
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
size_t decoderGetAttributeByteLength(Decoder *decoder, size_t id)
|
|
|
|
|
{
|
|
|
|
|
auto iter = decoder->buffers.find(id);
|
|
|
|
|
if (iter != decoder->buffers.end())
|
|
|
|
|
{
|
|
|
|
|
return iter->second.size();
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void decoderCopyAttribute(Decoder *decoder, size_t id, void *output)
|
|
|
|
|
{
|
|
|
|
|
auto iter = decoder->buffers.find(id);
|
|
|
|
|
if (iter != decoder->buffers.end())
|
|
|
|
|
{
|
|
|
|
|
memcpy(output, iter->second.data(), iter->second.size());
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2022-06-17 18:38:41 +02:00
|
|
|
template <class T>
|
2020-12-07 15:23:55 +01:00
|
|
|
void decodeIndices(Decoder *decoder)
|
|
|
|
|
{
|
|
|
|
|
std::vector<uint8_t> decodedIndices;
|
|
|
|
|
decodedIndices.resize(decoder->indexCount * sizeof(T));
|
|
|
|
|
T *typedView = reinterpret_cast<T *>(decodedIndices.data());
|
2022-06-17 18:38:41 +02:00
|
|
|
|
2020-12-07 15:23:55 +01:00
|
|
|
for (uint32_t faceIndex = 0; faceIndex < decoder->mesh->num_faces(); ++faceIndex)
|
|
|
|
|
{
|
|
|
|
|
const draco::Mesh::Face &face = decoder->mesh->face(draco::FaceIndex(faceIndex));
|
|
|
|
|
typedView[faceIndex * 3 + 0] = face[0].value();
|
|
|
|
|
typedView[faceIndex * 3 + 1] = face[1].value();
|
|
|
|
|
typedView[faceIndex * 3 + 2] = face[2].value();
|
|
|
|
|
}
|
2022-06-17 18:38:41 +02:00
|
|
|
|
2020-12-07 15:23:55 +01:00
|
|
|
decoder->indexBuffer = decodedIndices;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool decoderReadIndices(Decoder *decoder, size_t indexComponentType)
|
|
|
|
|
{
|
|
|
|
|
switch (indexComponentType)
|
|
|
|
|
{
|
2022-06-17 18:38:41 +02:00
|
|
|
case ComponentType::Byte:
|
|
|
|
|
decodeIndices<int8_t>(decoder);
|
|
|
|
|
break;
|
|
|
|
|
case ComponentType::UnsignedByte:
|
|
|
|
|
decodeIndices<uint8_t>(decoder);
|
|
|
|
|
break;
|
|
|
|
|
case ComponentType::Short:
|
|
|
|
|
decodeIndices<int16_t>(decoder);
|
|
|
|
|
break;
|
|
|
|
|
case ComponentType::UnsignedShort:
|
|
|
|
|
decodeIndices<uint16_t>(decoder);
|
|
|
|
|
break;
|
|
|
|
|
case ComponentType::UnsignedInt:
|
|
|
|
|
decodeIndices<uint32_t>(decoder);
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
printf(LOG_PREFIX "Index component type %zu not supported\n", indexComponentType);
|
|
|
|
|
return false;
|
2020-12-07 15:23:55 +01:00
|
|
|
}
|
2022-06-17 18:38:41 +02:00
|
|
|
|
2020-12-07 15:23:55 +01:00
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
size_t decoderGetIndicesByteLength(Decoder *decoder)
|
|
|
|
|
{
|
|
|
|
|
return decoder->indexBuffer.size();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void decoderCopyIndices(Decoder *decoder, void *output)
|
|
|
|
|
{
|
|
|
|
|
memcpy(output, decoder->indexBuffer.data(), decoder->indexBuffer.size());
|
|
|
|
|
}
|