Add Chromium-only Blender WebEngine parity work

This commit is contained in:
mes123456
2026-08-12 04:47:48 -04:00
commit 9fd26010f6
18225 changed files with 11622124 additions and 0 deletions

View File

@@ -0,0 +1,59 @@
/* SPDX-FileCopyrightText: 2026 Blender Authors
*
* SPDX-License-Identifier: Apache-2.0 */
#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);
}

View File

@@ -0,0 +1,39 @@
/* SPDX-FileCopyrightText: 2026 Blender Authors
*
* SPDX-License-Identifier: Apache-2.0 */
/**
* 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 <cstddef>
#include <cstdint>
#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);

View File

@@ -0,0 +1,205 @@
/* SPDX-FileCopyrightText: 2026 Blender Authors
*
* SPDX-License-Identifier: Apache-2.0 */
/**
* @author Jim Eckerlein <eckerlein@ux3d.io>
* @date 2020-11-18
*/
#include "decoder.h"
#include <cinttypes>
#include <memory>
#include <vector>
#include "draco/compression/decode.h"
#include "draco/core/decoder_buffer.h"
#include "draco/mesh/mesh.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());
}

View File

@@ -0,0 +1,55 @@
/* SPDX-FileCopyrightText: 2026 Blender Authors
*
* SPDX-License-Identifier: Apache-2.0 */
/**
* 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);

View File

@@ -0,0 +1,249 @@
/* SPDX-FileCopyrightText: 2026 Blender Authors
*
* SPDX-License-Identifier: Apache-2.0 */
/**
* @author Jim Eckerlein <eckerlein@ux3d.io>
* @date 2019-11-18
*/
#include "encoder.h"
#include <memory>
#include <vector>
#include "draco/compression/encode.h"
#include "draco/core/encoder_buffer.h"
#include "draco/mesh/mesh.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,
bool normalized)
{
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::GeometryAttribute::Type semantics = getAttributeSemantics(attributeName);
draco::GeometryAttribute attribute;
attribute.Init(
semantics, &*buffer, componentCount, getDataType(componentType), normalized, 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;
}

View File

@@ -0,0 +1,62 @@
/* SPDX-FileCopyrightText: 2026 Blender Authors
*
* SPDX-License-Identifier: Apache-2.0 */
/**
* 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,
bool normalized);
API(uint32_t)
encoderGetEncodedVertexCount(Encoder *encoder);
API(uint32_t)
encoderGetEncodedIndexCount(Encoder *encoder);