diff --git a/3rdparty/cgltf/cgltf.h b/3rdparty/cgltf/cgltf.h index 3cdfee197..83ac8e767 100644 --- a/3rdparty/cgltf/cgltf.h +++ b/3rdparty/cgltf/cgltf.h @@ -362,13 +362,25 @@ typedef struct cgltf_pbr_specular_glossiness cgltf_float glossiness_factor; } cgltf_pbr_specular_glossiness; +typedef struct cgltf_clearcoat +{ + cgltf_texture_view clearcoat_texture; + cgltf_texture_view clearcoat_roughness_texture; + cgltf_texture_view clearcoat_normal_texture; + + cgltf_float clearcoat_factor; + cgltf_float clearcoat_roughness_factor; +} cgltf_clearcoat; + typedef struct cgltf_material { char* name; cgltf_bool has_pbr_metallic_roughness; cgltf_bool has_pbr_specular_glossiness; + cgltf_bool has_clearcoat; cgltf_pbr_metallic_roughness pbr_metallic_roughness; cgltf_pbr_specular_glossiness pbr_specular_glossiness; + cgltf_clearcoat clearcoat; cgltf_texture_view normal_texture; cgltf_texture_view occlusion_texture; cgltf_texture_view emissive_texture; @@ -385,6 +397,12 @@ typedef struct cgltf_morph_target { cgltf_size attributes_count; } cgltf_morph_target; +typedef struct cgltf_draco_mesh_compression { + cgltf_buffer_view* buffer_view; + cgltf_attribute* attributes; + cgltf_size attributes_count; +} cgltf_draco_mesh_compression; + typedef struct cgltf_primitive { cgltf_primitive_type type; cgltf_accessor* indices; @@ -394,6 +412,8 @@ typedef struct cgltf_primitive { cgltf_morph_target* targets; cgltf_size targets_count; cgltf_extras extras; + cgltf_bool has_draco_mesh_compression; + cgltf_draco_mesh_compression draco_mesh_compression; } cgltf_primitive; typedef struct cgltf_mesh { @@ -632,8 +652,8 @@ cgltf_result cgltf_copy_extras_json(const cgltf_data* data, const cgltf_extras* * */ -#ifdef __INTELLISENSE__ -/* This makes MSVC intellisense work. */ +#if defined(__INTELLISENSE__) || defined(__JETBRAINS_IDE__) +/* This makes MSVC/CLion intellisense work. */ #define CGLTF_IMPLEMENTATION #endif @@ -1850,8 +1870,6 @@ static cgltf_uint cgltf_component_read_uint(const void* in, cgltf_component_type default: return 0; } - - return 0; } static cgltf_bool cgltf_element_read_uint(const uint8_t* element, cgltf_type type, cgltf_component_type component_type, cgltf_uint* out, cgltf_size element_size) @@ -2171,6 +2189,32 @@ static int cgltf_parse_json_extras(jsmntok_t const* tokens, int i, const uint8_t return i; } +static int cgltf_parse_json_draco_mesh_compression(cgltf_options* options, jsmntok_t const* tokens, int i, const uint8_t* json_chunk, cgltf_draco_mesh_compression* out_draco_mesh_compression) +{ + CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT); + + int size = tokens[i].size; + ++i; + + for (int j = 0; j < size; ++j) + { + CGLTF_CHECK_KEY(tokens[i]); + + if (cgltf_json_strcmp(tokens + i, json_chunk, "attributes") == 0) + { + i = cgltf_parse_json_attribute_list(options, tokens, i + 1, json_chunk, &out_draco_mesh_compression->attributes, &out_draco_mesh_compression->attributes_count); + } + else if (cgltf_json_strcmp(tokens + i, json_chunk, "bufferView") == 0) + { + ++i; + out_draco_mesh_compression->buffer_view = CGLTF_PTRINDEX(cgltf_buffer_view, cgltf_json_to_int(tokens + i, json_chunk)); + ++i; + } + } + + return i; +} + static int cgltf_parse_json_primitive(cgltf_options* options, jsmntok_t const* tokens, int i, const uint8_t* json_chunk, cgltf_primitive* out_prim) { CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT); @@ -2229,6 +2273,35 @@ static int cgltf_parse_json_primitive(cgltf_options* options, jsmntok_t const* t { i = cgltf_parse_json_extras(tokens, i + 1, json_chunk, &out_prim->extras); } + else if (cgltf_json_strcmp(tokens + i, json_chunk, "extensions") == 0) + { + ++i; + + CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT); + + int extensions_size = tokens[i].size; + ++i; + + for (int k = 0; k < extensions_size; ++k) + { + CGLTF_CHECK_KEY(tokens[i]); + + if (cgltf_json_strcmp(tokens+i, json_chunk, "KHR_draco_mesh_compression") == 0) + { + out_prim->has_draco_mesh_compression = 1; + i = cgltf_parse_json_draco_mesh_compression(options, tokens, i + 1, json_chunk, &out_prim->draco_mesh_compression); + } + else + { + i = cgltf_skip_json(tokens, i+1); + } + + if (i < 0) + { + return i; + } + } + } else { i = cgltf_skip_json(tokens, i+1); @@ -2844,6 +2917,54 @@ static int cgltf_parse_json_pbr_specular_glossiness(jsmntok_t const* tokens, int return i; } +static int cgltf_parse_json_clearcoat(jsmntok_t const* tokens, int i, const uint8_t* json_chunk, cgltf_clearcoat* out_clearcoat) +{ + CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT); + int size = tokens[i].size; + ++i; + + for (int j = 0; j < size; ++j) + { + CGLTF_CHECK_KEY(tokens[i]); + + if (cgltf_json_strcmp(tokens+i, json_chunk, "clearcoatFactor") == 0) + { + ++i; + out_clearcoat->clearcoat_factor = cgltf_json_to_float(tokens + i, json_chunk); + ++i; + } + else if (cgltf_json_strcmp(tokens+i, json_chunk, "clearcoatRoughnessFactor") == 0) + { + ++i; + out_clearcoat->clearcoat_roughness_factor = cgltf_json_to_float(tokens + i, json_chunk); + ++i; + } + else if (cgltf_json_strcmp(tokens+i, json_chunk, "clearcoatTexture") == 0) + { + i = cgltf_parse_json_texture_view(tokens, i + 1, json_chunk, &out_clearcoat->clearcoat_texture); + } + else if (cgltf_json_strcmp(tokens+i, json_chunk, "clearcoatRoughnessTexture") == 0) + { + i = cgltf_parse_json_texture_view(tokens, i + 1, json_chunk, &out_clearcoat->clearcoat_roughness_texture); + } + else if (cgltf_json_strcmp(tokens+i, json_chunk, "clearcoatNormalTexture") == 0) + { + i = cgltf_parse_json_texture_view(tokens, i + 1, json_chunk, &out_clearcoat->clearcoat_normal_texture); + } + else + { + i = cgltf_skip_json(tokens, i+1); + } + + if (i < 0) + { + return i; + } + } + + return i; +} + static int cgltf_parse_json_image(cgltf_options* options, jsmntok_t const* tokens, int i, const uint8_t* json_chunk, cgltf_image* out_image) { CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT); @@ -3104,6 +3225,11 @@ static int cgltf_parse_json_material(cgltf_options* options, jsmntok_t const* to out_material->unlit = 1; i = cgltf_skip_json(tokens, i+1); } + else if (cgltf_json_strcmp(tokens+i, json_chunk, "KHR_materials_clearcoat") == 0) + { + out_material->has_clearcoat = 1; + i = cgltf_parse_json_clearcoat(tokens, i + 1, json_chunk, &out_material->clearcoat); + } else { i = cgltf_skip_json(tokens, i+1); @@ -4583,6 +4709,14 @@ static int cgltf_fixup_pointers(cgltf_data* data) CGLTF_PTRFIXUP_REQ(data->meshes[i].primitives[j].targets[k].attributes[m].data, data->accessors, data->accessors_count); } } + + if (data->meshes[i].primitives[j].has_draco_mesh_compression) { + CGLTF_PTRFIXUP_REQ(data->meshes[i].primitives[j].draco_mesh_compression.buffer_view, data->buffer_views, data->buffer_views_count); + for (cgltf_size m = 0; m < data->meshes[i].primitives[j].draco_mesh_compression.attributes_count; ++m) + { + CGLTF_PTRFIXUP_REQ(data->meshes[i].primitives[j].draco_mesh_compression.attributes[m].data, data->accessors, data->accessors_count); + } + } } } @@ -4629,6 +4763,10 @@ static int cgltf_fixup_pointers(cgltf_data* data) CGLTF_PTRFIXUP(data->materials[i].pbr_specular_glossiness.diffuse_texture.texture, data->textures, data->textures_count); CGLTF_PTRFIXUP(data->materials[i].pbr_specular_glossiness.specular_glossiness_texture.texture, data->textures, data->textures_count); + + CGLTF_PTRFIXUP(data->materials[i].clearcoat.clearcoat_texture.texture, data->textures, data->textures_count); + CGLTF_PTRFIXUP(data->materials[i].clearcoat.clearcoat_roughness_texture.texture, data->textures, data->textures_count); + CGLTF_PTRFIXUP(data->materials[i].clearcoat.clearcoat_normal_texture.texture, data->textures, data->textures_count); } for (cgltf_size i = 0; i < data->buffer_views_count; ++i) diff --git a/3rdparty/cgltf/cgltf_write.h b/3rdparty/cgltf/cgltf_write.h index ce90bcd86..5bd752436 100644 --- a/3rdparty/cgltf/cgltf_write.h +++ b/3rdparty/cgltf/cgltf_write.h @@ -57,9 +57,9 @@ cgltf_size cgltf_write(const cgltf_options* options, char* buffer, cgltf_size si * */ -#ifdef __INTELLISENSE__ -/* This makes MSVC intellisense work. */ -#define CGLTF_WRITE_IMPLEMENTATION +#if defined(__INTELLISENSE__) || defined(__JETBRAINS_IDE__) +/* This makes MSVC/CLion intellisense work. */ +#define CGLTF_IMPLEMENTATION #endif #ifdef CGLTF_WRITE_IMPLEMENTATION @@ -69,10 +69,12 @@ cgltf_size cgltf_write(const cgltf_options* options, char* buffer, cgltf_size si #include #include -#define CGLTF_EXTENSION_FLAG_TEXTURE_TRANSFORM (1 << 0) -#define CGLTF_EXTENSION_FLAG_MATERIALS_UNLIT (1 << 1) -#define CGLTF_EXTENSION_FLAG_SPECULAR_GLOSSINESS (1 << 2) -#define CGLTF_EXTENSION_FLAG_LIGHTS_PUNCTUAL (1 << 3) +#define CGLTF_EXTENSION_FLAG_TEXTURE_TRANSFORM (1 << 0) +#define CGLTF_EXTENSION_FLAG_MATERIALS_UNLIT (1 << 1) +#define CGLTF_EXTENSION_FLAG_SPECULAR_GLOSSINESS (1 << 2) +#define CGLTF_EXTENSION_FLAG_LIGHTS_PUNCTUAL (1 << 3) +#define CGLTF_EXTENSION_FLAG_DRACO_MESH_COMPRESSION (1 << 4) +#define CGLTF_EXTENSION_FLAG_MATERIALS_CLEARCOAT (1 << 5) typedef struct { char* buffer; @@ -86,6 +88,7 @@ typedef struct { const char* indent; int needs_comma; uint32_t extension_flags; + uint32_t required_extension_flags; } cgltf_write_context; #define CGLTF_MIN(a, b) (a < b ? a : b) @@ -405,6 +408,31 @@ static void cgltf_write_primitive(cgltf_write_context* context, const cgltf_prim cgltf_write_line(context, "]"); } cgltf_write_extras(context, &prim->extras); + + cgltf_bool has_extensions = prim->has_draco_mesh_compression; + if (has_extensions) { + cgltf_write_line(context, "\"extensions\": {"); + + if (prim->has_draco_mesh_compression) { + context->extension_flags |= CGLTF_EXTENSION_FLAG_DRACO_MESH_COMPRESSION; + if (prim->attributes_count == 0 || prim->indices == 0) { + context->required_extension_flags |= CGLTF_EXTENSION_FLAG_DRACO_MESH_COMPRESSION; + } + + cgltf_write_line(context, "\"KHR_draco_mesh_compression\": {"); + CGLTF_WRITE_IDXPROP("bufferView", prim->draco_mesh_compression.buffer_view, context->data->buffer_views); + cgltf_write_line(context, "\"attributes\": {"); + for (cgltf_size i = 0; i < prim->draco_mesh_compression.attributes_count; ++i) + { + const cgltf_attribute* attr = prim->draco_mesh_compression.attributes + i; + CGLTF_WRITE_IDXPROP(attr->name, attr->data, context->data->accessors); + } + cgltf_write_line(context, "}"); + cgltf_write_line(context, "}"); + } + + cgltf_write_line(context, "}"); + } } static void cgltf_write_mesh(cgltf_write_context* context, const cgltf_mesh* mesh) @@ -469,6 +497,11 @@ static void cgltf_write_material(cgltf_write_context* context, const cgltf_mater context->extension_flags |= CGLTF_EXTENSION_FLAG_SPECULAR_GLOSSINESS; } + if (material->has_clearcoat) + { + context->extension_flags |= CGLTF_EXTENSION_FLAG_MATERIALS_CLEARCOAT; + } + if (material->has_pbr_metallic_roughness) { const cgltf_pbr_metallic_roughness* params = &material->pbr_metallic_roughness; @@ -485,9 +518,20 @@ static void cgltf_write_material(cgltf_write_context* context, const cgltf_mater cgltf_write_line(context, "}"); } - if (material->unlit || material->has_pbr_specular_glossiness) + if (material->unlit || material->has_pbr_specular_glossiness || material->has_clearcoat) { cgltf_write_line(context, "\"extensions\": {"); + if (material->has_clearcoat) + { + const cgltf_clearcoat* params = &material->clearcoat; + cgltf_write_line(context, "\"KHR_materials_clearcoat\": {"); + CGLTF_WRITE_TEXTURE_INFO("clearcoatTexture", params->clearcoat_texture); + CGLTF_WRITE_TEXTURE_INFO("clearcoatRoughnessTexture", params->clearcoat_roughness_texture); + CGLTF_WRITE_TEXTURE_INFO("clearcoatNormalTexture", params->clearcoat_normal_texture); + cgltf_write_floatprop(context, "clearcoatFactor", params->clearcoat_factor, 0.0f); + cgltf_write_floatprop(context, "clearcoatRoughnessFactor", params->clearcoat_roughness_factor, 0.0f); + cgltf_write_line(context, "}"); + } if (material->has_pbr_specular_glossiness) { const cgltf_pbr_specular_glossiness* params = &material->pbr_specular_glossiness; @@ -836,6 +880,28 @@ cgltf_result cgltf_write_file(const cgltf_options* options, const char* path, co return cgltf_result_success; } +static void cgltf_write_extensions(cgltf_write_context* context, uint32_t extension_flags) +{ + if (extension_flags & CGLTF_EXTENSION_FLAG_TEXTURE_TRANSFORM) { + cgltf_write_stritem(context, "KHR_texture_transform"); + } + if (extension_flags & CGLTF_EXTENSION_FLAG_MATERIALS_UNLIT) { + cgltf_write_stritem(context, "KHR_materials_unlit"); + } + if (extension_flags & CGLTF_EXTENSION_FLAG_SPECULAR_GLOSSINESS) { + cgltf_write_stritem(context, "KHR_materials_pbrSpecularGlossiness"); + } + if (extension_flags & CGLTF_EXTENSION_FLAG_LIGHTS_PUNCTUAL) { + cgltf_write_stritem(context, "KHR_lights_punctual"); + } + if (extension_flags & CGLTF_EXTENSION_FLAG_DRACO_MESH_COMPRESSION) { + cgltf_write_stritem(context, "KHR_draco_mesh_compression"); + } + if (extension_flags & CGLTF_EXTENSION_FLAG_MATERIALS_CLEARCOAT) { + cgltf_write_stritem(context, "KHR_materials_clearcoat"); + } +} + cgltf_size cgltf_write(const cgltf_options* options, char* buffer, cgltf_size size, const cgltf_data* data) { (void)options; @@ -850,6 +916,7 @@ cgltf_size cgltf_write(const cgltf_options* options, char* buffer, cgltf_size si ctx.indent = " "; ctx.needs_comma = 0; ctx.extension_flags = 0; + ctx.required_extension_flags = 0; cgltf_write_context* context = &ctx; @@ -1007,18 +1074,13 @@ cgltf_size cgltf_write(const cgltf_options* options, char* buffer, cgltf_size si if (context->extension_flags != 0) { cgltf_write_line(context, "\"extensionsUsed\": ["); - if (context->extension_flags & CGLTF_EXTENSION_FLAG_TEXTURE_TRANSFORM) { - cgltf_write_stritem(context, "KHR_texture_transform"); - } - if (context->extension_flags & CGLTF_EXTENSION_FLAG_MATERIALS_UNLIT) { - cgltf_write_stritem(context, "KHR_materials_unlit"); - } - if (context->extension_flags & CGLTF_EXTENSION_FLAG_SPECULAR_GLOSSINESS) { - cgltf_write_stritem(context, "KHR_materials_pbrSpecularGlossiness"); - } - if (context->extension_flags & CGLTF_EXTENSION_FLAG_LIGHTS_PUNCTUAL) { - cgltf_write_stritem(context, "KHR_lights_punctual"); - } + cgltf_write_extensions(context, context->extension_flags); + cgltf_write_line(context, "]"); + } + + if (context->required_extension_flags != 0) { + cgltf_write_line(context, "\"extensionsRequired\": ["); + cgltf_write_extensions(context, context->required_extension_flags); cgltf_write_line(context, "]"); }