From de9828bc6419064c302546313ce8ff5eac6cd703 Mon Sep 17 00:00:00 2001 From: Arseny Kapoulkine Date: Wed, 3 Dec 2025 08:39:07 -0800 Subject: [PATCH] Implement parsing support for KHR_meshopt_compression draft Because the JSON structure matches that of EXT_meshopt_compression, and both structures can't be present on the same buffer view, we reuse the existing C structure and merely tag the object "is_khr", which could be useful to decoding -- although the updated vertex data will be automatically decompressed with a meshoptimized update without code changes. In addition to vertex encoding v1, which will be decoded automatically, KHR_meshopt_compression adds support for color filters which requires an extra enum entry. --- cgltf.h | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/cgltf.h b/cgltf.h index 8d84e6d..316a11d 100644 --- a/cgltf.h +++ b/cgltf.h @@ -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 @@ -1661,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); } } @@ -5118,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 @@ -5228,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++]));