Skip to content

Commit b05ae3e

Browse files
committed
Merge pull request #107193 from aaronfranke/gltf-align-accessor-buffer
GLTF: Align accessor buffer `byteOffset` to multiple of component size
2 parents 0569822 + 968744e commit b05ae3e

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
@@ -1156,6 +1156,12 @@ Error GLTFDocument::_encode_buffer_view(Ref<GLTFState> p_state, const double *p_
11561156
const int component_count = COMPONENT_COUNT_FOR_ACCESSOR_TYPE[p_accessor_type];
11571157
const int component_size = _get_component_type_size(p_component_type);
11581158
ERR_FAIL_COND_V(component_size == 0, FAILED);
1159+
// The byte offset of an accessor MUST be a multiple of the accessor’s component size.
1160+
// https://registry.khronos.org/glTF/specs/2.0/glTF-2.0.html#data-alignment
1161+
int64_t offset = p_byte_offset;
1162+
if (p_byte_offset % component_size != 0) {
1163+
offset += component_size - (p_byte_offset % component_size);
1164+
}
11591165

11601166
int skip_every = 0;
11611167
int skip_bytes = 0;
@@ -1185,7 +1191,7 @@ Error GLTFDocument::_encode_buffer_view(Ref<GLTFState> p_state, const double *p_
11851191

11861192
Ref<GLTFBufferView> bv;
11871193
bv.instantiate();
1188-
const uint32_t offset = bv->byte_offset = p_byte_offset;
1194+
bv->byte_offset = offset;
11891195
Vector<uint8_t> &gltf_buffer = p_state->buffers.write[0];
11901196

11911197
int stride = component_count * component_size;
@@ -1195,7 +1201,7 @@ Error GLTFDocument::_encode_buffer_view(Ref<GLTFState> p_state, const double *p_
11951201
//use to debug
11961202
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));
11971203

1198-
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));
1204+
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));
11991205

12001206
const int buffer_end = (stride * (p_count - 1)) + component_size;
12011207
// TODO define bv->byte_stride
@@ -1466,6 +1472,12 @@ Error GLTFDocument::_decode_buffer_view(Ref<GLTFState> p_state, double *p_dst, c
14661472
}
14671473

14681474
ERR_FAIL_INDEX_V(bv->buffer, p_state->buffers.size(), ERR_PARSE_ERROR);
1475+
if (bv->byte_offset % p_component_size != 0) {
1476+
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.");
1477+
}
1478+
if (p_byte_offset % p_component_size != 0) {
1479+
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.");
1480+
}
14691481

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

0 commit comments

Comments
 (0)