diff --git a/modules/gltf/gltf_document.cpp b/modules/gltf/gltf_document.cpp index 27ffd1025d3..0c1be972c30 100644 --- a/modules/gltf/gltf_document.cpp +++ b/modules/gltf/gltf_document.cpp @@ -81,10 +81,6 @@ #include #include -constexpr int COMPONENT_COUNT_FOR_ACCESSOR_TYPE[7] = { - 1, 2, 3, 4, 4, 9, 16 -}; - static void _attach_extras_to_meta(const Dictionary &p_extras, Ref p_node) { if (!p_extras.is_empty()) { p_node->set_meta("extras", p_extras); @@ -908,32 +904,6 @@ Error GLTFDocument::_encode_accessors(Ref p_state) { return OK; } -String GLTFDocument::_get_accessor_type_name(const GLTFAccessor::GLTFAccessorType p_accessor_type) { - if (p_accessor_type == GLTFAccessor::TYPE_SCALAR) { - return "SCALAR"; - } - if (p_accessor_type == GLTFAccessor::TYPE_VEC2) { - return "VEC2"; - } - if (p_accessor_type == GLTFAccessor::TYPE_VEC3) { - return "VEC3"; - } - if (p_accessor_type == GLTFAccessor::TYPE_VEC4) { - return "VEC4"; - } - - if (p_accessor_type == GLTFAccessor::TYPE_MAT2) { - return "MAT2"; - } - if (p_accessor_type == GLTFAccessor::TYPE_MAT3) { - return "MAT3"; - } - if (p_accessor_type == GLTFAccessor::TYPE_MAT4) { - return "MAT4"; - } - ERR_FAIL_V("SCALAR"); -} - Error GLTFDocument::_parse_accessors(Ref p_state) { if (!p_state->json.has("accessors")) { return OK; @@ -954,647 +924,94 @@ Error GLTFDocument::_parse_accessors(Ref p_state) { return OK; } -String GLTFDocument::_get_component_type_name(const GLTFAccessor::GLTFComponentType p_component) { - switch (p_component) { - case GLTFAccessor::COMPONENT_TYPE_NONE: - return "None"; - case GLTFAccessor::COMPONENT_TYPE_SIGNED_BYTE: - return "Byte"; - case GLTFAccessor::COMPONENT_TYPE_UNSIGNED_BYTE: - return "UByte"; - case GLTFAccessor::COMPONENT_TYPE_SIGNED_SHORT: - return "Short"; - case GLTFAccessor::COMPONENT_TYPE_UNSIGNED_SHORT: - return "UShort"; - case GLTFAccessor::COMPONENT_TYPE_SIGNED_INT: - return "Int"; - case GLTFAccessor::COMPONENT_TYPE_UNSIGNED_INT: - return "UInt"; - case GLTFAccessor::COMPONENT_TYPE_SINGLE_FLOAT: - return "Float"; - case GLTFAccessor::COMPONENT_TYPE_DOUBLE_FLOAT: - return "Double"; - case GLTFAccessor::COMPONENT_TYPE_HALF_FLOAT: - return "Half"; - case GLTFAccessor::COMPONENT_TYPE_SIGNED_LONG: - return "Long"; - case GLTFAccessor::COMPONENT_TYPE_UNSIGNED_LONG: - return "ULong"; - } - - return ""; -} - -Error GLTFDocument::_decode_buffer_view(Ref p_state, double *p_dst, const GLTFBufferViewIndex p_buffer_view, const int64_t p_skip_every, const int64_t p_skip_bytes, const int64_t p_element_size, const int64_t p_count, const GLTFAccessor::GLTFAccessorType p_accessor_type, const int64_t p_component_count, const GLTFAccessor::GLTFComponentType p_component_type, const int64_t p_component_size, const bool p_normalized, const int64_t p_byte_offset, const bool p_for_vertex) { - const Ref bv = p_state->buffer_views[p_buffer_view]; - - int64_t stride = p_element_size; - if (bv->byte_stride > 0) { - stride = bv->byte_stride; - } - if (p_for_vertex && stride % 4) { - stride += 4 - (stride % 4); //according to spec must be multiple of 4 - } - - 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; - Vector buffer = p_state->buffers[bv->buffer]; //copy on write, so no performance hit - const uint8_t *bufptr = buffer.ptr(); - - //use to debug - print_verbose("glTF: accessor type " + _get_accessor_type_name(p_accessor_type) + " component type: " + _get_component_type_name(p_component_type) + " stride: " + itos(stride) + " amount " + itos(p_count)); - print_verbose("glTF: accessor offset " + itos(p_byte_offset) + " view offset: " + itos(bv->byte_offset) + " total buffer len: " + itos(buffer.size()) + " view len " + itos(bv->byte_length)); - - const int64_t buffer_end = (stride * (p_count - 1)) + p_element_size; - ERR_FAIL_COND_V(buffer_end > bv->byte_length, ERR_PARSE_ERROR); - - ERR_FAIL_COND_V((int)(offset + buffer_end) > buffer.size(), ERR_PARSE_ERROR); - - //fill everything as doubles - - for (int64_t i = 0; i < p_count; i++) { - const uint8_t *src = &bufptr[offset + i * stride]; - - for (int64_t j = 0; j < p_component_count; j++) { - if (p_skip_every && j > 0 && (j % p_skip_every) == 0) { - src += p_skip_bytes; - } - - double d = 0; - // 3.11. Implementations MUST use following equations to decode real floating-point value f from a normalized integer c and vise-versa. - // https://registry.khronos.org/glTF/specs/2.0/glTF-2.0.html#animations - switch (p_component_type) { - case GLTFAccessor::COMPONENT_TYPE_NONE: { - ERR_FAIL_V_MSG(ERR_INVALID_DATA, "glTF: Failed to decode buffer view, component type not set."); - } break; - case GLTFAccessor::COMPONENT_TYPE_SIGNED_BYTE: { - int8_t b = int8_t(*src); - if (p_normalized) { - d = MAX(double(b) / 127.0, -1.0); - } else { - d = double(b); - } - } break; - case GLTFAccessor::COMPONENT_TYPE_UNSIGNED_BYTE: { - uint8_t b = *src; - if (p_normalized) { - d = (double(b) / 255.0); - } else { - d = double(b); - } - } break; - case GLTFAccessor::COMPONENT_TYPE_SIGNED_SHORT: { - int16_t s = *(int16_t *)src; - if (p_normalized) { - d = MAX(double(s) / 32767.0, -1.0); - } else { - d = double(s); - } - } break; - case GLTFAccessor::COMPONENT_TYPE_UNSIGNED_SHORT: { - uint16_t s = *(uint16_t *)src; - if (p_normalized) { - d = (double(s) / 65535.0); - } else { - d = double(s); - } - } break; - case GLTFAccessor::COMPONENT_TYPE_SIGNED_INT: { - d = *(int32_t *)src; - } break; - case GLTFAccessor::COMPONENT_TYPE_UNSIGNED_INT: { - d = *(uint32_t *)src; - } break; - case GLTFAccessor::COMPONENT_TYPE_SINGLE_FLOAT: { - d = *(float *)src; - } break; - case GLTFAccessor::COMPONENT_TYPE_DOUBLE_FLOAT: { - d = *(double *)src; - } 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: { - d = *(int64_t *)src; - } break; - case GLTFAccessor::COMPONENT_TYPE_UNSIGNED_LONG: { - d = *(uint64_t *)src; - } break; - } - - *p_dst++ = d; - src += p_component_size; - } - } - - return OK; -} - -int GLTFDocument::_get_component_type_size(const GLTFAccessor::GLTFComponentType p_component_type) { - switch (p_component_type) { - case GLTFAccessor::COMPONENT_TYPE_NONE: - ERR_FAIL_V(0); - case GLTFAccessor::COMPONENT_TYPE_SIGNED_BYTE: - case GLTFAccessor::COMPONENT_TYPE_UNSIGNED_BYTE: - return 1; - case GLTFAccessor::COMPONENT_TYPE_SIGNED_SHORT: - case GLTFAccessor::COMPONENT_TYPE_UNSIGNED_SHORT: - case GLTFAccessor::COMPONENT_TYPE_HALF_FLOAT: - return 2; - case GLTFAccessor::COMPONENT_TYPE_SIGNED_INT: - case GLTFAccessor::COMPONENT_TYPE_UNSIGNED_INT: - case GLTFAccessor::COMPONENT_TYPE_SINGLE_FLOAT: - return 4; - case GLTFAccessor::COMPONENT_TYPE_DOUBLE_FLOAT: - case GLTFAccessor::COMPONENT_TYPE_SIGNED_LONG: - case GLTFAccessor::COMPONENT_TYPE_UNSIGNED_LONG: - return 8; - } - ERR_FAIL_V(0); -} - -Vector GLTFDocument::_decode_accessor(Ref p_state, const GLTFAccessorIndex p_accessor, const bool p_for_vertex) { - //spec, for reference: - //https://github.com/KhronosGroup/glTF/tree/master/specification/2.0#data-alignment - - ERR_FAIL_INDEX_V(p_accessor, p_state->accessors.size(), Vector()); - - const Ref a = p_state->accessors[p_accessor]; - - const int component_count = COMPONENT_COUNT_FOR_ACCESSOR_TYPE[a->accessor_type]; - const int component_size = _get_component_type_size(a->component_type); - ERR_FAIL_COND_V(component_size == 0, Vector()); - int element_size = component_count * component_size; - - int64_t skip_every = 0; - int64_t skip_bytes = 0; - //special case of alignments, as described in spec - switch (a->component_type) { - case GLTFAccessor::COMPONENT_TYPE_SIGNED_BYTE: - case GLTFAccessor::COMPONENT_TYPE_UNSIGNED_BYTE: { - if (a->accessor_type == GLTFAccessor::TYPE_MAT2) { - skip_every = 2; - skip_bytes = 2; - element_size = 8; //override for this case - } - if (a->accessor_type == GLTFAccessor::TYPE_MAT3) { - skip_every = 3; - skip_bytes = 1; - element_size = 12; //override for this case - } - } break; - case GLTFAccessor::COMPONENT_TYPE_SIGNED_SHORT: - case GLTFAccessor::COMPONENT_TYPE_UNSIGNED_SHORT: { - if (a->accessor_type == GLTFAccessor::TYPE_MAT3) { - skip_every = 6; - skip_bytes = 2; - element_size = 16; //override for this case - } - } break; - default: { - } - } - - Vector dst_buffer; - dst_buffer.resize(component_count * a->count); - double *dst = dst_buffer.ptrw(); - - if (a->buffer_view >= 0) { - ERR_FAIL_INDEX_V(a->buffer_view, p_state->buffer_views.size(), Vector()); - - const Error err = _decode_buffer_view(p_state, dst, a->buffer_view, skip_every, skip_bytes, element_size, a->count, a->accessor_type, component_count, a->component_type, component_size, a->normalized, a->byte_offset, p_for_vertex); - if (err != OK) { - return Vector(); - } - } else { - //fill with zeros, as bufferview is not defined. - for (int64_t i = 0; i < (a->count * component_count); i++) { - dst_buffer.write[i] = 0; - } - } - - if (a->sparse_count > 0) { - // I could not find any file using this, so this code is so far untested - Vector indices; - indices.resize(a->sparse_count); - const int indices_component_size = _get_component_type_size(a->sparse_indices_component_type); - - Error err = _decode_buffer_view(p_state, indices.ptrw(), a->sparse_indices_buffer_view, 0, 0, indices_component_size, a->sparse_count, GLTFAccessor::TYPE_SCALAR, 1, a->sparse_indices_component_type, indices_component_size, false, a->sparse_indices_byte_offset, false); - if (err != OK) { - return Vector(); - } - - Vector data; - data.resize(component_count * a->sparse_count); - err = _decode_buffer_view(p_state, data.ptrw(), a->sparse_values_buffer_view, skip_every, skip_bytes, element_size, a->sparse_count, a->accessor_type, component_count, a->component_type, component_size, a->normalized, a->sparse_values_byte_offset, p_for_vertex); - if (err != OK) { - return Vector(); - } - - for (int i = 0; i < indices.size(); i++) { - const int64_t write_offset = int(indices[i]) * component_count; - - for (int j = 0; j < component_count; j++) { - dst[write_offset + j] = data[i * component_count + j]; - } - } - } - - return dst_buffer; -} - -Vector GLTFDocument::_decode_accessor_as_ints(Ref p_state, const GLTFAccessorIndex p_accessor, const bool p_for_vertex, const Vector &p_packed_vertex_ids) { - const Vector attribs = _decode_accessor(p_state, p_accessor, p_for_vertex); - Vector ret; - - if (attribs.is_empty()) { - return ret; - } - - const double *attribs_ptr = attribs.ptr(); - int64_t ret_size = attribs.size(); - if (!p_packed_vertex_ids.is_empty()) { - ERR_FAIL_COND_V(p_packed_vertex_ids[p_packed_vertex_ids.size() - 1] >= ret_size, ret); - ret_size = p_packed_vertex_ids.size(); - } - ret.resize(ret_size); - for (int64_t i = 0; i < ret_size; i++) { - int64_t src_i = i; - if (!p_packed_vertex_ids.is_empty()) { - src_i = p_packed_vertex_ids[i]; - } - ret.write[i] = int(attribs_ptr[src_i]); +template +T GLTFDocument::_decode_unpack_indexed_data(const T &p_source, const PackedInt32Array &p_indices) { + // Handle unpacking indexed data as if it was a regular array. + // This isn't a feature of accessors, rather a feature of places using accessors like + // indexed meshes, but GLTFDocument needs it in several places when reading accessors. + T ret; + const int64_t last_index = p_indices[p_indices.size() - 1]; + ERR_FAIL_COND_V(last_index >= p_source.size(), ret); + ret.resize(p_indices.size()); + for (int64_t i = 0; i < p_indices.size(); i++) { + const int64_t source_index = p_indices[i]; + ret.set(i, p_source[source_index]); } return ret; } -Vector GLTFDocument::_decode_accessor_as_floats(Ref p_state, const GLTFAccessorIndex p_accessor, const bool p_for_vertex, const Vector &p_packed_vertex_ids) { - const Vector attribs = _decode_accessor(p_state, p_accessor, p_for_vertex); - Vector ret; - - if (attribs.is_empty()) { - return ret; +PackedFloat32Array GLTFDocument::_decode_accessor_as_float32s(const Ref p_gltf_state, GLTFAccessorIndex p_accessor_index, const PackedInt32Array &p_packed_vertex_ids) { + ERR_FAIL_INDEX_V(p_accessor_index, p_gltf_state->accessors.size(), PackedFloat32Array()); + Ref accessor = p_gltf_state->accessors[p_accessor_index]; + PackedFloat32Array numbers = accessor->decode_as_float32s(p_gltf_state); + if (p_packed_vertex_ids.is_empty()) { + return numbers; } - - const double *attribs_ptr = attribs.ptr(); - int64_t ret_size = attribs.size(); - if (!p_packed_vertex_ids.is_empty()) { - ERR_FAIL_COND_V(p_packed_vertex_ids[p_packed_vertex_ids.size() - 1] >= ret_size, ret); - ret_size = p_packed_vertex_ids.size(); - } - ret.resize(ret_size); - for (int64_t i = 0; i < ret_size; i++) { - int64_t src_i = i; - if (!p_packed_vertex_ids.is_empty()) { - src_i = p_packed_vertex_ids[i]; - } - ret.write[i] = float(attribs_ptr[src_i]); - } - return ret; + return _decode_unpack_indexed_data(numbers, p_packed_vertex_ids); } -Vector GLTFDocument::_decode_accessor_as_vec2(Ref p_state, const GLTFAccessorIndex p_accessor, const bool p_for_vertex, const Vector &p_packed_vertex_ids) { - const Vector attribs = _decode_accessor(p_state, p_accessor, p_for_vertex); - Vector ret; - - if (attribs.is_empty()) { - return ret; +PackedFloat64Array GLTFDocument::_decode_accessor_as_float64s(const Ref p_gltf_state, GLTFAccessorIndex p_accessor_index, const PackedInt32Array &p_packed_vertex_ids) { + ERR_FAIL_INDEX_V(p_accessor_index, p_gltf_state->accessors.size(), PackedFloat64Array()); + Ref accessor = p_gltf_state->accessors[p_accessor_index]; + PackedFloat64Array numbers = accessor->decode_as_float64s(p_gltf_state); + if (p_packed_vertex_ids.is_empty()) { + return numbers; } - - ERR_FAIL_COND_V(attribs.size() % 2 != 0, ret); - const double *attribs_ptr = attribs.ptr(); - int64_t ret_size = attribs.size() / 2; - if (!p_packed_vertex_ids.is_empty()) { - ERR_FAIL_COND_V(p_packed_vertex_ids[p_packed_vertex_ids.size() - 1] >= ret_size, ret); - ret_size = p_packed_vertex_ids.size(); - } - ret.resize(ret_size); - for (int64_t i = 0; i < ret_size; i++) { - int64_t src_i = i; - if (!p_packed_vertex_ids.is_empty()) { - src_i = p_packed_vertex_ids[i]; - } - ret.write[i] = Vector2(attribs_ptr[src_i * 2 + 0], attribs_ptr[src_i * 2 + 1]); - } - return ret; + return _decode_unpack_indexed_data(numbers, p_packed_vertex_ids); } -Vector GLTFDocument::_decode_accessor_as_vec3(Ref p_state, const GLTFAccessorIndex p_accessor, const bool p_for_vertex, const Vector &p_packed_vertex_ids) { - const Vector attribs = _decode_accessor(p_state, p_accessor, p_for_vertex); - Vector ret; - - if (attribs.is_empty()) { - return ret; +PackedInt32Array GLTFDocument::_decode_accessor_as_int32s(const Ref p_gltf_state, GLTFAccessorIndex p_accessor_index, const PackedInt32Array &p_packed_vertex_ids) { + ERR_FAIL_INDEX_V(p_accessor_index, p_gltf_state->accessors.size(), PackedInt32Array()); + Ref accessor = p_gltf_state->accessors[p_accessor_index]; + PackedInt32Array numbers = accessor->decode_as_int32s(p_gltf_state); + if (p_packed_vertex_ids.is_empty()) { + return numbers; } - - ERR_FAIL_COND_V(attribs.size() % 3 != 0, ret); - const double *attribs_ptr = attribs.ptr(); - int64_t ret_size = attribs.size() / 3; - if (!p_packed_vertex_ids.is_empty()) { - ERR_FAIL_COND_V(p_packed_vertex_ids[p_packed_vertex_ids.size() - 1] >= ret_size, ret); - ret_size = p_packed_vertex_ids.size(); - } - ret.resize(ret_size); - for (int64_t i = 0; i < ret_size; i++) { - int64_t src_i = i; - if (!p_packed_vertex_ids.is_empty()) { - src_i = p_packed_vertex_ids[i]; - } - ret.write[i] = Vector3(attribs_ptr[src_i * 3 + 0], attribs_ptr[src_i * 3 + 1], attribs_ptr[src_i * 3 + 2]); - } - return ret; + return _decode_unpack_indexed_data(numbers, p_packed_vertex_ids); } -Vector GLTFDocument::_decode_accessor_as_color(Ref p_state, const GLTFAccessorIndex p_accessor, const bool p_for_vertex, const Vector &p_packed_vertex_ids) { - const Vector attribs = _decode_accessor(p_state, p_accessor, p_for_vertex); - Vector ret; - - if (attribs.is_empty()) { - return ret; +PackedVector2Array GLTFDocument::_decode_accessor_as_vec2(const Ref p_gltf_state, GLTFAccessorIndex p_accessor_index, const PackedInt32Array &p_packed_vertex_ids) { + ERR_FAIL_INDEX_V(p_accessor_index, p_gltf_state->accessors.size(), PackedVector2Array()); + Ref accessor = p_gltf_state->accessors[p_accessor_index]; + PackedVector2Array vectors = accessor->decode_as_vector2s(p_gltf_state); + if (p_packed_vertex_ids.is_empty()) { + return vectors; } - - const GLTFAccessor::GLTFAccessorType accessor_type = p_state->accessors[p_accessor]->accessor_type; - ERR_FAIL_COND_V(!(accessor_type == GLTFAccessor::TYPE_VEC3 || accessor_type == GLTFAccessor::TYPE_VEC4), ret); - int vec_len = 3; - if (accessor_type == GLTFAccessor::TYPE_VEC4) { - vec_len = 4; - } - - ERR_FAIL_COND_V(attribs.size() % vec_len != 0, ret); - const double *attribs_ptr = attribs.ptr(); - int64_t ret_size = attribs.size() / vec_len; - if (!p_packed_vertex_ids.is_empty()) { - ERR_FAIL_COND_V(p_packed_vertex_ids[p_packed_vertex_ids.size() - 1] >= ret_size, ret); - ret_size = p_packed_vertex_ids.size(); - } - ret.resize(ret_size); - for (int64_t i = 0; i < ret_size; i++) { - int64_t src_i = i; - if (!p_packed_vertex_ids.is_empty()) { - src_i = p_packed_vertex_ids[i]; - } - ret.write[i] = Color(attribs_ptr[src_i * vec_len + 0], attribs_ptr[src_i * vec_len + 1], attribs_ptr[src_i * vec_len + 2], vec_len == 4 ? attribs_ptr[src_i * 4 + 3] : 1.0); - } - return ret; -} -Vector GLTFDocument::_decode_accessor_as_quaternion(Ref p_state, const GLTFAccessorIndex p_accessor, const bool p_for_vertex) { - const Vector attribs = _decode_accessor(p_state, p_accessor, p_for_vertex); - Vector ret; - - if (attribs.is_empty()) { - return ret; - } - - ERR_FAIL_COND_V(attribs.size() % 4 != 0, ret); - const double *attribs_ptr = attribs.ptr(); - const int64_t ret_size = attribs.size() / 4; - ret.resize(ret_size); - { - for (int64_t i = 0; i < ret_size; i++) { - ret.write[i] = Quaternion(attribs_ptr[i * 4 + 0], attribs_ptr[i * 4 + 1], attribs_ptr[i * 4 + 2], attribs_ptr[i * 4 + 3]).normalized(); - } - } - return ret; -} -Vector GLTFDocument::_decode_accessor_as_xform2d(Ref p_state, const GLTFAccessorIndex p_accessor, const bool p_for_vertex) { - const Vector attribs = _decode_accessor(p_state, p_accessor, p_for_vertex); - Vector ret; - - if (attribs.is_empty()) { - return ret; - } - - ERR_FAIL_COND_V(attribs.size() % 4 != 0, ret); - ret.resize(attribs.size() / 4); - for (int64_t i = 0; i < ret.size(); i++) { - ret.write[i][0] = Vector2(attribs[i * 4 + 0], attribs[i * 4 + 1]); - ret.write[i][1] = Vector2(attribs[i * 4 + 2], attribs[i * 4 + 3]); - } - return ret; + return _decode_unpack_indexed_data(vectors, p_packed_vertex_ids); } -Vector GLTFDocument::_decode_accessor_as_basis(Ref p_state, const GLTFAccessorIndex p_accessor, const bool p_for_vertex) { - const Vector attribs = _decode_accessor(p_state, p_accessor, p_for_vertex); - Vector ret; - - if (attribs.is_empty()) { - return ret; +PackedVector3Array GLTFDocument::_decode_accessor_as_vec3(const Ref p_gltf_state, GLTFAccessorIndex p_accessor_index, const PackedInt32Array &p_packed_vertex_ids) { + ERR_FAIL_INDEX_V(p_accessor_index, p_gltf_state->accessors.size(), PackedVector3Array()); + Ref accessor = p_gltf_state->accessors[p_accessor_index]; + PackedVector3Array vectors = accessor->decode_as_vector3s(p_gltf_state); + if (p_packed_vertex_ids.is_empty()) { + return vectors; } - - ERR_FAIL_COND_V(attribs.size() % 9 != 0, ret); - ret.resize(attribs.size() / 9); - for (int64_t i = 0; i < ret.size(); i++) { - ret.write[i].set_column(0, Vector3(attribs[i * 9 + 0], attribs[i * 9 + 1], attribs[i * 9 + 2])); - ret.write[i].set_column(1, Vector3(attribs[i * 9 + 3], attribs[i * 9 + 4], attribs[i * 9 + 5])); - ret.write[i].set_column(2, Vector3(attribs[i * 9 + 6], attribs[i * 9 + 7], attribs[i * 9 + 8])); - } - return ret; + return _decode_unpack_indexed_data(vectors, p_packed_vertex_ids); } -Vector GLTFDocument::_decode_accessor_as_xform(Ref p_state, const GLTFAccessorIndex p_accessor, const bool p_for_vertex) { - const Vector attribs = _decode_accessor(p_state, p_accessor, p_for_vertex); - Vector ret; - - if (attribs.is_empty()) { - return ret; +PackedColorArray GLTFDocument::_decode_accessor_as_color(const Ref p_gltf_state, GLTFAccessorIndex p_accessor_index, const PackedInt32Array &p_packed_vertex_ids) { + ERR_FAIL_INDEX_V(p_accessor_index, p_gltf_state->accessors.size(), PackedColorArray()); + Ref accessor = p_gltf_state->accessors[p_accessor_index]; + PackedColorArray colors = accessor->decode_as_colors(p_gltf_state); + if (p_packed_vertex_ids.is_empty()) { + return colors; } - - ERR_FAIL_COND_V(attribs.size() % 16 != 0, ret); - ret.resize(attribs.size() / 16); - for (int64_t i = 0; i < ret.size(); i++) { - ret.write[i].basis.set_column(0, Vector3(attribs[i * 16 + 0], attribs[i * 16 + 1], attribs[i * 16 + 2])); - ret.write[i].basis.set_column(1, Vector3(attribs[i * 16 + 4], attribs[i * 16 + 5], attribs[i * 16 + 6])); - ret.write[i].basis.set_column(2, Vector3(attribs[i * 16 + 8], attribs[i * 16 + 9], attribs[i * 16 + 10])); - ret.write[i].set_origin(Vector3(attribs[i * 16 + 12], attribs[i * 16 + 13], attribs[i * 16 + 14])); - } - return ret; + return _decode_unpack_indexed_data(colors, p_packed_vertex_ids); } -Vector GLTFDocument::_decode_accessor_as_variant(Ref p_state, const GLTFAccessorIndex p_accessor, Variant::Type p_variant_type, GLTFAccessor::GLTFAccessorType p_accessor_type) { - const Vector attribs = _decode_accessor(p_state, p_accessor, false); - Vector ret; - ERR_FAIL_COND_V_MSG(attribs.is_empty(), ret, "glTF: The accessor was empty."); - const int component_count = COMPONENT_COUNT_FOR_ACCESSOR_TYPE[p_accessor_type]; - ERR_FAIL_COND_V_MSG(attribs.size() % component_count != 0, ret, "glTF: The accessor size was not a multiple of the component count."); - const int64_t ret_size = attribs.size() / component_count; - ret.resize(ret_size); - for (int64_t i = 0; i < ret_size; i++) { - switch (p_variant_type) { - case Variant::BOOL: { - ret.write[i] = attribs[i * component_count] != 0.0; - } break; - case Variant::INT: { - ret.write[i] = (int64_t)attribs[i * component_count]; - } break; - case Variant::FLOAT: { - ret.write[i] = attribs[i * component_count]; - } break; - case Variant::VECTOR2: - case Variant::RECT2: - case Variant::VECTOR3: - case Variant::VECTOR4: - case Variant::PLANE: - case Variant::QUATERNION: { - // General-purpose code for importing glTF accessor data with any component count into structs up to 4 `real_t`s in size. - Variant v; - switch (component_count) { - case 1: { - v = Vector4(attribs[i * component_count], 0.0f, 0.0f, 0.0f); - } break; - case 2: { - v = Vector4(attribs[i * component_count], attribs[i * component_count + 1], 0.0f, 0.0f); - } break; - case 3: { - v = Vector4(attribs[i * component_count], attribs[i * component_count + 1], attribs[i * component_count + 2], 0.0f); - } break; - default: { - v = Vector4(attribs[i * component_count], attribs[i * component_count + 1], attribs[i * component_count + 2], attribs[i * component_count + 3]); - } break; - } - // Evil hack that relies on the structure of Variant, but it's the - // only way to accomplish this without a ton of code duplication. - *(Variant::Type *)&v = p_variant_type; - ret.write[i] = v; - } break; - case Variant::VECTOR2I: - case Variant::RECT2I: - case Variant::VECTOR3I: - case Variant::VECTOR4I: { - // General-purpose code for importing glTF accessor data with any component count into structs up to 4 `int32_t`s in size. - Variant v; - switch (component_count) { - case 1: { - v = Vector4i((int32_t)attribs[i * component_count], 0, 0, 0); - } break; - case 2: { - v = Vector4i((int32_t)attribs[i * component_count], (int32_t)attribs[i * component_count + 1], 0, 0); - } break; - case 3: { - v = Vector4i((int32_t)attribs[i * component_count], (int32_t)attribs[i * component_count + 1], (int32_t)attribs[i * component_count + 2], 0); - } break; - default: { - v = Vector4i((int32_t)attribs[i * component_count], (int32_t)attribs[i * component_count + 1], (int32_t)attribs[i * component_count + 2], (int32_t)attribs[i * component_count + 3]); - } break; - } - // Evil hack that relies on the structure of Variant, but it's the - // only way to accomplish this without a ton of code duplication. - *(Variant::Type *)&v = p_variant_type; - ret.write[i] = v; - } break; - // No more generalized hacks, each of the below types needs a lot of repetitive code. - case Variant::COLOR: { - Variant v; - switch (component_count) { - case 1: { - v = Color(attribs[i * component_count], 0.0f, 0.0f, 1.0f); - } break; - case 2: { - v = Color(attribs[i * component_count], attribs[i * component_count + 1], 0.0f, 1.0f); - } break; - case 3: { - v = Color(attribs[i * component_count], attribs[i * component_count + 1], attribs[i * component_count + 2], 1.0f); - } break; - default: { - v = Color(attribs[i * component_count], attribs[i * component_count + 1], attribs[i * component_count + 2], attribs[i * component_count + 3]); - } break; - } - ret.write[i] = v; - } break; - case Variant::TRANSFORM2D: { - Transform2D t; - switch (component_count) { - case 4: { - t.columns[0] = Vector2(attribs[i * component_count + 0], attribs[i * component_count + 1]); - t.columns[1] = Vector2(attribs[i * component_count + 2], attribs[i * component_count + 3]); - } break; - case 9: { - t.columns[0] = Vector2(attribs[i * component_count + 0], attribs[i * component_count + 1]); - t.columns[1] = Vector2(attribs[i * component_count + 3], attribs[i * component_count + 4]); - t.columns[2] = Vector2(attribs[i * component_count + 6], attribs[i * component_count + 7]); - } break; - case 16: { - t.columns[0] = Vector2(attribs[i * component_count + 0], attribs[i * component_count + 1]); - t.columns[1] = Vector2(attribs[i * component_count + 4], attribs[i * component_count + 5]); - t.columns[2] = Vector2(attribs[i * component_count + 12], attribs[i * component_count + 13]); - } break; - } - ret.write[i] = t; - } break; - case Variant::BASIS: { - Basis b; - switch (component_count) { - case 4: { - b.rows[0] = Vector3(attribs[i * component_count + 0], attribs[i * component_count + 2], 0.0f); - b.rows[1] = Vector3(attribs[i * component_count + 1], attribs[i * component_count + 3], 0.0f); - } break; - case 9: { - b.rows[0] = Vector3(attribs[i * component_count + 0], attribs[i * component_count + 3], attribs[i * component_count + 6]); - b.rows[1] = Vector3(attribs[i * component_count + 1], attribs[i * component_count + 4], attribs[i * component_count + 7]); - b.rows[2] = Vector3(attribs[i * component_count + 2], attribs[i * component_count + 5], attribs[i * component_count + 8]); - } break; - case 16: { - b.rows[0] = Vector3(attribs[i * component_count + 0], attribs[i * component_count + 4], attribs[i * component_count + 8]); - b.rows[1] = Vector3(attribs[i * component_count + 1], attribs[i * component_count + 5], attribs[i * component_count + 9]); - b.rows[2] = Vector3(attribs[i * component_count + 2], attribs[i * component_count + 6], attribs[i * component_count + 10]); - } break; - } - ret.write[i] = b; - } break; - case Variant::TRANSFORM3D: { - Transform3D t; - switch (component_count) { - case 4: { - t.basis.rows[0] = Vector3(attribs[i * component_count + 0], attribs[i * component_count + 2], 0.0f); - t.basis.rows[1] = Vector3(attribs[i * component_count + 1], attribs[i * component_count + 3], 0.0f); - } break; - case 9: { - t.basis.rows[0] = Vector3(attribs[i * component_count + 0], attribs[i * component_count + 3], attribs[i * component_count + 6]); - t.basis.rows[1] = Vector3(attribs[i * component_count + 1], attribs[i * component_count + 4], attribs[i * component_count + 7]); - t.basis.rows[2] = Vector3(attribs[i * component_count + 2], attribs[i * component_count + 5], attribs[i * component_count + 8]); - } break; - case 16: { - t.basis.rows[0] = Vector3(attribs[i * component_count + 0], attribs[i * component_count + 4], attribs[i * component_count + 8]); - t.basis.rows[1] = Vector3(attribs[i * component_count + 1], attribs[i * component_count + 5], attribs[i * component_count + 9]); - t.basis.rows[2] = Vector3(attribs[i * component_count + 2], attribs[i * component_count + 6], attribs[i * component_count + 10]); - t.origin = Vector3(attribs[i * component_count + 12], attribs[i * component_count + 13], attribs[i * component_count + 14]); - } break; - } - ret.write[i] = t; - } break; - case Variant::PROJECTION: { - Projection p; - switch (component_count) { - case 4: { - p.columns[0] = Vector4(attribs[i * component_count + 0], attribs[i * component_count + 1], 0.0f, 0.0f); - p.columns[1] = Vector4(attribs[i * component_count + 4], attribs[i * component_count + 5], 0.0f, 0.0f); - } break; - case 9: { - p.columns[0] = Vector4(attribs[i * component_count + 0], attribs[i * component_count + 1], attribs[i * component_count + 2], 0.0f); - p.columns[1] = Vector4(attribs[i * component_count + 4], attribs[i * component_count + 5], attribs[i * component_count + 6], 0.0f); - p.columns[2] = Vector4(attribs[i * component_count + 8], attribs[i * component_count + 9], attribs[i * component_count + 10], 0.0f); - } break; - case 16: { - p.columns[0] = Vector4(attribs[i * component_count + 0], attribs[i * component_count + 1], attribs[i * component_count + 2], attribs[i * component_count + 3]); - p.columns[1] = Vector4(attribs[i * component_count + 4], attribs[i * component_count + 5], attribs[i * component_count + 6], attribs[i * component_count + 7]); - p.columns[2] = Vector4(attribs[i * component_count + 8], attribs[i * component_count + 9], attribs[i * component_count + 10], attribs[i * component_count + 11]); - p.columns[3] = Vector4(attribs[i * component_count + 12], attribs[i * component_count + 13], attribs[i * component_count + 14], attribs[i * component_count + 15]); - } break; - } - ret.write[i] = p; - } break; - default: { - ERR_FAIL_V_MSG(ret, "glTF: Cannot decode accessor as Variant of type " + Variant::get_type_name(p_variant_type) + "."); - } - } - } - return ret; +Vector GLTFDocument::_decode_accessor_as_quaternion(const Ref p_gltf_state, GLTFAccessorIndex p_accessor_index) { + ERR_FAIL_INDEX_V(p_accessor_index, p_gltf_state->accessors.size(), Vector()); + Ref accessor = p_gltf_state->accessors[p_accessor_index]; + Vector quaternions = accessor->decode_as_quaternions(p_gltf_state); + return quaternions; +} + +Array GLTFDocument::_decode_accessor_as_variants(const Ref p_gltf_state, GLTFAccessorIndex p_accessor_index, Variant::Type p_variant_type) { + ERR_FAIL_INDEX_V(p_accessor_index, p_gltf_state->accessors.size(), Array()); + Ref accessor = p_gltf_state->accessors[p_accessor_index]; + Array variants = accessor->decode_as_variants(p_gltf_state, p_variant_type); + return variants; } Error GLTFDocument::_serialize_meshes(Ref p_state) { @@ -2095,7 +1512,7 @@ Error GLTFDocument::_parse_meshes(Ref p_state) { int32_t orig_vertex_num = 0; ERR_FAIL_COND_V(!a.has("POSITION"), ERR_PARSE_ERROR); if (a.has("POSITION")) { - PackedVector3Array vertices = _decode_accessor_as_vec3(p_state, a["POSITION"], true); + PackedVector3Array vertices = _decode_accessor_as_vec3(p_state, a["POSITION"]); array[Mesh::ARRAY_VERTEX] = vertices; orig_vertex_num = vertices.size(); } @@ -2106,7 +1523,7 @@ Error GLTFDocument::_parse_meshes(Ref p_state) { Vector indices_rev_mapping; Vector indices_vec4_mapping; if (mesh_prim.has("indices")) { - indices = _decode_accessor_as_ints(p_state, mesh_prim["indices"], false); + indices = _decode_accessor_as_int32s(p_state, mesh_prim["indices"]); const int index_count = indices.size(); if (primitive == Mesh::PRIMITIVE_TRIANGLES) { @@ -2145,20 +1562,20 @@ Error GLTFDocument::_parse_meshes(Ref p_state) { ERR_FAIL_COND_V(vertex_num <= 0, ERR_INVALID_DECLARATION); if (a.has("POSITION")) { - PackedVector3Array vertices = _decode_accessor_as_vec3(p_state, a["POSITION"], true, indices_mapping); + PackedVector3Array vertices = _decode_accessor_as_vec3(p_state, a["POSITION"], indices_mapping); array[Mesh::ARRAY_VERTEX] = vertices; } if (a.has("NORMAL")) { - array[Mesh::ARRAY_NORMAL] = _decode_accessor_as_vec3(p_state, a["NORMAL"], true, indices_mapping); + array[Mesh::ARRAY_NORMAL] = _decode_accessor_as_vec3(p_state, a["NORMAL"], indices_mapping); } if (a.has("TANGENT")) { - array[Mesh::ARRAY_TANGENT] = _decode_accessor_as_floats(p_state, a["TANGENT"], true, indices_vec4_mapping); + array[Mesh::ARRAY_TANGENT] = _decode_accessor_as_float32s(p_state, a["TANGENT"], indices_vec4_mapping); } if (a.has("TEXCOORD_0")) { - array[Mesh::ARRAY_TEX_UV] = _decode_accessor_as_vec2(p_state, a["TEXCOORD_0"], true, indices_mapping); + array[Mesh::ARRAY_TEX_UV] = _decode_accessor_as_vec2(p_state, a["TEXCOORD_0"], indices_mapping); } if (a.has("TEXCOORD_1")) { - array[Mesh::ARRAY_TEX_UV2] = _decode_accessor_as_vec2(p_state, a["TEXCOORD_1"], true, indices_mapping); + array[Mesh::ARRAY_TEX_UV2] = _decode_accessor_as_vec2(p_state, a["TEXCOORD_1"], indices_mapping); } for (int custom_i = 0; custom_i < 3; custom_i++) { Vector cur_custom; @@ -2169,12 +1586,12 @@ Error GLTFDocument::_parse_meshes(Ref p_state) { String gltf_texcoord_key = vformat("TEXCOORD_%d", texcoord_i); int num_channels = 0; if (a.has(gltf_texcoord_key)) { - texcoord_first = _decode_accessor_as_vec2(p_state, a[gltf_texcoord_key], true, indices_mapping); + texcoord_first = _decode_accessor_as_vec2(p_state, a[gltf_texcoord_key], indices_mapping); num_channels = 2; } gltf_texcoord_key = vformat("TEXCOORD_%d", texcoord_i + 1); if (a.has(gltf_texcoord_key)) { - texcoord_second = _decode_accessor_as_vec2(p_state, a[gltf_texcoord_key], true, indices_mapping); + texcoord_second = _decode_accessor_as_vec2(p_state, a[gltf_texcoord_key], indices_mapping); num_channels = 4; } if (!num_channels) { @@ -2215,16 +1632,16 @@ Error GLTFDocument::_parse_meshes(Ref p_state) { } } if (a.has("COLOR_0")) { - array[Mesh::ARRAY_COLOR] = _decode_accessor_as_color(p_state, a["COLOR_0"], true, indices_mapping); + array[Mesh::ARRAY_COLOR] = _decode_accessor_as_color(p_state, a["COLOR_0"], indices_mapping); has_vertex_color = true; } if (a.has("JOINTS_0") && !a.has("JOINTS_1")) { - PackedInt32Array joints_0 = _decode_accessor_as_ints(p_state, a["JOINTS_0"], true, indices_vec4_mapping); + PackedInt32Array joints_0 = _decode_accessor_as_int32s(p_state, a["JOINTS_0"], indices_vec4_mapping); ERR_FAIL_COND_V(joints_0.size() != 4 * vertex_num, ERR_INVALID_DATA); array[Mesh::ARRAY_BONES] = joints_0; } else if (a.has("JOINTS_0") && a.has("JOINTS_1")) { - PackedInt32Array joints_0 = _decode_accessor_as_ints(p_state, a["JOINTS_0"], true, indices_vec4_mapping); - PackedInt32Array joints_1 = _decode_accessor_as_ints(p_state, a["JOINTS_1"], true, indices_vec4_mapping); + PackedInt32Array joints_0 = _decode_accessor_as_int32s(p_state, a["JOINTS_0"], indices_vec4_mapping); + PackedInt32Array joints_1 = _decode_accessor_as_int32s(p_state, a["JOINTS_1"], indices_vec4_mapping); ERR_FAIL_COND_V(joints_0.size() != joints_1.size(), ERR_INVALID_DATA); ERR_FAIL_COND_V(joints_0.size() != 4 * vertex_num, ERR_INVALID_DATA); int32_t weight_8_count = JOINT_GROUP_SIZE * 2; @@ -2246,7 +1663,7 @@ Error GLTFDocument::_parse_meshes(Ref p_state) { // ArrayMesh uses a flat array of either 4 or 8 floats per vertex. // Therefore, decode up to two glTF VEC4 arrays as float arrays. if (a.has("WEIGHTS_0") && !a.has("WEIGHTS_1")) { - Vector weights = _decode_accessor_as_floats(p_state, a["WEIGHTS_0"], true, indices_vec4_mapping); + Vector weights = _decode_accessor_as_float32s(p_state, a["WEIGHTS_0"], indices_vec4_mapping); ERR_FAIL_COND_V(weights.size() != 4 * vertex_num, ERR_INVALID_DATA); { // glTF does not seem to normalize the weights for some reason. int wc = weights.size(); @@ -2268,8 +1685,8 @@ Error GLTFDocument::_parse_meshes(Ref p_state) { } array[Mesh::ARRAY_WEIGHTS] = weights; } else if (a.has("WEIGHTS_0") && a.has("WEIGHTS_1")) { - Vector weights_0 = _decode_accessor_as_floats(p_state, a["WEIGHTS_0"], true, indices_vec4_mapping); - Vector weights_1 = _decode_accessor_as_floats(p_state, a["WEIGHTS_1"], true, indices_vec4_mapping); + Vector weights_0 = _decode_accessor_as_float32s(p_state, a["WEIGHTS_0"], indices_vec4_mapping); + Vector weights_1 = _decode_accessor_as_float32s(p_state, a["WEIGHTS_1"], indices_vec4_mapping); Vector weights; ERR_FAIL_COND_V(weights_0.size() != weights_1.size(), ERR_INVALID_DATA); ERR_FAIL_COND_V(weights_0.size() != 4 * vertex_num, ERR_INVALID_DATA); @@ -2437,7 +1854,7 @@ Error GLTFDocument::_parse_meshes(Ref p_state) { } if (t.has("POSITION")) { - Vector varr = _decode_accessor_as_vec3(p_state, t["POSITION"], true, indices_mapping); + Vector varr = _decode_accessor_as_vec3(p_state, t["POSITION"], indices_mapping); const Vector src_varr = array[Mesh::ARRAY_VERTEX]; const int size = src_varr.size(); ERR_FAIL_COND_V(size == 0, ERR_PARSE_ERROR); @@ -2459,7 +1876,7 @@ Error GLTFDocument::_parse_meshes(Ref p_state) { array_copy[Mesh::ARRAY_VERTEX] = varr; } if (t.has("NORMAL")) { - Vector narr = _decode_accessor_as_vec3(p_state, t["NORMAL"], true, indices_mapping); + Vector narr = _decode_accessor_as_vec3(p_state, t["NORMAL"], indices_mapping); const Vector src_narr = array[Mesh::ARRAY_NORMAL]; int size = src_narr.size(); ERR_FAIL_COND_V(size == 0, ERR_PARSE_ERROR); @@ -2481,7 +1898,7 @@ Error GLTFDocument::_parse_meshes(Ref p_state) { array_copy[Mesh::ARRAY_NORMAL] = narr; } if (t.has("TANGENT")) { - const Vector tangents_v3 = _decode_accessor_as_vec3(p_state, t["TANGENT"], true, indices_mapping); + const Vector tangents_v3 = _decode_accessor_as_vec3(p_state, t["TANGENT"], indices_mapping); const Vector src_tangents = array[Mesh::ARRAY_TANGENT]; ERR_FAIL_COND_V(src_tangents.is_empty(), ERR_PARSE_ERROR); @@ -3908,8 +3325,10 @@ Error GLTFDocument::_parse_skins(Ref p_state) { const Array &joints = d["joints"]; if (d.has("inverseBindMatrices")) { - skin->inverse_binds = _decode_accessor_as_xform(p_state, d["inverseBindMatrices"], false); - ERR_FAIL_COND_V(skin->inverse_binds.size() != joints.size(), ERR_PARSE_ERROR); + const GLTFAccessorIndex inv_bind_accessor_index = d["inverseBindMatrices"]; + Array inv_binds_arr = _decode_accessor_as_variants(p_state, inv_bind_accessor_index, Variant::TRANSFORM3D); + ERR_FAIL_COND_V(inv_binds_arr.size() != joints.size(), ERR_PARSE_ERROR); + GLTFTemplateConvert::set_from_array(skin->inverse_binds, inv_binds_arr); } for (int j = 0; j < joints.size(); j++) { @@ -4424,7 +3843,7 @@ Error GLTFDocument::_parse_animations(Ref p_state) { output_count = 3; } } - const Vector times = _decode_accessor(p_state, input_time_accessor_index, false); + const PackedFloat64Array times = _decode_accessor_as_float64s(p_state, input_time_accessor_index); // Parse target. const Dictionary &anim_target = anim_channel["target"]; ERR_FAIL_COND_V_MSG(!anim_target.has("path"), ERR_PARSE_ERROR, "glTF: Animation channel target missing required 'path' property."); @@ -4457,22 +3876,22 @@ Error GLTFDocument::_parse_animations(Ref p_state) { track = &animation->get_node_tracks()[node]; if (path == "translation") { - const Vector positions = _decode_accessor_as_vec3(p_state, output_value_accessor_index, false); + const Vector positions = _decode_accessor_as_vec3(p_state, output_value_accessor_index); track->position_track.interpolation = interp; track->position_track.times = times; track->position_track.values = positions; } else if (path == "rotation") { - const Vector rotations = _decode_accessor_as_quaternion(p_state, output_value_accessor_index, false); + const Vector rotations = _decode_accessor_as_quaternion(p_state, output_value_accessor_index); track->rotation_track.interpolation = interp; track->rotation_track.times = times; track->rotation_track.values = rotations; } else if (path == "scale") { - const Vector scales = _decode_accessor_as_vec3(p_state, output_value_accessor_index, false); + const Vector scales = _decode_accessor_as_vec3(p_state, output_value_accessor_index); track->scale_track.interpolation = interp; track->scale_track.times = times; track->scale_track.values = scales; } else if (path == "weights") { - const Vector weights = _decode_accessor_as_floats(p_state, output_value_accessor_index, false); + const Vector weights = _decode_accessor_as_float32s(p_state, output_value_accessor_index); ERR_FAIL_INDEX_V(p_state->nodes[node]->mesh, p_state->meshes.size(), ERR_PARSE_ERROR); Ref mesh = p_state->meshes[p_state->nodes[node]->mesh]; @@ -4528,22 +3947,22 @@ void GLTFDocument::_parse_animation_pointer(Ref p_state, const String } GLTFAnimation::NodeTrack *track = &node_tracks[node_index]; if (split[2] == "translation") { - const Vector positions = _decode_accessor_as_vec3(p_state, p_output_value_accessor_index, false); + const Vector positions = _decode_accessor_as_vec3(p_state, p_output_value_accessor_index); track->position_track.interpolation = p_interp; track->position_track.times = p_times; track->position_track.values = positions; } else if (split[2] == "rotation") { - const Vector rotations = _decode_accessor_as_quaternion(p_state, p_output_value_accessor_index, false); + const Vector rotations = _decode_accessor_as_quaternion(p_state, p_output_value_accessor_index); track->rotation_track.interpolation = p_interp; track->rotation_track.times = p_times; track->rotation_track.values = rotations; } else if (split[2] == "scale") { - const Vector scales = _decode_accessor_as_vec3(p_state, p_output_value_accessor_index, false); + const Vector scales = _decode_accessor_as_vec3(p_state, p_output_value_accessor_index); track->scale_track.interpolation = p_interp; track->scale_track.times = p_times; track->scale_track.values = scales; } else if (split[2] == "matrix") { - const Vector transforms = _decode_accessor_as_xform(p_state, p_output_value_accessor_index, false); + Array transforms = _decode_accessor_as_variants(p_state, p_output_value_accessor_index, Variant::TRANSFORM3D); track->position_track.interpolation = p_interp; track->position_track.times = p_times; track->position_track.values.resize(transforms.size()); @@ -4554,12 +3973,13 @@ void GLTFDocument::_parse_animation_pointer(Ref p_state, const String track->scale_track.times = p_times; track->scale_track.values.resize(transforms.size()); for (int i = 0; i < transforms.size(); i++) { - track->position_track.values.write[i] = transforms[i].get_origin(); - track->rotation_track.values.write[i] = transforms[i].basis.get_rotation_quaternion(); - track->scale_track.values.write[i] = transforms[i].basis.get_scale(); + Transform3D transform = transforms[i]; + track->position_track.values.write[i] = transform.get_origin(); + track->rotation_track.values.write[i] = transform.basis.get_rotation_quaternion(); + track->scale_track.values.write[i] = transform.basis.get_scale(); } } else { // if (split[2] == "weights") - const Vector accessor_weights = _decode_accessor_as_floats(p_state, p_output_value_accessor_index, false); + const Vector accessor_weights = _decode_accessor_as_float32s(p_state, p_output_value_accessor_index); const GLTFMeshIndex mesh_index = p_state->nodes[node_index]->mesh; ERR_FAIL_INDEX(mesh_index, p_state->meshes.size()); const Ref gltf_mesh = p_state->meshes[mesh_index]; @@ -4598,7 +4018,9 @@ void GLTFDocument::_parse_animation_pointer(Ref p_state, const String GLTFAnimation::Channel channel; channel.interpolation = p_interp; channel.times = p_times; - channel.values = _decode_accessor_as_variant(p_state, p_output_value_accessor_index, obj_model_prop->get_variant_type(), obj_model_prop->get_accessor_type()); + Array values_arr = _decode_accessor_as_variants(p_state, p_output_value_accessor_index, obj_model_prop->get_variant_type()); + // TODO: This can be made faster after this pull request is merged: https://github.com/godotengine/godot/pull/109003 + GLTFTemplateConvert::set_from_array(channel.values, values_arr); anim_ptr_map[p_animation_json_pointer] = channel; } diff --git a/modules/gltf/gltf_document.h b/modules/gltf/gltf_document.h index 720035ead40..7bd7a3ce2f8 100644 --- a/modules/gltf/gltf_document.h +++ b/modules/gltf/gltf_document.h @@ -108,11 +108,8 @@ public: private: void _build_parent_hierarchy(Ref p_state); - String _get_component_type_name(const GLTFAccessor::GLTFComponentType p_component_type); - int _get_component_type_size(const GLTFAccessor::GLTFComponentType p_component_type); Error _parse_scenes(Ref p_state); Error _parse_nodes(Ref p_state); - String _get_accessor_type_name(const GLTFAccessor::GLTFAccessorType p_accessor_type); String _sanitize_animation_name(const String &p_name); String _gen_unique_animation_name(Ref p_state, const String &p_name); String _sanitize_bone_name(const String &p_name); @@ -133,53 +130,16 @@ private: Error _parse_buffers(Ref p_state, const String &p_base_path); Error _parse_buffer_views(Ref p_state); Error _parse_accessors(Ref p_state); - Error _decode_buffer_view(Ref p_state, double *p_dst, - const GLTFBufferViewIndex p_buffer_view, - const int64_t p_skip_every, const int64_t p_skip_bytes, - const int64_t p_element_size, const int64_t p_count, - const GLTFAccessor::GLTFAccessorType p_accessor_type, const int64_t p_component_count, - const GLTFAccessor::GLTFComponentType p_component_type, const int64_t p_component_size, - const bool p_normalized, const int64_t p_byte_offset, - const bool p_for_vertex); - Vector _decode_accessor(Ref p_state, - const GLTFAccessorIndex p_accessor, - const bool p_for_vertex); - Vector _decode_accessor_as_floats(Ref p_state, - const GLTFAccessorIndex p_accessor, - const bool p_for_vertex, - const Vector &p_packed_vertex_ids = Vector()); - Vector _decode_accessor_as_ints(Ref p_state, - const GLTFAccessorIndex p_accessor, - const bool p_for_vertex, - const Vector &p_packed_vertex_ids = Vector()); - Vector _decode_accessor_as_vec2(Ref p_state, - const GLTFAccessorIndex p_accessor, - const bool p_for_vertex, - const Vector &p_packed_vertex_ids = Vector()); - Vector _decode_accessor_as_vec3(Ref p_state, - const GLTFAccessorIndex p_accessor, - const bool p_for_vertex, - const Vector &p_packed_vertex_ids = Vector()); - Vector _decode_accessor_as_color(Ref p_state, - const GLTFAccessorIndex p_accessor, - const bool p_for_vertex, - const Vector &p_packed_vertex_ids = Vector()); - Vector _decode_accessor_as_quaternion(Ref p_state, - const GLTFAccessorIndex p_accessor, - const bool p_for_vertex); - Vector _decode_accessor_as_xform2d(Ref p_state, - const GLTFAccessorIndex p_accessor, - const bool p_for_vertex); - Vector _decode_accessor_as_basis(Ref p_state, - const GLTFAccessorIndex p_accessor, - const bool p_for_vertex); - Vector _decode_accessor_as_xform(Ref p_state, - const GLTFAccessorIndex p_accessor, - const bool p_for_vertex); - Vector _decode_accessor_as_variant(Ref p_state, - const GLTFAccessorIndex p_accessor, - Variant::Type p_variant_type, - GLTFAccessor::GLTFAccessorType p_accessor_type); + template + static T _decode_unpack_indexed_data(const T &p_source, const PackedInt32Array &p_indices); + PackedFloat32Array _decode_accessor_as_float32s(const Ref p_gltf_state, GLTFAccessorIndex p_accessor_index, const PackedInt32Array &p_packed_vertex_ids = PackedInt32Array()); + PackedFloat64Array _decode_accessor_as_float64s(const Ref p_gltf_state, GLTFAccessorIndex p_accessor_index, const PackedInt32Array &p_packed_vertex_ids = PackedInt32Array()); + PackedInt32Array _decode_accessor_as_int32s(const Ref p_gltf_state, GLTFAccessorIndex p_accessor_index, const PackedInt32Array &p_packed_vertex_ids = PackedInt32Array()); + PackedVector2Array _decode_accessor_as_vec2(const Ref p_gltf_state, GLTFAccessorIndex p_accessor_index, const PackedInt32Array &p_packed_vertex_ids = PackedInt32Array()); + PackedVector3Array _decode_accessor_as_vec3(const Ref p_gltf_state, GLTFAccessorIndex p_accessor_index, const PackedInt32Array &p_packed_vertex_ids = PackedInt32Array()); + PackedColorArray _decode_accessor_as_color(const Ref p_gltf_state, GLTFAccessorIndex p_accessor_index, const PackedInt32Array &p_packed_vertex_ids = PackedInt32Array()); + Vector _decode_accessor_as_quaternion(const Ref p_gltf_state, GLTFAccessorIndex p_accessor_index); + Array _decode_accessor_as_variants(const Ref p_gltf_state, GLTFAccessorIndex p_accessor_index, Variant::Type p_variant_type); Error _parse_meshes(Ref p_state); Error _serialize_textures(Ref p_state); Error _serialize_texture_samplers(Ref p_state); diff --git a/modules/gltf/structures/gltf_accessor.cpp b/modules/gltf/structures/gltf_accessor.cpp index 43cf45f2af0..0f650c589d5 100644 --- a/modules/gltf/structures/gltf_accessor.cpp +++ b/modules/gltf/structures/gltf_accessor.cpp @@ -443,6 +443,63 @@ int64_t GLTFAccessor::_get_vector_size() const { ERR_FAIL_V(0); } +int64_t GLTFAccessor::_get_numbers_per_variant_for_gltf(Variant::Type p_variant_type) { + // Note that these numbers are used to determine the size of the glTF accessor appropriate for the type (see `_get_vector_size`). + // Therefore, the only valid values this can return are 1 (SCALAR), 2 (VEC2), 3 (VEC3), 4 (VEC4/MAT2), 9 (MAT3), and 16 (MAT4). + // The value 0 indicates the Variant type can't map to glTF accessors, and INT64_MAX indicates it needs special handling. + switch (p_variant_type) { + case Variant::NIL: + case Variant::STRING: + case Variant::STRING_NAME: + case Variant::NODE_PATH: + case Variant::RID: + case Variant::OBJECT: + case Variant::CALLABLE: + case Variant::SIGNAL: + case Variant::DICTIONARY: + case Variant::ARRAY: + case Variant::PACKED_STRING_ARRAY: + case Variant::PACKED_VECTOR2_ARRAY: + case Variant::PACKED_VECTOR3_ARRAY: + case Variant::PACKED_COLOR_ARRAY: + case Variant::PACKED_VECTOR4_ARRAY: + case Variant::VARIANT_MAX: + return 0; // Not supported. + case Variant::BOOL: + case Variant::INT: + case Variant::FLOAT: + return 1; + case Variant::VECTOR2: + case Variant::VECTOR2I: + return 2; + case Variant::VECTOR3: + case Variant::VECTOR3I: + return 3; + case Variant::RECT2: + case Variant::RECT2I: + case Variant::VECTOR4: + case Variant::VECTOR4I: + case Variant::PLANE: + case Variant::QUATERNION: + case Variant::COLOR: + return 4; + case Variant::TRANSFORM2D: + case Variant::AABB: + case Variant::BASIS: + return 9; + case Variant::TRANSFORM3D: + case Variant::PROJECTION: + return 16; + case Variant::PACKED_BYTE_ARRAY: + case Variant::PACKED_INT32_ARRAY: + case Variant::PACKED_INT64_ARRAY: + case Variant::PACKED_FLOAT32_ARRAY: + case Variant::PACKED_FLOAT64_ARRAY: + return INT64_MAX; // Special, use `_get_vector_size()` only to determine size. + } + return 0; +} + int64_t GLTFAccessor::_get_bytes_per_component(const GLTFComponentType p_component_type) { switch (p_component_type) { case GLTFAccessor::COMPONENT_TYPE_NONE: @@ -491,6 +548,546 @@ bool GLTFAccessor::is_equal_exact(const Ref &p_other) const { sparse_values_byte_offset == p_other->sparse_values_byte_offset); } +// Private decode functions. + +PackedInt64Array GLTFAccessor::_decode_sparse_indices(const Ref &p_gltf_state, const TypedArray &p_buffer_views) const { + const int64_t bytes_per_component = _get_bytes_per_component(sparse_indices_component_type); + PackedInt64Array numbers; + ERR_FAIL_INDEX_V(sparse_indices_buffer_view, p_buffer_views.size(), numbers); + const Ref actual_buffer_view = p_buffer_views[sparse_indices_buffer_view]; + const PackedByteArray raw_bytes = actual_buffer_view->load_buffer_view_data(p_gltf_state); + const int64_t min_raw_byte_size = bytes_per_component * sparse_count + sparse_indices_byte_offset; + ERR_FAIL_COND_V_MSG(raw_bytes.size() < min_raw_byte_size, numbers, "glTF import: Sparse indices buffer view did not have enough bytes to read the expected number of indices. Returning an empty array."); + numbers.resize(sparse_count); + const uint8_t *raw_pointer = raw_bytes.ptr(); + int64_t raw_read_offset = sparse_indices_byte_offset; + for (int64_t i = 0; i < sparse_count; i++) { + const uint8_t *raw_source = &raw_pointer[raw_read_offset]; + int64_t number = 0; + switch (sparse_indices_component_type) { + case GLTFAccessor::COMPONENT_TYPE_UNSIGNED_BYTE: { + number = *(uint8_t *)raw_source; + } break; + case GLTFAccessor::COMPONENT_TYPE_UNSIGNED_SHORT: { + number = *(uint16_t *)raw_source; + } break; + case GLTFAccessor::COMPONENT_TYPE_UNSIGNED_INT: { + number = *(uint32_t *)raw_source; + } break; + case GLTFAccessor::COMPONENT_TYPE_UNSIGNED_LONG: { + number = *(uint64_t *)raw_source; + } break; + default: { + ERR_FAIL_V_MSG(PackedInt64Array(), "glTF import: Sparse indices must have an unsigned integer component type. Failed to decode, returning an empty array."); + } + } + numbers.set(i, number); + raw_read_offset += bytes_per_component; + } + ERR_FAIL_COND_V_MSG(raw_read_offset != raw_bytes.size(), numbers, "glTF import: Sparse indices buffer view size did not exactly match the expected size."); + return numbers; +} + +template +Vector GLTFAccessor::_decode_raw_numbers(const Ref &p_gltf_state, const TypedArray &p_buffer_views, bool p_sparse_values) const { + const int64_t bytes_per_component = _get_bytes_per_component(component_type); + const int64_t bytes_per_vector = _get_bytes_per_vector(); + const int64_t vector_size = _get_vector_size(); + int64_t pad_skip_every = 0; + int64_t pad_skip_bytes = 0; + _determine_pad_skip(pad_skip_every, pad_skip_bytes); + int64_t raw_vector_count; + int64_t raw_buffer_view_index; + int64_t raw_read_offset_start; + if (p_sparse_values) { + raw_vector_count = sparse_count; + raw_buffer_view_index = sparse_values_buffer_view; + raw_read_offset_start = sparse_values_byte_offset; + } else { + raw_vector_count = count; + raw_buffer_view_index = buffer_view; + raw_read_offset_start = byte_offset; + } + const int64_t raw_number_count = raw_vector_count * vector_size; + Vector ret_numbers; + if (raw_buffer_view_index == -1) { + ret_numbers.resize(raw_number_count); + // No buffer view, so fill with zeros. + for (int64_t i = 0; i < raw_number_count; i++) { + ret_numbers.set(i, T(0)); + } + return ret_numbers; + } + ERR_FAIL_INDEX_V(raw_buffer_view_index, p_buffer_views.size(), ret_numbers); + const Ref raw_buffer_view = p_buffer_views[raw_buffer_view_index]; + if (raw_buffer_view->get_byte_offset() % bytes_per_component != 0) { + WARN_PRINT("glTF import: 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 (byte_offset % bytes_per_component != 0) { + WARN_PRINT("glTF import: 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."); + } + int64_t declared_byte_stride = raw_buffer_view->get_byte_stride(); + int64_t actual_byte_stride = bytes_per_vector; + int64_t stride_skip_every = 0; + int64_t stride_skip_bytes = 0; + if (declared_byte_stride != -1) { + ERR_FAIL_COND_V_MSG(declared_byte_stride % 4 != 0, ret_numbers, "glTF import: The declared buffer view byte stride " + itos(declared_byte_stride) + " was not a multiple of 4 as required by glTF. Returning an empty array."); + if (declared_byte_stride > bytes_per_vector) { + actual_byte_stride = declared_byte_stride; + stride_skip_every = vector_size; + stride_skip_bytes = declared_byte_stride - bytes_per_vector; + } + } else if (raw_buffer_view->get_vertex_attributes()) { + print_verbose("WARNING: glTF import: Buffer view byte stride should be declared for vertex attributes. Assuming packed data and reading anyway."); + } + const int64_t min_raw_byte_size = actual_byte_stride * (raw_vector_count - 1) + bytes_per_vector + raw_read_offset_start; + const PackedByteArray raw_bytes = raw_buffer_view->load_buffer_view_data(p_gltf_state); + ERR_FAIL_COND_V_MSG(raw_bytes.size() < min_raw_byte_size, ret_numbers, "glTF import: The buffer view size was smaller than the minimum required size for the accessor. Returning an empty array."); + ret_numbers.resize(raw_number_count); + const uint8_t *raw_pointer = raw_bytes.ptr(); + int64_t raw_read_offset = raw_read_offset_start; + for (int64_t i = 0; i < raw_number_count; i++) { + const uint8_t *raw_source = &raw_pointer[raw_read_offset]; + T number = 0; + // 3.11. Implementations MUST use following equations to decode real floating-point value f from a normalized integer c and vice-versa. + // https://registry.khronos.org/glTF/specs/2.0/glTF-2.0.html#animations + switch (component_type) { + case GLTFAccessor::COMPONENT_TYPE_NONE: { + ERR_FAIL_V_MSG(Vector(), "glTF import: Failed to decode buffer view, component type not set. Returning an empty array."); + } break; + case GLTFAccessor::COMPONENT_TYPE_SIGNED_BYTE: { + int8_t prim = *(int8_t *)raw_source; + if (normalized) { + number = T(MAX(double(prim) / 127.0, -1.0)); + } else { + number = T(prim); + } + } break; + case GLTFAccessor::COMPONENT_TYPE_UNSIGNED_BYTE: { + uint8_t prim = *(uint8_t *)raw_source; + if (normalized) { + number = T((double(prim) / 255.0)); + } else { + number = T(prim); + } + } break; + case GLTFAccessor::COMPONENT_TYPE_SIGNED_SHORT: { + int16_t prim = *(int16_t *)raw_source; + if (normalized) { + number = T(MAX(double(prim) / 32767.0, -1.0)); + } else { + number = T(prim); + } + } break; + case GLTFAccessor::COMPONENT_TYPE_UNSIGNED_SHORT: { + uint16_t prim = *(uint16_t *)raw_source; + if (normalized) { + number = T(double(prim) / 65535.0); + } else { + number = T(prim); + } + } break; + case GLTFAccessor::COMPONENT_TYPE_SIGNED_INT: { + number = T(*(int32_t *)raw_source); + } break; + case GLTFAccessor::COMPONENT_TYPE_UNSIGNED_INT: { + number = T(*(uint32_t *)raw_source); + } break; + case GLTFAccessor::COMPONENT_TYPE_SINGLE_FLOAT: { + number = T(*(float *)raw_source); + } break; + case GLTFAccessor::COMPONENT_TYPE_DOUBLE_FLOAT: { + number = T(*(double *)raw_source); + } break; + case GLTFAccessor::COMPONENT_TYPE_HALF_FLOAT: { + number = Math::half_to_float(*(uint16_t *)raw_source); + } break; + case GLTFAccessor::COMPONENT_TYPE_SIGNED_LONG: { + number = T(*(int64_t *)raw_source); + } break; + case GLTFAccessor::COMPONENT_TYPE_UNSIGNED_LONG: { + number = T(*(uint64_t *)raw_source); + } break; + } + ret_numbers.set(i, number); + raw_read_offset += bytes_per_component; + // Padding and stride skipping are distinct concepts that both need to be handled. + // For example, a 2-in-1 interleaved MAT3 bytes accessor has both, and would look like: + // AAA0 AAA0 AAA0 BBB0 BBB0 BBB0 AAA0 AAA0 AAA0 BBB0 BBB0 BBB0 + // The "0" is skipped by the padding, and the "BBB0" is skipped by the stride. + // https://registry.khronos.org/glTF/specs/2.0/glTF-2.0.html#data-alignment + if (unlikely(pad_skip_every > 0)) { + if ((i + 1) % pad_skip_every == 0) { + raw_read_offset += pad_skip_bytes; + } + } + if (unlikely(stride_skip_every > 0)) { + if ((i + 1) % stride_skip_every == 0) { + raw_read_offset += stride_skip_bytes; + } + } + } + return ret_numbers; +} + +template +Vector GLTFAccessor::_decode_as_numbers(const Ref &p_gltf_state) const { + const TypedArray &p_buffer_views = p_gltf_state->get_buffer_views(); + Vector ret_numbers = _decode_raw_numbers(p_gltf_state, p_buffer_views, false); + if (sparse_count == 0) { + return ret_numbers; + } + // Handle sparse accessors. + PackedInt64Array sparse_indices = _decode_sparse_indices(p_gltf_state, p_buffer_views); + ERR_FAIL_COND_V_MSG(sparse_indices.size() != sparse_count, ret_numbers, "glTF import: Sparse indices size does not match the sparse count."); + const int64_t vector_size = _get_vector_size(); + Vector sparse_values = _decode_raw_numbers(p_gltf_state, p_buffer_views, true); + ERR_FAIL_COND_V_MSG(sparse_values.size() != sparse_count * vector_size, ret_numbers, "glTF import: Sparse values size does not match the sparse count."); + for (int64_t in_sparse = 0; in_sparse < sparse_count; in_sparse++) { + const int64_t sparse_index = sparse_indices[in_sparse]; + const int64_t array_offset = sparse_index * vector_size; + ERR_FAIL_INDEX_V_MSG(array_offset, ret_numbers.size(), ret_numbers, "glTF import: Sparse indices were out of bounds for the accessor."); + for (int64_t in_vec = 0; in_vec < vector_size; in_vec++) { + ret_numbers.set(array_offset + in_vec, sparse_values[in_sparse * vector_size + in_vec]); + } + } + return ret_numbers; +} + +// High-level decode functions. + +PackedColorArray GLTFAccessor::decode_as_colors(const Ref &p_gltf_state) const { + PackedColorArray ret; + PackedFloat32Array numbers = _decode_as_numbers(p_gltf_state); + if (accessor_type == TYPE_VEC3) { + ERR_FAIL_COND_V_MSG(numbers.size() != count * 3, ret, "glTF import: The accessor does not have the expected amount of numbers for the given count and vector size."); + ret.resize(count); + for (int64_t i = 0; i < count; i++) { + const int64_t number_index = i * 3; + ret.set(i, Color(numbers[number_index], numbers[number_index + 1], numbers[number_index + 2], 1.0f)); + } + } else if (accessor_type == TYPE_VEC4) { + ERR_FAIL_COND_V_MSG(numbers.size() != count * 4, ret, "glTF import: The accessor does not have the expected amount of numbers for the given count and vector size."); + ret.resize(count); + for (int64_t i = 0; i < count; i++) { + const int64_t number_index = i * 4; + ret.set(i, Color(numbers[number_index], numbers[number_index + 1], numbers[number_index + 2], numbers[number_index + 3])); + } + } else { + ERR_FAIL_V_MSG(ret, "glTF import: The `decode_as_colors` function is designed to be fast and can only be used with accessors of type \"VEC3\" or \"VEC4\", but was called with type \"" + _get_accessor_type_name() + "\". Consider using `decode_as_variants` if you need more flexible behavior with support for any accessor type."); + } + return ret; +} + +PackedFloat32Array GLTFAccessor::decode_as_float32s(const Ref &p_gltf_state) const { + return _decode_as_numbers(p_gltf_state); +} + +PackedFloat64Array GLTFAccessor::decode_as_float64s(const Ref &p_gltf_state) const { + return _decode_as_numbers(p_gltf_state); +} + +PackedInt32Array GLTFAccessor::decode_as_int32s(const Ref &p_gltf_state) const { + return _decode_as_numbers(p_gltf_state); +} + +PackedInt64Array GLTFAccessor::decode_as_int64s(const Ref &p_gltf_state) const { + return _decode_as_numbers(p_gltf_state); +} + +Vector GLTFAccessor::decode_as_quaternions(const Ref &p_gltf_state) const { + Vector ret; + ERR_FAIL_COND_V_MSG(accessor_type != TYPE_VEC4, ret, "glTF import: The `decode_as_quaternions` function is designed to be fast and can only be used with accessors of type \"VEC4\", but was called with type \"" + _get_accessor_type_name() + "\". Consider using `decode_as_variants` if you need more flexible behavior with support for any accessor type."); + PackedRealArray numbers = _decode_as_numbers(p_gltf_state); + ERR_FAIL_COND_V_MSG(numbers.size() != count * 4, ret, "glTF import: The accessor does not have the expected amount of numbers for the given count and vector size."); + ret.resize(count); + for (int64_t i = 0; i < count; i++) { + const int64_t number_index = i * 4; + ret.set(i, Quaternion(numbers[number_index], numbers[number_index + 1], numbers[number_index + 2], numbers[number_index + 3]).normalized()); + } + return ret; +} + +Array GLTFAccessor::decode_as_variants(const Ref &p_gltf_state, Variant::Type p_variant_type) const { + const int64_t numbers_per_variant = _get_numbers_per_variant_for_gltf(p_variant_type); + Array ret; + ERR_FAIL_COND_V_MSG(numbers_per_variant < 1, ret, "glTF import: The Variant type '" + Variant::get_type_name(p_variant_type) + "' is not supported. Returning an empty array."); + const PackedFloat64Array numbers = _decode_as_numbers(p_gltf_state); + const int64_t vector_size = _get_vector_size(); + ERR_FAIL_COND_V_MSG(vector_size < 1, ret, "glTF import: The accessor type '" + _get_accessor_type_name() + "' is not supported. Returning an empty array."); + const int64_t numbers_to_read = MIN(vector_size, numbers_per_variant); + ERR_FAIL_COND_V_MSG(numbers.size() != count * vector_size, ret, "glTF import: The accessor does not have the expected amount of numbers for the given count and vector size."); + ret.resize(count); + for (int64_t value_index = 0; value_index < count; value_index++) { + const int64_t number_index = value_index * vector_size; + switch (p_variant_type) { + case Variant::BOOL: { + ret[value_index] = numbers[number_index] != 0.0; + } break; + case Variant::INT: { + ret[value_index] = (int64_t)numbers[number_index]; + } break; + case Variant::FLOAT: { + ret[value_index] = numbers[number_index]; + } break; + case Variant::VECTOR2: + case Variant::RECT2: + case Variant::VECTOR3: + case Variant::VECTOR4: + case Variant::PLANE: + case Variant::QUATERNION: { + // General-purpose code for importing glTF accessor data with any component count into structs up to 4 `real_t`s in size. + Vector4 vec; + switch (numbers_to_read) { + case 1: { + vec = Vector4(numbers[number_index], 0.0f, 0.0f, 0.0f); + } break; + case 2: { + vec = Vector4(numbers[number_index], numbers[number_index + 1], 0.0f, 0.0f); + } break; + case 3: { + vec = Vector4(numbers[number_index], numbers[number_index + 1], numbers[number_index + 2], 0.0f); + } break; + default: { + vec = Vector4(numbers[number_index], numbers[number_index + 1], numbers[number_index + 2], numbers[number_index + 3]); + } break; + } + if (p_variant_type == Variant::QUATERNION) { + vec.normalize(); + } + // Evil hack that relies on the structure of Variant, but it's the + // only way to accomplish this without a ton of code duplication. + Variant variant = vec; + *(Variant::Type *)&variant = p_variant_type; + ret[value_index] = variant; + } break; + case Variant::VECTOR2I: + case Variant::RECT2I: + case Variant::VECTOR3I: + case Variant::VECTOR4I: { + // General-purpose code for importing glTF accessor data with any component count into structs up to 4 `int32_t`s in size. + Vector4i vec; + switch (numbers_to_read) { + case 1: { + vec = Vector4i((int32_t)numbers[number_index], 0, 0, 0); + } break; + case 2: { + vec = Vector4i((int32_t)numbers[number_index], (int32_t)numbers[number_index + 1], 0, 0); + } break; + case 3: { + vec = Vector4i((int32_t)numbers[number_index], (int32_t)numbers[number_index + 1], (int32_t)numbers[number_index + 2], 0); + } break; + default: { + vec = Vector4i((int32_t)numbers[number_index], (int32_t)numbers[number_index + 1], (int32_t)numbers[number_index + 2], (int32_t)numbers[number_index + 3]); + } break; + } + // Evil hack that relies on the structure of Variant, but it's the + // only way to accomplish this without a ton of code duplication. + Variant variant = vec; + *(Variant::Type *)&variant = p_variant_type; + ret[value_index] = variant; + } break; + // No more generalized hacks, each of the below types needs a lot of repetitive code. + case Variant::COLOR: { + Color color; + switch (numbers_to_read) { + case 1: { + color = Color(numbers[number_index], 0.0f, 0.0f, 1.0f); + } break; + case 2: { + color = Color(numbers[number_index], numbers[number_index + 1], 0.0f, 1.0f); + } break; + case 3: { + color = Color(numbers[number_index], numbers[number_index + 1], numbers[number_index + 2], 1.0f); + } break; + default: { + color = Color(numbers[number_index], numbers[number_index + 1], numbers[number_index + 2], numbers[number_index + 3]); + } break; + } + ret[value_index] = color; + } break; + case Variant::TRANSFORM2D: { + Transform2D t; + switch (numbers_to_read) { + case 4: { + t.columns[0] = Vector2(numbers[number_index + 0], numbers[number_index + 1]); + t.columns[1] = Vector2(numbers[number_index + 2], numbers[number_index + 3]); + } break; + case 9: { + t.columns[0] = Vector2(numbers[number_index + 0], numbers[number_index + 1]); + t.columns[1] = Vector2(numbers[number_index + 3], numbers[number_index + 4]); + t.columns[2] = Vector2(numbers[number_index + 6], numbers[number_index + 7]); + } break; + case 16: { + t.columns[0] = Vector2(numbers[number_index + 0], numbers[number_index + 1]); + t.columns[1] = Vector2(numbers[number_index + 4], numbers[number_index + 5]); + t.columns[2] = Vector2(numbers[number_index + 12], numbers[number_index + 13]); + } break; + } + ret[value_index] = t; + } break; + case Variant::AABB: { + AABB aabb; + switch (numbers_to_read) { + case 4: { + aabb.position = Vector3(numbers[number_index + 0], numbers[number_index + 1], 0.0f); + aabb.size = Vector3(numbers[number_index + 2], numbers[number_index + 3], 0.0f); + } break; + case 9: { + aabb.position = Vector3(numbers[number_index + 0], numbers[number_index + 1], numbers[number_index + 2]); + aabb.size = Vector3(numbers[number_index + 3], numbers[number_index + 4], numbers[number_index + 5]); + } break; + case 16: { + aabb.position = Vector3(numbers[number_index + 0], numbers[number_index + 1], numbers[number_index + 2]); + aabb.size = Vector3(numbers[number_index + 4], numbers[number_index + 5], numbers[number_index + 6]); + } break; + } + ret[value_index] = aabb; + } break; + case Variant::BASIS: { + Basis b; + switch (numbers_to_read) { + case 4: { + b.rows[0] = Vector3(numbers[number_index + 0], numbers[number_index + 2], 0.0f); + b.rows[1] = Vector3(numbers[number_index + 1], numbers[number_index + 3], 0.0f); + } break; + case 9: { + b.rows[0] = Vector3(numbers[number_index + 0], numbers[number_index + 3], numbers[number_index + 6]); + b.rows[1] = Vector3(numbers[number_index + 1], numbers[number_index + 4], numbers[number_index + 7]); + b.rows[2] = Vector3(numbers[number_index + 2], numbers[number_index + 5], numbers[number_index + 8]); + } break; + case 16: { + b.rows[0] = Vector3(numbers[number_index + 0], numbers[number_index + 4], numbers[number_index + 8]); + b.rows[1] = Vector3(numbers[number_index + 1], numbers[number_index + 5], numbers[number_index + 9]); + b.rows[2] = Vector3(numbers[number_index + 2], numbers[number_index + 6], numbers[number_index + 10]); + } break; + } + ret[value_index] = b; + } break; + case Variant::TRANSFORM3D: { + Transform3D t; + switch (numbers_to_read) { + case 4: { + t.basis.rows[0] = Vector3(numbers[number_index + 0], numbers[number_index + 2], 0.0f); + t.basis.rows[1] = Vector3(numbers[number_index + 1], numbers[number_index + 3], 0.0f); + } break; + case 9: { + t.basis.rows[0] = Vector3(numbers[number_index + 0], numbers[number_index + 3], numbers[number_index + 6]); + t.basis.rows[1] = Vector3(numbers[number_index + 1], numbers[number_index + 4], numbers[number_index + 7]); + t.basis.rows[2] = Vector3(numbers[number_index + 2], numbers[number_index + 5], numbers[number_index + 8]); + } break; + case 16: { + t.basis.rows[0] = Vector3(numbers[number_index + 0], numbers[number_index + 4], numbers[number_index + 8]); + t.basis.rows[1] = Vector3(numbers[number_index + 1], numbers[number_index + 5], numbers[number_index + 9]); + t.basis.rows[2] = Vector3(numbers[number_index + 2], numbers[number_index + 6], numbers[number_index + 10]); + t.origin = Vector3(numbers[number_index + 12], numbers[number_index + 13], numbers[number_index + 14]); + } break; + } + ret[value_index] = t; + } break; + case Variant::PROJECTION: { + Projection p; + switch (numbers_to_read) { + case 4: { + p.columns[0] = Vector4(numbers[number_index + 0], numbers[number_index + 1], 0.0f, 0.0f); + p.columns[1] = Vector4(numbers[number_index + 4], numbers[number_index + 5], 0.0f, 0.0f); + } break; + case 9: { + p.columns[0] = Vector4(numbers[number_index + 0], numbers[number_index + 1], numbers[number_index + 2], 0.0f); + p.columns[1] = Vector4(numbers[number_index + 4], numbers[number_index + 5], numbers[number_index + 6], 0.0f); + p.columns[2] = Vector4(numbers[number_index + 8], numbers[number_index + 9], numbers[number_index + 10], 0.0f); + } break; + case 16: { + p.columns[0] = Vector4(numbers[number_index + 0], numbers[number_index + 1], numbers[number_index + 2], numbers[number_index + 3]); + p.columns[1] = Vector4(numbers[number_index + 4], numbers[number_index + 5], numbers[number_index + 6], numbers[number_index + 7]); + p.columns[2] = Vector4(numbers[number_index + 8], numbers[number_index + 9], numbers[number_index + 10], numbers[number_index + 11]); + p.columns[3] = Vector4(numbers[number_index + 12], numbers[number_index + 13], numbers[number_index + 14], numbers[number_index + 15]); + } break; + } + ret[value_index] = p; + } break; + case Variant::PACKED_BYTE_ARRAY: { + PackedByteArray packed_array; + packed_array.resize(numbers_to_read); + for (int64_t j = 0; j < numbers_to_read; j++) { + packed_array.set(value_index, numbers[number_index + j]); + } + } break; + case Variant::PACKED_INT32_ARRAY: { + PackedInt32Array packed_array; + packed_array.resize(numbers_to_read); + for (int64_t j = 0; j < numbers_to_read; j++) { + packed_array.set(value_index, numbers[number_index + j]); + } + } break; + case Variant::PACKED_INT64_ARRAY: { + PackedInt64Array packed_array; + packed_array.resize(numbers_to_read); + for (int64_t j = 0; j < numbers_to_read; j++) { + packed_array.set(value_index, numbers[number_index + j]); + } + } break; + case Variant::PACKED_FLOAT32_ARRAY: { + PackedFloat32Array packed_array; + packed_array.resize(numbers_to_read); + for (int64_t j = 0; j < numbers_to_read; j++) { + packed_array.set(value_index, numbers[number_index + j]); + } + } break; + case Variant::PACKED_FLOAT64_ARRAY: { + PackedFloat64Array packed_array; + packed_array.resize(numbers_to_read); + for (int64_t j = 0; j < numbers_to_read; j++) { + packed_array.set(value_index, numbers[number_index + j]); + } + } break; + default: { + ERR_FAIL_V_MSG(ret, "glTF: Cannot decode accessor as Variant of type " + Variant::get_type_name(p_variant_type) + "."); + } + } + } + return ret; +} + +PackedVector2Array GLTFAccessor::decode_as_vector2s(const Ref &p_gltf_state) const { + PackedVector2Array ret; + ERR_FAIL_COND_V_MSG(accessor_type != TYPE_VEC2, ret, "glTF import: The `decode_as_vector2s` function is designed to be fast and can only be used with accessors of type \"VEC2\", but was called with type \"" + _get_accessor_type_name() + "\". Consider using `decode_as_variants` if you need more flexible behavior with support for any accessor type."); + PackedRealArray numbers = _decode_as_numbers(p_gltf_state); + ERR_FAIL_COND_V_MSG(numbers.size() != count * 2, ret, "glTF import: The accessor does not have the expected amount of numbers for the given count and vector size."); + ret.resize(count); + for (int64_t i = 0; i < count; i++) { + const int64_t number_index = i * 2; + ret.set(i, Vector2(numbers[number_index], numbers[number_index + 1])); + } + return ret; +} + +PackedVector3Array GLTFAccessor::decode_as_vector3s(const Ref &p_gltf_state) const { + PackedVector3Array ret; + ERR_FAIL_COND_V_MSG(accessor_type != TYPE_VEC3, ret, "glTF import: The `decode_as_vector3s` function is designed to be fast and can only be used with accessors of type \"VEC3\", but was called with type \"" + _get_accessor_type_name() + "\". Consider using `decode_as_variants` if you need more flexible behavior with support for any accessor type."); + PackedRealArray numbers = _decode_as_numbers(p_gltf_state); + ERR_FAIL_COND_V_MSG(numbers.size() != count * 3, ret, "glTF import: The accessor does not have the expected amount of numbers for the given count and vector size."); + ret.resize(count); + for (int64_t i = 0; i < count; i++) { + const int64_t number_index = i * 3; + ret.set(i, Vector3(numbers[number_index], numbers[number_index + 1], numbers[number_index + 2])); + } + return ret; +} + +PackedVector4Array GLTFAccessor::decode_as_vector4s(const Ref &p_gltf_state) const { + PackedVector4Array ret; + ERR_FAIL_COND_V_MSG(accessor_type != TYPE_VEC4, ret, "glTF import: The `decode_as_vector4s` function is designed to be fast and can only be used with accessors of type \"VEC4\", but was called with type \"" + _get_accessor_type_name() + "\". Consider using `decode_as_variants` if you need more flexible behavior with support for any accessor type."); + PackedRealArray numbers = _decode_as_numbers(p_gltf_state); + ERR_FAIL_COND_V_MSG(numbers.size() != count * 4, ret, "glTF import: The accessor does not have the expected amount of numbers for the given count and vector size."); + ret.resize(count); + for (int64_t i = 0; i < count; i++) { + const int64_t number_index = i * 4; + ret.set(i, Vector4(numbers[number_index], numbers[number_index + 1], numbers[number_index + 2], numbers[number_index + 3])); + } + return ret; +} + // Private encode functions. PackedFloat64Array GLTFAccessor::_encode_variants_as_floats(const Array &p_input_data, Variant::Type p_variant_type) const { diff --git a/modules/gltf/structures/gltf_accessor.h b/modules/gltf/structures/gltf_accessor.h index ffffd26eb9f..4b92a2b6685 100644 --- a/modules/gltf/structures/gltf_accessor.h +++ b/modules/gltf/structures/gltf_accessor.h @@ -90,9 +90,17 @@ private: static GLTFAccessorType _get_accessor_type_from_str(const String &p_string); String _get_accessor_type_name() const; int64_t _get_vector_size() const; + static int64_t _get_numbers_per_variant_for_gltf(Variant::Type p_variant_type); static int64_t _get_bytes_per_component(const GLTFComponentType p_component_type); int64_t _get_bytes_per_vector() const; + // Private decode functions. + PackedInt64Array _decode_sparse_indices(const Ref &p_gltf_state, const TypedArray &p_buffer_views) const; + template + Vector _decode_raw_numbers(const Ref &p_gltf_state, const TypedArray &p_buffer_views, bool p_sparse_values) const; + template + Vector _decode_as_numbers(const Ref &p_gltf_state) const; + // Private encode functions. PackedFloat64Array _encode_variants_as_floats(const Array &p_input_data, Variant::Type p_variant_type) const; void _store_sparse_indices_into_state(const Ref &p_gltf_state, const PackedInt64Array &p_sparse_indices, const bool p_deduplicate = true); @@ -171,6 +179,18 @@ public: bool is_equal_exact(const Ref &p_other) const; + // High-level decode functions. + PackedColorArray decode_as_colors(const Ref &p_gltf_state) const; + PackedFloat32Array decode_as_float32s(const Ref &p_gltf_state) const; + PackedFloat64Array decode_as_float64s(const Ref &p_gltf_state) const; + PackedInt32Array decode_as_int32s(const Ref &p_gltf_state) const; + PackedInt64Array decode_as_int64s(const Ref &p_gltf_state) const; + Vector decode_as_quaternions(const Ref &p_gltf_state) const; + PackedVector2Array decode_as_vector2s(const Ref &p_gltf_state) const; + PackedVector3Array decode_as_vector3s(const Ref &p_gltf_state) const; + PackedVector4Array decode_as_vector4s(const Ref &p_gltf_state) const; + Array decode_as_variants(const Ref &p_gltf_state, Variant::Type p_variant_type) const; + // Low-level encode functions. static GLTFComponentType get_minimal_integer_component_type_from_ints(const PackedInt64Array &p_numbers); PackedByteArray encode_floats_as_bytes(const PackedFloat64Array &p_input_numbers);