Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'extern/draco/src')
-rw-r--r--extern/draco/src/common.cpp77
-rw-r--r--extern/draco/src/common.h50
-rw-r--r--extern/draco/src/decoder.cpp222
-rw-r--r--extern/draco/src/decoder.h53
-rw-r--r--extern/draco/src/draco-compressor.cpp277
-rw-r--r--extern/draco/src/draco-compressor.h173
-rw-r--r--extern/draco/src/encoder.cpp247
-rw-r--r--extern/draco/src/encoder.h51
8 files changed, 700 insertions, 450 deletions
diff --git a/extern/draco/src/common.cpp b/extern/draco/src/common.cpp
new file mode 100644
index 00000000000..6f98d8db7ef
--- /dev/null
+++ b/extern/draco/src/common.cpp
@@ -0,0 +1,77 @@
+/*
+ * 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.
+ */
+
+#include "common.h"
+
+#include <cstring>
+
+size_t getNumberOfComponents(char *dataType)
+{
+ if (!strcmp(dataType, "SCALAR"))
+ {
+ return 1;
+ }
+ if (!strcmp(dataType, "VEC2"))
+ {
+ return 2;
+ }
+ if (!strcmp(dataType, "VEC3"))
+ {
+ return 3;
+ }
+ if (!strcmp(dataType, "VEC4"))
+ {
+ return 4;
+ }
+ if (!strcmp(dataType, "MAT2"))
+ {
+ return 4;
+ }
+ if (!strcmp(dataType, "MAT3"))
+ {
+ return 9;
+ }
+ if (!strcmp(dataType, "MAT4"))
+ {
+ return 16;
+ }
+
+ return 0;
+}
+
+size_t getComponentByteLength(size_t componentType)
+{
+ switch (componentType)
+ {
+ case ComponentType::Byte:
+ case ComponentType::UnsignedByte:
+ return 1;
+
+ case ComponentType::Short:
+ case ComponentType::UnsignedShort:
+ return 2;
+
+ case ComponentType::UnsignedInt:
+ case ComponentType::Float:
+ return 4;
+
+ default:
+ return 0;
+ }
+}
+
+size_t getAttributeStride(size_t componentType, char *dataType)
+{
+ return getComponentByteLength(componentType) * getNumberOfComponents(dataType);
+}
diff --git a/extern/draco/src/common.h b/extern/draco/src/common.h
new file mode 100644
index 00000000000..beaf7d91adb
--- /dev/null
+++ b/extern/draco/src/common.h
@@ -0,0 +1,50 @@
+/*
+ * 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.
+ */
+
+/**
+ * Library for the Draco encoding/decoding feature inside the glTF-Blender-IO project.
+ *
+ * The python script within glTF-Blender-IO uses the CTypes library to open the DLL,
+ * load function pointers add pass the raw data to the encoder.
+ *
+ * @author Jim Eckerlein <eckerlein@ux3d.io>
+ * @date 2020-11-18
+ */
+
+#pragma once
+
+#include <cstdint>
+#include <cstddef>
+
+#if defined(_MSC_VER)
+#define API(returnType) extern "C" __declspec(dllexport) returnType __cdecl
+#else
+#define API(returnType) extern "C" returnType
+#endif
+
+enum ComponentType: size_t
+{
+ Byte = 5120,
+ UnsignedByte = 5121,
+ Short = 5122,
+ UnsignedShort = 5123,
+ UnsignedInt = 5125,
+ Float = 5126,
+};
+
+size_t getNumberOfComponents(char *dataType);
+
+size_t getComponentByteLength(size_t componentType);
+
+size_t getAttributeStride(size_t componentType, char *dataType);
diff --git a/extern/draco/src/decoder.cpp b/extern/draco/src/decoder.cpp
new file mode 100644
index 00000000000..3f3e03bd9f2
--- /dev/null
+++ b/extern/draco/src/decoder.cpp
@@ -0,0 +1,222 @@
+/*
+ * 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 | "
+
+struct Decoder {
+ 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);
+
+ auto decoderStatus = dracoDecoder.DecodeMeshFromBuffer(&dracoDecoderBuffer);
+ if (!decoderStatus.ok())
+ {
+ printf(LOG_PREFIX "Error during Draco decoding: %s\n", decoderStatus.status().error_msg());
+ return false;
+ }
+
+ decoder->mesh = std::move(decoderStatus).value();
+ decoder->vertexCount = decoder->mesh->num_points();
+ decoder->indexCount = decoder->mesh->num_faces() * 3;
+
+ printf(LOG_PREFIX "Decoded %" PRIu32 " vertices, %" PRIu32 " indices\n", decoder->vertexCount, decoder->indexCount);
+
+ 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)
+{
+ const draco::PointAttribute* attribute = decoder->mesh->GetAttributeByUniqueId(id);
+ return attribute != nullptr && attribute->normalized();
+}
+
+bool decoderReadAttribute(Decoder *decoder, uint32_t id, size_t componentType, char *dataType)
+{
+ const draco::PointAttribute* attribute = decoder->mesh->GetAttributeByUniqueId(id);
+
+ if (attribute == nullptr)
+ {
+ printf(LOG_PREFIX "Attribute with id=%" PRIu32 " does not exist in Draco data\n", id);
+ return false;
+ }
+
+ size_t stride = getAttributeStride(componentType, dataType);
+
+ std::vector<uint8_t> decodedData;
+ decodedData.resize(stride * decoder->vertexCount);
+
+ for (uint32_t i = 0; i < decoder->vertexCount; ++i)
+ {
+ auto index = attribute->mapped_index(draco::PointIndex(i));
+ uint8_t *value = decodedData.data() + i * stride;
+
+ bool converted = false;
+
+ 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;
+ }
+ }
+
+ 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());
+ }
+}
+
+template<class T>
+void decodeIndices(Decoder *decoder)
+{
+ std::vector<uint8_t> decodedIndices;
+ decodedIndices.resize(decoder->indexCount * sizeof(T));
+ T *typedView = reinterpret_cast<T *>(decodedIndices.data());
+
+ 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();
+ }
+
+ decoder->indexBuffer = decodedIndices;
+}
+
+bool decoderReadIndices(Decoder *decoder, size_t indexComponentType)
+{
+ switch (indexComponentType)
+ {
+ 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;
+ }
+
+ 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());
+}
diff --git a/extern/draco/src/decoder.h b/extern/draco/src/decoder.h
new file mode 100644
index 00000000000..914eb776e8f
--- /dev/null
+++ b/extern/draco/src/decoder.h
@@ -0,0 +1,53 @@
+/*
+ * 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.
+ */
+
+/**
+ * Library for the Draco encoding/decoding feature inside the glTF-Blender-IO project.
+ *
+ * The python script within glTF-Blender-IO uses the CTypes library to open the DLL,
+ * load function pointers add pass the raw data to the encoder.
+ *
+ * @author Jim Eckerlein <eckerlein@ux3d.io>
+ * @date 2020-11-18
+ */
+
+#pragma once
+
+#include "common.h"
+
+struct Decoder;
+
+API(Decoder *) decoderCreate();
+
+API(void) decoderRelease(Decoder *decoder);
+
+API(bool) decoderDecode(Decoder *decoder, void *data, size_t byteLength);
+
+API(uint32_t) decoderGetVertexCount(Decoder *decoder);
+
+API(uint32_t) decoderGetIndexCount(Decoder *decoder);
+
+API(bool) decoderAttributeIsNormalized(Decoder *decoder, uint32_t id);
+
+API(bool) decoderReadAttribute(Decoder *decoder, uint32_t id, size_t componentType, char *dataType);
+
+API(size_t) decoderGetAttributeByteLength(Decoder *decoder, size_t id);
+
+API(void) decoderCopyAttribute(Decoder *decoder, size_t id, void *output);
+
+API(bool) decoderReadIndices(Decoder *decoder, size_t indexComponentType);
+
+API(size_t) decoderGetIndicesByteLength(Decoder *decoder);
+
+API(void) decoderCopyIndices(Decoder *decoder, void *output);
diff --git a/extern/draco/src/draco-compressor.cpp b/extern/draco/src/draco-compressor.cpp
deleted file mode 100644
index 4ae528888fe..00000000000
--- a/extern/draco/src/draco-compressor.cpp
+++ /dev/null
@@ -1,277 +0,0 @@
-/*
- * 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 2019-11-29
- */
-
-#include "draco-compressor.h"
-
-#include <memory>
-#include <vector>
-
-#include "draco/mesh/mesh.h"
-#include "draco/core/encoder_buffer.h"
-#include "draco/compression/encode.h"
-
-/**
- * Prefix used for logging messages.
- */
-const char *logTag = "DRACO-COMPRESSOR";
-
-struct DracoCompressor {
- draco::Mesh mesh;
-
- // One data buffer per attribute.
- std::vector<std::unique_ptr<draco::DataBuffer>> buffers;
-
- // The buffer the mesh is compressed into.
- draco::EncoderBuffer encoderBuffer;
-
- // Level of compression [0-10].
- // Higher values mean slower encoding.
- uint32_t compressionLevel = 7;
-
- struct {
- uint32_t positions = 14;
- uint32_t normals = 10;
- uint32_t uvs = 12;
- uint32_t generic = 12;
- } quantization;
-};
-
-DracoCompressor *create_compressor() {
- return new DracoCompressor;
-}
-
-void set_compression_level(
- DracoCompressor *const compressor,
- uint32_t const compressionLevel
-) {
- compressor->compressionLevel = compressionLevel;
-}
-
-void set_position_quantization(
- DracoCompressor *const compressor,
- uint32_t const quantizationBitsPosition
-) {
- compressor->quantization.positions = quantizationBitsPosition;
-}
-
-void set_normal_quantization(
- DracoCompressor *const compressor,
- uint32_t const quantizationBitsNormal
-) {
- compressor->quantization.normals = quantizationBitsNormal;
-}
-
-void set_uv_quantization(
- DracoCompressor *const compressor,
- uint32_t const quantizationBitsTexCoord
-) {
- compressor->quantization.uvs = quantizationBitsTexCoord;
-}
-
-void set_generic_quantization(
- DracoCompressor *const compressor,
- uint32_t const bits
-) {
- compressor->quantization.generic = bits;
-}
-
-bool compress(
- DracoCompressor *const compressor
-) {
- draco::Encoder encoder;
-
- encoder.SetSpeedOptions(10 - (int)compressor->compressionLevel, 10 - (int)compressor->compressionLevel);
- encoder.SetAttributeQuantization(draco::GeometryAttribute::POSITION, compressor->quantization.positions);
- encoder.SetAttributeQuantization(draco::GeometryAttribute::NORMAL, compressor->quantization.normals);
- encoder.SetAttributeQuantization(draco::GeometryAttribute::TEX_COORD, compressor->quantization.uvs);
- encoder.SetAttributeQuantization(draco::GeometryAttribute::GENERIC, compressor->quantization.generic);
-
- return encoder.EncodeMeshToBuffer(compressor->mesh, &compressor->encoderBuffer).ok();
-}
-
-bool compress_morphed(
- DracoCompressor *const compressor
-) {
- draco::Encoder encoder;
-
- encoder.SetSpeedOptions(10 - (int)compressor->compressionLevel, 10 - (int)compressor->compressionLevel);
-
- // For some reason, `EncodeMeshToBuffer` crashes when not disabling prediction or when enabling quantization
- // for attributes other position.
- encoder.SetAttributeQuantization(draco::GeometryAttribute::POSITION, compressor->quantization.positions);
- encoder.SetAttributePredictionScheme(draco::GeometryAttribute::POSITION, draco::PREDICTION_NONE);
- encoder.SetAttributePredictionScheme(draco::GeometryAttribute::NORMAL, draco::PREDICTION_NONE);
- encoder.SetAttributePredictionScheme(draco::GeometryAttribute::TEX_COORD, draco::PREDICTION_NONE);
- encoder.SetAttributePredictionScheme(draco::GeometryAttribute::GENERIC, draco::PREDICTION_NONE);
-
- // Enforce triangle order preservation.
- encoder.SetEncodingMethod(draco::MESH_SEQUENTIAL_ENCODING);
-
- return encoder.EncodeMeshToBuffer(compressor->mesh, &compressor->encoderBuffer).ok();
-}
-
-uint64_t get_compressed_size(
- DracoCompressor const *const compressor
-) {
- return compressor->encoderBuffer.size();
-}
-
-void copy_to_bytes(
- DracoCompressor const *const compressor,
- uint8_t *const o_data
-) {
- memcpy(o_data, compressor->encoderBuffer.data(), compressor->encoderBuffer.size());
-}
-
-void destroy_compressor(
- DracoCompressor *const compressor
-) {
- delete compressor;
-}
-
-template<class T>
-void set_faces_impl(
- draco::Mesh &mesh,
- int const index_count,
- T const *const indices
-) {
- mesh.SetNumFaces((size_t) index_count / 3);
-
- for (int i = 0; i < index_count; i += 3)
- {
- const auto a = draco::PointIndex(indices[i]);
- const auto b = draco::PointIndex(indices[i + 1]);
- const auto c = draco::PointIndex(indices[i + 2]);
- mesh.SetFace(draco::FaceIndex((uint32_t) i), {a, b, c});
- }
-}
-
-void set_faces(
- DracoCompressor *const compressor,
- uint32_t const index_count,
- uint32_t const index_byte_length,
- uint8_t const *const indices
-) {
- switch (index_byte_length)
- {
- case 1:
- {
- set_faces_impl(compressor->mesh, index_count, (uint8_t *) indices);
- break;
- }
- case 2:
- {
- set_faces_impl(compressor->mesh, index_count, (uint16_t *) indices);
- break;
- }
- case 4:
- {
- set_faces_impl(compressor->mesh, index_count, (uint32_t *) indices);
- break;
- }
- default:
- {
- printf("%s: Unsupported index size %d\n", logTag, index_byte_length);
- break;
- }
- }
-}
-
-uint32_t add_attribute_to_mesh(
- DracoCompressor *const compressor,
- draco::GeometryAttribute::Type const semantics,
- draco::DataType const data_type,
- uint32_t const count,
- uint8_t const component_count,
- uint8_t const component_size,
- uint8_t const *const data
-) {
- auto buffer = std::make_unique<draco::DataBuffer>();
-
- draco::GeometryAttribute attribute;
-
- attribute.Init(
- semantics,
- &*buffer,
- component_count,
- data_type,
- false,
- component_size * component_count,
- 0
- );
-
- auto const id = (uint32_t)compressor->mesh.AddAttribute(attribute, true, count);
-
- for (uint32_t i = 0; i < count; i++)
- {
- compressor->mesh.attribute(id)->SetAttributeValue(
- draco::AttributeValueIndex(i),
- data + i * component_count * component_size
- );
- }
-
- compressor->buffers.emplace_back(std::move(buffer));
-
- return id;
-}
-
-uint32_t add_positions_f32(
- DracoCompressor *const compressor,
- uint32_t const count,
- uint8_t const *const data
-) {
- return add_attribute_to_mesh(compressor, draco::GeometryAttribute::POSITION,
- draco::DT_FLOAT32, count, 3, sizeof(float), data);
-}
-
-uint32_t add_normals_f32(
- DracoCompressor *const compressor,
- uint32_t const count,
- uint8_t const *const data
-) {
- return add_attribute_to_mesh(compressor, draco::GeometryAttribute::NORMAL,
- draco::DT_FLOAT32, count, 3, sizeof(float), data);
-}
-
-uint32_t add_uvs_f32(
- DracoCompressor *const compressor,
- uint32_t const count,
- uint8_t const *const data
-) {
- return add_attribute_to_mesh(compressor, draco::GeometryAttribute::TEX_COORD,
- draco::DT_FLOAT32, count, 2, sizeof(float), data);
-}
-
-uint32_t add_joints_u16(
- DracoCompressor *compressor,
- uint32_t const count,
- uint8_t const *const data
-) {
- return add_attribute_to_mesh(compressor, draco::GeometryAttribute::GENERIC,
- draco::DT_UINT16, count, 4, sizeof(uint16_t), data);
-}
-
-uint32_t add_weights_f32(
- DracoCompressor *compressor,
- uint32_t const count,
- uint8_t const *const data
-) {
- return add_attribute_to_mesh(compressor, draco::GeometryAttribute::GENERIC,
- draco::DT_FLOAT32, count, 4, sizeof(float), data);
-}
diff --git a/extern/draco/src/draco-compressor.h b/extern/draco/src/draco-compressor.h
deleted file mode 100644
index fb6168a61af..00000000000
--- a/extern/draco/src/draco-compressor.h
+++ /dev/null
@@ -1,173 +0,0 @@
-/*
- * 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.
- */
-
-/**
- * C++ library for the Draco compression feature inside the glTF-Blender-IO project.
- *
- * The python side uses the CTypes library to open the DLL, load function
- * pointers add pass the data to the compressor as raw bytes.
- *
- * The compressor intercepts the regular glTF exporter after data has been
- * gathered and right before the data is converted to a JSON representation,
- * which is going to be written out.
- *
- * The original uncompressed data is removed and replaces an extension,
- * pointing to the newly created buffer containing the compressed data.
- *
- * @author Jim Eckerlein <eckerlein@ux3d.io>
- * @date 2019-11-29
- */
-
-#include <cstdint>
-
-#if defined(_MSC_VER)
-#define DLL_EXPORT(retType) extern "C" __declspec(dllexport) retType __cdecl
-#else
-#define DLL_EXPORT(retType) extern "C" retType
-#endif
-
-/**
- * This tuple is opaquely exposed to Python through a pointer.
- * It encapsulates the complete current compressor state.
- *
- * A single instance is only intended to compress a single primitive.
- */
-struct DracoCompressor;
-
-DLL_EXPORT(DracoCompressor *)
-create_compressor ();
-
-DLL_EXPORT(void)
-set_compression_level (
- DracoCompressor *compressor,
- uint32_t compressionLevel
-);
-
-DLL_EXPORT(void)
-set_position_quantization (
- DracoCompressor *compressor,
- uint32_t quantizationBitsPosition
-);
-
-DLL_EXPORT(void)
-set_normal_quantization (
- DracoCompressor *compressor,
- uint32_t quantizationBitsNormal
-);
-
-DLL_EXPORT(void)
-set_uv_quantization (
- DracoCompressor *compressor,
- uint32_t quantizationBitsTexCoord
-);
-
-DLL_EXPORT(void)
-set_generic_quantization (
- DracoCompressor *compressor,
- uint32_t bits
-);
-
-/// Compresses a mesh.
-/// Use `compress_morphed` when compressing primitives which have morph targets.
-DLL_EXPORT(bool)
-compress (
- DracoCompressor *compressor
-);
-
-/// Compresses the mesh.
-/// Use this instead of `compress`, because this procedure takes into account that mesh triangles must not be reordered.
-DLL_EXPORT(bool)
-compress_morphed (
- DracoCompressor *compressor
-);
-
-/**
- * Returns the size of the compressed data in bytes.
- */
-DLL_EXPORT(uint64_t)
-get_compressed_size (
- DracoCompressor const *compressor
-);
-
-/**
- * Copies the compressed mesh into the given byte buffer.
- *
- * @param[o_data] A Python `bytes` object.
- */
-DLL_EXPORT(void)
-copy_to_bytes (
- DracoCompressor const *compressor,
- uint8_t *o_data
-);
-
-/**
- * Releases all memory allocated by the compressor.
- */
-DLL_EXPORT(void)
-destroy_compressor (
- DracoCompressor *compressor
-);
-
-DLL_EXPORT(void)
-set_faces (
- DracoCompressor *compressor,
- uint32_t index_count,
- uint32_t index_byte_length,
- uint8_t const *indices
-);
-
-/// Adds a `float` position attribute to the current mesh.
-/// Returns the id Draco has assigned to this attribute.
-DLL_EXPORT(uint32_t)
-add_positions_f32 (
- DracoCompressor *compressor,
- uint32_t count,
- uint8_t const *data
-);
-
-/// Adds a `float` normal attribute to the current mesh.
-/// Returns the id Draco has assigned to this attribute.
-DLL_EXPORT(uint32_t)
-add_normals_f32 (
- DracoCompressor *compressor,
- uint32_t count,
- uint8_t const *data
-);
-
-/// Adds a `float` texture coordinate attribute to the current mesh.
-/// Returns the id Draco has assigned to this attribute.
-DLL_EXPORT(uint32_t)
-add_uvs_f32 (
- DracoCompressor *compressor,
- uint32_t count,
- uint8_t const *data
-);
-
-/// Adds a `unsigned short` joint attribute to the current mesh.
-/// Returns the id Draco has assigned to this attribute.
-DLL_EXPORT(uint32_t)
-add_joints_u16 (
- DracoCompressor *compressor,
- uint32_t count,
- uint8_t const *data
-);
-
-/// Adds a `float` weight attribute to the current mesh.
-/// Returns the id Draco has assigned to this attribute.
-DLL_EXPORT(uint32_t)
-add_weights_f32 (
- DracoCompressor *compressor,
- uint32_t count,
- uint8_t const *data
-);
diff --git a/extern/draco/src/encoder.cpp b/extern/draco/src/encoder.cpp
new file mode 100644
index 00000000000..ff7570ecfcd
--- /dev/null
+++ b/extern/draco/src/encoder.cpp
@@ -0,0 +1,247 @@
+/*
+ * 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 2019-11-18
+ */
+
+#include "encoder.h"
+
+#include <memory>
+#include <vector>
+
+#include "draco/mesh/mesh.h"
+#include "draco/core/encoder_buffer.h"
+#include "draco/compression/encode.h"
+
+#define LOG_PREFIX "DracoEncoder | "
+
+struct Encoder
+{
+ draco::Mesh mesh;
+ uint32_t encodedVertices;
+ uint32_t encodedIndices;
+ std::vector<std::unique_ptr<draco::DataBuffer>> buffers;
+ draco::EncoderBuffer encoderBuffer;
+ uint32_t compressionLevel = 7;
+ size_t rawSize = 0;
+ struct
+ {
+ uint32_t position = 14;
+ uint32_t normal = 10;
+ uint32_t uv = 12;
+ uint32_t color = 10;
+ uint32_t generic = 12;
+ } quantization;
+};
+
+Encoder *encoderCreate(uint32_t vertexCount)
+{
+ Encoder *encoder = new Encoder;
+ encoder->mesh.set_num_points(vertexCount);
+ return encoder;
+}
+
+void encoderRelease(Encoder *encoder)
+{
+ delete encoder;
+}
+
+void encoderSetCompressionLevel(Encoder *encoder, uint32_t compressionLevel) {
+ encoder->compressionLevel = compressionLevel;
+}
+
+void encoderSetQuantizationBits(Encoder *encoder, uint32_t position, uint32_t normal, uint32_t uv, uint32_t color, uint32_t generic)
+{
+ encoder->quantization.position = position;
+ encoder->quantization.normal = normal;
+ encoder->quantization.uv = uv;
+ encoder->quantization.color = color;
+ encoder->quantization.generic = generic;
+}
+
+bool encoderEncode(Encoder *encoder, uint8_t preserveTriangleOrder)
+{
+ printf(LOG_PREFIX "Preserve triangle order: %s\n", preserveTriangleOrder ? "yes" : "no");
+
+ draco::Encoder dracoEncoder;
+
+ int speed = 10 - static_cast<int>(encoder->compressionLevel);
+ dracoEncoder.SetSpeedOptions(speed, speed);
+
+ dracoEncoder.SetAttributeQuantization(draco::GeometryAttribute::POSITION, encoder->quantization.position);
+ dracoEncoder.SetAttributeQuantization(draco::GeometryAttribute::NORMAL, encoder->quantization.normal);
+ dracoEncoder.SetAttributeQuantization(draco::GeometryAttribute::TEX_COORD, encoder->quantization.uv);
+ dracoEncoder.SetAttributeQuantization(draco::GeometryAttribute::COLOR, encoder->quantization.color);
+ dracoEncoder.SetAttributeQuantization(draco::GeometryAttribute::GENERIC, encoder->quantization.generic);
+ dracoEncoder.SetTrackEncodedProperties(true);
+
+ if (preserveTriangleOrder)
+ {
+ dracoEncoder.SetEncodingMethod(draco::MESH_SEQUENTIAL_ENCODING);
+ }
+
+ auto encoderStatus = dracoEncoder.EncodeMeshToBuffer(encoder->mesh, &encoder->encoderBuffer);
+ if (encoderStatus.ok())
+ {
+ encoder->encodedVertices = static_cast<uint32_t>(dracoEncoder.num_encoded_points());
+ encoder->encodedIndices = static_cast<uint32_t>(dracoEncoder.num_encoded_faces() * 3);
+ size_t encodedSize = encoder->encoderBuffer.size();
+ float compressionRatio = static_cast<float>(encoder->rawSize) / static_cast<float>(encodedSize);
+ printf(LOG_PREFIX "Encoded %" PRIu32 " vertices, %" PRIu32 " indices, raw size: %zu, encoded size: %zu, compression ratio: %.2f\n", encoder->encodedVertices, encoder->encodedIndices, encoder->rawSize, encodedSize, compressionRatio);
+ return true;
+ }
+ else
+ {
+ printf(LOG_PREFIX "Error during Draco encoding: %s\n", encoderStatus.error_msg());
+ return false;
+ }
+}
+
+uint32_t encoderGetEncodedVertexCount(Encoder *encoder)
+{
+ return encoder->encodedVertices;
+}
+
+uint32_t encoderGetEncodedIndexCount(Encoder *encoder)
+{
+ return encoder->encodedIndices;
+}
+
+uint64_t encoderGetByteLength(Encoder *encoder)
+{
+ return encoder->encoderBuffer.size();
+}
+
+void encoderCopy(Encoder *encoder, uint8_t *data)
+{
+ memcpy(data, encoder->encoderBuffer.data(), encoder->encoderBuffer.size());
+}
+
+template<class T>
+void encodeIndices(Encoder *encoder, uint32_t indexCount, T *indices)
+{
+ int face_count = indexCount / 3;
+ encoder->mesh.SetNumFaces(static_cast<size_t>(face_count));
+ encoder->rawSize += indexCount * sizeof(T);
+
+ for (int i = 0; i < face_count; ++i)
+ {
+ draco::Mesh::Face face = {
+ draco::PointIndex(indices[3 * i + 0]),
+ draco::PointIndex(indices[3 * i + 1]),
+ draco::PointIndex(indices[3 * i + 2])
+ };
+ encoder->mesh.SetFace(draco::FaceIndex(static_cast<uint32_t>(i)), face);
+ }
+}
+
+void encoderSetIndices(Encoder *encoder, size_t indexComponentType, uint32_t indexCount, void *indices)
+{
+ switch (indexComponentType)
+ {
+ case ComponentType::Byte:
+ encodeIndices(encoder, indexCount, reinterpret_cast<int8_t *>(indices));
+ break;
+ case ComponentType::UnsignedByte:
+ encodeIndices(encoder, indexCount, reinterpret_cast<uint8_t *>(indices));
+ break;
+ case ComponentType::Short:
+ encodeIndices(encoder, indexCount, reinterpret_cast<int16_t *>(indices));
+ break;
+ case ComponentType::UnsignedShort:
+ encodeIndices(encoder, indexCount, reinterpret_cast<uint16_t *>(indices));
+ break;
+ case ComponentType::UnsignedInt:
+ encodeIndices(encoder, indexCount, reinterpret_cast<uint32_t *>(indices));
+ break;
+ default:
+ printf(LOG_PREFIX "Index component type %zu not supported\n", indexComponentType);
+ }
+}
+
+draco::GeometryAttribute::Type getAttributeSemantics(char *attribute)
+{
+ if (!strcmp(attribute, "POSITION"))
+ {
+ return draco::GeometryAttribute::POSITION;
+ }
+ if (!strcmp(attribute, "NORMAL"))
+ {
+ return draco::GeometryAttribute::NORMAL;
+ }
+ if (!strncmp(attribute, "TEXCOORD", strlen("TEXCOORD")))
+ {
+ return draco::GeometryAttribute::TEX_COORD;
+ }
+ if (!strncmp(attribute, "COLOR", strlen("COLOR")))
+ {
+ return draco::GeometryAttribute::COLOR;
+ }
+
+ return draco::GeometryAttribute::GENERIC;
+}
+
+draco::DataType getDataType(size_t componentType)
+{
+ switch (componentType)
+ {
+ case ComponentType::Byte:
+ return draco::DataType::DT_INT8;
+
+ case ComponentType::UnsignedByte:
+ return draco::DataType::DT_UINT8;
+
+ case ComponentType::Short:
+ return draco::DataType::DT_INT16;
+
+ case ComponentType::UnsignedShort:
+ return draco::DataType::DT_UINT16;
+
+ case ComponentType::UnsignedInt:
+ return draco::DataType::DT_UINT32;
+
+ case ComponentType::Float:
+ return draco::DataType::DT_FLOAT32;
+
+ default:
+ return draco::DataType::DT_INVALID;
+ }
+}
+
+API(uint32_t) encoderSetAttribute(Encoder *encoder, char *attributeName, size_t componentType, char *dataType, void *data)
+{
+ auto buffer = std::make_unique<draco::DataBuffer>();
+ uint32_t count = encoder->mesh.num_points();
+ size_t componentCount = getNumberOfComponents(dataType);
+ size_t stride = getAttributeStride(componentType, dataType);
+ draco::DataType dracoDataType = getDataType(componentType);
+
+ draco::GeometryAttribute::Type semantics = getAttributeSemantics(attributeName);
+ draco::GeometryAttribute attribute;
+ attribute.Init(semantics, &*buffer, componentCount, getDataType(componentType), false, stride, 0);
+
+ auto id = static_cast<uint32_t>(encoder->mesh.AddAttribute(attribute, true, count));
+ auto dataBytes = reinterpret_cast<uint8_t *>(data);
+
+ for (uint32_t i = 0; i < count; i++)
+ {
+ encoder->mesh.attribute(id)->SetAttributeValue(draco::AttributeValueIndex(i), dataBytes + i * stride);
+ }
+
+ encoder->buffers.emplace_back(std::move(buffer));
+ encoder->rawSize += count * stride;
+ return id;
+}
diff --git a/extern/draco/src/encoder.h b/extern/draco/src/encoder.h
new file mode 100644
index 00000000000..2f7f21a469b
--- /dev/null
+++ b/extern/draco/src/encoder.h
@@ -0,0 +1,51 @@
+/*
+ * 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.
+ */
+
+/**
+ * Library for the Draco encoding/decoding feature inside the glTF-Blender-IO project.
+ *
+ * The python script within glTF-Blender-IO uses the CTypes library to open the DLL,
+ * load function pointers add pass the raw data to the encoder.
+ *
+ * @author Jim Eckerlein <eckerlein@ux3d.io>
+ * @date 2020-11-18
+ */
+
+#pragma once
+
+#include "common.h"
+
+struct Encoder;
+
+API(Encoder *) encoderCreate(uint32_t vertexCount);
+
+API(void) encoderRelease(Encoder *encoder);
+
+API(void) encoderSetCompressionLevel(Encoder *encoder, uint32_t compressionLevel);
+
+API(void) encoderSetQuantizationBits(Encoder *encoder, uint32_t position, uint32_t normal, uint32_t uv, uint32_t color, uint32_t generic);
+
+API(bool) encoderEncode(Encoder *encoder, uint8_t preserveTriangleOrder);
+
+API(uint64_t) encoderGetByteLength(Encoder *encoder);
+
+API(void) encoderCopy(Encoder *encoder, uint8_t *data);
+
+API(void) encoderSetIndices(Encoder *encoder, size_t indexComponentType, uint32_t indexCount, void *indices);
+
+API(uint32_t) encoderSetAttribute(Encoder *encoder, char *attributeName, size_t componentType, char *dataType, void *data);
+
+API(uint32_t) encoderGetEncodedVertexCount(Encoder *encoder);
+
+API(uint32_t) encoderGetEncodedIndexCount(Encoder *encoder);