diff --git a/modules/gltf/gltf_document.cpp b/modules/gltf/gltf_document.cpp index 95c0ea5f158f..b3e313b9b5a9 100644 --- a/modules/gltf/gltf_document.cpp +++ b/modules/gltf/gltf_document.cpp @@ -730,24 +730,40 @@ static Vector _parse_base64_uri(const String &p_uri) { return buf; } +inline bool _all_buffers_empty(const Vector> &p_buffers, int start_idx = 0) { + for (int i = start_idx; i < p_buffers.size(); i++) { + if (!p_buffers[i].is_empty()) { + return false; + } + } + return true; +} + Error GLTFDocument::_encode_buffer_glb(Ref p_state, const String &p_path) { print_verbose("glTF: Total buffers: " + itos(p_state->buffers.size())); - if (p_state->buffers.is_empty()) { + if (p_state->buffers.is_empty() || _all_buffers_empty(p_state->buffers)) { + ERR_FAIL_COND_V_MSG(!p_state->buffer_views.is_empty(), ERR_INVALID_DATA, "glTF: Buffer views are present, but buffers are empty."); return OK; } Array buffers; - if (!p_state->buffers.is_empty()) { - Vector buffer_data = p_state->buffers[0]; - Dictionary gltf_buffer; + Dictionary first_buffer; - gltf_buffer["byteLength"] = buffer_data.size(); - buffers.push_back(gltf_buffer); - } + first_buffer["byteLength"] = p_state->buffers[0].size(); + buffers.push_back(first_buffer); for (GLTFBufferIndex i = 1; i < p_state->buffers.size(); i++) { - Vector buffer_data = p_state->buffers[i]; + const Vector &buffer_data = p_state->buffers[i]; Dictionary gltf_buffer; + if (buffer_data.is_empty()) { + if (i < p_state->buffers.size() - 1 && !_all_buffers_empty(p_state->buffers, i + 1)) { + // Have to push back an empty buffer to avoid changing the buffer index, even though this is against spec. + WARN_PRINT("glTF: Buffer " + itos(i) + " is empty, but there are non-empty subsequent buffers."); + gltf_buffer["byteLength"] = 0; + buffers.push_back(gltf_buffer); + } + continue; + } String filename = p_path.get_basename().get_file() + itos(i) + ".bin"; String path = p_path.get_base_dir() + "/" + filename; Error err; @@ -755,9 +771,6 @@ Error GLTFDocument::_encode_buffer_glb(Ref p_state, const String &p_p if (file.is_null()) { return err; } - if (buffer_data.is_empty()) { - return OK; - } file->create(FileAccess::ACCESS_RESOURCES); file->store_buffer(buffer_data.ptr(), buffer_data.size()); gltf_buffer["uri"] = filename; @@ -772,14 +785,24 @@ Error GLTFDocument::_encode_buffer_glb(Ref p_state, const String &p_p Error GLTFDocument::_encode_buffer_bins(Ref p_state, const String &p_path) { print_verbose("glTF: Total buffers: " + itos(p_state->buffers.size())); - if (p_state->buffers.is_empty()) { + if (p_state->buffers.is_empty() || _all_buffers_empty(p_state->buffers)) { + ERR_FAIL_COND_V_MSG(!p_state->buffer_views.is_empty(), ERR_INVALID_DATA, "glTF: Buffer views are present, but buffers are empty."); return OK; } Array buffers; for (GLTFBufferIndex i = 0; i < p_state->buffers.size(); i++) { - Vector buffer_data = p_state->buffers[i]; + const Vector &buffer_data = p_state->buffers[i]; Dictionary gltf_buffer; + if (buffer_data.is_empty()) { + if (i < p_state->buffers.size() - 1 && !_all_buffers_empty(p_state->buffers, i + 1)) { + // Have to push back an empty buffer to avoid changing the buffer index, even though this is against spec. + WARN_PRINT("glTF: Buffer " + itos(i) + " is empty, but there are non-empty subsequent buffers."); + gltf_buffer["byteLength"] = 0; + buffers.push_back(gltf_buffer); + } + continue; + } String filename = p_path.get_basename().get_file() + itos(i) + ".bin"; String path = p_path.get_base_dir() + "/" + filename; Error err; @@ -787,16 +810,14 @@ Error GLTFDocument::_encode_buffer_bins(Ref p_state, const String &p_ if (file.is_null()) { return err; } - if (buffer_data.is_empty()) { - return OK; - } - file->create(FileAccess::ACCESS_RESOURCES); file->store_buffer(buffer_data.ptr(), buffer_data.size()); gltf_buffer["uri"] = filename; gltf_buffer["byteLength"] = buffer_data.size(); buffers.push_back(gltf_buffer); } - p_state->json["buffers"] = buffers; + if (!buffers.is_empty()) { + p_state->json["buffers"] = buffers; + } return OK; }