3.x: Fix validation errors due to chunk padding and empty skins.
GLB chunk padding length calculation was backwards and missing for the BIN chunk. Fixed error caused by "skins":[] when no skins were present. Finally, encode animations before textures to avoid accessor misalignment due to texture byteLength.
This commit is contained in:
parent
221beb8152
commit
e49f8c5823
1 changed files with 31 additions and 24 deletions
|
@ -117,30 +117,30 @@ Error GLTFDocument::serialize(Ref<GLTFState> state, Node *p_root, const String &
|
||||||
return Error::FAILED;
|
return Error::FAILED;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* STEP 7 SERIALIZE IMAGES */
|
/* STEP 7 SERIALIZE ANIMATIONS */
|
||||||
err = _serialize_images(state, p_path);
|
|
||||||
if (err != OK) {
|
|
||||||
return Error::FAILED;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* STEP 8 SERIALIZE TEXTURES */
|
|
||||||
err = _serialize_textures(state);
|
|
||||||
if (err != OK) {
|
|
||||||
return Error::FAILED;
|
|
||||||
}
|
|
||||||
|
|
||||||
// /* STEP 9 SERIALIZE ANIMATIONS */
|
|
||||||
err = _serialize_animations(state);
|
err = _serialize_animations(state);
|
||||||
if (err != OK) {
|
if (err != OK) {
|
||||||
return Error::FAILED;
|
return Error::FAILED;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* STEP 10 SERIALIZE ACCESSORS */
|
/* STEP 8 SERIALIZE ACCESSORS */
|
||||||
err = _encode_accessors(state);
|
err = _encode_accessors(state);
|
||||||
if (err != OK) {
|
if (err != OK) {
|
||||||
return Error::FAILED;
|
return Error::FAILED;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* STEP 9 SERIALIZE IMAGES */
|
||||||
|
err = _serialize_images(state, p_path);
|
||||||
|
if (err != OK) {
|
||||||
|
return Error::FAILED;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* STEP 10 SERIALIZE TEXTURES */
|
||||||
|
err = _serialize_textures(state);
|
||||||
|
if (err != OK) {
|
||||||
|
return Error::FAILED;
|
||||||
|
}
|
||||||
|
|
||||||
for (GLTFBufferViewIndex i = 0; i < state->buffer_views.size(); i++) {
|
for (GLTFBufferViewIndex i = 0; i < state->buffer_views.size(); i++) {
|
||||||
state->buffer_views.write[i]->buffer = 0;
|
state->buffer_views.write[i]->buffer = 0;
|
||||||
}
|
}
|
||||||
|
@ -4366,6 +4366,10 @@ Error GLTFDocument::_serialize_skins(Ref<GLTFState> state) {
|
||||||
json_skin["name"] = gltf_skin->get_name();
|
json_skin["name"] = gltf_skin->get_name();
|
||||||
json_skins.push_back(json_skin);
|
json_skins.push_back(json_skin);
|
||||||
}
|
}
|
||||||
|
if (!state->skins.size()) {
|
||||||
|
return OK;
|
||||||
|
}
|
||||||
|
|
||||||
state->json["skins"] = json_skins;
|
state->json["skins"] = json_skins;
|
||||||
return OK;
|
return OK;
|
||||||
}
|
}
|
||||||
|
@ -6717,33 +6721,36 @@ Error GLTFDocument::_serialize_file(Ref<GLTFState> state, const String p_path) {
|
||||||
const uint32_t magic = 0x46546C67; // GLTF
|
const uint32_t magic = 0x46546C67; // GLTF
|
||||||
const int32_t header_size = 12;
|
const int32_t header_size = 12;
|
||||||
const int32_t chunk_header_size = 8;
|
const int32_t chunk_header_size = 8;
|
||||||
|
|
||||||
for (int32_t pad_i = 0; pad_i < (chunk_header_size + json.utf8().length()) % 4; pad_i++) {
|
|
||||||
json += " ";
|
|
||||||
}
|
|
||||||
CharString cs = json.utf8();
|
CharString cs = json.utf8();
|
||||||
const uint32_t text_chunk_length = cs.length();
|
const uint32_t text_data_length = cs.length();
|
||||||
|
const uint32_t text_chunk_length = ((text_data_length + 3) & (~3));
|
||||||
const uint32_t text_chunk_type = 0x4E4F534A; //JSON
|
const uint32_t text_chunk_type = 0x4E4F534A; //JSON
|
||||||
int32_t binary_data_length = 0;
|
|
||||||
|
uint32_t binary_data_length = 0;
|
||||||
if (state->buffers.size()) {
|
if (state->buffers.size()) {
|
||||||
binary_data_length = state->buffers[0].size();
|
binary_data_length = state->buffers[0].size();
|
||||||
}
|
}
|
||||||
const int32_t binary_chunk_length = binary_data_length;
|
const uint32_t binary_chunk_length = ((binary_data_length + 3) & (~3));
|
||||||
const int32_t binary_chunk_type = 0x004E4942; //BIN
|
const uint32_t binary_chunk_type = 0x004E4942; //BIN
|
||||||
|
|
||||||
f->create(FileAccess::ACCESS_RESOURCES);
|
f->create(FileAccess::ACCESS_RESOURCES);
|
||||||
f->store_32(magic);
|
f->store_32(magic);
|
||||||
f->store_32(state->major_version); // version
|
f->store_32(state->major_version); // version
|
||||||
f->store_32(header_size + chunk_header_size + text_chunk_length + chunk_header_size + binary_data_length); // length
|
f->store_32(header_size + chunk_header_size + text_chunk_length + chunk_header_size + binary_chunk_length); // length
|
||||||
f->store_32(text_chunk_length);
|
f->store_32(text_chunk_length);
|
||||||
f->store_32(text_chunk_type);
|
f->store_32(text_chunk_type);
|
||||||
f->store_buffer((uint8_t *)&cs[0], cs.length());
|
f->store_buffer((uint8_t *)&cs[0], cs.length());
|
||||||
|
for (uint32_t pad_i = text_data_length; pad_i < text_chunk_length; pad_i++) {
|
||||||
|
f->store_8(' ');
|
||||||
|
}
|
||||||
if (binary_chunk_length) {
|
if (binary_chunk_length) {
|
||||||
f->store_32(binary_chunk_length);
|
f->store_32(binary_chunk_length);
|
||||||
f->store_32(binary_chunk_type);
|
f->store_32(binary_chunk_type);
|
||||||
f->store_buffer(state->buffers[0].ptr(), binary_data_length);
|
f->store_buffer(state->buffers[0].ptr(), binary_data_length);
|
||||||
}
|
}
|
||||||
|
for (uint32_t pad_i = binary_data_length; pad_i < binary_chunk_length; pad_i++) {
|
||||||
|
f->store_8(0);
|
||||||
|
}
|
||||||
|
|
||||||
f->close();
|
f->close();
|
||||||
} else {
|
} else {
|
||||||
|
|
Loading…
Reference in a new issue