Updated cgltf.

This commit is contained in:
Бранимир Караџић 2022-10-02 22:07:31 -07:00
parent d9c5475cf1
commit c25aab33eb
2 changed files with 262 additions and 98 deletions

237
3rdparty/cgltf/cgltf.h vendored
View File

@ -1,7 +1,7 @@
/**
* cgltf - a single-file glTF 2.0 parser written in C99.
*
* Version: 1.12
* Version: 1.13
*
* Website: https://github.com/jkuhlmann/cgltf
*
@ -80,13 +80,9 @@
* `cgltf_accessor_read_index` is similar to its floating-point counterpart, but it returns size_t
* and only works with single-component data types.
*
* `cgltf_result cgltf_copy_extras_json(const cgltf_data*, const cgltf_extras*,
* char* dest, cgltf_size* dest_size)` allows users to retrieve the "extras" data that
* can be attached to many glTF objects (which can be arbitrary JSON data). The
* `cgltf_extras` struct stores the offsets of the start and end of the extras JSON data
* as it appears in the complete glTF JSON data. This function copies the extras data
* into the provided buffer. If `dest` is NULL, the length of the data is written into
* `dest_size`. You can then parse this data using your own JSON parser
* `cgltf_copy_extras_json` allows users to retrieve the "extras" data that can be attached to many
* glTF objects (which can be arbitrary JSON data). This is a legacy function, consider using
* cgltf_extras::data directly instead. You can parse this data using your own JSON parser
* or, if you've included the cgltf implementation using the integrated JSMN JSON parser.
*/
#ifndef CGLTF_H_INCLUDED__
@ -256,8 +252,10 @@ typedef enum cgltf_data_free_method {
} cgltf_data_free_method;
typedef struct cgltf_extras {
cgltf_size start_offset;
cgltf_size end_offset;
cgltf_size start_offset; /* this field is deprecated and will be removed in the future; use data instead */
cgltf_size end_offset; /* this field is deprecated and will be removed in the future; use data instead */
char* data;
} cgltf_extras;
typedef struct cgltf_extension {
@ -432,8 +430,6 @@ typedef struct cgltf_pbr_metallic_roughness
cgltf_float base_color_factor[4];
cgltf_float metallic_factor;
cgltf_float roughness_factor;
cgltf_extras extras;
} cgltf_pbr_metallic_roughness;
typedef struct cgltf_pbr_specular_glossiness
@ -841,6 +837,7 @@ cgltf_size cgltf_num_components(cgltf_type type);
cgltf_size cgltf_accessor_unpack_floats(const cgltf_accessor* accessor, cgltf_float* out, cgltf_size float_count);
/* this function is deprecated and will be removed in the future; use cgltf_extras::data instead */
cgltf_result cgltf_copy_extras_json(const cgltf_data* data, const cgltf_extras* extras, char* dest, cgltf_size* dest_size);
#ifdef __cplusplus
@ -924,12 +921,15 @@ static int jsmn_parse(jsmn_parser *parser, const char *js, size_t len, jsmntok_t
*/
#ifndef CGLTF_CONSTS
static const cgltf_size GlbHeaderSize = 12;
static const cgltf_size GlbChunkHeaderSize = 8;
static const uint32_t GlbVersion = 2;
static const uint32_t GlbMagic = 0x46546C67;
static const uint32_t GlbMagicJsonChunk = 0x4E4F534A;
static const uint32_t GlbMagicBinChunk = 0x004E4942;
#define CGLTF_CONSTS
#endif
#ifndef CGLTF_MALLOC
#define CGLTF_MALLOC(size) malloc(size)
@ -1745,7 +1745,12 @@ cgltf_result cgltf_copy_extras_json(const cgltf_data* data, const cgltf_extras*
return cgltf_result_success;
}
void cgltf_free_extensions(cgltf_data* data, cgltf_extension* extensions, cgltf_size extensions_count)
static void cgltf_free_extras(cgltf_data* data, cgltf_extras* extras)
{
data->memory.free_func(data->memory.user_data, extras->data);
}
static void cgltf_free_extensions(cgltf_data* data, cgltf_extension* extensions, cgltf_size extensions_count)
{
for (cgltf_size i = 0; i < extensions_count; ++i)
{
@ -1755,6 +1760,12 @@ void cgltf_free_extensions(cgltf_data* data, cgltf_extension* extensions, cgltf_
data->memory.free_func(data->memory.user_data, extensions);
}
static void cgltf_free_texture_view(cgltf_data* data, cgltf_texture_view* view)
{
cgltf_free_extensions(data, view->extensions, view->extensions_count);
cgltf_free_extras(data, &view->extras);
}
void cgltf_free(cgltf_data* data)
{
if (!data)
@ -1770,6 +1781,7 @@ void cgltf_free(cgltf_data* data)
data->memory.free_func(data->memory.user_data, data->asset.min_version);
cgltf_free_extensions(data, data->asset.extensions, data->asset.extensions_count);
cgltf_free_extras(data, &data->asset.extras);
for (cgltf_size i = 0; i < data->accessors_count; ++i)
{
@ -1780,8 +1792,12 @@ void cgltf_free(cgltf_data* data)
cgltf_free_extensions(data, data->accessors[i].sparse.extensions, data->accessors[i].sparse.extensions_count);
cgltf_free_extensions(data, data->accessors[i].sparse.indices_extensions, data->accessors[i].sparse.indices_extensions_count);
cgltf_free_extensions(data, data->accessors[i].sparse.values_extensions, data->accessors[i].sparse.values_extensions_count);
cgltf_free_extras(data, &data->accessors[i].sparse.extras);
cgltf_free_extras(data, &data->accessors[i].sparse.indices_extras);
cgltf_free_extras(data, &data->accessors[i].sparse.values_extras);
}
cgltf_free_extensions(data, data->accessors[i].extensions, data->accessors[i].extensions_count);
cgltf_free_extras(data, &data->accessors[i].extras);
}
data->memory.free_func(data->memory.user_data, data->accessors);
@ -1791,6 +1807,7 @@ void cgltf_free(cgltf_data* data)
data->memory.free_func(data->memory.user_data, data->buffer_views[i].data);
cgltf_free_extensions(data, data->buffer_views[i].extensions, data->buffer_views[i].extensions_count);
cgltf_free_extras(data, &data->buffer_views[i].extras);
}
data->memory.free_func(data->memory.user_data, data->buffer_views);
@ -1810,8 +1827,8 @@ void cgltf_free(cgltf_data* data)
data->memory.free_func(data->memory.user_data, data->buffers[i].uri);
cgltf_free_extensions(data, data->buffers[i].extensions, data->buffers[i].extensions_count);
cgltf_free_extras(data, &data->buffers[i].extras);
}
data->memory.free_func(data->memory.user_data, data->buffers);
for (cgltf_size i = 0; i < data->meshes_count; ++i)
@ -1849,9 +1866,15 @@ void cgltf_free(cgltf_data* data)
data->memory.free_func(data->memory.user_data, data->meshes[i].primitives[j].draco_mesh_compression.attributes);
}
for (cgltf_size k = 0; k < data->meshes[i].primitives[j].mappings_count; ++k)
{
cgltf_free_extras(data, &data->meshes[i].primitives[j].mappings[k].extras);
}
data->memory.free_func(data->memory.user_data, data->meshes[i].primitives[j].mappings);
cgltf_free_extensions(data, data->meshes[i].primitives[j].extensions, data->meshes[i].primitives[j].extensions_count);
cgltf_free_extras(data, &data->meshes[i].primitives[j].extras);
}
data->memory.free_func(data->memory.user_data, data->meshes[i].primitives);
@ -1863,6 +1886,7 @@ void cgltf_free(cgltf_data* data)
}
cgltf_free_extensions(data, data->meshes[i].extensions, data->meshes[i].extensions_count);
cgltf_free_extras(data, &data->meshes[i].extras);
data->memory.free_func(data->memory.user_data, data->meshes[i].target_names);
}
@ -1875,49 +1899,50 @@ void cgltf_free(cgltf_data* data)
if(data->materials[i].has_pbr_metallic_roughness)
{
cgltf_free_extensions(data, data->materials[i].pbr_metallic_roughness.metallic_roughness_texture.extensions, data->materials[i].pbr_metallic_roughness.metallic_roughness_texture.extensions_count);
cgltf_free_extensions(data, data->materials[i].pbr_metallic_roughness.base_color_texture.extensions, data->materials[i].pbr_metallic_roughness.base_color_texture.extensions_count);
cgltf_free_texture_view(data, &data->materials[i].pbr_metallic_roughness.metallic_roughness_texture);
cgltf_free_texture_view(data, &data->materials[i].pbr_metallic_roughness.base_color_texture);
}
if(data->materials[i].has_pbr_specular_glossiness)
{
cgltf_free_extensions(data, data->materials[i].pbr_specular_glossiness.diffuse_texture.extensions, data->materials[i].pbr_specular_glossiness.diffuse_texture.extensions_count);
cgltf_free_extensions(data, data->materials[i].pbr_specular_glossiness.specular_glossiness_texture.extensions, data->materials[i].pbr_specular_glossiness.specular_glossiness_texture.extensions_count);
cgltf_free_texture_view(data, &data->materials[i].pbr_specular_glossiness.diffuse_texture);
cgltf_free_texture_view(data, &data->materials[i].pbr_specular_glossiness.specular_glossiness_texture);
}
if(data->materials[i].has_clearcoat)
{
cgltf_free_extensions(data, data->materials[i].clearcoat.clearcoat_texture.extensions, data->materials[i].clearcoat.clearcoat_texture.extensions_count);
cgltf_free_extensions(data, data->materials[i].clearcoat.clearcoat_roughness_texture.extensions, data->materials[i].clearcoat.clearcoat_roughness_texture.extensions_count);
cgltf_free_extensions(data, data->materials[i].clearcoat.clearcoat_normal_texture.extensions, data->materials[i].clearcoat.clearcoat_normal_texture.extensions_count);
cgltf_free_texture_view(data, &data->materials[i].clearcoat.clearcoat_texture);
cgltf_free_texture_view(data, &data->materials[i].clearcoat.clearcoat_roughness_texture);
cgltf_free_texture_view(data, &data->materials[i].clearcoat.clearcoat_normal_texture);
}
if(data->materials[i].has_specular)
{
cgltf_free_extensions(data, data->materials[i].specular.specular_texture.extensions, data->materials[i].specular.specular_texture.extensions_count);
cgltf_free_extensions(data, data->materials[i].specular.specular_color_texture.extensions, data->materials[i].specular.specular_color_texture.extensions_count);
cgltf_free_texture_view(data, &data->materials[i].specular.specular_texture);
cgltf_free_texture_view(data, &data->materials[i].specular.specular_color_texture);
}
if(data->materials[i].has_transmission)
{
cgltf_free_extensions(data, data->materials[i].transmission.transmission_texture.extensions, data->materials[i].transmission.transmission_texture.extensions_count);
cgltf_free_texture_view(data, &data->materials[i].transmission.transmission_texture);
}
if (data->materials[i].has_volume)
{
cgltf_free_extensions(data, data->materials[i].volume.thickness_texture.extensions, data->materials[i].volume.thickness_texture.extensions_count);
cgltf_free_texture_view(data, &data->materials[i].volume.thickness_texture);
}
if(data->materials[i].has_sheen)
{
cgltf_free_extensions(data, data->materials[i].sheen.sheen_color_texture.extensions, data->materials[i].sheen.sheen_color_texture.extensions_count);
cgltf_free_extensions(data, data->materials[i].sheen.sheen_roughness_texture.extensions, data->materials[i].sheen.sheen_roughness_texture.extensions_count);
cgltf_free_texture_view(data, &data->materials[i].sheen.sheen_color_texture);
cgltf_free_texture_view(data, &data->materials[i].sheen.sheen_roughness_texture);
}
if(data->materials[i].has_iridescence)
{
cgltf_free_extensions(data, data->materials[i].iridescence.iridescence_texture.extensions, data->materials[i].iridescence.iridescence_texture.extensions_count);
cgltf_free_extensions(data, data->materials[i].iridescence.iridescence_thickness_texture.extensions, data->materials[i].iridescence.iridescence_thickness_texture.extensions_count);
cgltf_free_texture_view(data, &data->materials[i].iridescence.iridescence_texture);
cgltf_free_texture_view(data, &data->materials[i].iridescence.iridescence_thickness_texture);
}
cgltf_free_extensions(data, data->materials[i].normal_texture.extensions, data->materials[i].normal_texture.extensions_count);
cgltf_free_extensions(data, data->materials[i].occlusion_texture.extensions, data->materials[i].occlusion_texture.extensions_count);
cgltf_free_extensions(data, data->materials[i].emissive_texture.extensions, data->materials[i].emissive_texture.extensions_count);
cgltf_free_texture_view(data, &data->materials[i].normal_texture);
cgltf_free_texture_view(data, &data->materials[i].occlusion_texture);
cgltf_free_texture_view(data, &data->materials[i].emissive_texture);
cgltf_free_extensions(data, data->materials[i].extensions, data->materials[i].extensions_count);
cgltf_free_extras(data, &data->materials[i].extras);
}
data->memory.free_func(data->memory.user_data, data->materials);
@ -1929,6 +1954,7 @@ void cgltf_free(cgltf_data* data)
data->memory.free_func(data->memory.user_data, data->images[i].mime_type);
cgltf_free_extensions(data, data->images[i].extensions, data->images[i].extensions_count);
cgltf_free_extras(data, &data->images[i].extras);
}
data->memory.free_func(data->memory.user_data, data->images);
@ -1936,7 +1962,9 @@ void cgltf_free(cgltf_data* data)
for (cgltf_size i = 0; i < data->textures_count; ++i)
{
data->memory.free_func(data->memory.user_data, data->textures[i].name);
cgltf_free_extensions(data, data->textures[i].extensions, data->textures[i].extensions_count);
cgltf_free_extras(data, &data->textures[i].extras);
}
data->memory.free_func(data->memory.user_data, data->textures);
@ -1944,7 +1972,9 @@ void cgltf_free(cgltf_data* data)
for (cgltf_size i = 0; i < data->samplers_count; ++i)
{
data->memory.free_func(data->memory.user_data, data->samplers[i].name);
cgltf_free_extensions(data, data->samplers[i].extensions, data->samplers[i].extensions_count);
cgltf_free_extras(data, &data->samplers[i].extras);
}
data->memory.free_func(data->memory.user_data, data->samplers);
@ -1955,6 +1985,7 @@ void cgltf_free(cgltf_data* data)
data->memory.free_func(data->memory.user_data, data->skins[i].joints);
cgltf_free_extensions(data, data->skins[i].extensions, data->skins[i].extensions_count);
cgltf_free_extras(data, &data->skins[i].extras);
}
data->memory.free_func(data->memory.user_data, data->skins);
@ -1962,7 +1993,18 @@ void cgltf_free(cgltf_data* data)
for (cgltf_size i = 0; i < data->cameras_count; ++i)
{
data->memory.free_func(data->memory.user_data, data->cameras[i].name);
if (data->cameras[i].type == cgltf_camera_type_perspective)
{
cgltf_free_extras(data, &data->cameras[i].data.perspective.extras);
}
else if (data->cameras[i].type == cgltf_camera_type_orthographic)
{
cgltf_free_extras(data, &data->cameras[i].data.orthographic.extras);
}
cgltf_free_extensions(data, data->cameras[i].extensions, data->cameras[i].extensions_count);
cgltf_free_extras(data, &data->cameras[i].extras);
}
data->memory.free_func(data->memory.user_data, data->cameras);
@ -1970,6 +2012,8 @@ void cgltf_free(cgltf_data* data)
for (cgltf_size i = 0; i < data->lights_count; ++i)
{
data->memory.free_func(data->memory.user_data, data->lights[i].name);
cgltf_free_extras(data, &data->lights[i].extras);
}
data->memory.free_func(data->memory.user_data, data->lights);
@ -1979,7 +2023,19 @@ void cgltf_free(cgltf_data* data)
data->memory.free_func(data->memory.user_data, data->nodes[i].name);
data->memory.free_func(data->memory.user_data, data->nodes[i].children);
data->memory.free_func(data->memory.user_data, data->nodes[i].weights);
if (data->nodes[i].has_mesh_gpu_instancing)
{
for (cgltf_size j = 0; j < data->nodes[i].mesh_gpu_instancing.attributes_count; ++j)
{
data->memory.free_func(data->memory.user_data, data->nodes[i].mesh_gpu_instancing.attributes[j].name);
}
data->memory.free_func(data->memory.user_data, data->nodes[i].mesh_gpu_instancing.attributes);
}
cgltf_free_extensions(data, data->nodes[i].extensions, data->nodes[i].extensions_count);
cgltf_free_extras(data, &data->nodes[i].extras);
}
data->memory.free_func(data->memory.user_data, data->nodes);
@ -1990,6 +2046,7 @@ void cgltf_free(cgltf_data* data)
data->memory.free_func(data->memory.user_data, data->scenes[i].nodes);
cgltf_free_extensions(data, data->scenes[i].extensions, data->scenes[i].extensions_count);
cgltf_free_extras(data, &data->scenes[i].extras);
}
data->memory.free_func(data->memory.user_data, data->scenes);
@ -2000,16 +2057,19 @@ void cgltf_free(cgltf_data* data)
for (cgltf_size j = 0; j < data->animations[i].samplers_count; ++j)
{
cgltf_free_extensions(data, data->animations[i].samplers[j].extensions, data->animations[i].samplers[j].extensions_count);
cgltf_free_extras(data, &data->animations[i].samplers[j].extras);
}
data->memory.free_func(data->memory.user_data, data->animations[i].samplers);
for (cgltf_size j = 0; j < data->animations[i].channels_count; ++j)
{
cgltf_free_extensions(data, data->animations[i].channels[j].extensions, data->animations[i].channels[j].extensions_count);
cgltf_free_extras(data, &data->animations[i].channels[j].extras);
}
data->memory.free_func(data->memory.user_data, data->animations[i].channels);
cgltf_free_extensions(data, data->animations[i].extensions, data->animations[i].extensions_count);
cgltf_free_extras(data, &data->animations[i].extras);
}
data->memory.free_func(data->memory.user_data, data->animations);
@ -2017,11 +2077,14 @@ void cgltf_free(cgltf_data* data)
for (cgltf_size i = 0; i < data->variants_count; ++i)
{
data->memory.free_func(data->memory.user_data, data->variants[i].name);
cgltf_free_extras(data, &data->variants[i].extras);
}
data->memory.free_func(data->memory.user_data, data->variants);
cgltf_free_extensions(data, data->data_extensions, data->data_extensions_count);
cgltf_free_extras(data, &data->extras);
for (cgltf_size i = 0; i < data->extensions_used_count; ++i)
{
@ -2683,11 +2746,27 @@ static int cgltf_parse_json_attribute_list(cgltf_options* options, jsmntok_t con
return i;
}
static int cgltf_parse_json_extras(jsmntok_t const* tokens, int i, const uint8_t* json_chunk, cgltf_extras* out_extras)
static int cgltf_parse_json_extras(cgltf_options* options, jsmntok_t const* tokens, int i, const uint8_t* json_chunk, cgltf_extras* out_extras)
{
(void)json_chunk;
if (out_extras->data)
{
return CGLTF_ERROR_JSON;
}
/* fill deprecated fields for now, this will be removed in the future */
out_extras->start_offset = tokens[i].start;
out_extras->end_offset = tokens[i].end;
size_t start = tokens[i].start;
size_t size = tokens[i].end - start;
out_extras->data = (char*)options->memory.alloc_func(options->memory.user_data, size + 1);
if (!out_extras->data)
{
return CGLTF_ERROR_NOMEM;
}
strncpy(out_extras->data, (const char*)json_chunk + start, size);
out_extras->data[size] = '\0';
i = cgltf_skip_json(tokens, i);
return i;
}
@ -2842,7 +2921,7 @@ static int cgltf_parse_json_material_mapping_data(cgltf_options* options, jsmnto
int material = -1;
int variants_tok = -1;
cgltf_extras extras = {0, 0};
int extras_tok = -1;
for (int k = 0; k < obj_size; ++k)
{
@ -2863,7 +2942,8 @@ static int cgltf_parse_json_material_mapping_data(cgltf_options* options, jsmnto
}
else if (cgltf_json_strcmp(tokens + i, json_chunk, "extras") == 0)
{
i = cgltf_parse_json_extras(tokens, i + 1, json_chunk, &extras);
extras_tok = i + 1;
i = cgltf_skip_json(tokens, extras_tok);
}
else
{
@ -2891,7 +2971,13 @@ static int cgltf_parse_json_material_mapping_data(cgltf_options* options, jsmnto
out_mappings[*offset].material = CGLTF_PTRINDEX(cgltf_material, material);
out_mappings[*offset].variant = variant;
out_mappings[*offset].extras = extras;
if (extras_tok >= 0)
{
int e = cgltf_parse_json_extras(options, tokens, extras_tok, json_chunk, &out_mappings[*offset].extras);
if (e < 0)
return e;
}
(*offset)++;
}
@ -3006,7 +3092,7 @@ static int cgltf_parse_json_primitive(cgltf_options* options, jsmntok_t const* t
}
else if (cgltf_json_strcmp(tokens + i, json_chunk, "extras") == 0)
{
i = cgltf_parse_json_extras(tokens, i + 1, json_chunk, &out_prim->extras);
i = cgltf_parse_json_extras(options, tokens, i + 1, json_chunk, &out_prim->extras);
}
else if (cgltf_json_strcmp(tokens + i, json_chunk, "extensions") == 0)
{
@ -3253,7 +3339,7 @@ static int cgltf_parse_json_accessor_sparse(cgltf_options* options, jsmntok_t co
}
else if (cgltf_json_strcmp(tokens + i, json_chunk, "extras") == 0)
{
i = cgltf_parse_json_extras(tokens, i + 1, json_chunk, &out_sparse->indices_extras);
i = cgltf_parse_json_extras(options, tokens, i + 1, json_chunk, &out_sparse->indices_extras);
}
else if (cgltf_json_strcmp(tokens + i, json_chunk, "extensions") == 0)
{
@ -3296,7 +3382,7 @@ static int cgltf_parse_json_accessor_sparse(cgltf_options* options, jsmntok_t co
}
else if (cgltf_json_strcmp(tokens + i, json_chunk, "extras") == 0)
{
i = cgltf_parse_json_extras(tokens, i + 1, json_chunk, &out_sparse->values_extras);
i = cgltf_parse_json_extras(options, tokens, i + 1, json_chunk, &out_sparse->values_extras);
}
else if (cgltf_json_strcmp(tokens + i, json_chunk, "extensions") == 0)
{
@ -3315,7 +3401,7 @@ static int cgltf_parse_json_accessor_sparse(cgltf_options* options, jsmntok_t co
}
else if (cgltf_json_strcmp(tokens + i, json_chunk, "extras") == 0)
{
i = cgltf_parse_json_extras(tokens, i + 1, json_chunk, &out_sparse->extras);
i = cgltf_parse_json_extras(options, tokens, i + 1, json_chunk, &out_sparse->extras);
}
else if (cgltf_json_strcmp(tokens + i, json_chunk, "extensions") == 0)
{
@ -3438,7 +3524,7 @@ static int cgltf_parse_json_accessor(cgltf_options* options, jsmntok_t const* to
}
else if (cgltf_json_strcmp(tokens + i, json_chunk, "extras") == 0)
{
i = cgltf_parse_json_extras(tokens, i + 1, json_chunk, &out_accessor->extras);
i = cgltf_parse_json_extras(options, tokens, i + 1, json_chunk, &out_accessor->extras);
}
else if (cgltf_json_strcmp(tokens + i, json_chunk, "extensions") == 0)
{
@ -3544,7 +3630,7 @@ static int cgltf_parse_json_texture_view(cgltf_options* options, jsmntok_t const
}
else if (cgltf_json_strcmp(tokens + i, json_chunk, "extras") == 0)
{
i = cgltf_parse_json_extras(tokens, i + 1, json_chunk, &out_texture_view->extras);
i = cgltf_parse_json_extras(options, tokens, i + 1, json_chunk, &out_texture_view->extras);
}
else if (cgltf_json_strcmp(tokens + i, json_chunk, "extensions") == 0)
{
@ -3640,10 +3726,6 @@ static int cgltf_parse_json_pbr_metallic_roughness(cgltf_options* options, jsmnt
i = cgltf_parse_json_texture_view(options, tokens, i + 1, json_chunk,
&out_pbr->metallic_roughness_texture);
}
else if (cgltf_json_strcmp(tokens + i, json_chunk, "extras") == 0)
{
i = cgltf_parse_json_extras(tokens, i + 1, json_chunk, &out_pbr->extras);
}
else
{
i = cgltf_skip_json(tokens, i+1);
@ -4076,7 +4158,7 @@ static int cgltf_parse_json_image(cgltf_options* options, jsmntok_t const* token
}
else if (cgltf_json_strcmp(tokens + i, json_chunk, "extras") == 0)
{
i = cgltf_parse_json_extras(tokens, i + 1, json_chunk, &out_image->extras);
i = cgltf_parse_json_extras(options, tokens, i + 1, json_chunk, &out_image->extras);
}
else if (cgltf_json_strcmp(tokens + i, json_chunk, "extensions") == 0)
{
@ -4145,7 +4227,7 @@ static int cgltf_parse_json_sampler(cgltf_options* options, jsmntok_t const* tok
}
else if (cgltf_json_strcmp(tokens + i, json_chunk, "extras") == 0)
{
i = cgltf_parse_json_extras(tokens, i + 1, json_chunk, &out_sampler->extras);
i = cgltf_parse_json_extras(options, tokens, i + 1, json_chunk, &out_sampler->extras);
}
else if (cgltf_json_strcmp(tokens + i, json_chunk, "extensions") == 0)
{
@ -4194,7 +4276,7 @@ static int cgltf_parse_json_texture(cgltf_options* options, jsmntok_t const* tok
}
else if (cgltf_json_strcmp(tokens + i, json_chunk, "extras") == 0)
{
i = cgltf_parse_json_extras(tokens, i + 1, json_chunk, &out_texture->extras);
i = cgltf_parse_json_extras(options, tokens, i + 1, json_chunk, &out_texture->extras);
}
else if (cgltf_json_strcmp(tokens + i, json_chunk, "extensions") == 0)
{
@ -4357,7 +4439,7 @@ static int cgltf_parse_json_material(cgltf_options* options, jsmntok_t const* to
}
else if (cgltf_json_strcmp(tokens + i, json_chunk, "extras") == 0)
{
i = cgltf_parse_json_extras(tokens, i + 1, json_chunk, &out_material->extras);
i = cgltf_parse_json_extras(options, tokens, i + 1, json_chunk, &out_material->extras);
}
else if (cgltf_json_strcmp(tokens + i, json_chunk, "extensions") == 0)
{
@ -4710,7 +4792,7 @@ static int cgltf_parse_json_buffer_view(cgltf_options* options, jsmntok_t const*
}
else if (cgltf_json_strcmp(tokens + i, json_chunk, "extras") == 0)
{
i = cgltf_parse_json_extras(tokens, i + 1, json_chunk, &out_buffer_view->extras);
i = cgltf_parse_json_extras(options, tokens, i + 1, json_chunk, &out_buffer_view->extras);
}
else if (cgltf_json_strcmp(tokens + i, json_chunk, "extensions") == 0)
{
@ -4813,7 +4895,7 @@ static int cgltf_parse_json_buffer(cgltf_options* options, jsmntok_t const* toke
}
else if (cgltf_json_strcmp(tokens + i, json_chunk, "extras") == 0)
{
i = cgltf_parse_json_extras(tokens, i + 1, json_chunk, &out_buffer->extras);
i = cgltf_parse_json_extras(options, tokens, i + 1, json_chunk, &out_buffer->extras);
}
else if (cgltf_json_strcmp(tokens + i, json_chunk, "extensions") == 0)
{
@ -4897,7 +4979,7 @@ static int cgltf_parse_json_skin(cgltf_options* options, jsmntok_t const* tokens
}
else if (cgltf_json_strcmp(tokens + i, json_chunk, "extras") == 0)
{
i = cgltf_parse_json_extras(tokens, i + 1, json_chunk, &out_skin->extras);
i = cgltf_parse_json_extras(options, tokens, i + 1, json_chunk, &out_skin->extras);
}
else if (cgltf_json_strcmp(tokens + i, json_chunk, "extensions") == 0)
{
@ -4951,19 +5033,6 @@ static int cgltf_parse_json_camera(cgltf_options* options, jsmntok_t const* toke
{
i = cgltf_parse_json_string(options, tokens, i + 1, json_chunk, &out_camera->name);
}
else if (cgltf_json_strcmp(tokens+i, json_chunk, "type") == 0)
{
++i;
if (cgltf_json_strcmp(tokens + i, json_chunk, "perspective") == 0)
{
out_camera->type = cgltf_camera_type_perspective;
}
else if (cgltf_json_strcmp(tokens + i, json_chunk, "orthographic") == 0)
{
out_camera->type = cgltf_camera_type_orthographic;
}
++i;
}
else if (cgltf_json_strcmp(tokens+i, json_chunk, "perspective") == 0)
{
++i;
@ -4973,6 +5042,11 @@ static int cgltf_parse_json_camera(cgltf_options* options, jsmntok_t const* toke
int data_size = tokens[i].size;
++i;
if (out_camera->type != cgltf_camera_type_invalid)
{
return CGLTF_ERROR_JSON;
}
out_camera->type = cgltf_camera_type_perspective;
for (int k = 0; k < data_size; ++k)
@ -5007,7 +5081,7 @@ static int cgltf_parse_json_camera(cgltf_options* options, jsmntok_t const* toke
}
else if (cgltf_json_strcmp(tokens + i, json_chunk, "extras") == 0)
{
i = cgltf_parse_json_extras(tokens, i + 1, json_chunk, &out_camera->data.perspective.extras);
i = cgltf_parse_json_extras(options, tokens, i + 1, json_chunk, &out_camera->data.perspective.extras);
}
else
{
@ -5029,6 +5103,11 @@ static int cgltf_parse_json_camera(cgltf_options* options, jsmntok_t const* toke
int data_size = tokens[i].size;
++i;
if (out_camera->type != cgltf_camera_type_invalid)
{
return CGLTF_ERROR_JSON;
}
out_camera->type = cgltf_camera_type_orthographic;
for (int k = 0; k < data_size; ++k)
@ -5061,7 +5140,7 @@ static int cgltf_parse_json_camera(cgltf_options* options, jsmntok_t const* toke
}
else if (cgltf_json_strcmp(tokens + i, json_chunk, "extras") == 0)
{
i = cgltf_parse_json_extras(tokens, i + 1, json_chunk, &out_camera->data.orthographic.extras);
i = cgltf_parse_json_extras(options, tokens, i + 1, json_chunk, &out_camera->data.orthographic.extras);
}
else
{
@ -5076,7 +5155,7 @@ static int cgltf_parse_json_camera(cgltf_options* options, jsmntok_t const* toke
}
else if (cgltf_json_strcmp(tokens + i, json_chunk, "extras") == 0)
{
i = cgltf_parse_json_extras(tokens, i + 1, json_chunk, &out_camera->extras);
i = cgltf_parse_json_extras(options, tokens, i + 1, json_chunk, &out_camera->extras);
}
else if (cgltf_json_strcmp(tokens + i, json_chunk, "extensions") == 0)
{
@ -5209,7 +5288,7 @@ static int cgltf_parse_json_light(cgltf_options* options, jsmntok_t const* token
}
else if (cgltf_json_strcmp(tokens + i, json_chunk, "extras") == 0)
{
i = cgltf_parse_json_extras(tokens, i + 1, json_chunk, &out_light->extras);
i = cgltf_parse_json_extras(options, tokens, i + 1, json_chunk, &out_light->extras);
}
else
{
@ -5335,7 +5414,7 @@ static int cgltf_parse_json_node(cgltf_options* options, jsmntok_t const* tokens
}
else if (cgltf_json_strcmp(tokens + i, json_chunk, "extras") == 0)
{
i = cgltf_parse_json_extras(tokens, i + 1, json_chunk, &out_node->extras);
i = cgltf_parse_json_extras(options, tokens, i + 1, json_chunk, &out_node->extras);
}
else if (cgltf_json_strcmp(tokens + i, json_chunk, "extensions") == 0)
{
@ -5473,7 +5552,7 @@ static int cgltf_parse_json_scene(cgltf_options* options, jsmntok_t const* token
}
else if (cgltf_json_strcmp(tokens + i, json_chunk, "extras") == 0)
{
i = cgltf_parse_json_extras(tokens, i + 1, json_chunk, &out_scene->extras);
i = cgltf_parse_json_extras(options, tokens, i + 1, json_chunk, &out_scene->extras);
}
else if (cgltf_json_strcmp(tokens + i, json_chunk, "extensions") == 0)
{
@ -5555,7 +5634,7 @@ static int cgltf_parse_json_animation_sampler(cgltf_options* options, jsmntok_t
}
else if (cgltf_json_strcmp(tokens + i, json_chunk, "extras") == 0)
{
i = cgltf_parse_json_extras(tokens, i + 1, json_chunk, &out_sampler->extras);
i = cgltf_parse_json_extras(options, tokens, i + 1, json_chunk, &out_sampler->extras);
}
else if (cgltf_json_strcmp(tokens + i, json_chunk, "extensions") == 0)
{
@ -5635,7 +5714,7 @@ static int cgltf_parse_json_animation_channel(cgltf_options* options, jsmntok_t
}
else if (cgltf_json_strcmp(tokens + i, json_chunk, "extras") == 0)
{
i = cgltf_parse_json_extras(tokens, i + 1, json_chunk, &out_channel->extras);
i = cgltf_parse_json_extras(options, tokens, i + 1, json_chunk, &out_channel->extras);
}
else if (cgltf_json_strcmp(tokens + i, json_chunk, "extensions") == 0)
{
@ -5717,7 +5796,7 @@ static int cgltf_parse_json_animation(cgltf_options* options, jsmntok_t const* t
}
else if (cgltf_json_strcmp(tokens + i, json_chunk, "extras") == 0)
{
i = cgltf_parse_json_extras(tokens, i + 1, json_chunk, &out_animation->extras);
i = cgltf_parse_json_extras(options, tokens, i + 1, json_chunk, &out_animation->extras);
}
else if (cgltf_json_strcmp(tokens + i, json_chunk, "extensions") == 0)
{
@ -5773,7 +5852,7 @@ static int cgltf_parse_json_variant(cgltf_options* options, jsmntok_t const* tok
}
else if (cgltf_json_strcmp(tokens + i, json_chunk, "extras") == 0)
{
i = cgltf_parse_json_extras(tokens, i + 1, json_chunk, &out_variant->extras);
i = cgltf_parse_json_extras(options, tokens, i + 1, json_chunk, &out_variant->extras);
}
else
{
@ -5837,7 +5916,7 @@ static int cgltf_parse_json_asset(cgltf_options* options, jsmntok_t const* token
}
else if (cgltf_json_strcmp(tokens + i, json_chunk, "extras") == 0)
{
i = cgltf_parse_json_extras(tokens, i + 1, json_chunk, &out_asset->extras);
i = cgltf_parse_json_extras(options, tokens, i + 1, json_chunk, &out_asset->extras);
}
else if (cgltf_json_strcmp(tokens + i, json_chunk, "extensions") == 0)
{
@ -5993,7 +6072,7 @@ static int cgltf_parse_json_root(cgltf_options* options, jsmntok_t const* tokens
}
else if (cgltf_json_strcmp(tokens+i, json_chunk, "extras") == 0)
{
i = cgltf_parse_json_extras(tokens, i + 1, json_chunk, &out_data->extras);
i = cgltf_parse_json_extras(options, tokens, i + 1, json_chunk, &out_data->extras);
}
else if (cgltf_json_strcmp(tokens + i, json_chunk, "extensions") == 0)
{

View File

@ -1,7 +1,7 @@
/**
* cgltf_write - a single-file glTF 2.0 writer written in C99.
*
* Version: 1.12
* Version: 1.13
*
* Website: https://github.com/jkuhlmann/cgltf
*
@ -15,19 +15,17 @@
*
* Reference:
* `cgltf_result cgltf_write_file(const cgltf_options* options, const char*
* path, const cgltf_data* data)` writes JSON to the given file path. Buffer
* files and external images are not written out. `data` is not deallocated.
* path, const cgltf_data* data)` writes a glTF data to the given file path.
* If `options->type` is `cgltf_file_type_glb`, both JSON content and binary
* buffer of the given glTF data will be written in a GLB format.
* Otherwise, only the JSON part will be written.
* External buffers and images are not written out. `data` is not deallocated.
*
* `cgltf_size cgltf_write(const cgltf_options* options, char* buffer,
* cgltf_size size, const cgltf_data* data)` writes JSON into the given memory
* buffer. Returns the number of bytes written to `buffer`, including a null
* terminator. If buffer is null, returns the number of bytes that would have
* been written. `data` is not deallocated.
*
* To write custom JSON into the `extras` field, aggregate all the custom JSON
* into a single buffer, then set `file_data` to this buffer. By supplying
* start_offset and end_offset values for various objects, you can select a
* range of characters within the aggregated buffer.
*/
#ifndef CGLTF_WRITE_H_INCLUDED__
#define CGLTF_WRITE_H_INCLUDED__
@ -147,6 +145,17 @@ typedef struct {
context->needs_comma = 1; }
#define CGLTF_WRITE_TEXTURE_INFO(label, info) if (info.texture) { \
cgltf_write_line(context, "\"" label "\": {"); \
CGLTF_WRITE_IDXPROP("index", info.texture, context->data->textures); \
cgltf_write_intprop(context, "texCoord", info.texcoord, 0); \
if (info.has_transform) { \
context->extension_flags |= CGLTF_EXTENSION_FLAG_TEXTURE_TRANSFORM; \
cgltf_write_texture_transform(context, &info.transform); \
} \
cgltf_write_extras(context, &info.extras); \
cgltf_write_line(context, "}"); }
#define CGLTF_WRITE_NORMAL_TEXTURE_INFO(label, info) if (info.texture) { \
cgltf_write_line(context, "\"" label "\": {"); \
CGLTF_WRITE_IDXPROP("index", info.texture, context->data->textures); \
cgltf_write_intprop(context, "texCoord", info.texcoord, 0); \
@ -158,6 +167,28 @@ typedef struct {
cgltf_write_extras(context, &info.extras); \
cgltf_write_line(context, "}"); }
#define CGLTF_WRITE_OCCLUSION_TEXTURE_INFO(label, info) if (info.texture) { \
cgltf_write_line(context, "\"" label "\": {"); \
CGLTF_WRITE_IDXPROP("index", info.texture, context->data->textures); \
cgltf_write_intprop(context, "texCoord", info.texcoord, 0); \
cgltf_write_floatprop(context, "strength", info.scale, 1.0f); \
if (info.has_transform) { \
context->extension_flags |= CGLTF_EXTENSION_FLAG_TEXTURE_TRANSFORM; \
cgltf_write_texture_transform(context, &info.transform); \
} \
cgltf_write_extras(context, &info.extras); \
cgltf_write_line(context, "}"); }
#ifndef CGLTF_CONSTS
static const cgltf_size GlbHeaderSize = 12;
static const cgltf_size GlbChunkHeaderSize = 8;
static const uint32_t GlbVersion = 2;
static const uint32_t GlbMagic = 0x46546C67;
static const uint32_t GlbMagicJsonChunk = 0x4E4F534A;
static const uint32_t GlbMagicBinChunk = 0x004E4942;
#define CGLTF_CONSTS
#endif
static void cgltf_write_indent(cgltf_write_context* context)
{
if (context->needs_comma)
@ -208,15 +239,24 @@ static void cgltf_write_strprop(cgltf_write_context* context, const char* label,
static void cgltf_write_extras(cgltf_write_context* context, const cgltf_extras* extras)
{
cgltf_size length = extras->end_offset - extras->start_offset;
if (length > 0 && context->data->file_data)
if (extras->data)
{
char* json_string = ((char*) context->data->file_data) + extras->start_offset;
cgltf_write_indent(context);
CGLTF_SPRINTF("%s", "\"extras\": ");
CGLTF_SNPRINTF(length, "%.*s", (int)(extras->end_offset - extras->start_offset), json_string);
CGLTF_SPRINTF("\"extras\": %s", extras->data);
context->needs_comma = 1;
}
else
{
cgltf_size length = extras->end_offset - extras->start_offset;
if (length > 0 && context->data->json)
{
char* json_string = ((char*) context->data->json) + extras->start_offset;
cgltf_write_indent(context);
CGLTF_SPRINTF("%s", "\"extras\": ");
CGLTF_SNPRINTF(length, "%.*s", (int)(extras->end_offset - extras->start_offset), json_string);
context->needs_comma = 1;
}
}
}
static void cgltf_write_stritem(cgltf_write_context* context, const char* item)
@ -613,7 +653,6 @@ static void cgltf_write_material(cgltf_write_context* context, const cgltf_mater
{
cgltf_write_floatarrayprop(context, "baseColorFactor", params->base_color_factor, 4);
}
cgltf_write_extras(context, &params->extras);
cgltf_write_line(context, "}");
}
@ -626,7 +665,7 @@ static void cgltf_write_material(cgltf_write_context* context, const cgltf_mater
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_NORMAL_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, "}");
@ -731,8 +770,8 @@ static void cgltf_write_material(cgltf_write_context* context, const cgltf_mater
cgltf_write_line(context, "}");
}
CGLTF_WRITE_TEXTURE_INFO("normalTexture", material->normal_texture);
CGLTF_WRITE_TEXTURE_INFO("occlusionTexture", material->occlusion_texture);
CGLTF_WRITE_NORMAL_TEXTURE_INFO("normalTexture", material->normal_texture);
CGLTF_WRITE_OCCLUSION_TEXTURE_INFO("occlusionTexture", material->occlusion_texture);
CGLTF_WRITE_TEXTURE_INFO("emissiveTexture", material->emissive_texture);
if (cgltf_check_floatarray(material->emissive_factor, 3, 0.0f))
{
@ -1097,6 +1136,47 @@ static void cgltf_write_variant(cgltf_write_context* context, const cgltf_materi
cgltf_write_line(context, "}");
}
static void cgltf_write_glb(FILE* file, const void* json_buf, const cgltf_size json_size, const void* bin_buf, const cgltf_size bin_size)
{
char header[GlbHeaderSize];
char chunk_header[GlbChunkHeaderSize];
char json_pad[3] = { 0x20, 0x20, 0x20 };
char bin_pad[3] = { 0, 0, 0 };
cgltf_size json_padsize = (json_size % 4 != 0) ? 4 - json_size % 4 : 0;
cgltf_size bin_padsize = (bin_size % 4 != 0) ? 4 - bin_size % 4 : 0;
cgltf_size total_size = GlbHeaderSize + GlbChunkHeaderSize + json_size + json_padsize;
if (bin_buf != NULL && bin_size > 0) {
total_size += GlbChunkHeaderSize + bin_size + bin_padsize;
}
// Write a GLB header
memcpy(header, &GlbMagic, 4);
memcpy(header + 4, &GlbVersion, 4);
memcpy(header + 8, &total_size, 4);
fwrite(header, 1, GlbHeaderSize, file);
// Write a JSON chunk (header & data)
uint32_t json_chunk_size = (uint32_t)(json_size + json_padsize);
memcpy(chunk_header, &json_chunk_size, 4);
memcpy(chunk_header + 4, &GlbMagicJsonChunk, 4);
fwrite(chunk_header, 1, GlbChunkHeaderSize, file);
fwrite(json_buf, 1, json_size, file);
fwrite(json_pad, 1, json_padsize, file);
if (bin_buf != NULL && bin_size > 0) {
// Write a binary chunk (header & data)
uint32_t bin_chunk_size = (uint32_t)(bin_size + bin_padsize);
memcpy(chunk_header, &bin_chunk_size, 4);
memcpy(chunk_header + 4, &GlbMagicBinChunk, 4);
fwrite(chunk_header, 1, GlbChunkHeaderSize, file);
fwrite(bin_buf, 1, bin_size, file);
fwrite(bin_pad, 1, bin_padsize, file);
}
}
cgltf_result cgltf_write_file(const cgltf_options* options, const char* path, const cgltf_data* data)
{
cgltf_size expected = cgltf_write(options, NULL, 0, data);
@ -1105,13 +1185,18 @@ cgltf_result cgltf_write_file(const cgltf_options* options, const char* path, co
if (expected != actual) {
fprintf(stderr, "Error: expected %zu bytes but wrote %zu bytes.\n", expected, actual);
}
FILE* file = fopen(path, "wt");
FILE* file = fopen(path, "wb");
if (!file)
{
return cgltf_result_file_not_found;
}
// Note that cgltf_write() includes a null terminator, which we omit from the file content.
fwrite(buffer, actual - 1, 1, file);
if (options->type == cgltf_file_type_glb) {
cgltf_write_glb(file, buffer, actual - 1, data->bin, data->bin_size);
} else {
// Write a plain JSON file.
fwrite(buffer, actual - 1, 1, file);
}
fclose(file);
free(buffer);
return cgltf_result_success;