Saving progres on glb parsing. All checks of structures are done
This commit is contained in:
parent
24a8be3a75
commit
795f675e6a
@ -151,6 +151,7 @@ typedef struct {
|
||||
U64 offset;
|
||||
U64 stride; // Set to 0 when not specified. May replace with Option later
|
||||
/* name is overlooked */
|
||||
U64 usage_in_accessors;
|
||||
} GltfBufferView;
|
||||
|
||||
#include "../../../gen/l1/eve/VecGltfBufferView.h"
|
||||
@ -183,6 +184,43 @@ typedef struct {
|
||||
/* name is overlooked */
|
||||
} GltfAccessor;
|
||||
|
||||
U64 GltfAccessor_get_type_size(const GltfAccessor* self) {
|
||||
U64 cs;
|
||||
if (self->component_type == GltfAccessorComponentType_byte)
|
||||
cs = 1;
|
||||
else if (self->component_type == GltfAccessorComponentType_unsigned_byte)
|
||||
cs = 1;
|
||||
else if (self->component_type == GltfAccessorComponentType_short)
|
||||
cs = 2;
|
||||
else if (self->component_type == GltfAccessorComponentType_unsigned_short)
|
||||
cs = 2;
|
||||
else if (self->component_type == GltfAccessorComponentType_unsigned_int)
|
||||
cs = 4;
|
||||
else if (self->component_type == GltfAccessorComponentType_float)
|
||||
cs = 4;
|
||||
else
|
||||
assert(false);
|
||||
U64 cc;
|
||||
if (self->matrix_type == GltfAccessorMatrixType_scalar)
|
||||
cc = 1;
|
||||
else if (self->matrix_type == GltfAccessorMatrixType_vec2)
|
||||
cc = 2;
|
||||
else if (self->matrix_type == GltfAccessorMatrixType_vec3)
|
||||
cc = 3;
|
||||
else if (self->matrix_type == GltfAccessorMatrixType_vec4)
|
||||
cc = 4;
|
||||
else if (self->matrix_type == GltfAccessorMatrixType_mat2)
|
||||
cc = 4;
|
||||
else if (self->matrix_type == GltfAccessorMatrixType_mat3)
|
||||
cc = 9;
|
||||
else if (self->matrix_type == GltfAccessorMatrixType_mat4)
|
||||
cc = 16;
|
||||
else
|
||||
assert(false);
|
||||
assert(cc * cs <= 64);
|
||||
return cc * cs;
|
||||
}
|
||||
|
||||
#include "../../../gen/l1/eve/VecGltfAccessor.h"
|
||||
|
||||
typedef enum {
|
||||
@ -322,15 +360,6 @@ OptionGltfTextureInfo glb_file_json_dict_field_try_as_tex_info(const Json* dict,
|
||||
ResultGltfFileStructureOrVecU8 glb_file_get_structure(GLBFileSegments* segments) {
|
||||
const Json* json = &segments->gltf;
|
||||
|
||||
/* default_scene "scene" : Option<index into scenes>
|
||||
*
|
||||
* scenes "scenes" : Vec<Scene> {
|
||||
* if "scenes" field is not present, it counts as empty vector }
|
||||
*
|
||||
* nodes "nodes" : Vec<Node> {
|
||||
* if "nodes" field is not present, it counts as empty vector }
|
||||
*/
|
||||
|
||||
VecVecU8 external_files = VecVecU8_new();
|
||||
VecU8 ret_error = VecU8_new();
|
||||
OptionU64 default_scene = None_U64();
|
||||
@ -539,8 +568,10 @@ ResultGltfFileStructureOrVecU8 glb_file_get_structure(GLBFileSegments* segments)
|
||||
U64 byte_stride = opt_byte_stride.variant == Option_Some ? opt_byte_stride.some : 0;
|
||||
/* Ignoring an error */
|
||||
|
||||
VecGltfBufferView_append(&buffer_views, (GltfBufferView){.buffer = opt_buffer_id.some,
|
||||
.offset = byte_offset, .length = opt_byte_length.some, .stride = byte_stride});
|
||||
VecGltfBufferView_append(&buffer_views, (GltfBufferView){
|
||||
.buffer = opt_buffer_id.some,
|
||||
.offset = byte_offset, .length = opt_byte_length.some, .stride = byte_stride,
|
||||
.usage_in_accessors = 0});
|
||||
}
|
||||
}
|
||||
|
||||
@ -693,10 +724,12 @@ ResultGltfFileStructureOrVecU8 glb_file_get_structure(GLBFileSegments* segments)
|
||||
OptionFlt32 opt_metallic_factor = Json_dict_field_try_as_float(pbr_mr, cstr("metallicFactor"));
|
||||
if (opt_metallic_factor.some != Option_Some)
|
||||
metallic_factor = opt_metallic_factor.some;
|
||||
metallic_factor = MIN_float(MAX_float(0, metallic_factor), 1);
|
||||
|
||||
OptionFlt32 opt_roughness_factor = Json_dict_field_try_as_float(pbr_mr, cstr("roughnessFactor"));
|
||||
if (opt_roughness_factor.some != Option_Some)
|
||||
roughness_factor = opt_roughness_factor.some;
|
||||
roughness_factor = MIN_float(MAX_float(0, roughness_factor), 1);
|
||||
}
|
||||
|
||||
VecGltfMaterial_append(&materials, (GltfMaterial){.name = VecU8_from_span(name),
|
||||
@ -786,6 +819,142 @@ ResultGltfFileStructureOrVecU8 glb_file_get_structure(GLBFileSegments* segments)
|
||||
}
|
||||
|
||||
/* Now we are doing some checks and filling fields that were not directly specified */
|
||||
for (U64 i = 0; i < buffers.len; i++) {
|
||||
const GltfBuffer* buffer = &buffers.buf[i];
|
||||
if (!buffer->is_external) {
|
||||
if (buffer->length > segments->bin_segment.len) {
|
||||
ret_error = VecU8_fmt("Buffer corresponding to bin segment is larger than the actual segment");
|
||||
goto destroy_everything_return_error;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (U64 i = 0; i < accessors.len; i++) {
|
||||
const GltfAccessor* accessor = &accessors.buf[i];
|
||||
U64 bv = accessor->buffer_view;
|
||||
if (bv >= buffer_views.len) {
|
||||
ret_error = VecU8_fmt("Accessor %u has bufferView %u, it is out-of-bounds", i, bv);
|
||||
goto destroy_everything_return_error;
|
||||
}
|
||||
buffer_views.buf[bv].usage_in_accessors++;
|
||||
}
|
||||
|
||||
for (U64 bv = 0; bv < buffer_views.len; bv++) {
|
||||
const GltfBufferView* buffer_view = &buffer_views.buf[bv];
|
||||
if (buffer_view->usage_in_accessors >= 2 && buffer_view->stride == 0) {
|
||||
ret_error = VecU8_fmt("BufferView %u is used by several accessors, but stride isn't specified", bv);
|
||||
goto destroy_everything_return_error;
|
||||
}
|
||||
U64 buf_id = buffer_view->buffer;
|
||||
if (buf_id >= buffers.len) {
|
||||
ret_error = VecU8_fmt("BufferView %u has buffer %u, that is out-of-bounds of buffers array", bv, buf_id);
|
||||
goto destroy_everything_return_error;
|
||||
}
|
||||
const GltfBuffer* buffer = &buffers.buf[buf_id];
|
||||
|
||||
if (buffer_view->stride > 900 ||
|
||||
buffer_view->offset > 10000000000000000 || buffer_view->length > 10000000000000000) {
|
||||
ret_error = VecU8_fmt("Insane buffer view");
|
||||
goto destroy_everything_return_error;
|
||||
}
|
||||
|
||||
U64 view_end = buffer_view->offset + buffer_view->length;
|
||||
if (view_end > buffer->length) {
|
||||
ret_error = VecU8_fmt("BufferView %u is out-of-bound of it's Buffer %u", bv, buf_id);
|
||||
goto destroy_everything_return_error;
|
||||
}
|
||||
}
|
||||
|
||||
for (U64 i = 0; i < accessors.len; i++) {
|
||||
const GltfAccessor* accessor = &accessors.buf[i];
|
||||
if (accessor->count < 1) {
|
||||
ret_error = VecU8_fmt("Accessor %u has count 0", i);
|
||||
goto destroy_everything_return_error;
|
||||
}
|
||||
|
||||
U64 bv = accessor->buffer_view;
|
||||
const GltfBufferView* buffer_view = VecGltfBufferView_at(&buffer_views, bv);
|
||||
assert(buffer_view->stride <= 900);
|
||||
U64 my_type_size = GltfAccessor_get_type_size(accessor);
|
||||
U64 bv_stride = buffer_view->stride;
|
||||
assert(bv_stride <= 900);
|
||||
if (bv_stride == 0) {
|
||||
bv_stride = my_type_size;
|
||||
} else if (my_type_size > bv_stride) {
|
||||
ret_error = VecU8_fmt("O_o");
|
||||
goto destroy_everything_return_error;
|
||||
}
|
||||
if (accessor->count > 10000000000000 || accessor->offset > 10000000000000000) {
|
||||
ret_error = VecU8_fmt("Insane accessor");
|
||||
goto destroy_everything_return_error;
|
||||
}
|
||||
U64 accsr_end = accessor->offset + my_type_size + (accessor->count - 1) * bv_stride;
|
||||
if (accsr_end > buffer_view->length) {
|
||||
ret_error = VecU8_fmt("Accessor %u is out-of-bound of it's BufferView %u", i, bv);
|
||||
goto destroy_everything_return_error;
|
||||
}
|
||||
}
|
||||
|
||||
for (U64 i = 0; i < textures.len; i++) {
|
||||
const GltfTexture* texture = &textures.buf[i];
|
||||
if (texture->is_in_buffer_view) {
|
||||
U64 bv = texture->source_buffer_view;
|
||||
if (bv >= buffer_views.len) {
|
||||
ret_error = VecU8_fmt("$images[$textures[%u].source].bufferView %u is out-of-bounds", i, bv);
|
||||
goto destroy_everything_return_error;
|
||||
}
|
||||
if (buffer_views.buf[bv].usage_in_accessors > 0) {
|
||||
ret_error = VecU8_fmt("Please, don't use bufferView both by accessor and image, it's scary", i, bv);
|
||||
goto destroy_everything_return_error;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (U64 i = 0; i < materials.len; i++) {
|
||||
const GltfMaterial* material = &materials.buf[i];
|
||||
if (material->base_color_tex.variant == Option_Some) {
|
||||
if (material->base_color_tex.some.index >= textures.len) {
|
||||
ret_error = VecU8_fmt("Material's %u base color texture is out-of-bounds of textures array", i);
|
||||
goto destroy_everything_return_error;
|
||||
}
|
||||
if (material->base_color_tex.some.tex_coord_set_index > 0) {
|
||||
ret_error = VecU8_fmt("Sorry, texCoord bigger than 0 isn't supported");
|
||||
goto destroy_everything_return_error;
|
||||
}
|
||||
}
|
||||
if (material->normal_map_tex.variant == Option_Some) {
|
||||
if (material->normal_map_tex.some.index >= textures.len) {
|
||||
ret_error = VecU8_fmt("Material's %u normal map texture is out-of-bounds of textures array", i);
|
||||
goto destroy_everything_return_error;
|
||||
}
|
||||
if (material->normal_map_tex.some.tex_coord_set_index > 0) {
|
||||
ret_error = VecU8_fmt("Mmmmm NOPE");
|
||||
goto destroy_everything_return_error;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (U64 i = 0; i < meshes.len; i++) {
|
||||
const GltfMesh* mesh = &meshes.buf[i];
|
||||
for (U64 p = 0; p < mesh->primitives.len; p++) {
|
||||
const GltfMeshPrimitivePart* primitive = &mesh->primitives.buf[p];
|
||||
if (
|
||||
(primitive->position.variant == Option_Some && primitive->position.some >= accessors.len) ||
|
||||
(primitive->color_0.variant == Option_Some && primitive->color_0.some >= accessors.len) ||
|
||||
(primitive->texcoord_0.variant == Option_Some && primitive->texcoord_0.some >= accessors.len) ||
|
||||
(primitive->indices.variant == Option_Some && primitive->indices.some >= accessors.len)
|
||||
/* And whenever I fill like adding another attribute I have to come here and add a check */
|
||||
) {
|
||||
ret_error = VecU8_fmt("Primitive %u of Mesh %u has an attribute with out-of-bounds accessor", i, p);
|
||||
goto destroy_everything_return_error;
|
||||
}
|
||||
if (primitive->material.variant == Option_Some && primitive->material.some >= materials.len) {
|
||||
ret_error = VecU8_fmt("Mesh %u Primitiv %u material is out-of-bounds of materials array", i, p);
|
||||
goto destroy_everything_return_error;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (U64 i = 0; i < nodes.len; i++) {
|
||||
const GltfNode* node = &nodes.buf[i];
|
||||
for (size_t jjj = 0; jjj < node->children.len; jjj++) {
|
||||
@ -802,6 +971,10 @@ ResultGltfFileStructureOrVecU8 glb_file_get_structure(GLBFileSegments* segments)
|
||||
lower_node->has_parent = true;
|
||||
lower_node->parent = i;
|
||||
}
|
||||
if (node->mesh.variant == Option_Some && node->mesh.some >= meshes.len) {
|
||||
ret_error = VecU8_fmt("Node %u has msh %u that is out-of-bounds of meshes array", i, node->mesh.some);
|
||||
goto destroy_everything_return_error;
|
||||
}
|
||||
}
|
||||
|
||||
for (U64 s = 0; s < scenes.len; s++) {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user