mirror of
https://github.com/godotengine/godot.git
synced 2025-12-07 22:00:10 +00:00
Merge pull request #108304 from aaronfranke/4.3-gltf-buffer-nasty
[4.3] GLTF: Fix nasty bug with incorrect buffer indices
This commit is contained in:
commit
c6c91cfcad
3 changed files with 225 additions and 101 deletions
|
|
@ -70,6 +70,10 @@
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
|
|
||||||
|
constexpr int COMPONENT_COUNT_FOR_ACCESSOR_TYPE[7] = {
|
||||||
|
1, 2, 3, 4, 4, 9, 16
|
||||||
|
};
|
||||||
|
|
||||||
static Ref<ImporterMesh> _mesh_to_importer_mesh(Ref<Mesh> p_mesh) {
|
static Ref<ImporterMesh> _mesh_to_importer_mesh(Ref<Mesh> p_mesh) {
|
||||||
Ref<ImporterMesh> importer_mesh;
|
Ref<ImporterMesh> importer_mesh;
|
||||||
importer_mesh.instantiate();
|
importer_mesh.instantiate();
|
||||||
|
|
@ -169,10 +173,6 @@ Error GLTFDocument::_serialize(Ref<GLTFState> p_state) {
|
||||||
return Error::FAILED;
|
return Error::FAILED;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (GLTFBufferViewIndex i = 0; i < p_state->buffer_views.size(); i++) {
|
|
||||||
p_state->buffer_views.write[i]->buffer = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* STEP SERIALIZE BUFFER VIEWS */
|
/* STEP SERIALIZE BUFFER VIEWS */
|
||||||
err = _encode_buffer_views(p_state);
|
err = _encode_buffer_views(p_state);
|
||||||
if (err != OK) {
|
if (err != OK) {
|
||||||
|
|
@ -1090,18 +1090,21 @@ String GLTFDocument::_get_component_type_name(const uint32_t p_component) {
|
||||||
return "<Error>";
|
return "<Error>";
|
||||||
}
|
}
|
||||||
|
|
||||||
Error GLTFDocument::_encode_buffer_view(Ref<GLTFState> p_state, const double *p_src, const int p_count, const GLTFAccessor::GLTFAccessorType p_accessor_type, const int p_component_type, const bool p_normalized, const int p_byte_offset, const bool p_for_vertex, GLTFBufferViewIndex &r_accessor, const bool p_for_vertex_indices) {
|
Error GLTFDocument::_encode_accessor_into_buffer_view(Ref<GLTFState> p_state, const double *p_src, const int64_t p_count, const GLTFAccessor::GLTFAccessorType p_accessor_type, const int p_component_type, const bool p_normalized, const int64_t p_byte_offset, const bool p_for_vertex, GLTFBufferViewIndex &r_buffer_view, const bool p_for_vertex_indices) {
|
||||||
const int component_count_for_type[7] = {
|
const int component_count = COMPONENT_COUNT_FOR_ACCESSOR_TYPE[p_accessor_type];
|
||||||
1, 2, 3, 4, 4, 9, 16
|
|
||||||
};
|
|
||||||
|
|
||||||
const int component_count = component_count_for_type[p_accessor_type];
|
|
||||||
const int component_size = _get_component_type_size(p_component_type);
|
const int component_size = _get_component_type_size(p_component_type);
|
||||||
ERR_FAIL_COND_V(component_size == 0, FAILED);
|
ERR_FAIL_COND_V(component_size == 0, FAILED);
|
||||||
|
// The byte offset of an accessor MUST be a multiple of the accessor's component size.
|
||||||
|
// See 3.6.2.4: https://registry.khronos.org/glTF/specs/2.0/glTF-2.0.html#data-alignment
|
||||||
|
int64_t offset = p_byte_offset;
|
||||||
|
if (p_byte_offset % component_size != 0) {
|
||||||
|
offset += component_size - (p_byte_offset % component_size);
|
||||||
|
}
|
||||||
|
|
||||||
int skip_every = 0;
|
int64_t skip_every = 0;
|
||||||
int skip_bytes = 0;
|
int64_t skip_bytes = 0;
|
||||||
//special case of alignments, as described in spec
|
// Accessors of matrix type have data stored in column-major order. The start of each column MUST be aligned to 4-byte boundaries.
|
||||||
|
// See 3.6.2.4: https://registry.khronos.org/glTF/specs/2.0/glTF-2.0.html#data-alignment
|
||||||
switch (p_component_type) {
|
switch (p_component_type) {
|
||||||
case COMPONENT_TYPE_BYTE:
|
case COMPONENT_TYPE_BYTE:
|
||||||
case COMPONENT_TYPE_UNSIGNED_BYTE: {
|
case COMPONENT_TYPE_UNSIGNED_BYTE: {
|
||||||
|
|
@ -1118,7 +1121,7 @@ Error GLTFDocument::_encode_buffer_view(Ref<GLTFState> p_state, const double *p_
|
||||||
case COMPONENT_TYPE_UNSIGNED_SHORT: {
|
case COMPONENT_TYPE_UNSIGNED_SHORT: {
|
||||||
if (p_accessor_type == GLTFAccessor::TYPE_MAT3) {
|
if (p_accessor_type == GLTFAccessor::TYPE_MAT3) {
|
||||||
skip_every = 6;
|
skip_every = 6;
|
||||||
skip_bytes = 4;
|
skip_bytes = 2;
|
||||||
}
|
}
|
||||||
} break;
|
} break;
|
||||||
default: {
|
default: {
|
||||||
|
|
@ -1127,8 +1130,10 @@ Error GLTFDocument::_encode_buffer_view(Ref<GLTFState> p_state, const double *p_
|
||||||
|
|
||||||
Ref<GLTFBufferView> bv;
|
Ref<GLTFBufferView> bv;
|
||||||
bv.instantiate();
|
bv.instantiate();
|
||||||
const uint32_t offset = bv->byte_offset = p_byte_offset;
|
const GLTFBufferIndex buffer0 = 0;
|
||||||
Vector<uint8_t> &gltf_buffer = p_state->buffers.write[0];
|
bv->buffer = buffer0;
|
||||||
|
bv->byte_offset = offset;
|
||||||
|
Vector<uint8_t> &gltf_buffer = p_state->buffers.write[buffer0];
|
||||||
|
|
||||||
int stride = component_count * component_size;
|
int stride = component_count * component_size;
|
||||||
if (p_for_vertex && stride % 4) {
|
if (p_for_vertex && stride % 4) {
|
||||||
|
|
@ -1150,139 +1155,237 @@ Error GLTFDocument::_encode_buffer_view(Ref<GLTFState> p_state, const double *p_
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (p_component_type) {
|
switch (p_component_type) {
|
||||||
case COMPONENT_TYPE_BYTE: {
|
case GLTFAccessor::COMPONENT_TYPE_NONE: {
|
||||||
Vector<int8_t> buffer;
|
ERR_FAIL_V_MSG(ERR_INVALID_DATA, "glTF: Failed to encode buffer view, component type not set.");
|
||||||
buffer.resize(p_count * component_count);
|
}
|
||||||
int32_t dst_i = 0;
|
case GLTFAccessor::COMPONENT_TYPE_SIGNED_BYTE: {
|
||||||
for (int i = 0; i < p_count; i++) {
|
Vector<int8_t> encoded_data;
|
||||||
for (int j = 0; j < component_count; j++) {
|
encoded_data.resize(p_count * component_count);
|
||||||
|
int64_t dst_i = 0;
|
||||||
|
for (int64_t i = 0; i < p_count; i++) {
|
||||||
|
for (int64_t j = 0; j < component_count; j++) {
|
||||||
if (skip_every && j > 0 && (j % skip_every) == 0) {
|
if (skip_every && j > 0 && (j % skip_every) == 0) {
|
||||||
dst_i += skip_bytes;
|
dst_i += skip_bytes;
|
||||||
}
|
}
|
||||||
double d = *p_src;
|
double d = *p_src;
|
||||||
if (p_normalized) {
|
if (p_normalized) {
|
||||||
buffer.write[dst_i] = d * 128.0;
|
encoded_data.write[dst_i] = d * 128.0;
|
||||||
} else {
|
} else {
|
||||||
buffer.write[dst_i] = d;
|
encoded_data.write[dst_i] = d;
|
||||||
}
|
}
|
||||||
p_src++;
|
p_src++;
|
||||||
dst_i++;
|
dst_i++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
int64_t old_size = gltf_buffer.size();
|
const int64_t old_size = gltf_buffer.size();
|
||||||
gltf_buffer.resize(old_size + (buffer.size() * sizeof(int8_t)));
|
const size_t buffer_size = encoded_data.size() * sizeof(int8_t);
|
||||||
memcpy(gltf_buffer.ptrw() + old_size, buffer.ptrw(), buffer.size() * sizeof(int8_t));
|
gltf_buffer.resize(old_size + buffer_size);
|
||||||
bv->byte_length = buffer.size() * sizeof(int8_t);
|
memcpy(gltf_buffer.ptrw() + old_size, encoded_data.ptrw(), buffer_size);
|
||||||
|
bv->byte_length = buffer_size;
|
||||||
} break;
|
} break;
|
||||||
case COMPONENT_TYPE_UNSIGNED_BYTE: {
|
case GLTFAccessor::COMPONENT_TYPE_UNSIGNED_BYTE: {
|
||||||
Vector<uint8_t> buffer;
|
Vector<uint8_t> encoded_data;
|
||||||
buffer.resize(p_count * component_count);
|
encoded_data.resize(p_count * component_count);
|
||||||
int32_t dst_i = 0;
|
int64_t dst_i = 0;
|
||||||
for (int i = 0; i < p_count; i++) {
|
for (int64_t i = 0; i < p_count; i++) {
|
||||||
for (int j = 0; j < component_count; j++) {
|
for (int64_t j = 0; j < component_count; j++) {
|
||||||
if (skip_every && j > 0 && (j % skip_every) == 0) {
|
if (skip_every && j > 0 && (j % skip_every) == 0) {
|
||||||
dst_i += skip_bytes;
|
dst_i += skip_bytes;
|
||||||
}
|
}
|
||||||
double d = *p_src;
|
double d = *p_src;
|
||||||
if (p_normalized) {
|
if (p_normalized) {
|
||||||
buffer.write[dst_i] = d * 255.0;
|
encoded_data.write[dst_i] = d * 255.0;
|
||||||
} else {
|
} else {
|
||||||
buffer.write[dst_i] = d;
|
encoded_data.write[dst_i] = d;
|
||||||
}
|
}
|
||||||
p_src++;
|
p_src++;
|
||||||
dst_i++;
|
dst_i++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
gltf_buffer.append_array(buffer);
|
gltf_buffer.append_array(encoded_data);
|
||||||
bv->byte_length = buffer.size() * sizeof(uint8_t);
|
const size_t buffer_size = encoded_data.size() * sizeof(uint8_t);
|
||||||
|
bv->byte_length = buffer_size;
|
||||||
} break;
|
} break;
|
||||||
case COMPONENT_TYPE_SHORT: {
|
case GLTFAccessor::COMPONENT_TYPE_SIGNED_SHORT: {
|
||||||
Vector<int16_t> buffer;
|
Vector<int16_t> encoded_data;
|
||||||
buffer.resize(p_count * component_count);
|
encoded_data.resize(p_count * component_count);
|
||||||
int32_t dst_i = 0;
|
int64_t dst_i = 0;
|
||||||
for (int i = 0; i < p_count; i++) {
|
for (int64_t i = 0; i < p_count; i++) {
|
||||||
for (int j = 0; j < component_count; j++) {
|
for (int64_t j = 0; j < component_count; j++) {
|
||||||
if (skip_every && j > 0 && (j % skip_every) == 0) {
|
if (skip_every && j > 0 && (j % skip_every) == 0) {
|
||||||
dst_i += skip_bytes;
|
dst_i += skip_bytes;
|
||||||
}
|
}
|
||||||
double d = *p_src;
|
double d = *p_src;
|
||||||
if (p_normalized) {
|
if (p_normalized) {
|
||||||
buffer.write[dst_i] = d * 32768.0;
|
encoded_data.write[dst_i] = d * 32768.0;
|
||||||
} else {
|
} else {
|
||||||
buffer.write[dst_i] = d;
|
encoded_data.write[dst_i] = d;
|
||||||
}
|
}
|
||||||
p_src++;
|
p_src++;
|
||||||
dst_i++;
|
dst_i++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
int64_t old_size = gltf_buffer.size();
|
const int64_t old_size = gltf_buffer.size();
|
||||||
gltf_buffer.resize(old_size + (buffer.size() * sizeof(int16_t)));
|
const size_t buffer_size = encoded_data.size() * sizeof(int16_t);
|
||||||
memcpy(gltf_buffer.ptrw() + old_size, buffer.ptrw(), buffer.size() * sizeof(int16_t));
|
gltf_buffer.resize(old_size + buffer_size);
|
||||||
bv->byte_length = buffer.size() * sizeof(int16_t);
|
memcpy(gltf_buffer.ptrw() + old_size, encoded_data.ptrw(), buffer_size);
|
||||||
|
bv->byte_length = buffer_size;
|
||||||
} break;
|
} break;
|
||||||
case COMPONENT_TYPE_UNSIGNED_SHORT: {
|
case GLTFAccessor::COMPONENT_TYPE_UNSIGNED_SHORT: {
|
||||||
Vector<uint16_t> buffer;
|
Vector<uint16_t> encoded_data;
|
||||||
buffer.resize(p_count * component_count);
|
encoded_data.resize(p_count * component_count);
|
||||||
int32_t dst_i = 0;
|
int64_t dst_i = 0;
|
||||||
for (int i = 0; i < p_count; i++) {
|
for (int64_t i = 0; i < p_count; i++) {
|
||||||
for (int j = 0; j < component_count; j++) {
|
for (int64_t j = 0; j < component_count; j++) {
|
||||||
if (skip_every && j > 0 && (j % skip_every) == 0) {
|
if (skip_every && j > 0 && (j % skip_every) == 0) {
|
||||||
dst_i += skip_bytes;
|
dst_i += skip_bytes;
|
||||||
}
|
}
|
||||||
double d = *p_src;
|
double d = *p_src;
|
||||||
if (p_normalized) {
|
if (p_normalized) {
|
||||||
buffer.write[dst_i] = d * 65535.0;
|
encoded_data.write[dst_i] = d * 65535.0;
|
||||||
} else {
|
} else {
|
||||||
buffer.write[dst_i] = d;
|
encoded_data.write[dst_i] = d;
|
||||||
}
|
}
|
||||||
p_src++;
|
p_src++;
|
||||||
dst_i++;
|
dst_i++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
int64_t old_size = gltf_buffer.size();
|
const int64_t old_size = gltf_buffer.size();
|
||||||
gltf_buffer.resize(old_size + (buffer.size() * sizeof(uint16_t)));
|
const size_t buffer_size = encoded_data.size() * sizeof(uint16_t);
|
||||||
memcpy(gltf_buffer.ptrw() + old_size, buffer.ptrw(), buffer.size() * sizeof(uint16_t));
|
gltf_buffer.resize(old_size + buffer_size);
|
||||||
bv->byte_length = buffer.size() * sizeof(uint16_t);
|
memcpy(gltf_buffer.ptrw() + old_size, encoded_data.ptrw(), buffer_size);
|
||||||
|
bv->byte_length = buffer_size;
|
||||||
} break;
|
} break;
|
||||||
case COMPONENT_TYPE_INT: {
|
case GLTFAccessor::COMPONENT_TYPE_SIGNED_INT: {
|
||||||
Vector<int> buffer;
|
Vector<int32_t> encoded_data;
|
||||||
buffer.resize(p_count * component_count);
|
encoded_data.resize(p_count * component_count);
|
||||||
int32_t dst_i = 0;
|
int64_t dst_i = 0;
|
||||||
for (int i = 0; i < p_count; i++) {
|
for (int64_t i = 0; i < p_count; i++) {
|
||||||
for (int j = 0; j < component_count; j++) {
|
for (int64_t j = 0; j < component_count; j++) {
|
||||||
if (skip_every && j > 0 && (j % skip_every) == 0) {
|
if (skip_every && j > 0 && (j % skip_every) == 0) {
|
||||||
dst_i += skip_bytes;
|
dst_i += skip_bytes;
|
||||||
}
|
}
|
||||||
double d = *p_src;
|
double d = *p_src;
|
||||||
buffer.write[dst_i] = d;
|
encoded_data.write[dst_i] = d;
|
||||||
p_src++;
|
p_src++;
|
||||||
dst_i++;
|
dst_i++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
int64_t old_size = gltf_buffer.size();
|
const int64_t old_size = gltf_buffer.size();
|
||||||
gltf_buffer.resize(old_size + (buffer.size() * sizeof(int32_t)));
|
const size_t buffer_size = encoded_data.size() * sizeof(int32_t);
|
||||||
memcpy(gltf_buffer.ptrw() + old_size, buffer.ptrw(), buffer.size() * sizeof(int32_t));
|
gltf_buffer.resize(old_size + buffer_size);
|
||||||
bv->byte_length = buffer.size() * sizeof(int32_t);
|
memcpy(gltf_buffer.ptrw() + old_size, encoded_data.ptrw(), buffer_size);
|
||||||
|
bv->byte_length = buffer_size;
|
||||||
} break;
|
} break;
|
||||||
case COMPONENT_TYPE_FLOAT: {
|
case GLTFAccessor::COMPONENT_TYPE_UNSIGNED_INT: {
|
||||||
Vector<float> buffer;
|
Vector<uint32_t> encoded_data;
|
||||||
buffer.resize(p_count * component_count);
|
encoded_data.resize(p_count * component_count);
|
||||||
int32_t dst_i = 0;
|
int64_t dst_i = 0;
|
||||||
for (int i = 0; i < p_count; i++) {
|
for (int64_t i = 0; i < p_count; i++) {
|
||||||
for (int j = 0; j < component_count; j++) {
|
for (int64_t j = 0; j < component_count; j++) {
|
||||||
if (skip_every && j > 0 && (j % skip_every) == 0) {
|
if (skip_every && j > 0 && (j % skip_every) == 0) {
|
||||||
dst_i += skip_bytes;
|
dst_i += skip_bytes;
|
||||||
}
|
}
|
||||||
double d = *p_src;
|
double d = *p_src;
|
||||||
buffer.write[dst_i] = d;
|
encoded_data.write[dst_i] = d;
|
||||||
p_src++;
|
p_src++;
|
||||||
dst_i++;
|
dst_i++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
int64_t old_size = gltf_buffer.size();
|
const int64_t old_size = gltf_buffer.size();
|
||||||
gltf_buffer.resize(old_size + (buffer.size() * sizeof(float)));
|
const size_t buffer_size = encoded_data.size() * sizeof(uint32_t);
|
||||||
memcpy(gltf_buffer.ptrw() + old_size, buffer.ptrw(), buffer.size() * sizeof(float));
|
gltf_buffer.resize(old_size + buffer_size);
|
||||||
bv->byte_length = buffer.size() * sizeof(float);
|
memcpy(gltf_buffer.ptrw() + old_size, encoded_data.ptrw(), buffer_size);
|
||||||
|
bv->byte_length = buffer_size;
|
||||||
|
} break;
|
||||||
|
case GLTFAccessor::COMPONENT_TYPE_SINGLE_FLOAT: {
|
||||||
|
Vector<float> encoded_data;
|
||||||
|
encoded_data.resize(p_count * component_count);
|
||||||
|
int64_t dst_i = 0;
|
||||||
|
for (int64_t i = 0; i < p_count; i++) {
|
||||||
|
for (int64_t j = 0; j < component_count; j++) {
|
||||||
|
if (skip_every && j > 0 && (j % skip_every) == 0) {
|
||||||
|
dst_i += skip_bytes;
|
||||||
|
}
|
||||||
|
double d = *p_src;
|
||||||
|
encoded_data.write[dst_i] = d;
|
||||||
|
p_src++;
|
||||||
|
dst_i++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const int64_t old_size = gltf_buffer.size();
|
||||||
|
const size_t buffer_size = encoded_data.size() * sizeof(float);
|
||||||
|
gltf_buffer.resize(old_size + buffer_size);
|
||||||
|
memcpy(gltf_buffer.ptrw() + old_size, encoded_data.ptrw(), buffer_size);
|
||||||
|
bv->byte_length = buffer_size;
|
||||||
|
} break;
|
||||||
|
case GLTFAccessor::COMPONENT_TYPE_DOUBLE_FLOAT: {
|
||||||
|
Vector<double> encoded_data;
|
||||||
|
encoded_data.resize(p_count * component_count);
|
||||||
|
int64_t dst_i = 0;
|
||||||
|
for (int64_t i = 0; i < p_count; i++) {
|
||||||
|
for (int64_t j = 0; j < component_count; j++) {
|
||||||
|
if (skip_every && j > 0 && (j % skip_every) == 0) {
|
||||||
|
dst_i += skip_bytes;
|
||||||
|
}
|
||||||
|
double d = *p_src;
|
||||||
|
encoded_data.write[dst_i] = d;
|
||||||
|
p_src++;
|
||||||
|
dst_i++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const int64_t old_size = gltf_buffer.size();
|
||||||
|
const size_t buffer_size = encoded_data.size() * sizeof(double);
|
||||||
|
gltf_buffer.resize(old_size + buffer_size);
|
||||||
|
memcpy(gltf_buffer.ptrw() + old_size, encoded_data.ptrw(), buffer_size);
|
||||||
|
bv->byte_length = buffer_size;
|
||||||
|
} break;
|
||||||
|
case GLTFAccessor::COMPONENT_TYPE_HALF_FLOAT: {
|
||||||
|
ERR_FAIL_V_MSG(ERR_UNAVAILABLE, "glTF: Half float not supported yet.");
|
||||||
|
} break;
|
||||||
|
case GLTFAccessor::COMPONENT_TYPE_SIGNED_LONG: {
|
||||||
|
Vector<int64_t> encoded_data;
|
||||||
|
encoded_data.resize(p_count * component_count);
|
||||||
|
int64_t dst_i = 0;
|
||||||
|
for (int64_t i = 0; i < p_count; i++) {
|
||||||
|
for (int64_t j = 0; j < component_count; j++) {
|
||||||
|
if (skip_every && j > 0 && (j % skip_every) == 0) {
|
||||||
|
dst_i += skip_bytes;
|
||||||
|
}
|
||||||
|
// FIXME: This can result in precision loss because int64_t can store some values that double can't.
|
||||||
|
double d = *p_src;
|
||||||
|
encoded_data.write[dst_i] = d;
|
||||||
|
p_src++;
|
||||||
|
dst_i++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const int64_t old_size = gltf_buffer.size();
|
||||||
|
const size_t buffer_size = encoded_data.size() * sizeof(int64_t);
|
||||||
|
gltf_buffer.resize(old_size + buffer_size);
|
||||||
|
memcpy(gltf_buffer.ptrw() + old_size, encoded_data.ptrw(), buffer_size);
|
||||||
|
bv->byte_length = buffer_size;
|
||||||
|
} break;
|
||||||
|
case GLTFAccessor::COMPONENT_TYPE_UNSIGNED_LONG: {
|
||||||
|
Vector<uint64_t> encoded_data;
|
||||||
|
encoded_data.resize(p_count * component_count);
|
||||||
|
int64_t dst_i = 0;
|
||||||
|
for (int64_t i = 0; i < p_count; i++) {
|
||||||
|
for (int64_t j = 0; j < component_count; j++) {
|
||||||
|
if (skip_every && j > 0 && (j % skip_every) == 0) {
|
||||||
|
dst_i += skip_bytes;
|
||||||
|
}
|
||||||
|
// FIXME: This can result in precision loss because int64_t can store some values that double can't.
|
||||||
|
double d = *p_src;
|
||||||
|
encoded_data.write[dst_i] = d;
|
||||||
|
p_src++;
|
||||||
|
dst_i++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const int64_t old_size = gltf_buffer.size();
|
||||||
|
const size_t buffer_size = encoded_data.size() * sizeof(uint64_t);
|
||||||
|
gltf_buffer.resize(old_size + buffer_size);
|
||||||
|
memcpy(gltf_buffer.ptrw() + old_size, encoded_data.ptrw(), buffer_size);
|
||||||
|
bv->byte_length = buffer_size;
|
||||||
} break;
|
} break;
|
||||||
}
|
}
|
||||||
ERR_FAIL_COND_V(buffer_end > bv->byte_length, ERR_INVALID_DATA);
|
ERR_FAIL_COND_V(buffer_end > bv->byte_length, ERR_INVALID_DATA);
|
||||||
|
|
@ -1293,7 +1396,7 @@ Error GLTFDocument::_encode_buffer_view(Ref<GLTFState> p_state, const double *p_
|
||||||
gltf_buffer.push_back(0);
|
gltf_buffer.push_back(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
r_accessor = bv->buffer = p_state->buffer_views.size();
|
r_buffer_view = p_state->buffer_views.size();
|
||||||
p_state->buffer_views.push_back(bv);
|
p_state->buffer_views.push_back(bv);
|
||||||
return OK;
|
return OK;
|
||||||
}
|
}
|
||||||
|
|
@ -1310,6 +1413,12 @@ Error GLTFDocument::_decode_buffer_view(Ref<GLTFState> p_state, double *p_dst, c
|
||||||
}
|
}
|
||||||
|
|
||||||
ERR_FAIL_INDEX_V(bv->buffer, p_state->buffers.size(), ERR_PARSE_ERROR);
|
ERR_FAIL_INDEX_V(bv->buffer, p_state->buffers.size(), ERR_PARSE_ERROR);
|
||||||
|
if (bv->byte_offset % p_component_size != 0) {
|
||||||
|
WARN_PRINT("glTF: Buffer view byte offset is not a multiple of accessor component size. This file is invalid per the glTF specification and will not load correctly in some glTF viewers, but Godot will try to load it anyway.");
|
||||||
|
}
|
||||||
|
if (p_byte_offset % p_component_size != 0) {
|
||||||
|
WARN_PRINT("glTF: Accessor byte offset is not a multiple of accessor component size. This file is invalid per the glTF specification and will not load correctly in some glTF viewers, but Godot will try to load it anyway.");
|
||||||
|
}
|
||||||
|
|
||||||
const uint32_t offset = bv->byte_offset + p_byte_offset;
|
const uint32_t offset = bv->byte_offset + p_byte_offset;
|
||||||
Vector<uint8_t> buffer = p_state->buffers[bv->buffer]; //copy on write, so no performance hit
|
Vector<uint8_t> buffer = p_state->buffers[bv->buffer]; //copy on write, so no performance hit
|
||||||
|
|
@ -1553,7 +1662,7 @@ GLTFAccessorIndex GLTFDocument::_encode_accessor_as_ints(Ref<GLTFState> p_state,
|
||||||
accessor->accessor_type = accessor_type;
|
accessor->accessor_type = accessor_type;
|
||||||
accessor->component_type = component_type;
|
accessor->component_type = component_type;
|
||||||
accessor->byte_offset = 0;
|
accessor->byte_offset = 0;
|
||||||
Error err = _encode_buffer_view(p_state, attribs.ptr(), attribs.size(), accessor_type, component_type, accessor->normalized, size, p_for_vertex, buffer_view_i, p_for_vertex_indices);
|
Error err = _encode_accessor_into_buffer_view(p_state, attribs.ptr(), attribs.size(), accessor_type, component_type, accessor->normalized, size, p_for_vertex, buffer_view_i, p_for_vertex_indices);
|
||||||
if (err != OK) {
|
if (err != OK) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
@ -1662,7 +1771,7 @@ GLTFAccessorIndex GLTFDocument::_encode_accessor_as_vec2(Ref<GLTFState> p_state,
|
||||||
accessor->accessor_type = accessor_type;
|
accessor->accessor_type = accessor_type;
|
||||||
accessor->component_type = component_type;
|
accessor->component_type = component_type;
|
||||||
accessor->byte_offset = 0;
|
accessor->byte_offset = 0;
|
||||||
Error err = _encode_buffer_view(p_state, attribs.ptr(), p_attribs.size(), accessor_type, component_type, accessor->normalized, size, p_for_vertex, buffer_view_i);
|
Error err = _encode_accessor_into_buffer_view(p_state, attribs.ptr(), p_attribs.size(), accessor_type, component_type, accessor->normalized, size, p_for_vertex, buffer_view_i);
|
||||||
if (err != OK) {
|
if (err != OK) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
@ -1715,7 +1824,7 @@ GLTFAccessorIndex GLTFDocument::_encode_accessor_as_color(Ref<GLTFState> p_state
|
||||||
accessor->accessor_type = accessor_type;
|
accessor->accessor_type = accessor_type;
|
||||||
accessor->component_type = component_type;
|
accessor->component_type = component_type;
|
||||||
accessor->byte_offset = 0;
|
accessor->byte_offset = 0;
|
||||||
Error err = _encode_buffer_view(p_state, attribs.ptr(), p_attribs.size(), accessor_type, component_type, accessor->normalized, size, p_for_vertex, buffer_view_i);
|
Error err = _encode_accessor_into_buffer_view(p_state, attribs.ptr(), p_attribs.size(), accessor_type, component_type, accessor->normalized, size, p_for_vertex, buffer_view_i);
|
||||||
if (err != OK) {
|
if (err != OK) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
@ -1782,7 +1891,7 @@ GLTFAccessorIndex GLTFDocument::_encode_accessor_as_weights(Ref<GLTFState> p_sta
|
||||||
accessor->accessor_type = accessor_type;
|
accessor->accessor_type = accessor_type;
|
||||||
accessor->component_type = component_type;
|
accessor->component_type = component_type;
|
||||||
accessor->byte_offset = 0;
|
accessor->byte_offset = 0;
|
||||||
Error err = _encode_buffer_view(p_state, attribs.ptr(), p_attribs.size(), accessor_type, component_type, accessor->normalized, size, p_for_vertex, buffer_view_i);
|
Error err = _encode_accessor_into_buffer_view(p_state, attribs.ptr(), p_attribs.size(), accessor_type, component_type, accessor->normalized, size, p_for_vertex, buffer_view_i);
|
||||||
if (err != OK) {
|
if (err != OK) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
@ -1833,7 +1942,7 @@ GLTFAccessorIndex GLTFDocument::_encode_accessor_as_joints(Ref<GLTFState> p_stat
|
||||||
accessor->accessor_type = accessor_type;
|
accessor->accessor_type = accessor_type;
|
||||||
accessor->component_type = component_type;
|
accessor->component_type = component_type;
|
||||||
accessor->byte_offset = 0;
|
accessor->byte_offset = 0;
|
||||||
Error err = _encode_buffer_view(p_state, attribs.ptr(), p_attribs.size(), accessor_type, component_type, accessor->normalized, size, p_for_vertex, buffer_view_i);
|
Error err = _encode_accessor_into_buffer_view(p_state, attribs.ptr(), p_attribs.size(), accessor_type, component_type, accessor->normalized, size, p_for_vertex, buffer_view_i);
|
||||||
if (err != OK) {
|
if (err != OK) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
@ -1886,7 +1995,7 @@ GLTFAccessorIndex GLTFDocument::_encode_accessor_as_quaternions(Ref<GLTFState> p
|
||||||
accessor->accessor_type = accessor_type;
|
accessor->accessor_type = accessor_type;
|
||||||
accessor->component_type = component_type;
|
accessor->component_type = component_type;
|
||||||
accessor->byte_offset = 0;
|
accessor->byte_offset = 0;
|
||||||
Error err = _encode_buffer_view(p_state, attribs.ptr(), p_attribs.size(), accessor_type, component_type, accessor->normalized, size, p_for_vertex, buffer_view_i);
|
Error err = _encode_accessor_into_buffer_view(p_state, attribs.ptr(), p_attribs.size(), accessor_type, component_type, accessor->normalized, size, p_for_vertex, buffer_view_i);
|
||||||
if (err != OK) {
|
if (err != OK) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
@ -1961,7 +2070,7 @@ GLTFAccessorIndex GLTFDocument::_encode_accessor_as_floats(Ref<GLTFState> p_stat
|
||||||
accessor->accessor_type = accessor_type;
|
accessor->accessor_type = accessor_type;
|
||||||
accessor->component_type = component_type;
|
accessor->component_type = component_type;
|
||||||
accessor->byte_offset = 0;
|
accessor->byte_offset = 0;
|
||||||
Error err = _encode_buffer_view(p_state, attribs.ptr(), attribs.size(), accessor_type, component_type, accessor->normalized, size, p_for_vertex, buffer_view_i);
|
Error err = _encode_accessor_into_buffer_view(p_state, attribs.ptr(), attribs.size(), accessor_type, component_type, accessor->normalized, size, p_for_vertex, buffer_view_i);
|
||||||
if (err != OK) {
|
if (err != OK) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
@ -2011,7 +2120,7 @@ GLTFAccessorIndex GLTFDocument::_encode_accessor_as_vec3(Ref<GLTFState> p_state,
|
||||||
accessor->accessor_type = accessor_type;
|
accessor->accessor_type = accessor_type;
|
||||||
accessor->component_type = component_type;
|
accessor->component_type = component_type;
|
||||||
accessor->byte_offset = 0;
|
accessor->byte_offset = 0;
|
||||||
Error err = _encode_buffer_view(p_state, attribs.ptr(), p_attribs.size(), accessor_type, component_type, accessor->normalized, size, p_for_vertex, buffer_view_i);
|
Error err = _encode_accessor_into_buffer_view(p_state, attribs.ptr(), p_attribs.size(), accessor_type, component_type, accessor->normalized, size, p_for_vertex, buffer_view_i);
|
||||||
if (err != OK) {
|
if (err != OK) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
@ -2105,11 +2214,11 @@ GLTFAccessorIndex GLTFDocument::_encode_sparse_accessor_as_vec3(Ref<GLTFState> p
|
||||||
} else {
|
} else {
|
||||||
sparse_accessor->sparse_indices_component_type = GLTFDocument::COMPONENT_TYPE_UNSIGNED_SHORT;
|
sparse_accessor->sparse_indices_component_type = GLTFDocument::COMPONENT_TYPE_UNSIGNED_SHORT;
|
||||||
}
|
}
|
||||||
if (_encode_buffer_view(p_state, changed_indices.ptr(), changed_indices.size(), GLTFAccessor::TYPE_SCALAR, sparse_accessor->sparse_indices_component_type, sparse_accessor->normalized, sparse_accessor->sparse_indices_byte_offset, false, buffer_view_i_indices) != OK) {
|
if (_encode_accessor_into_buffer_view(p_state, changed_indices.ptr(), changed_indices.size(), GLTFAccessor::TYPE_SCALAR, sparse_accessor->sparse_indices_component_type, sparse_accessor->normalized, sparse_accessor->sparse_indices_byte_offset, false, buffer_view_i_indices) != OK) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
// We use changed_indices.size() here, because we must pass the number of vec3 values rather than the number of components.
|
// We use changed_indices.size() here, because we must pass the number of vec3 values rather than the number of components.
|
||||||
if (_encode_buffer_view(p_state, changed_values.ptr(), changed_indices.size(), sparse_accessor->accessor_type, sparse_accessor->component_type, sparse_accessor->normalized, sparse_accessor->sparse_values_byte_offset, false, buffer_view_i_values) != OK) {
|
if (_encode_accessor_into_buffer_view(p_state, changed_values.ptr(), changed_indices.size(), sparse_accessor->accessor_type, sparse_accessor->component_type, sparse_accessor->normalized, sparse_accessor->sparse_values_byte_offset, false, buffer_view_i_values) != OK) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
sparse_accessor->sparse_indices_buffer_view = buffer_view_i_indices;
|
sparse_accessor->sparse_indices_buffer_view = buffer_view_i_indices;
|
||||||
|
|
@ -2118,7 +2227,7 @@ GLTFAccessorIndex GLTFDocument::_encode_sparse_accessor_as_vec3(Ref<GLTFState> p
|
||||||
} else if (changed_indices.size() > 0) {
|
} else if (changed_indices.size() > 0) {
|
||||||
GLTFBufferIndex buffer_view_i;
|
GLTFBufferIndex buffer_view_i;
|
||||||
sparse_accessor->byte_offset = 0;
|
sparse_accessor->byte_offset = 0;
|
||||||
Error err = _encode_buffer_view(p_state, attribs.ptr(), p_attribs.size(), accessor_type, component_type, sparse_accessor->normalized, size, p_for_vertex, buffer_view_i);
|
Error err = _encode_accessor_into_buffer_view(p_state, attribs.ptr(), p_attribs.size(), accessor_type, component_type, sparse_accessor->normalized, size, p_for_vertex, buffer_view_i);
|
||||||
if (err != OK) {
|
if (err != OK) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
@ -2192,7 +2301,7 @@ GLTFAccessorIndex GLTFDocument::_encode_accessor_as_xform(Ref<GLTFState> p_state
|
||||||
accessor->accessor_type = accessor_type;
|
accessor->accessor_type = accessor_type;
|
||||||
accessor->component_type = component_type;
|
accessor->component_type = component_type;
|
||||||
accessor->byte_offset = 0;
|
accessor->byte_offset = 0;
|
||||||
Error err = _encode_buffer_view(p_state, attribs.ptr(), p_attribs.size(), accessor_type, component_type, accessor->normalized, size, p_for_vertex, buffer_view_i);
|
Error err = _encode_accessor_into_buffer_view(p_state, attribs.ptr(), p_attribs.size(), accessor_type, component_type, accessor->normalized, size, p_for_vertex, buffer_view_i);
|
||||||
if (err != OK) {
|
if (err != OK) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -265,11 +265,11 @@ private:
|
||||||
GLTFAccessorIndex _encode_accessor_as_xform(Ref<GLTFState> p_state,
|
GLTFAccessorIndex _encode_accessor_as_xform(Ref<GLTFState> p_state,
|
||||||
const Vector<Transform3D> p_attribs,
|
const Vector<Transform3D> p_attribs,
|
||||||
const bool p_for_vertex);
|
const bool p_for_vertex);
|
||||||
Error _encode_buffer_view(Ref<GLTFState> p_state, const double *p_src,
|
Error _encode_accessor_into_buffer_view(Ref<GLTFState> p_state, const double *p_src,
|
||||||
const int p_count, const GLTFAccessor::GLTFAccessorType p_accessor_type,
|
const int64_t p_count, const GLTFAccessor::GLTFAccessorType p_accessor_type,
|
||||||
const int p_component_type, const bool p_normalized,
|
const int p_component_type, const bool p_normalized,
|
||||||
const int p_byte_offset, const bool p_for_vertex,
|
const int64_t p_byte_offset, const bool p_for_vertex,
|
||||||
GLTFBufferViewIndex &r_accessor, const bool p_for_indices = false);
|
GLTFBufferViewIndex &r_buffer_view, const bool p_for_indices = false);
|
||||||
|
|
||||||
Error _encode_accessors(Ref<GLTFState> p_state);
|
Error _encode_accessors(Ref<GLTFState> p_state);
|
||||||
Error _encode_buffer_views(Ref<GLTFState> p_state);
|
Error _encode_buffer_views(Ref<GLTFState> p_state);
|
||||||
|
|
|
||||||
|
|
@ -50,6 +50,21 @@ public:
|
||||||
TYPE_MAT4,
|
TYPE_MAT4,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum GLTFComponentType {
|
||||||
|
COMPONENT_TYPE_NONE = 0,
|
||||||
|
COMPONENT_TYPE_SIGNED_BYTE = 5120,
|
||||||
|
COMPONENT_TYPE_UNSIGNED_BYTE = 5121,
|
||||||
|
COMPONENT_TYPE_SIGNED_SHORT = 5122,
|
||||||
|
COMPONENT_TYPE_UNSIGNED_SHORT = 5123,
|
||||||
|
COMPONENT_TYPE_SIGNED_INT = 5124,
|
||||||
|
COMPONENT_TYPE_UNSIGNED_INT = 5125,
|
||||||
|
COMPONENT_TYPE_SINGLE_FLOAT = 5126,
|
||||||
|
COMPONENT_TYPE_DOUBLE_FLOAT = 5130,
|
||||||
|
COMPONENT_TYPE_HALF_FLOAT = 5131,
|
||||||
|
COMPONENT_TYPE_SIGNED_LONG = 5134,
|
||||||
|
COMPONENT_TYPE_UNSIGNED_LONG = 5135,
|
||||||
|
};
|
||||||
|
|
||||||
private:
|
private:
|
||||||
GLTFBufferViewIndex buffer_view = -1;
|
GLTFBufferViewIndex buffer_view = -1;
|
||||||
int byte_offset = 0;
|
int byte_offset = 0;
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue