Skip to content

Commit 968744e

Browse files
committed
GLTF: Align accessor buffer byteOffset to multiple of component size
1 parent 5dd7696 commit 968744e

File tree

1 file changed

+14
-2
lines changed

1 file changed

+14
-2
lines changed

modules/gltf/gltf_document.cpp

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1152,6 +1152,12 @@ Error GLTFDocument::_encode_buffer_view(Ref<GLTFState> p_state, const double *p_
11521152
const int component_count = COMPONENT_COUNT_FOR_ACCESSOR_TYPE[p_accessor_type];
11531153
const int component_size = _get_component_type_size(p_component_type);
11541154
ERR_FAIL_COND_V(component_size == 0, FAILED);
1155+
// The byte offset of an accessor MUST be a multiple of the accessor’s component size.
1156+
// https://registry.khronos.org/glTF/specs/2.0/glTF-2.0.html#data-alignment
1157+
int64_t offset = p_byte_offset;
1158+
if (p_byte_offset % component_size != 0) {
1159+
offset += component_size - (p_byte_offset % component_size);
1160+
}
11551161

11561162
int skip_every = 0;
11571163
int skip_bytes = 0;
@@ -1181,7 +1187,7 @@ Error GLTFDocument::_encode_buffer_view(Ref<GLTFState> p_state, const double *p_
11811187

11821188
Ref<GLTFBufferView> bv;
11831189
bv.instantiate();
1184-
const uint32_t offset = bv->byte_offset = p_byte_offset;
1190+
bv->byte_offset = offset;
11851191
Vector<uint8_t> &gltf_buffer = p_state->buffers.write[0];
11861192

11871193
int stride = component_count * component_size;
@@ -1191,7 +1197,7 @@ Error GLTFDocument::_encode_buffer_view(Ref<GLTFState> p_state, const double *p_
11911197
//use to debug
11921198
print_verbose("glTF: encoding 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));
11931199

1194-
print_verbose("glTF: encoding accessor offset " + itos(p_byte_offset) + " view offset: " + itos(bv->byte_offset) + " total buffer len: " + itos(gltf_buffer.size()) + " view len " + itos(bv->byte_length));
1200+
print_verbose("glTF: encoding accessor offset " + itos(offset) + " view offset: " + itos(bv->byte_offset) + " total buffer len: " + itos(gltf_buffer.size()) + " view len " + itos(bv->byte_length));
11951201

11961202
const int buffer_end = (stride * (p_count - 1)) + component_size;
11971203
// TODO define bv->byte_stride
@@ -1462,6 +1468,12 @@ Error GLTFDocument::_decode_buffer_view(Ref<GLTFState> p_state, double *p_dst, c
14621468
}
14631469

14641470
ERR_FAIL_INDEX_V(bv->buffer, p_state->buffers.size(), ERR_PARSE_ERROR);
1471+
if (bv->byte_offset % p_component_size != 0) {
1472+
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.");
1473+
}
1474+
if (p_byte_offset % p_component_size != 0) {
1475+
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.");
1476+
}
14651477

14661478
const uint32_t offset = bv->byte_offset + p_byte_offset;
14671479
Vector<uint8_t> buffer = p_state->buffers[bv->buffer]; //copy on write, so no performance hit

0 commit comments

Comments
 (0)