From a1bf8d9c752041423a245a21bce73274a9215c9e Mon Sep 17 00:00:00 2001 From: Ray Date: Sun, 29 Mar 2026 21:17:51 +0200 Subject: [PATCH] Update cgltf.h --- src/external/cgltf.h | 211 +++++++++++++++++++++++++++++++++++++------ 1 file changed, 185 insertions(+), 26 deletions(-) diff --git a/src/external/cgltf.h b/src/external/cgltf.h index 36fd644e1..316a11dfd 100644 --- a/src/external/cgltf.h +++ b/src/external/cgltf.h @@ -1,7 +1,7 @@ /** * cgltf - a single-file glTF 2.0 parser written in C99. * - * Version: 1.14 + * Version: 1.15 * * Website: https://github.com/jkuhlmann/cgltf * @@ -141,7 +141,7 @@ typedef struct cgltf_memory_options typedef struct cgltf_file_options { cgltf_result(*read)(const struct cgltf_memory_options* memory_options, const struct cgltf_file_options* file_options, const char* path, cgltf_size* size, void** data); - void (*release)(const struct cgltf_memory_options* memory_options, const struct cgltf_file_options* file_options, void* data); + void (*release)(const struct cgltf_memory_options* memory_options, const struct cgltf_file_options* file_options, void* data, cgltf_size size); void* user_data; } cgltf_file_options; @@ -296,6 +296,7 @@ typedef enum cgltf_meshopt_compression_filter { cgltf_meshopt_compression_filter_octahedral, cgltf_meshopt_compression_filter_quaternion, cgltf_meshopt_compression_filter_exponential, + cgltf_meshopt_compression_filter_color, cgltf_meshopt_compression_filter_max_enum } cgltf_meshopt_compression_filter; @@ -308,6 +309,7 @@ typedef struct cgltf_meshopt_compression cgltf_size count; cgltf_meshopt_compression_mode mode; cgltf_meshopt_compression_filter filter; + cgltf_bool is_khr; } cgltf_meshopt_compression; typedef struct cgltf_buffer_view @@ -376,13 +378,29 @@ typedef struct cgltf_image cgltf_extension* extensions; } cgltf_image; +typedef enum cgltf_filter_type { + cgltf_filter_type_undefined = 0, + cgltf_filter_type_nearest = 9728, + cgltf_filter_type_linear = 9729, + cgltf_filter_type_nearest_mipmap_nearest = 9984, + cgltf_filter_type_linear_mipmap_nearest = 9985, + cgltf_filter_type_nearest_mipmap_linear = 9986, + cgltf_filter_type_linear_mipmap_linear = 9987 +} cgltf_filter_type; + +typedef enum cgltf_wrap_mode { + cgltf_wrap_mode_clamp_to_edge = 33071, + cgltf_wrap_mode_mirrored_repeat = 33648, + cgltf_wrap_mode_repeat = 10497 +} cgltf_wrap_mode; + typedef struct cgltf_sampler { char* name; - cgltf_int mag_filter; - cgltf_int min_filter; - cgltf_int wrap_s; - cgltf_int wrap_t; + cgltf_filter_type mag_filter; + cgltf_filter_type min_filter; + cgltf_wrap_mode wrap_s; + cgltf_wrap_mode wrap_t; cgltf_extras extras; cgltf_size extensions_count; cgltf_extension* extensions; @@ -500,6 +518,14 @@ typedef struct cgltf_iridescence cgltf_texture_view iridescence_thickness_texture; } cgltf_iridescence; +typedef struct cgltf_diffuse_transmission +{ + cgltf_texture_view diffuse_transmission_texture; + cgltf_float diffuse_transmission_factor; + cgltf_float diffuse_transmission_color_factor[3]; + cgltf_texture_view diffuse_transmission_color_texture; +} cgltf_diffuse_transmission; + typedef struct cgltf_anisotropy { cgltf_float anisotropy_strength; @@ -525,6 +551,7 @@ typedef struct cgltf_material cgltf_bool has_sheen; cgltf_bool has_emissive_strength; cgltf_bool has_iridescence; + cgltf_bool has_diffuse_transmission; cgltf_bool has_anisotropy; cgltf_bool has_dispersion; cgltf_pbr_metallic_roughness pbr_metallic_roughness; @@ -537,6 +564,7 @@ typedef struct cgltf_material cgltf_volume volume; cgltf_emissive_strength emissive_strength; cgltf_iridescence iridescence; + cgltf_diffuse_transmission diffuse_transmission; cgltf_anisotropy anisotropy; cgltf_dispersion dispersion; cgltf_texture_view normal_texture; @@ -743,6 +771,7 @@ typedef struct cgltf_data { cgltf_file_type file_type; void* file_data; + cgltf_size file_size; cgltf_asset asset; @@ -844,6 +873,8 @@ void cgltf_node_transform_world(const cgltf_node* node, cgltf_float* out_matrix) const uint8_t* cgltf_buffer_view_data(const cgltf_buffer_view* view); +const cgltf_accessor* cgltf_find_accessor(const cgltf_primitive* prim, cgltf_attribute_type type, cgltf_int index); + cgltf_bool cgltf_accessor_read_float(const cgltf_accessor* accessor, cgltf_size index, cgltf_float* out, cgltf_size element_size); cgltf_bool cgltf_accessor_read_uint(const cgltf_accessor* accessor, cgltf_size index, cgltf_uint* out, cgltf_size element_size); cgltf_size cgltf_accessor_read_index(const cgltf_accessor* accessor, cgltf_size index); @@ -1071,9 +1102,10 @@ static cgltf_result cgltf_default_file_read(const struct cgltf_memory_options* m return cgltf_result_success; } -static void cgltf_default_file_release(const struct cgltf_memory_options* memory_options, const struct cgltf_file_options* file_options, void* data) +static void cgltf_default_file_release(const struct cgltf_memory_options* memory_options, const struct cgltf_file_options* file_options, void* data, cgltf_size size) { (void)file_options; + (void)size; void (*memfree)(void*, void*) = memory_options->free_func ? memory_options->free_func : &cgltf_default_free; memfree(memory_options->user_data, data); } @@ -1220,7 +1252,7 @@ cgltf_result cgltf_parse_file(const cgltf_options* options, const char* path, cg } cgltf_result (*file_read)(const struct cgltf_memory_options*, const struct cgltf_file_options*, const char*, cgltf_size*, void**) = options->file.read ? options->file.read : &cgltf_default_file_read; - void (*file_release)(const struct cgltf_memory_options*, const struct cgltf_file_options*, void* data) = options->file.release ? options->file.release : cgltf_default_file_release; + void (*file_release)(const struct cgltf_memory_options*, const struct cgltf_file_options*, void* data, cgltf_size size) = options->file.release ? options->file.release : cgltf_default_file_release; void* file_data = NULL; cgltf_size file_size = 0; @@ -1234,11 +1266,12 @@ cgltf_result cgltf_parse_file(const cgltf_options* options, const char* path, cg if (result != cgltf_result_success) { - file_release(&options->memory, &options->file, file_data); + file_release(&options->memory, &options->file, file_data, file_size); return result; } (*out_data)->file_data = file_data; + (*out_data)->file_size = file_size; return cgltf_result_success; } @@ -1630,8 +1663,8 @@ cgltf_result cgltf_validate(cgltf_data* data) CGLTF_ASSERT_IF((mc->mode == cgltf_meshopt_compression_mode_triangles || mc->mode == cgltf_meshopt_compression_mode_indices) && mc->filter != cgltf_meshopt_compression_filter_none, cgltf_result_invalid_gltf); CGLTF_ASSERT_IF(mc->filter == cgltf_meshopt_compression_filter_octahedral && mc->stride != 4 && mc->stride != 8, cgltf_result_invalid_gltf); - CGLTF_ASSERT_IF(mc->filter == cgltf_meshopt_compression_filter_quaternion && mc->stride != 8, cgltf_result_invalid_gltf); + CGLTF_ASSERT_IF(mc->filter == cgltf_meshopt_compression_filter_color && mc->stride != 4 && mc->stride != 8, cgltf_result_invalid_gltf); } } @@ -1822,7 +1855,7 @@ void cgltf_free(cgltf_data* data) return; } - void (*file_release)(const struct cgltf_memory_options*, const struct cgltf_file_options*, void* data) = data->file.release ? data->file.release : cgltf_default_file_release; + void (*file_release)(const struct cgltf_memory_options*, const struct cgltf_file_options*, void* data, cgltf_size size) = data->file.release ? data->file.release : cgltf_default_file_release; data->memory.free_func(data->memory.user_data, data->asset.copyright); data->memory.free_func(data->memory.user_data, data->asset.generator); @@ -1857,7 +1890,7 @@ void cgltf_free(cgltf_data* data) if (data->buffers[i].data_free_method == cgltf_data_free_method_file_release) { - file_release(&data->memory, &data->file, data->buffers[i].data); + file_release(&data->memory, &data->file, data->buffers[i].data, data->buffers[i].size); } else if (data->buffers[i].data_free_method == cgltf_data_free_method_memory_free) { @@ -2096,7 +2129,7 @@ void cgltf_free(cgltf_data* data) data->memory.free_func(data->memory.user_data, data->extensions_required); - file_release(&data->memory, &data->file, data->file_data); + file_release(&data->memory, &data->file, data->file_data, data->file_size); data->memory.free_func(data->memory.user_data, data); } @@ -2312,11 +2345,58 @@ const uint8_t* cgltf_buffer_view_data(const cgltf_buffer_view* view) return result; } +const cgltf_accessor* cgltf_find_accessor(const cgltf_primitive* prim, cgltf_attribute_type type, cgltf_int index) +{ + for (cgltf_size i = 0; i < prim->attributes_count; ++i) + { + const cgltf_attribute* attr = &prim->attributes[i]; + if (attr->type == type && attr->index == index) + return attr->data; + } + + return NULL; +} + +static const uint8_t* cgltf_find_sparse_index(const cgltf_accessor* accessor, cgltf_size needle) +{ + const cgltf_accessor_sparse* sparse = &accessor->sparse; + const uint8_t* index_data = cgltf_buffer_view_data(sparse->indices_buffer_view); + const uint8_t* value_data = cgltf_buffer_view_data(sparse->values_buffer_view); + + if (index_data == NULL || value_data == NULL) + return NULL; + + index_data += sparse->indices_byte_offset; + value_data += sparse->values_byte_offset; + + cgltf_size index_stride = cgltf_component_size(sparse->indices_component_type); + + cgltf_size offset = 0; + cgltf_size length = sparse->count; + + while (length) + { + cgltf_size rem = length % 2; + length /= 2; + + cgltf_size index = cgltf_component_read_index(index_data + (offset + length) * index_stride, sparse->indices_component_type); + offset += index < needle ? length + rem : 0; + } + + if (offset == sparse->count) + return NULL; + + cgltf_size index = cgltf_component_read_index(index_data + offset * index_stride, sparse->indices_component_type); + return index == needle ? value_data + offset * accessor->stride : NULL; +} + cgltf_bool cgltf_accessor_read_float(const cgltf_accessor* accessor, cgltf_size index, cgltf_float* out, cgltf_size element_size) { if (accessor->is_sparse) { - return 0; + const uint8_t* element = cgltf_find_sparse_index(accessor, index); + if (element) + return cgltf_element_read_float(element, accessor->type, accessor->component_type, accessor->normalized, out, element_size); } if (accessor->buffer_view == NULL) { @@ -2460,11 +2540,13 @@ cgltf_bool cgltf_accessor_read_uint(const cgltf_accessor* accessor, cgltf_size i { if (accessor->is_sparse) { - return 0; + const uint8_t* element = cgltf_find_sparse_index(accessor, index); + if (element) + return cgltf_element_read_uint(element, accessor->type, accessor->component_type, out, element_size); } if (accessor->buffer_view == NULL) { - memset(out, 0, element_size * sizeof( cgltf_uint )); + memset(out, 0, element_size * sizeof(cgltf_uint)); return 1; } const uint8_t* element = cgltf_buffer_view_data(accessor->buffer_view); @@ -2480,7 +2562,9 @@ cgltf_size cgltf_accessor_read_index(const cgltf_accessor* accessor, cgltf_size { if (accessor->is_sparse) { - return 0; // This is an error case, but we can't communicate the error with existing interface. + const uint8_t* element = cgltf_find_sparse_index(accessor, index); + if (element) + return cgltf_component_read_index(element, accessor->component_type); } if (accessor->buffer_view == NULL) { @@ -2598,7 +2682,10 @@ cgltf_size cgltf_accessor_unpack_indices(const cgltf_accessor* accessor, void* o return accessor->count; } - index_count = accessor->count < index_count ? accessor->count : index_count; + cgltf_size numbers_per_element = cgltf_num_components(accessor->type); + cgltf_size available_numbers = accessor->count * numbers_per_element; + + index_count = available_numbers < index_count ? available_numbers : index_count; cgltf_size index_component_size = cgltf_component_size(accessor->component_type); if (accessor->is_sparse) @@ -2620,15 +2707,23 @@ cgltf_size cgltf_accessor_unpack_indices(const cgltf_accessor* accessor, void* o } element += accessor->offset; - if (index_component_size == out_component_size && accessor->stride == out_component_size) + if (index_component_size == out_component_size && accessor->stride == out_component_size * numbers_per_element) { memcpy(out, element, index_count * index_component_size); return index_count; } + // Data couldn't be copied with memcpy due to stride being larger than the component size. + // OR // The component size of the output array is larger than the component size of the index data, so index data will be padded. switch (out_component_size) { + case 1: + for (cgltf_size index = 0; index < index_count; index++, element += accessor->stride) + { + ((uint8_t*)out)[index] = (uint8_t)cgltf_component_read_index(element, accessor->component_type); + } + break; case 2: for (cgltf_size index = 0; index < index_count; index++, element += accessor->stride) { @@ -2642,7 +2737,7 @@ cgltf_size cgltf_accessor_unpack_indices(const cgltf_accessor* accessor, void* o } break; default: - break; + return 0; } return index_count; @@ -4278,6 +4373,52 @@ static int cgltf_parse_json_iridescence(cgltf_options* options, jsmntok_t const* return i; } +static int cgltf_parse_json_diffuse_transmission(cgltf_options* options, jsmntok_t const* tokens, int i, const uint8_t* json_chunk, cgltf_diffuse_transmission* out_diff_transmission) +{ + CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT); + int size = tokens[i].size; + ++i; + + // Defaults + cgltf_fill_float_array(out_diff_transmission->diffuse_transmission_color_factor, 3, 1.0f); + out_diff_transmission->diffuse_transmission_factor = 0.f; + + for (int j = 0; j < size; ++j) + { + CGLTF_CHECK_KEY(tokens[i]); + + if (cgltf_json_strcmp(tokens + i, json_chunk, "diffuseTransmissionFactor") == 0) + { + ++i; + out_diff_transmission->diffuse_transmission_factor = cgltf_json_to_float(tokens + i, json_chunk); + ++i; + } + else if (cgltf_json_strcmp(tokens + i, json_chunk, "diffuseTransmissionTexture") == 0) + { + i = cgltf_parse_json_texture_view(options, tokens, i + 1, json_chunk, &out_diff_transmission->diffuse_transmission_texture); + } + else if (cgltf_json_strcmp(tokens + i, json_chunk, "diffuseTransmissionColorFactor") == 0) + { + i = cgltf_parse_json_float_array(tokens, i + 1, json_chunk, out_diff_transmission->diffuse_transmission_color_factor, 3); + } + else if (cgltf_json_strcmp(tokens + i, json_chunk, "diffuseTransmissionColorTexture") == 0) + { + i = cgltf_parse_json_texture_view(options, tokens, i + 1, json_chunk, &out_diff_transmission->diffuse_transmission_color_texture); + } + else + { + i = cgltf_skip_json(tokens, i + 1); + } + + if (i < 0) + { + return i; + } + } + + return i; +} + static int cgltf_parse_json_anisotropy(cgltf_options* options, jsmntok_t const* tokens, int i, const uint8_t* json_chunk, cgltf_anisotropy* out_anisotropy) { CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT); @@ -4406,8 +4547,8 @@ static int cgltf_parse_json_sampler(cgltf_options* options, jsmntok_t const* tok (void)options; CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT); - out_sampler->wrap_s = 10497; - out_sampler->wrap_t = 10497; + out_sampler->wrap_s = cgltf_wrap_mode_repeat; + out_sampler->wrap_t = cgltf_wrap_mode_repeat; int size = tokens[i].size; ++i; @@ -4424,28 +4565,28 @@ static int cgltf_parse_json_sampler(cgltf_options* options, jsmntok_t const* tok { ++i; out_sampler->mag_filter - = cgltf_json_to_int(tokens + i, json_chunk); + = (cgltf_filter_type)cgltf_json_to_int(tokens + i, json_chunk); ++i; } else if (cgltf_json_strcmp(tokens + i, json_chunk, "minFilter") == 0) { ++i; out_sampler->min_filter - = cgltf_json_to_int(tokens + i, json_chunk); + = (cgltf_filter_type)cgltf_json_to_int(tokens + i, json_chunk); ++i; } else if (cgltf_json_strcmp(tokens + i, json_chunk, "wrapS") == 0) { ++i; out_sampler->wrap_s - = cgltf_json_to_int(tokens + i, json_chunk); + = (cgltf_wrap_mode)cgltf_json_to_int(tokens + i, json_chunk); ++i; } else if (cgltf_json_strcmp(tokens + i, json_chunk, "wrapT") == 0) { ++i; out_sampler->wrap_t - = cgltf_json_to_int(tokens + i, json_chunk); + = (cgltf_wrap_mode)cgltf_json_to_int(tokens + i, json_chunk); ++i; } else if (cgltf_json_strcmp(tokens + i, json_chunk, "extras") == 0) @@ -4766,6 +4907,11 @@ static int cgltf_parse_json_material(cgltf_options* options, jsmntok_t const* to out_material->has_iridescence = 1; i = cgltf_parse_json_iridescence(options, tokens, i + 1, json_chunk, &out_material->iridescence); } + else if (cgltf_json_strcmp(tokens + i, json_chunk, "KHR_materials_diffuse_transmission") == 0) + { + out_material->has_diffuse_transmission = 1; + i = cgltf_parse_json_diffuse_transmission(options, tokens, i + 1, json_chunk, &out_material->diffuse_transmission); + } else if (cgltf_json_strcmp(tokens + i, json_chunk, "KHR_materials_anisotropy") == 0) { out_material->has_anisotropy = 1; @@ -4974,6 +5120,10 @@ static int cgltf_parse_json_meshopt_compression(cgltf_options* options, jsmntok_ { out_meshopt_compression->filter = cgltf_meshopt_compression_filter_exponential; } + else if (cgltf_json_strcmp(tokens+i, json_chunk, "COLOR") == 0) + { + out_meshopt_compression->filter = cgltf_meshopt_compression_filter_color; + } ++i; } else @@ -5084,6 +5234,12 @@ static int cgltf_parse_json_buffer_view(cgltf_options* options, jsmntok_t const* out_buffer_view->has_meshopt_compression = 1; i = cgltf_parse_json_meshopt_compression(options, tokens, i + 1, json_chunk, &out_buffer_view->meshopt_compression); } + else if (cgltf_json_strcmp(tokens+i, json_chunk, "KHR_meshopt_compression") == 0) + { + out_buffer_view->has_meshopt_compression = 1; + out_buffer_view->meshopt_compression.is_khr = 1; + i = cgltf_parse_json_meshopt_compression(options, tokens, i + 1, json_chunk, &out_buffer_view->meshopt_compression); + } else { i = cgltf_parse_json_unprocessed_extension(options, tokens, i, json_chunk, &(out_buffer_view->extensions[out_buffer_view->extensions_count++])); @@ -6629,6 +6785,9 @@ static int cgltf_fixup_pointers(cgltf_data* data) CGLTF_PTRFIXUP(data->materials[i].iridescence.iridescence_texture.texture, data->textures, data->textures_count); CGLTF_PTRFIXUP(data->materials[i].iridescence.iridescence_thickness_texture.texture, data->textures, data->textures_count); + CGLTF_PTRFIXUP(data->materials[i].diffuse_transmission.diffuse_transmission_texture.texture, data->textures, data->textures_count); + CGLTF_PTRFIXUP(data->materials[i].diffuse_transmission.diffuse_transmission_color_texture.texture, data->textures, data->textures_count); + CGLTF_PTRFIXUP(data->materials[i].anisotropy.anisotropy_texture.texture, data->textures, data->textures_count); }