summaryrefslogtreecommitdiff
path: root/libs/raylib/src/external/cgltf.h
diff options
context:
space:
mode:
Diffstat (limited to 'libs/raylib/src/external/cgltf.h')
-rw-r--r--libs/raylib/src/external/cgltf.h1624
1 files changed, 1441 insertions, 183 deletions
diff --git a/libs/raylib/src/external/cgltf.h b/libs/raylib/src/external/cgltf.h
index bbc641c..4cc2d7e 100644
--- a/libs/raylib/src/external/cgltf.h
+++ b/libs/raylib/src/external/cgltf.h
@@ -1,7 +1,7 @@
/**
* cgltf - a single-file glTF 2.0 parser written in C99.
*
- * Version: 1.5
+ * Version: 1.10
*
* Website: https://github.com/jkuhlmann/cgltf
*
@@ -24,7 +24,7 @@
*
* `cgltf_options` is the struct passed to `cgltf_parse()` to control
* parts of the parsing process. You can use it to force the file type
- * and provide memory allocation as well as file operation callbacks.
+ * and provide memory allocation as well as file operation callbacks.
* Should be zero-initialized to trigger default behavior.
*
* `cgltf_data` is the struct allocated and filled by `cgltf_parse()`.
@@ -42,8 +42,8 @@
*
* `cgltf_result cgltf_load_buffer_base64(const cgltf_options* options,
* cgltf_size size, const char* base64, void** out_data)` decodes
- * base64-encoded data content. Used internally by `cgltf_load_buffers()`
- * and may be useful if you're not dealing with normal files.
+ * base64-encoded data content. Used internally by `cgltf_load_buffers()`.
+ * This is useful when decoding data URIs in images.
*
* `cgltf_result cgltf_parse_file(const cgltf_options* options, const
* char* path, cgltf_data** out_data)` can be used to open the given
@@ -239,22 +239,61 @@ typedef struct cgltf_extras {
cgltf_size end_offset;
} cgltf_extras;
+typedef struct cgltf_extension {
+ char* name;
+ char* data;
+} cgltf_extension;
+
typedef struct cgltf_buffer
{
+ char* name;
cgltf_size size;
char* uri;
void* data; /* loaded by cgltf_load_buffers */
cgltf_extras extras;
+ cgltf_size extensions_count;
+ cgltf_extension* extensions;
} cgltf_buffer;
+typedef enum cgltf_meshopt_compression_mode {
+ cgltf_meshopt_compression_mode_invalid,
+ cgltf_meshopt_compression_mode_attributes,
+ cgltf_meshopt_compression_mode_triangles,
+ cgltf_meshopt_compression_mode_indices,
+} cgltf_meshopt_compression_mode;
+
+typedef enum cgltf_meshopt_compression_filter {
+ cgltf_meshopt_compression_filter_none,
+ cgltf_meshopt_compression_filter_octahedral,
+ cgltf_meshopt_compression_filter_quaternion,
+ cgltf_meshopt_compression_filter_exponential,
+} cgltf_meshopt_compression_filter;
+
+typedef struct cgltf_meshopt_compression
+{
+ cgltf_buffer* buffer;
+ cgltf_size offset;
+ cgltf_size size;
+ cgltf_size stride;
+ cgltf_size count;
+ cgltf_meshopt_compression_mode mode;
+ cgltf_meshopt_compression_filter filter;
+} cgltf_meshopt_compression;
+
typedef struct cgltf_buffer_view
{
+ char *name;
cgltf_buffer* buffer;
cgltf_size offset;
cgltf_size size;
cgltf_size stride; /* 0 == automatically determined by accessor */
cgltf_buffer_view_type type;
+ void* data; /* overrides buffer->data if present, filled by extensions */
+ cgltf_bool has_meshopt_compression;
+ cgltf_meshopt_compression meshopt_compression;
cgltf_extras extras;
+ cgltf_size extensions_count;
+ cgltf_extension* extensions;
} cgltf_buffer_view;
typedef struct cgltf_accessor_sparse
@@ -268,10 +307,17 @@ typedef struct cgltf_accessor_sparse
cgltf_extras extras;
cgltf_extras indices_extras;
cgltf_extras values_extras;
+ cgltf_size extensions_count;
+ cgltf_extension* extensions;
+ cgltf_size indices_extensions_count;
+ cgltf_extension* indices_extensions;
+ cgltf_size values_extensions_count;
+ cgltf_extension* values_extensions;
} cgltf_accessor_sparse;
typedef struct cgltf_accessor
{
+ char* name;
cgltf_component_type component_type;
cgltf_bool normalized;
cgltf_type type;
@@ -286,6 +332,8 @@ typedef struct cgltf_accessor
cgltf_bool is_sparse;
cgltf_accessor_sparse sparse;
cgltf_extras extras;
+ cgltf_size extensions_count;
+ cgltf_extension* extensions;
} cgltf_accessor;
typedef struct cgltf_attribute
@@ -303,15 +351,20 @@ typedef struct cgltf_image
cgltf_buffer_view* buffer_view;
char* mime_type;
cgltf_extras extras;
+ cgltf_size extensions_count;
+ cgltf_extension* extensions;
} cgltf_image;
typedef struct cgltf_sampler
{
+ char* name;
cgltf_int mag_filter;
cgltf_int min_filter;
cgltf_int wrap_s;
cgltf_int wrap_t;
cgltf_extras extras;
+ cgltf_size extensions_count;
+ cgltf_extension* extensions;
} cgltf_sampler;
typedef struct cgltf_texture
@@ -320,6 +373,8 @@ typedef struct cgltf_texture
cgltf_image* image;
cgltf_sampler* sampler;
cgltf_extras extras;
+ cgltf_size extensions_count;
+ cgltf_extension* extensions;
} cgltf_texture;
typedef struct cgltf_texture_transform
@@ -338,6 +393,8 @@ typedef struct cgltf_texture_view
cgltf_bool has_transform;
cgltf_texture_transform transform;
cgltf_extras extras;
+ cgltf_size extensions_count;
+ cgltf_extension* extensions;
} cgltf_texture_view;
typedef struct cgltf_pbr_metallic_roughness
@@ -362,13 +419,70 @@ 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_transmission
+{
+ cgltf_texture_view transmission_texture;
+ cgltf_float transmission_factor;
+} cgltf_transmission;
+
+typedef struct cgltf_ior
+{
+ cgltf_float ior;
+} cgltf_ior;
+
+typedef struct cgltf_specular
+{
+ cgltf_texture_view specular_texture;
+ cgltf_texture_view specular_color_texture;
+ cgltf_float specular_color_factor[3];
+ cgltf_float specular_factor;
+} cgltf_specular;
+
+typedef struct cgltf_volume
+{
+ cgltf_texture_view thickness_texture;
+ cgltf_float thickness_factor;
+ cgltf_float attenuation_color[3];
+ cgltf_float attenuation_distance;
+} cgltf_volume;
+
+typedef struct cgltf_sheen
+{
+ cgltf_texture_view sheen_color_texture;
+ cgltf_float sheen_color_factor[3];
+ cgltf_texture_view sheen_roughness_texture;
+ cgltf_float sheen_roughness_factor;
+} cgltf_sheen;
+
typedef struct cgltf_material
{
char* name;
cgltf_bool has_pbr_metallic_roughness;
cgltf_bool has_pbr_specular_glossiness;
+ cgltf_bool has_clearcoat;
+ cgltf_bool has_transmission;
+ cgltf_bool has_volume;
+ cgltf_bool has_ior;
+ cgltf_bool has_specular;
+ cgltf_bool has_sheen;
cgltf_pbr_metallic_roughness pbr_metallic_roughness;
cgltf_pbr_specular_glossiness pbr_specular_glossiness;
+ cgltf_clearcoat clearcoat;
+ cgltf_ior ior;
+ cgltf_specular specular;
+ cgltf_sheen sheen;
+ cgltf_transmission transmission;
+ cgltf_volume volume;
cgltf_texture_view normal_texture;
cgltf_texture_view occlusion_texture;
cgltf_texture_view emissive_texture;
@@ -378,13 +492,28 @@ typedef struct cgltf_material
cgltf_bool double_sided;
cgltf_bool unlit;
cgltf_extras extras;
+ cgltf_size extensions_count;
+ cgltf_extension* extensions;
} cgltf_material;
+typedef struct cgltf_material_mapping
+{
+ cgltf_size variant;
+ cgltf_material* material;
+ cgltf_extras extras;
+} cgltf_material_mapping;
+
typedef struct cgltf_morph_target {
cgltf_attribute* attributes;
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 +523,12 @@ 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_material_mapping* mappings;
+ cgltf_size mappings_count;
+ cgltf_size extensions_count;
+ cgltf_extension* extensions;
} cgltf_primitive;
typedef struct cgltf_mesh {
@@ -405,6 +540,8 @@ typedef struct cgltf_mesh {
char** target_names;
cgltf_size target_names_count;
cgltf_extras extras;
+ cgltf_size extensions_count;
+ cgltf_extension* extensions;
} cgltf_mesh;
typedef struct cgltf_node cgltf_node;
@@ -416,11 +553,15 @@ typedef struct cgltf_skin {
cgltf_node* skeleton;
cgltf_accessor* inverse_bind_matrices;
cgltf_extras extras;
+ cgltf_size extensions_count;
+ cgltf_extension* extensions;
} cgltf_skin;
typedef struct cgltf_camera_perspective {
+ cgltf_bool has_aspect_ratio;
cgltf_float aspect_ratio;
cgltf_float yfov;
+ cgltf_bool has_zfar;
cgltf_float zfar;
cgltf_float znear;
cgltf_extras extras;
@@ -442,6 +583,8 @@ typedef struct cgltf_camera {
cgltf_camera_orthographic orthographic;
} data;
cgltf_extras extras;
+ cgltf_size extensions_count;
+ cgltf_extension* extensions;
} cgltf_camera;
typedef struct cgltf_light {
@@ -474,6 +617,8 @@ struct cgltf_node {
cgltf_float scale[3];
cgltf_float matrix[16];
cgltf_extras extras;
+ cgltf_size extensions_count;
+ cgltf_extension* extensions;
};
typedef struct cgltf_scene {
@@ -481,6 +626,8 @@ typedef struct cgltf_scene {
cgltf_node** nodes;
cgltf_size nodes_count;
cgltf_extras extras;
+ cgltf_size extensions_count;
+ cgltf_extension* extensions;
} cgltf_scene;
typedef struct cgltf_animation_sampler {
@@ -488,6 +635,8 @@ typedef struct cgltf_animation_sampler {
cgltf_accessor* output;
cgltf_interpolation_type interpolation;
cgltf_extras extras;
+ cgltf_size extensions_count;
+ cgltf_extension* extensions;
} cgltf_animation_sampler;
typedef struct cgltf_animation_channel {
@@ -495,6 +644,8 @@ typedef struct cgltf_animation_channel {
cgltf_node* target_node;
cgltf_animation_path_type target_path;
cgltf_extras extras;
+ cgltf_size extensions_count;
+ cgltf_extension* extensions;
} cgltf_animation_channel;
typedef struct cgltf_animation {
@@ -504,14 +655,24 @@ typedef struct cgltf_animation {
cgltf_animation_channel* channels;
cgltf_size channels_count;
cgltf_extras extras;
+ cgltf_size extensions_count;
+ cgltf_extension* extensions;
} cgltf_animation;
+typedef struct cgltf_material_variant
+{
+ char* name;
+ cgltf_extras extras;
+} cgltf_material_variant;
+
typedef struct cgltf_asset {
char* copyright;
char* generator;
char* version;
char* min_version;
cgltf_extras extras;
+ cgltf_size extensions_count;
+ cgltf_extension* extensions;
} cgltf_asset;
typedef struct cgltf_data
@@ -565,8 +726,14 @@ typedef struct cgltf_data
cgltf_animation* animations;
cgltf_size animations_count;
+ cgltf_material_variant* variants;
+ cgltf_size variants_count;
+
cgltf_extras extras;
+ cgltf_size data_extensions_count;
+ cgltf_extension* data_extensions;
+
char** extensions_used;
cgltf_size extensions_used_count;
@@ -599,9 +766,10 @@ cgltf_result cgltf_load_buffers(
cgltf_data* data,
const char* gltf_path);
-
cgltf_result cgltf_load_buffer_base64(const cgltf_options* options, cgltf_size size, const char* base64, void** out_data);
+void cgltf_decode_uri(char* uri);
+
cgltf_result cgltf_validate(cgltf_data* data);
void cgltf_free(cgltf_data* data);
@@ -632,8 +800,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
@@ -643,6 +811,7 @@ cgltf_result cgltf_copy_extras_json(const cgltf_data* data, const cgltf_extras*
#include <string.h> /* For strncpy */
#include <stdio.h> /* For fopen */
#include <limits.h> /* For UINT_MAX etc */
+#include <float.h> /* For FLT_MAX */
#if !defined(CGLTF_MALLOC) || !defined(CGLTF_FREE) || !defined(CGLTF_ATOI) || !defined(CGLTF_ATOF)
#include <stdlib.h> /* For malloc, free, atoi, atof */
@@ -714,6 +883,9 @@ static const uint32_t GlbMagicBinChunk = 0x004E4942;
#ifndef CGLTF_ATOF
#define CGLTF_ATOF(str) atof(str)
#endif
+#ifndef CGLTF_VALIDATE_ENABLE_ASSERTS
+#define CGLTF_VALIDATE_ENABLE_ASSERTS 0
+#endif
static void* cgltf_default_alloc(void* user, cgltf_size size)
{
@@ -948,7 +1120,6 @@ cgltf_result cgltf_parse_file(const cgltf_options* options, const char* path, cg
return cgltf_result_invalid_options;
}
- void* (*memory_alloc)(void*, cgltf_size) = options->memory.alloc ? options->memory.alloc : &cgltf_default_alloc;
void (*memory_free)(void*, void*) = options->memory.free ? options->memory.free : &cgltf_default_free;
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;
@@ -1006,16 +1177,17 @@ static cgltf_result cgltf_load_buffer_file(const cgltf_options* options, cgltf_s
cgltf_combine_paths(path, gltf_path, uri);
+ // after combining, the tail of the resulting path is a uri; decode_uri converts it into path
+ cgltf_decode_uri(path + strlen(path) - strlen(uri));
+
void* file_data = NULL;
cgltf_result result = file_read(&options->memory, &options->file, path, &size, &file_data);
- if (result != cgltf_result_success)
- {
- return result;
- }
- *out_data = file_data;
+ memory_free(options->memory.user_data, path);
- return cgltf_result_success;
+ *out_data = (result == cgltf_result_success) ? file_data : NULL;
+
+ return result;
}
cgltf_result cgltf_load_buffer_base64(const cgltf_options* options, cgltf_size size, const char* base64, void** out_data)
@@ -1065,6 +1237,45 @@ cgltf_result cgltf_load_buffer_base64(const cgltf_options* options, cgltf_size s
return cgltf_result_success;
}
+static int cgltf_unhex(char ch)
+{
+ return
+ (unsigned)(ch - '0') < 10 ? (ch - '0') :
+ (unsigned)(ch - 'A') < 6 ? (ch - 'A') + 10 :
+ (unsigned)(ch - 'a') < 6 ? (ch - 'a') + 10 :
+ -1;
+}
+
+void cgltf_decode_uri(char* uri)
+{
+ char* write = uri;
+ char* i = uri;
+
+ while (*i)
+ {
+ if (*i == '%')
+ {
+ int ch1 = cgltf_unhex(i[1]);
+
+ if (ch1 >= 0)
+ {
+ int ch2 = cgltf_unhex(i[2]);
+
+ if (ch2 >= 0)
+ {
+ *write++ = (char)(ch1 * 16 + ch2);
+ i += 3;
+ continue;
+ }
+ }
+ }
+
+ *write++ = *i++;
+ }
+
+ *write = 0;
+}
+
cgltf_result cgltf_load_buffers(const cgltf_options* options, cgltf_data* data, const char* gltf_path)
{
if (options == NULL)
@@ -1172,6 +1383,12 @@ static cgltf_size cgltf_calc_index_bound(cgltf_buffer_view* buffer_view, cgltf_s
return bound;
}
+#if CGLTF_VALIDATE_ENABLE_ASSERTS
+#define CGLTF_ASSERT_IF(cond, result) assert(!(cond)); if (cond) return result;
+#else
+#define CGLTF_ASSERT_IF(cond, result) if (cond) return result;
+#endif
+
cgltf_result cgltf_validate(cgltf_data* data)
{
for (cgltf_size i = 0; i < data->accessors_count; ++i)
@@ -1184,10 +1401,7 @@ cgltf_result cgltf_validate(cgltf_data* data)
{
cgltf_size req_size = accessor->offset + accessor->stride * (accessor->count - 1) + element_size;
- if (accessor->buffer_view->size < req_size)
- {
- return cgltf_result_data_too_short;
- }
+ CGLTF_ASSERT_IF(accessor->buffer_view->size < req_size, cgltf_result_data_too_short);
}
if (accessor->is_sparse)
@@ -1198,27 +1412,18 @@ cgltf_result cgltf_validate(cgltf_data* data)
cgltf_size indices_req_size = sparse->indices_byte_offset + indices_component_size * sparse->count;
cgltf_size values_req_size = sparse->values_byte_offset + element_size * sparse->count;
- if (sparse->indices_buffer_view->size < indices_req_size ||
- sparse->values_buffer_view->size < values_req_size)
- {
- return cgltf_result_data_too_short;
- }
+ CGLTF_ASSERT_IF(sparse->indices_buffer_view->size < indices_req_size ||
+ sparse->values_buffer_view->size < values_req_size, cgltf_result_data_too_short);
- if (sparse->indices_component_type != cgltf_component_type_r_8u &&
- sparse->indices_component_type != cgltf_component_type_r_16u &&
- sparse->indices_component_type != cgltf_component_type_r_32u)
- {
- return cgltf_result_invalid_gltf;
- }
+ CGLTF_ASSERT_IF(sparse->indices_component_type != cgltf_component_type_r_8u &&
+ sparse->indices_component_type != cgltf_component_type_r_16u &&
+ sparse->indices_component_type != cgltf_component_type_r_32u, cgltf_result_invalid_gltf);
if (sparse->indices_buffer_view->buffer->data)
{
cgltf_size index_bound = cgltf_calc_index_bound(sparse->indices_buffer_view, sparse->indices_byte_offset, sparse->indices_component_type, sparse->count);
- if (index_bound >= accessor->count)
- {
- return cgltf_result_data_too_short;
- }
+ CGLTF_ASSERT_IF(index_bound >= accessor->count, cgltf_result_data_too_short);
}
}
}
@@ -1227,9 +1432,31 @@ cgltf_result cgltf_validate(cgltf_data* data)
{
cgltf_size req_size = data->buffer_views[i].offset + data->buffer_views[i].size;
- if (data->buffer_views[i].buffer && data->buffer_views[i].buffer->size < req_size)
+ CGLTF_ASSERT_IF(data->buffer_views[i].buffer && data->buffer_views[i].buffer->size < req_size, cgltf_result_data_too_short);
+
+ if (data->buffer_views[i].has_meshopt_compression)
{
- return cgltf_result_data_too_short;
+ cgltf_meshopt_compression* mc = &data->buffer_views[i].meshopt_compression;
+
+ CGLTF_ASSERT_IF(mc->buffer == NULL || mc->buffer->size < mc->offset + mc->size, cgltf_result_data_too_short);
+
+ CGLTF_ASSERT_IF(data->buffer_views[i].stride && mc->stride != data->buffer_views[i].stride, cgltf_result_invalid_gltf);
+
+ CGLTF_ASSERT_IF(data->buffer_views[i].size != mc->stride * mc->count, cgltf_result_invalid_gltf);
+
+ CGLTF_ASSERT_IF(mc->mode == cgltf_meshopt_compression_mode_invalid, cgltf_result_invalid_gltf);
+
+ CGLTF_ASSERT_IF(mc->mode == cgltf_meshopt_compression_mode_attributes && !(mc->stride % 4 == 0 && mc->stride <= 256), cgltf_result_invalid_gltf);
+
+ CGLTF_ASSERT_IF(mc->mode == cgltf_meshopt_compression_mode_triangles && mc->count % 3 != 0, cgltf_result_invalid_gltf);
+
+ CGLTF_ASSERT_IF((mc->mode == cgltf_meshopt_compression_mode_triangles || mc->mode == cgltf_meshopt_compression_mode_indices) && mc->stride != 2 && mc->stride != 4, cgltf_result_invalid_gltf);
+
+ 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);
}
}
@@ -1237,26 +1464,17 @@ cgltf_result cgltf_validate(cgltf_data* data)
{
if (data->meshes[i].weights)
{
- if (data->meshes[i].primitives_count && data->meshes[i].primitives[0].targets_count != data->meshes[i].weights_count)
- {
- return cgltf_result_invalid_gltf;
- }
+ CGLTF_ASSERT_IF(data->meshes[i].primitives_count && data->meshes[i].primitives[0].targets_count != data->meshes[i].weights_count, cgltf_result_invalid_gltf);
}
if (data->meshes[i].target_names)
{
- if (data->meshes[i].primitives_count && data->meshes[i].primitives[0].targets_count != data->meshes[i].target_names_count)
- {
- return cgltf_result_invalid_gltf;
- }
+ CGLTF_ASSERT_IF(data->meshes[i].primitives_count && data->meshes[i].primitives[0].targets_count != data->meshes[i].target_names_count, cgltf_result_invalid_gltf);
}
for (cgltf_size j = 0; j < data->meshes[i].primitives_count; ++j)
{
- if (data->meshes[i].primitives[j].targets_count != data->meshes[i].primitives[0].targets_count)
- {
- return cgltf_result_invalid_gltf;
- }
+ CGLTF_ASSERT_IF(data->meshes[i].primitives[j].targets_count != data->meshes[i].primitives[0].targets_count, cgltf_result_invalid_gltf);
if (data->meshes[i].primitives[j].attributes_count)
{
@@ -1264,41 +1482,34 @@ cgltf_result cgltf_validate(cgltf_data* data)
for (cgltf_size k = 0; k < data->meshes[i].primitives[j].attributes_count; ++k)
{
- if (data->meshes[i].primitives[j].attributes[k].data->count != first->count)
- {
- return cgltf_result_invalid_gltf;
- }
+ CGLTF_ASSERT_IF(data->meshes[i].primitives[j].attributes[k].data->count != first->count, cgltf_result_invalid_gltf);
}
for (cgltf_size k = 0; k < data->meshes[i].primitives[j].targets_count; ++k)
{
for (cgltf_size m = 0; m < data->meshes[i].primitives[j].targets[k].attributes_count; ++m)
{
- if (data->meshes[i].primitives[j].targets[k].attributes[m].data->count != first->count)
- {
- return cgltf_result_invalid_gltf;
- }
+ CGLTF_ASSERT_IF(data->meshes[i].primitives[j].targets[k].attributes[m].data->count != first->count, cgltf_result_invalid_gltf);
}
}
cgltf_accessor* indices = data->meshes[i].primitives[j].indices;
- if (indices &&
+ CGLTF_ASSERT_IF(indices &&
indices->component_type != cgltf_component_type_r_8u &&
indices->component_type != cgltf_component_type_r_16u &&
- indices->component_type != cgltf_component_type_r_32u)
- {
- return cgltf_result_invalid_gltf;
- }
+ indices->component_type != cgltf_component_type_r_32u, cgltf_result_invalid_gltf);
if (indices && indices->buffer_view && indices->buffer_view->buffer->data)
{
cgltf_size index_bound = cgltf_calc_index_bound(indices->buffer_view, indices->offset, indices->component_type, indices->count);
- if (index_bound >= first->count)
- {
- return cgltf_result_data_too_short;
- }
+ CGLTF_ASSERT_IF(index_bound >= first->count, cgltf_result_data_too_short);
+ }
+
+ for (cgltf_size k = 0; k < data->meshes[i].primitives[j].mappings_count; ++k)
+ {
+ CGLTF_ASSERT_IF(data->meshes[i].primitives[j].mappings[k].variant >= data->variants_count, cgltf_result_invalid_gltf);
}
}
}
@@ -1308,10 +1519,7 @@ cgltf_result cgltf_validate(cgltf_data* data)
{
if (data->nodes[i].weights && data->nodes[i].mesh)
{
- if (data->nodes[i].mesh->primitives_count && data->nodes[i].mesh->primitives[0].targets_count != data->nodes[i].weights_count)
- {
- return cgltf_result_invalid_gltf;
- }
+ CGLTF_ASSERT_IF (data->nodes[i].mesh->primitives_count && data->nodes[i].mesh->primitives[0].targets_count != data->nodes[i].weights_count, cgltf_result_invalid_gltf);
}
}
@@ -1322,10 +1530,7 @@ cgltf_result cgltf_validate(cgltf_data* data)
while (p1 && p2)
{
- if (p1 == p2)
- {
- return cgltf_result_invalid_gltf;
- }
+ CGLTF_ASSERT_IF(p1 == p2, cgltf_result_invalid_gltf);
p1 = p1->parent;
p2 = p2->parent ? p2->parent->parent : NULL;
@@ -1336,10 +1541,7 @@ cgltf_result cgltf_validate(cgltf_data* data)
{
for (cgltf_size j = 0; j < data->scenes[i].nodes_count; ++j)
{
- if (data->scenes[i].nodes[j]->parent)
- {
- return cgltf_result_invalid_gltf;
- }
+ CGLTF_ASSERT_IF(data->scenes[i].nodes[j]->parent, cgltf_result_invalid_gltf);
}
}
@@ -1358,20 +1560,14 @@ cgltf_result cgltf_validate(cgltf_data* data)
if (channel->target_path == cgltf_animation_path_type_weights)
{
- if (!channel->target_node->mesh || !channel->target_node->mesh->primitives_count)
- {
- return cgltf_result_invalid_gltf;
- }
+ CGLTF_ASSERT_IF(!channel->target_node->mesh || !channel->target_node->mesh->primitives_count, cgltf_result_invalid_gltf);
components = channel->target_node->mesh->primitives[0].targets_count;
}
cgltf_size values = channel->sampler->interpolation == cgltf_interpolation_type_cubic_spline ? 3 : 1;
- if (channel->sampler->input->count * components * values != channel->sampler->output->count)
- {
- return cgltf_result_data_too_short;
- }
+ CGLTF_ASSERT_IF(channel->sampler->input->count * components * values != channel->sampler->output->count, cgltf_result_data_too_short);
}
}
@@ -1406,6 +1602,16 @@ 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)
+{
+ for (cgltf_size i = 0; i < extensions_count; ++i)
+ {
+ data->memory.free(data->memory.user_data, extensions[i].name);
+ data->memory.free(data->memory.user_data, extensions[i].data);
+ }
+ data->memory.free(data->memory.user_data, extensions);
+}
+
void cgltf_free(cgltf_data* data)
{
if (!data)
@@ -1420,17 +1626,42 @@ void cgltf_free(cgltf_data* data)
data->memory.free(data->memory.user_data, data->asset.version);
data->memory.free(data->memory.user_data, data->asset.min_version);
+ cgltf_free_extensions(data, data->asset.extensions, data->asset.extensions_count);
+
+ for (cgltf_size i = 0; i < data->accessors_count; ++i)
+ {
+ data->memory.free(data->memory.user_data, data->accessors[i].name);
+
+ if(data->accessors[i].is_sparse)
+ {
+ 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_extensions(data, data->accessors[i].extensions, data->accessors[i].extensions_count);
+ }
data->memory.free(data->memory.user_data, data->accessors);
+
+ for (cgltf_size i = 0; i < data->buffer_views_count; ++i)
+ {
+ data->memory.free(data->memory.user_data, data->buffer_views[i].name);
+ data->memory.free(data->memory.user_data, data->buffer_views[i].data);
+
+ cgltf_free_extensions(data, data->buffer_views[i].extensions, data->buffer_views[i].extensions_count);
+ }
data->memory.free(data->memory.user_data, data->buffer_views);
for (cgltf_size i = 0; i < data->buffers_count; ++i)
{
+ data->memory.free(data->memory.user_data, data->buffers[i].name);
+
if (data->buffers[i].data != data->bin)
{
file_release(&data->memory, &data->file, data->buffers[i].data);
}
-
data->memory.free(data->memory.user_data, data->buffers[i].uri);
+
+ cgltf_free_extensions(data, data->buffers[i].extensions, data->buffers[i].extensions_count);
}
data->memory.free(data->memory.user_data, data->buffers);
@@ -1459,6 +1690,20 @@ void cgltf_free(cgltf_data* data)
}
data->memory.free(data->memory.user_data, data->meshes[i].primitives[j].targets);
+
+ if (data->meshes[i].primitives[j].has_draco_mesh_compression)
+ {
+ for (cgltf_size k = 0; k < data->meshes[i].primitives[j].draco_mesh_compression.attributes_count; ++k)
+ {
+ data->memory.free(data->memory.user_data, data->meshes[i].primitives[j].draco_mesh_compression.attributes[k].name);
+ }
+
+ data->memory.free(data->memory.user_data, data->meshes[i].primitives[j].draco_mesh_compression.attributes);
+ }
+
+ data->memory.free(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);
}
data->memory.free(data->memory.user_data, data->meshes[i].primitives);
@@ -1469,6 +1714,8 @@ void cgltf_free(cgltf_data* data)
data->memory.free(data->memory.user_data, data->meshes[i].target_names[j]);
}
+ cgltf_free_extensions(data, data->meshes[i].extensions, data->meshes[i].extensions_count);
+
data->memory.free(data->memory.user_data, data->meshes[i].target_names);
}
@@ -1477,6 +1724,47 @@ void cgltf_free(cgltf_data* data)
for (cgltf_size i = 0; i < data->materials_count; ++i)
{
data->memory.free(data->memory.user_data, data->materials[i].name);
+
+ 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);
+ }
+ 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);
+ }
+ 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);
+ }
+ 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);
+ }
+ 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);
+ }
+ 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);
+ }
+ 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_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_extensions(data, data->materials[i].extensions, data->materials[i].extensions_count);
}
data->memory.free(data->memory.user_data, data->materials);
@@ -1486,6 +1774,8 @@ void cgltf_free(cgltf_data* data)
data->memory.free(data->memory.user_data, data->images[i].name);
data->memory.free(data->memory.user_data, data->images[i].uri);
data->memory.free(data->memory.user_data, data->images[i].mime_type);
+
+ cgltf_free_extensions(data, data->images[i].extensions, data->images[i].extensions_count);
}
data->memory.free(data->memory.user_data, data->images);
@@ -1493,16 +1783,25 @@ void cgltf_free(cgltf_data* data)
for (cgltf_size i = 0; i < data->textures_count; ++i)
{
data->memory.free(data->memory.user_data, data->textures[i].name);
+ cgltf_free_extensions(data, data->textures[i].extensions, data->textures[i].extensions_count);
}
data->memory.free(data->memory.user_data, data->textures);
+ for (cgltf_size i = 0; i < data->samplers_count; ++i)
+ {
+ data->memory.free(data->memory.user_data, data->samplers[i].name);
+ cgltf_free_extensions(data, data->samplers[i].extensions, data->samplers[i].extensions_count);
+ }
+
data->memory.free(data->memory.user_data, data->samplers);
for (cgltf_size i = 0; i < data->skins_count; ++i)
{
data->memory.free(data->memory.user_data, data->skins[i].name);
data->memory.free(data->memory.user_data, data->skins[i].joints);
+
+ cgltf_free_extensions(data, data->skins[i].extensions, data->skins[i].extensions_count);
}
data->memory.free(data->memory.user_data, data->skins);
@@ -1510,6 +1809,7 @@ void cgltf_free(cgltf_data* data)
for (cgltf_size i = 0; i < data->cameras_count; ++i)
{
data->memory.free(data->memory.user_data, data->cameras[i].name);
+ cgltf_free_extensions(data, data->cameras[i].extensions, data->cameras[i].extensions_count);
}
data->memory.free(data->memory.user_data, data->cameras);
@@ -1526,6 +1826,7 @@ void cgltf_free(cgltf_data* data)
data->memory.free(data->memory.user_data, data->nodes[i].name);
data->memory.free(data->memory.user_data, data->nodes[i].children);
data->memory.free(data->memory.user_data, data->nodes[i].weights);
+ cgltf_free_extensions(data, data->nodes[i].extensions, data->nodes[i].extensions_count);
}
data->memory.free(data->memory.user_data, data->nodes);
@@ -1534,6 +1835,8 @@ void cgltf_free(cgltf_data* data)
{
data->memory.free(data->memory.user_data, data->scenes[i].name);
data->memory.free(data->memory.user_data, data->scenes[i].nodes);
+
+ cgltf_free_extensions(data, data->scenes[i].extensions, data->scenes[i].extensions_count);
}
data->memory.free(data->memory.user_data, data->scenes);
@@ -1541,12 +1844,32 @@ void cgltf_free(cgltf_data* data)
for (cgltf_size i = 0; i < data->animations_count; ++i)
{
data->memory.free(data->memory.user_data, data->animations[i].name);
+ 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);
+ }
data->memory.free(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);
+ }
data->memory.free(data->memory.user_data, data->animations[i].channels);
+
+ cgltf_free_extensions(data, data->animations[i].extensions, data->animations[i].extensions_count);
}
data->memory.free(data->memory.user_data, data->animations);
+ for (cgltf_size i = 0; i < data->variants_count; ++i)
+ {
+ data->memory.free(data->memory.user_data, data->variants[i].name);
+ }
+
+ data->memory.free(data->memory.user_data, data->variants);
+
+ cgltf_free_extensions(data, data->data_extensions, data->data_extensions_count);
+
for (cgltf_size i = 0; i < data->extensions_used_count; ++i)
{
data->memory.free(data->memory.user_data, data->extensions_used[i]);
@@ -1753,6 +2076,19 @@ static cgltf_bool cgltf_element_read_float(const uint8_t* element, cgltf_type ty
return 1;
}
+const uint8_t* cgltf_buffer_view_data(const cgltf_buffer_view* view)
+{
+ if (view->data)
+ return (const uint8_t*)view->data;
+
+ if (!view->buffer->data)
+ return NULL;
+
+ const uint8_t* result = (const uint8_t*)view->buffer->data;
+ result += view->offset;
+ return result;
+}
+
cgltf_bool cgltf_accessor_read_float(const cgltf_accessor* accessor, cgltf_size index, cgltf_float* out, cgltf_size element_size)
{
if (accessor->is_sparse)
@@ -1764,13 +2100,12 @@ cgltf_bool cgltf_accessor_read_float(const cgltf_accessor* accessor, cgltf_size
memset(out, 0, element_size * sizeof(cgltf_float));
return 1;
}
- if (accessor->buffer_view->buffer->data == NULL)
+ const uint8_t* element = cgltf_buffer_view_data(accessor->buffer_view);
+ if (element == NULL)
{
return 0;
}
- cgltf_size offset = accessor->offset + accessor->buffer_view->offset;
- const uint8_t* element = (const uint8_t*) accessor->buffer_view->buffer->data;
- element += offset + accessor->stride * index;
+ element += accessor->offset + accessor->stride * index;
return cgltf_element_read_float(element, accessor->type, accessor->component_type, accessor->normalized, out, element_size);
}
@@ -1803,16 +2138,18 @@ cgltf_size cgltf_accessor_unpack_floats(const cgltf_accessor* accessor, cgltf_fl
{
const cgltf_accessor_sparse* sparse = &dense.sparse;
- if (sparse->indices_buffer_view->buffer->data == NULL || sparse->values_buffer_view->buffer->data == NULL)
+ const uint8_t* index_data = cgltf_buffer_view_data(sparse->indices_buffer_view);
+ const uint8_t* reader_head = cgltf_buffer_view_data(sparse->values_buffer_view);
+
+ if (index_data == NULL || reader_head == NULL)
{
return 0;
}
- const uint8_t* index_data = (const uint8_t*) sparse->indices_buffer_view->buffer->data;
- index_data += sparse->indices_byte_offset + sparse->indices_buffer_view->offset;
+ index_data += sparse->indices_byte_offset;
+ reader_head += sparse->values_byte_offset;
+
cgltf_size index_stride = cgltf_component_size(sparse->indices_component_type);
- const uint8_t* reader_head = (const uint8_t*) sparse->values_buffer_view->buffer->data;
- reader_head += sparse->values_byte_offset + sparse->values_buffer_view->offset;
for (cgltf_size reader_index = 0; reader_index < sparse->count; reader_index++, index_data += index_stride)
{
size_t writer_index = cgltf_component_read_index(index_data, sparse->indices_component_type);
@@ -1852,53 +2189,50 @@ 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)
{
- cgltf_size num_components = cgltf_num_components(type);
+ cgltf_size num_components = cgltf_num_components(type);
- if (element_size < num_components)
- {
- return 0;
- }
+ if (element_size < num_components)
+ {
+ return 0;
+ }
// Reading integer matrices is not a valid use case
- if (type == cgltf_type_mat2 || type == cgltf_type_mat3 || type == cgltf_type_mat4)
- {
- return 0;
- }
-
- cgltf_size component_size = cgltf_component_size(component_type);
-
- for (cgltf_size i = 0; i < num_components; ++i)
- {
- out[i] = cgltf_component_read_uint(element + component_size * i, component_type);
- }
- return 1;
+ if (type == cgltf_type_mat2 || type == cgltf_type_mat3 || type == cgltf_type_mat4)
+ {
+ return 0;
+ }
+
+ cgltf_size component_size = cgltf_component_size(component_type);
+
+ for (cgltf_size i = 0; i < num_components; ++i)
+ {
+ out[i] = cgltf_component_read_uint(element + component_size * i, component_type);
+ }
+ return 1;
}
cgltf_bool cgltf_accessor_read_uint(const cgltf_accessor* accessor, cgltf_size index, cgltf_uint* out, cgltf_size element_size)
{
- if (accessor->is_sparse)
- {
- return 0;
- }
- if (accessor->buffer_view == NULL)
- {
- memset(out, 0, element_size * sizeof( cgltf_uint ));
- return 1;
- }
- if (accessor->buffer_view->buffer->data == NULL)
- {
- return 0;
- }
- cgltf_size offset = accessor->offset + accessor->buffer_view->offset;
- const uint8_t* element = (const uint8_t*) accessor->buffer_view->buffer->data;
- element += offset + accessor->stride * index;
- return cgltf_element_read_uint(element, accessor->type, accessor->component_type, out, element_size);
+ if (accessor->is_sparse)
+ {
+ return 0;
+ }
+ if (accessor->buffer_view == NULL)
+ {
+ memset(out, 0, element_size * sizeof( cgltf_uint ));
+ return 1;
+ }
+ const uint8_t* element = cgltf_buffer_view_data(accessor->buffer_view);
+ if (element == NULL)
+ {
+ return 0;
+ }
+ element += accessor->offset + accessor->stride * index;
+ return cgltf_element_read_uint(element, accessor->type, accessor->component_type, out, element_size);
}
cgltf_size cgltf_accessor_read_index(const cgltf_accessor* accessor, cgltf_size index)
@@ -1911,14 +2245,12 @@ cgltf_size cgltf_accessor_read_index(const cgltf_accessor* accessor, cgltf_size
{
return 0;
}
- if (accessor->buffer_view->buffer->data == NULL)
+ const uint8_t* element = cgltf_buffer_view_data(accessor->buffer_view);
+ if (element == NULL)
{
return 0; // This is an error case, but we can't communicate the error with existing interface.
}
-
- cgltf_size offset = accessor->offset + accessor->buffer_view->offset;
- const uint8_t* element = (const uint8_t*) accessor->buffer_view->buffer->data;
- element += offset + accessor->stride * index;
+ element += accessor->offset + accessor->stride * index;
return cgltf_component_read_index(element, accessor->component_type);
}
@@ -2065,22 +2397,22 @@ static int cgltf_parse_json_array(cgltf_options* options, jsmntok_t const* token
static int cgltf_parse_json_string_array(cgltf_options* options, jsmntok_t const* tokens, int i, const uint8_t* json_chunk, char*** out_array, cgltf_size* out_size)
{
- CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_ARRAY);
- i = cgltf_parse_json_array(options, tokens, i, json_chunk, sizeof(char*), (void**)out_array, out_size);
- if (i < 0)
- {
- return i;
- }
-
- for (cgltf_size j = 0; j < *out_size; ++j)
- {
- i = cgltf_parse_json_string(options, tokens, i, json_chunk, j + (*out_array));
- if (i < 0)
- {
- return i;
- }
- }
- return i;
+ CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_ARRAY);
+ i = cgltf_parse_json_array(options, tokens, i, json_chunk, sizeof(char*), (void**)out_array, out_size);
+ if (i < 0)
+ {
+ return i;
+ }
+
+ for (cgltf_size j = 0; j < *out_size; ++j)
+ {
+ i = cgltf_parse_json_string(options, tokens, i, json_chunk, j + (*out_array));
+ if (i < 0)
+ {
+ return i;
+ }
+ }
+ return i;
}
static void cgltf_parse_attribute_type(const char* name, cgltf_attribute_type* out_type, int* out_index)
@@ -2173,6 +2505,233 @@ static int cgltf_parse_json_extras(jsmntok_t const* tokens, int i, const uint8_t
return i;
}
+static int cgltf_parse_json_unprocessed_extension(cgltf_options* options, jsmntok_t const* tokens, int i, const uint8_t* json_chunk, cgltf_extension* out_extension)
+{
+ CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_STRING);
+ CGLTF_CHECK_TOKTYPE(tokens[i+1], JSMN_OBJECT);
+ if (out_extension->name)
+ {
+ return CGLTF_ERROR_JSON;
+ }
+
+ cgltf_size name_length = tokens[i].end - tokens[i].start;
+ out_extension->name = (char*)options->memory.alloc(options->memory.user_data, name_length + 1);
+ if (!out_extension->name)
+ {
+ return CGLTF_ERROR_NOMEM;
+ }
+ strncpy(out_extension->name, (const char*)json_chunk + tokens[i].start, name_length);
+ out_extension->name[name_length] = 0;
+ i++;
+
+ size_t start = tokens[i].start;
+ size_t size = tokens[i].end - start;
+ out_extension->data = (char*)options->memory.alloc(options->memory.user_data, size + 1);
+ if (!out_extension->data)
+ {
+ return CGLTF_ERROR_NOMEM;
+ }
+ strncpy(out_extension->data, (const char*)json_chunk + start, size);
+ out_extension->data[size] = '\0';
+
+ i = cgltf_skip_json(tokens, i);
+
+ return i;
+}
+
+static int cgltf_parse_json_unprocessed_extensions(cgltf_options* options, jsmntok_t const* tokens, int i, const uint8_t* json_chunk, cgltf_size* out_extensions_count, cgltf_extension** out_extensions)
+{
+ ++i;
+
+ CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
+ if(*out_extensions)
+ {
+ return CGLTF_ERROR_JSON;
+ }
+
+ int extensions_size = tokens[i].size;
+ *out_extensions_count = 0;
+ *out_extensions = (cgltf_extension*)cgltf_calloc(options, sizeof(cgltf_extension), extensions_size);
+
+ if (!*out_extensions)
+ {
+ return CGLTF_ERROR_NOMEM;
+ }
+
+ ++i;
+
+ for (int j = 0; j < extensions_size; ++j)
+ {
+ CGLTF_CHECK_KEY(tokens[i]);
+
+ cgltf_size extension_index = (*out_extensions_count)++;
+ cgltf_extension* extension = &((*out_extensions)[extension_index]);
+ i = cgltf_parse_json_unprocessed_extension(options, tokens, i, json_chunk, extension);
+
+ if (i < 0)
+ {
+ return i;
+ }
+ }
+ 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;
+ }
+
+ if (i < 0)
+ {
+ return i;
+ }
+ }
+
+ return i;
+}
+
+static int cgltf_parse_json_material_mapping_data(cgltf_options* options, jsmntok_t const* tokens, int i, const uint8_t* json_chunk, cgltf_material_mapping* out_mappings, cgltf_size* offset)
+{
+ (void)options;
+ CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_ARRAY);
+
+ int size = tokens[i].size;
+ ++i;
+
+ for (int j = 0; j < size; ++j)
+ {
+ CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
+
+ int obj_size = tokens[i].size;
+ ++i;
+
+ int material = -1;
+ int variants_tok = -1;
+ cgltf_extras extras = {0, 0};
+
+ for (int k = 0; k < obj_size; ++k)
+ {
+ CGLTF_CHECK_KEY(tokens[i]);
+
+ if (cgltf_json_strcmp(tokens + i, json_chunk, "material") == 0)
+ {
+ ++i;
+ material = cgltf_json_to_int(tokens + i, json_chunk);
+ ++i;
+ }
+ else if (cgltf_json_strcmp(tokens + i, json_chunk, "variants") == 0)
+ {
+ variants_tok = i+1;
+ CGLTF_CHECK_TOKTYPE(tokens[variants_tok], JSMN_ARRAY);
+
+ i = cgltf_skip_json(tokens, i+1);
+ }
+ else if (cgltf_json_strcmp(tokens + i, json_chunk, "extras") == 0)
+ {
+ i = cgltf_parse_json_extras(tokens, i + 1, json_chunk, &extras);
+ }
+ else
+ {
+ i = cgltf_skip_json(tokens, i+1);
+ }
+
+ if (i < 0)
+ {
+ return i;
+ }
+ }
+
+ if (material < 0 || variants_tok < 0)
+ {
+ return CGLTF_ERROR_JSON;
+ }
+
+ if (out_mappings)
+ {
+ for (int k = 0; k < tokens[variants_tok].size; ++k)
+ {
+ int variant = cgltf_json_to_int(&tokens[variants_tok + 1 + k], json_chunk);
+ if (variant < 0)
+ return variant;
+
+ out_mappings[*offset].material = CGLTF_PTRINDEX(cgltf_material, material);
+ out_mappings[*offset].variant = variant;
+ out_mappings[*offset].extras = extras;
+
+ (*offset)++;
+ }
+ }
+ else
+ {
+ (*offset) += tokens[variants_tok].size;
+ }
+ }
+
+ return i;
+}
+
+static int cgltf_parse_json_material_mappings(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);
+
+ 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, "mappings") == 0)
+ {
+ if (out_prim->mappings)
+ {
+ return CGLTF_ERROR_JSON;
+ }
+
+ cgltf_size mappings_offset = 0;
+ int k = cgltf_parse_json_material_mapping_data(options, tokens, i + 1, json_chunk, NULL, &mappings_offset);
+ if (k < 0)
+ {
+ return k;
+ }
+
+ out_prim->mappings_count = mappings_offset;
+ out_prim->mappings = (cgltf_material_mapping*)cgltf_calloc(options, sizeof(cgltf_material_mapping), out_prim->mappings_count);
+
+ mappings_offset = 0;
+ i = cgltf_parse_json_material_mapping_data(options, tokens, i + 1, json_chunk, out_prim->mappings, &mappings_offset);
+ }
+ else
+ {
+ i = cgltf_skip_json(tokens, i+1);
+ }
+
+ if (i < 0)
+ {
+ return 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);
@@ -2231,6 +2790,50 @@ 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);
+ if(out_prim->extensions)
+ {
+ return CGLTF_ERROR_JSON;
+ }
+
+ int extensions_size = tokens[i].size;
+ out_prim->extensions_count = 0;
+ out_prim->extensions = (cgltf_extension*)cgltf_calloc(options, sizeof(cgltf_extension), extensions_size);
+
+ if (!out_prim->extensions)
+ {
+ return CGLTF_ERROR_NOMEM;
+ }
+
+ ++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 if (cgltf_json_strcmp(tokens+i, json_chunk, "KHR_materials_variants") == 0)
+ {
+ i = cgltf_parse_json_material_mappings(options, tokens, i + 1, json_chunk, out_prim);
+ }
+ else
+ {
+ i = cgltf_parse_json_unprocessed_extension(options, tokens, i, json_chunk, &(out_prim->extensions[out_prim->extensions_count++]));
+ }
+
+ if (i < 0)
+ {
+ return i;
+ }
+ }
+ }
else
{
i = cgltf_skip_json(tokens, i+1);
@@ -2303,7 +2906,7 @@ static int cgltf_parse_json_mesh(cgltf_options* options, jsmntok_t const* tokens
{
CGLTF_CHECK_KEY(tokens[i]);
- if (cgltf_json_strcmp(tokens+i, json_chunk, "targetNames") == 0)
+ if (cgltf_json_strcmp(tokens+i, json_chunk, "targetNames") == 0 && tokens[i+1].type == JSMN_ARRAY)
{
i = cgltf_parse_json_string_array(options, tokens, i + 1, json_chunk, &out_mesh->target_names, &out_mesh->target_names_count);
}
@@ -2323,6 +2926,10 @@ static int cgltf_parse_json_mesh(cgltf_options* options, jsmntok_t const* tokens
i = cgltf_skip_json(tokens, i);
}
}
+ else if (cgltf_json_strcmp(tokens + i, json_chunk, "extensions") == 0)
+ {
+ i = cgltf_parse_json_unprocessed_extensions(options, tokens, i, json_chunk, &out_mesh->extensions_count, &out_mesh->extensions);
+ }
else
{
i = cgltf_skip_json(tokens, i+1);
@@ -2379,7 +2986,7 @@ static cgltf_component_type cgltf_json_to_component_type(jsmntok_t const* tok, c
}
}
-static int cgltf_parse_json_accessor_sparse(jsmntok_t const* tokens, int i, const uint8_t* json_chunk, cgltf_accessor_sparse* out_sparse)
+static int cgltf_parse_json_accessor_sparse(cgltf_options* options, jsmntok_t const* tokens, int i, const uint8_t* json_chunk, cgltf_accessor_sparse* out_sparse)
{
CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
@@ -2430,6 +3037,10 @@ static int cgltf_parse_json_accessor_sparse(jsmntok_t const* tokens, int i, cons
{
i = cgltf_parse_json_extras(tokens, i + 1, json_chunk, &out_sparse->indices_extras);
}
+ else if (cgltf_json_strcmp(tokens + i, json_chunk, "extensions") == 0)
+ {
+ i = cgltf_parse_json_unprocessed_extensions(options, tokens, i, json_chunk, &out_sparse->indices_extensions_count, &out_sparse->indices_extensions);
+ }
else
{
i = cgltf_skip_json(tokens, i+1);
@@ -2469,6 +3080,10 @@ static int cgltf_parse_json_accessor_sparse(jsmntok_t const* tokens, int i, cons
{
i = cgltf_parse_json_extras(tokens, i + 1, json_chunk, &out_sparse->values_extras);
}
+ else if (cgltf_json_strcmp(tokens + i, json_chunk, "extensions") == 0)
+ {
+ i = cgltf_parse_json_unprocessed_extensions(options, tokens, i, json_chunk, &out_sparse->values_extensions_count, &out_sparse->values_extensions);
+ }
else
{
i = cgltf_skip_json(tokens, i+1);
@@ -2484,6 +3099,10 @@ static int cgltf_parse_json_accessor_sparse(jsmntok_t const* tokens, int i, cons
{
i = cgltf_parse_json_extras(tokens, i + 1, json_chunk, &out_sparse->extras);
}
+ else if (cgltf_json_strcmp(tokens + i, json_chunk, "extensions") == 0)
+ {
+ i = cgltf_parse_json_unprocessed_extensions(options, tokens, i, json_chunk, &out_sparse->extensions_count, &out_sparse->extensions);
+ }
else
{
i = cgltf_skip_json(tokens, i+1);
@@ -2498,7 +3117,7 @@ static int cgltf_parse_json_accessor_sparse(jsmntok_t const* tokens, int i, cons
return i;
}
-static int cgltf_parse_json_accessor(jsmntok_t const* tokens, int i, const uint8_t* json_chunk, cgltf_accessor* out_accessor)
+static int cgltf_parse_json_accessor(cgltf_options* options, jsmntok_t const* tokens, int i, const uint8_t* json_chunk, cgltf_accessor* out_accessor)
{
CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
@@ -2509,7 +3128,11 @@ static int cgltf_parse_json_accessor(jsmntok_t const* tokens, int i, const uint8
{
CGLTF_CHECK_KEY(tokens[i]);
- if (cgltf_json_strcmp(tokens+i, json_chunk, "bufferView") == 0)
+ if (cgltf_json_strcmp(tokens + i, json_chunk, "name") == 0)
+ {
+ i = cgltf_parse_json_string(options, tokens, i + 1, json_chunk, &out_accessor->name);
+ }
+ else if (cgltf_json_strcmp(tokens+i, json_chunk, "bufferView") == 0)
{
++i;
out_accessor->buffer_view = CGLTF_PTRINDEX(cgltf_buffer_view, cgltf_json_to_int(tokens + i, json_chunk));
@@ -2593,12 +3216,16 @@ static int cgltf_parse_json_accessor(jsmntok_t const* tokens, int i, const uint8
else if (cgltf_json_strcmp(tokens + i, json_chunk, "sparse") == 0)
{
out_accessor->is_sparse = 1;
- i = cgltf_parse_json_accessor_sparse(tokens, i + 1, json_chunk, &out_accessor->sparse);
+ i = cgltf_parse_json_accessor_sparse(options, tokens, i + 1, json_chunk, &out_accessor->sparse);
}
else if (cgltf_json_strcmp(tokens + i, json_chunk, "extras") == 0)
{
i = cgltf_parse_json_extras(tokens, i + 1, json_chunk, &out_accessor->extras);
}
+ else if (cgltf_json_strcmp(tokens + i, json_chunk, "extensions") == 0)
+ {
+ i = cgltf_parse_json_unprocessed_extensions(options, tokens, i, json_chunk, &out_accessor->extensions_count, &out_accessor->extensions);
+ }
else
{
i = cgltf_skip_json(tokens, i+1);
@@ -2658,7 +3285,7 @@ static int cgltf_parse_json_texture_transform(jsmntok_t const* tokens, int i, co
return i;
}
-static int cgltf_parse_json_texture_view(jsmntok_t const* tokens, int i, const uint8_t* json_chunk, cgltf_texture_view* out_texture_view)
+static int cgltf_parse_json_texture_view(cgltf_options* options, jsmntok_t const* tokens, int i, const uint8_t* json_chunk, cgltf_texture_view* out_texture_view)
{
CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
@@ -2705,8 +3332,20 @@ static int cgltf_parse_json_texture_view(jsmntok_t const* tokens, int i, const u
++i;
CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
+ if(out_texture_view->extensions)
+ {
+ return CGLTF_ERROR_JSON;
+ }
int extensions_size = tokens[i].size;
+ out_texture_view->extensions_count = 0;
+ out_texture_view->extensions = (cgltf_extension*)cgltf_calloc(options, sizeof(cgltf_extension), extensions_size);
+
+ if (!out_texture_view->extensions)
+ {
+ return CGLTF_ERROR_NOMEM;
+ }
+
++i;
for (int k = 0; k < extensions_size; ++k)
@@ -2720,7 +3359,7 @@ static int cgltf_parse_json_texture_view(jsmntok_t const* tokens, int i, const u
}
else
{
- i = cgltf_skip_json(tokens, i+1);
+ i = cgltf_parse_json_unprocessed_extension(options, tokens, i, json_chunk, &(out_texture_view->extensions[out_texture_view->extensions_count++]));
}
if (i < 0)
@@ -2743,7 +3382,7 @@ static int cgltf_parse_json_texture_view(jsmntok_t const* tokens, int i, const u
return i;
}
-static int cgltf_parse_json_pbr_metallic_roughness(jsmntok_t const* tokens, int i, const uint8_t* json_chunk, cgltf_pbr_metallic_roughness* out_pbr)
+static int cgltf_parse_json_pbr_metallic_roughness(cgltf_options* options, jsmntok_t const* tokens, int i, const uint8_t* json_chunk, cgltf_pbr_metallic_roughness* out_pbr)
{
CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
@@ -2774,12 +3413,12 @@ static int cgltf_parse_json_pbr_metallic_roughness(jsmntok_t const* tokens, int
}
else if (cgltf_json_strcmp(tokens+i, json_chunk, "baseColorTexture") == 0)
{
- i = cgltf_parse_json_texture_view(tokens, i + 1, json_chunk,
+ i = cgltf_parse_json_texture_view(options, tokens, i + 1, json_chunk,
&out_pbr->base_color_texture);
}
else if (cgltf_json_strcmp(tokens + i, json_chunk, "metallicRoughnessTexture") == 0)
{
- i = cgltf_parse_json_texture_view(tokens, i + 1, json_chunk,
+ 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)
@@ -2800,7 +3439,7 @@ static int cgltf_parse_json_pbr_metallic_roughness(jsmntok_t const* tokens, int
return i;
}
-static int cgltf_parse_json_pbr_specular_glossiness(jsmntok_t const* tokens, int i, const uint8_t* json_chunk, cgltf_pbr_specular_glossiness* out_pbr)
+static int cgltf_parse_json_pbr_specular_glossiness(cgltf_options* options, jsmntok_t const* tokens, int i, const uint8_t* json_chunk, cgltf_pbr_specular_glossiness* out_pbr)
{
CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
int size = tokens[i].size;
@@ -2826,11 +3465,258 @@ static int cgltf_parse_json_pbr_specular_glossiness(jsmntok_t const* tokens, int
}
else if (cgltf_json_strcmp(tokens+i, json_chunk, "diffuseTexture") == 0)
{
- i = cgltf_parse_json_texture_view(tokens, i + 1, json_chunk, &out_pbr->diffuse_texture);
+ i = cgltf_parse_json_texture_view(options, tokens, i + 1, json_chunk, &out_pbr->diffuse_texture);
}
else if (cgltf_json_strcmp(tokens+i, json_chunk, "specularGlossinessTexture") == 0)
{
- i = cgltf_parse_json_texture_view(tokens, i + 1, json_chunk, &out_pbr->specular_glossiness_texture);
+ i = cgltf_parse_json_texture_view(options, tokens, i + 1, json_chunk, &out_pbr->specular_glossiness_texture);
+ }
+ else
+ {
+ i = cgltf_skip_json(tokens, i+1);
+ }
+
+ if (i < 0)
+ {
+ return i;
+ }
+ }
+
+ return i;
+}
+
+static int cgltf_parse_json_clearcoat(cgltf_options* options, 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(options, 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(options, 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(options, 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_ior(jsmntok_t const* tokens, int i, const uint8_t* json_chunk, cgltf_ior* out_ior)
+{
+ CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
+ int size = tokens[i].size;
+ ++i;
+
+ // Default values
+ out_ior->ior = 1.5f;
+
+ for (int j = 0; j < size; ++j)
+ {
+ CGLTF_CHECK_KEY(tokens[i]);
+
+ if (cgltf_json_strcmp(tokens+i, json_chunk, "ior") == 0)
+ {
+ ++i;
+ out_ior->ior = cgltf_json_to_float(tokens + i, json_chunk);
+ ++i;
+ }
+ else
+ {
+ i = cgltf_skip_json(tokens, i+1);
+ }
+
+ if (i < 0)
+ {
+ return i;
+ }
+ }
+
+ return i;
+}
+
+static int cgltf_parse_json_specular(cgltf_options* options, jsmntok_t const* tokens, int i, const uint8_t* json_chunk, cgltf_specular* out_specular)
+{
+ CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
+ int size = tokens[i].size;
+ ++i;
+
+ // Default values
+ out_specular->specular_factor = 1.0f;
+ cgltf_fill_float_array(out_specular->specular_color_factor, 3, 1.0f);
+
+ for (int j = 0; j < size; ++j)
+ {
+ CGLTF_CHECK_KEY(tokens[i]);
+
+ if (cgltf_json_strcmp(tokens+i, json_chunk, "specularFactor") == 0)
+ {
+ ++i;
+ out_specular->specular_factor = cgltf_json_to_float(tokens + i, json_chunk);
+ ++i;
+ }
+ else if (cgltf_json_strcmp(tokens+i, json_chunk, "specularColorFactor") == 0)
+ {
+ i = cgltf_parse_json_float_array(tokens, i + 1, json_chunk, out_specular->specular_color_factor, 3);
+ }
+ else if (cgltf_json_strcmp(tokens+i, json_chunk, "specularTexture") == 0)
+ {
+ i = cgltf_parse_json_texture_view(options, tokens, i + 1, json_chunk, &out_specular->specular_texture);
+ }
+ else if (cgltf_json_strcmp(tokens + i, json_chunk, "specularColorTexture") == 0)
+ {
+ i = cgltf_parse_json_texture_view(options, tokens, i + 1, json_chunk, &out_specular->specular_color_texture);
+ }
+ else
+ {
+ i = cgltf_skip_json(tokens, i+1);
+ }
+
+ if (i < 0)
+ {
+ return i;
+ }
+ }
+
+ return i;
+}
+
+static int cgltf_parse_json_transmission(cgltf_options* options, jsmntok_t const* tokens, int i, const uint8_t* json_chunk, cgltf_transmission* out_transmission)
+{
+ 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, "transmissionFactor") == 0)
+ {
+ ++i;
+ out_transmission->transmission_factor = cgltf_json_to_float(tokens + i, json_chunk);
+ ++i;
+ }
+ else if (cgltf_json_strcmp(tokens+i, json_chunk, "transmissionTexture") == 0)
+ {
+ i = cgltf_parse_json_texture_view(options, tokens, i + 1, json_chunk, &out_transmission->transmission_texture);
+ }
+ else
+ {
+ i = cgltf_skip_json(tokens, i+1);
+ }
+
+ if (i < 0)
+ {
+ return i;
+ }
+ }
+
+ return i;
+}
+
+static int cgltf_parse_json_volume(cgltf_options* options, jsmntok_t const* tokens, int i, const uint8_t* json_chunk, cgltf_volume* out_volume)
+{
+ 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, "thicknessFactor") == 0)
+ {
+ ++i;
+ out_volume->thickness_factor = cgltf_json_to_float(tokens + i, json_chunk);
+ ++i;
+ }
+ else if (cgltf_json_strcmp(tokens + i, json_chunk, "thicknessTexture") == 0)
+ {
+ i = cgltf_parse_json_texture_view(options, tokens, i + 1, json_chunk, &out_volume->thickness_texture);
+ }
+ else if (cgltf_json_strcmp(tokens + i, json_chunk, "attenuationColor") == 0)
+ {
+ i = cgltf_parse_json_float_array(tokens, i + 1, json_chunk, out_volume->attenuation_color, 3);
+ }
+ else if (cgltf_json_strcmp(tokens + i, json_chunk, "attenuationDistance") == 0)
+ {
+ ++i;
+ out_volume->attenuation_distance = cgltf_json_to_float(tokens + i, json_chunk);
+ ++i;
+ }
+ else
+ {
+ i = cgltf_skip_json(tokens, i + 1);
+ }
+
+ if (i < 0)
+ {
+ return i;
+ }
+ }
+
+ return i;
+}
+
+static int cgltf_parse_json_sheen(cgltf_options* options, jsmntok_t const* tokens, int i, const uint8_t* json_chunk, cgltf_sheen* out_sheen)
+{
+ 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, "sheenColorFactor") == 0)
+ {
+ i = cgltf_parse_json_float_array(tokens, i + 1, json_chunk, out_sheen->sheen_color_factor, 3);
+ }
+ else if (cgltf_json_strcmp(tokens+i, json_chunk, "sheenColorTexture") == 0)
+ {
+ i = cgltf_parse_json_texture_view(options, tokens, i + 1, json_chunk, &out_sheen->sheen_color_texture);
+ }
+ else if (cgltf_json_strcmp(tokens+i, json_chunk, "sheenRoughnessFactor") == 0)
+ {
+ ++i;
+ out_sheen->sheen_roughness_factor = cgltf_json_to_float(tokens + i, json_chunk);
+ ++i;
+ }
+ else if (cgltf_json_strcmp(tokens+i, json_chunk, "sheenRoughnessTexture") == 0)
+ {
+ i = cgltf_parse_json_texture_view(options, tokens, i + 1, json_chunk, &out_sheen->sheen_roughness_texture);
}
else
{
@@ -2879,6 +3765,10 @@ static int cgltf_parse_json_image(cgltf_options* options, jsmntok_t const* token
{
i = cgltf_parse_json_extras(tokens, i + 1, json_chunk, &out_image->extras);
}
+ else if (cgltf_json_strcmp(tokens + i, json_chunk, "extensions") == 0)
+ {
+ i = cgltf_parse_json_unprocessed_extensions(options, tokens, i, json_chunk, &out_image->extensions_count, &out_image->extensions);
+ }
else
{
i = cgltf_skip_json(tokens, i + 1);
@@ -2908,7 +3798,11 @@ static int cgltf_parse_json_sampler(cgltf_options* options, jsmntok_t const* tok
{
CGLTF_CHECK_KEY(tokens[i]);
- if (cgltf_json_strcmp(tokens + i, json_chunk, "magFilter") == 0)
+ if (cgltf_json_strcmp(tokens + i, json_chunk, "name") == 0)
+ {
+ i = cgltf_parse_json_string(options, tokens, i + 1, json_chunk, &out_sampler->name);
+ }
+ else if (cgltf_json_strcmp(tokens + i, json_chunk, "magFilter") == 0)
{
++i;
out_sampler->mag_filter
@@ -2940,6 +3834,10 @@ static int cgltf_parse_json_sampler(cgltf_options* options, jsmntok_t const* tok
{
i = cgltf_parse_json_extras(tokens, i + 1, json_chunk, &out_sampler->extras);
}
+ else if (cgltf_json_strcmp(tokens + i, json_chunk, "extensions") == 0)
+ {
+ i = cgltf_parse_json_unprocessed_extensions(options, tokens, i, json_chunk, &out_sampler->extensions_count, &out_sampler->extensions);
+ }
else
{
i = cgltf_skip_json(tokens, i + 1);
@@ -2954,7 +3852,6 @@ static int cgltf_parse_json_sampler(cgltf_options* options, jsmntok_t const* tok
return i;
}
-
static int cgltf_parse_json_texture(cgltf_options* options, jsmntok_t const* tokens, int i, const uint8_t* json_chunk, cgltf_texture* out_texture)
{
CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
@@ -2986,6 +3883,10 @@ static int cgltf_parse_json_texture(cgltf_options* options, jsmntok_t const* tok
{
i = cgltf_parse_json_extras(tokens, i + 1, json_chunk, &out_texture->extras);
}
+ else if (cgltf_json_strcmp(tokens + i, json_chunk, "extensions") == 0)
+ {
+ i = cgltf_parse_json_unprocessed_extensions(options, tokens, i, json_chunk, &out_texture->extensions_count, &out_texture->extensions);
+ }
else
{
i = cgltf_skip_json(tokens, i + 1);
@@ -3012,6 +3913,9 @@ static int cgltf_parse_json_material(cgltf_options* options, jsmntok_t const* to
cgltf_fill_float_array(out_material->pbr_specular_glossiness.specular_factor, 3, 1.0f);
out_material->pbr_specular_glossiness.glossiness_factor = 1.0f;
+ cgltf_fill_float_array(out_material->volume.attenuation_color, 3, 1.0f);
+ out_material->volume.attenuation_distance = FLT_MAX;
+
out_material->alpha_cutoff = 0.5f;
int size = tokens[i].size;
@@ -3028,7 +3932,7 @@ static int cgltf_parse_json_material(cgltf_options* options, jsmntok_t const* to
else if (cgltf_json_strcmp(tokens+i, json_chunk, "pbrMetallicRoughness") == 0)
{
out_material->has_pbr_metallic_roughness = 1;
- i = cgltf_parse_json_pbr_metallic_roughness(tokens, i + 1, json_chunk, &out_material->pbr_metallic_roughness);
+ i = cgltf_parse_json_pbr_metallic_roughness(options, tokens, i + 1, json_chunk, &out_material->pbr_metallic_roughness);
}
else if (cgltf_json_strcmp(tokens+i, json_chunk, "emissiveFactor") == 0)
{
@@ -3036,17 +3940,17 @@ static int cgltf_parse_json_material(cgltf_options* options, jsmntok_t const* to
}
else if (cgltf_json_strcmp(tokens + i, json_chunk, "normalTexture") == 0)
{
- i = cgltf_parse_json_texture_view(tokens, i + 1, json_chunk,
+ i = cgltf_parse_json_texture_view(options, tokens, i + 1, json_chunk,
&out_material->normal_texture);
}
else if (cgltf_json_strcmp(tokens + i, json_chunk, "occlusionTexture") == 0)
{
- i = cgltf_parse_json_texture_view(tokens, i + 1, json_chunk,
+ i = cgltf_parse_json_texture_view(options, tokens, i + 1, json_chunk,
&out_material->occlusion_texture);
}
else if (cgltf_json_strcmp(tokens + i, json_chunk, "emissiveTexture") == 0)
{
- i = cgltf_parse_json_texture_view(tokens, i + 1, json_chunk,
+ i = cgltf_parse_json_texture_view(options, tokens, i + 1, json_chunk,
&out_material->emissive_texture);
}
else if (cgltf_json_strcmp(tokens + i, json_chunk, "alphaMode") == 0)
@@ -3088,9 +3992,20 @@ static int cgltf_parse_json_material(cgltf_options* options, jsmntok_t const* to
++i;
CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
+ if(out_material->extensions)
+ {
+ return CGLTF_ERROR_JSON;
+ }
int extensions_size = tokens[i].size;
++i;
+ out_material->extensions = (cgltf_extension*)cgltf_calloc(options, sizeof(cgltf_extension), extensions_size);
+ out_material->extensions_count= 0;
+
+ if (!out_material->extensions)
+ {
+ return CGLTF_ERROR_NOMEM;
+ }
for (int k = 0; k < extensions_size; ++k)
{
@@ -3099,16 +4014,46 @@ static int cgltf_parse_json_material(cgltf_options* options, jsmntok_t const* to
if (cgltf_json_strcmp(tokens+i, json_chunk, "KHR_materials_pbrSpecularGlossiness") == 0)
{
out_material->has_pbr_specular_glossiness = 1;
- i = cgltf_parse_json_pbr_specular_glossiness(tokens, i + 1, json_chunk, &out_material->pbr_specular_glossiness);
+ i = cgltf_parse_json_pbr_specular_glossiness(options, tokens, i + 1, json_chunk, &out_material->pbr_specular_glossiness);
}
else if (cgltf_json_strcmp(tokens+i, json_chunk, "KHR_materials_unlit") == 0)
{
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(options, tokens, i + 1, json_chunk, &out_material->clearcoat);
+ }
+ else if (cgltf_json_strcmp(tokens+i, json_chunk, "KHR_materials_ior") == 0)
+ {
+ out_material->has_ior = 1;
+ i = cgltf_parse_json_ior(tokens, i + 1, json_chunk, &out_material->ior);
+ }
+ else if (cgltf_json_strcmp(tokens+i, json_chunk, "KHR_materials_specular") == 0)
+ {
+ out_material->has_specular = 1;
+ i = cgltf_parse_json_specular(options, tokens, i + 1, json_chunk, &out_material->specular);
+ }
+ else if (cgltf_json_strcmp(tokens+i, json_chunk, "KHR_materials_transmission") == 0)
+ {
+ out_material->has_transmission = 1;
+ i = cgltf_parse_json_transmission(options, tokens, i + 1, json_chunk, &out_material->transmission);
+ }
+ else if (cgltf_json_strcmp(tokens + i, json_chunk, "KHR_materials_volume") == 0)
+ {
+ out_material->has_volume = 1;
+ i = cgltf_parse_json_volume(options, tokens, i + 1, json_chunk, &out_material->volume);
+ }
+ else if (cgltf_json_strcmp(tokens+i, json_chunk, "KHR_materials_sheen") == 0)
+ {
+ out_material->has_sheen = 1;
+ i = cgltf_parse_json_sheen(options, tokens, i + 1, json_chunk, &out_material->sheen);
+ }
else
{
- i = cgltf_skip_json(tokens, i+1);
+ i = cgltf_parse_json_unprocessed_extension(options, tokens, i, json_chunk, &(out_material->extensions[out_material->extensions_count++]));
}
if (i < 0)
@@ -3141,7 +4086,7 @@ static int cgltf_parse_json_accessors(cgltf_options* options, jsmntok_t const* t
for (cgltf_size j = 0; j < out_data->accessors_count; ++j)
{
- i = cgltf_parse_json_accessor(tokens, i, json_chunk, &out_data->accessors[j]);
+ i = cgltf_parse_json_accessor(options, tokens, i, json_chunk, &out_data->accessors[j]);
if (i < 0)
{
return i;
@@ -3226,8 +4171,9 @@ static int cgltf_parse_json_samplers(cgltf_options* options, jsmntok_t const* to
return i;
}
-static int cgltf_parse_json_buffer_view(jsmntok_t const* tokens, int i, const uint8_t* json_chunk, cgltf_buffer_view* out_buffer_view)
+static int cgltf_parse_json_meshopt_compression(cgltf_options* options, jsmntok_t const* tokens, int i, const uint8_t* json_chunk, cgltf_meshopt_compression* out_meshopt_compression)
{
+ (void)options;
CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
int size = tokens[i].size;
@@ -3240,6 +4186,103 @@ static int cgltf_parse_json_buffer_view(jsmntok_t const* tokens, int i, const ui
if (cgltf_json_strcmp(tokens+i, json_chunk, "buffer") == 0)
{
++i;
+ out_meshopt_compression->buffer = CGLTF_PTRINDEX(cgltf_buffer, cgltf_json_to_int(tokens + i, json_chunk));
+ ++i;
+ }
+ else if (cgltf_json_strcmp(tokens+i, json_chunk, "byteOffset") == 0)
+ {
+ ++i;
+ out_meshopt_compression->offset = cgltf_json_to_int(tokens+i, json_chunk);
+ ++i;
+ }
+ else if (cgltf_json_strcmp(tokens+i, json_chunk, "byteLength") == 0)
+ {
+ ++i;
+ out_meshopt_compression->size = cgltf_json_to_int(tokens+i, json_chunk);
+ ++i;
+ }
+ else if (cgltf_json_strcmp(tokens+i, json_chunk, "byteStride") == 0)
+ {
+ ++i;
+ out_meshopt_compression->stride = cgltf_json_to_int(tokens+i, json_chunk);
+ ++i;
+ }
+ else if (cgltf_json_strcmp(tokens+i, json_chunk, "count") == 0)
+ {
+ ++i;
+ out_meshopt_compression->count = cgltf_json_to_int(tokens+i, json_chunk);
+ ++i;
+ }
+ else if (cgltf_json_strcmp(tokens+i, json_chunk, "mode") == 0)
+ {
+ ++i;
+ if (cgltf_json_strcmp(tokens+i, json_chunk, "ATTRIBUTES") == 0)
+ {
+ out_meshopt_compression->mode = cgltf_meshopt_compression_mode_attributes;
+ }
+ else if (cgltf_json_strcmp(tokens+i, json_chunk, "TRIANGLES") == 0)
+ {
+ out_meshopt_compression->mode = cgltf_meshopt_compression_mode_triangles;
+ }
+ else if (cgltf_json_strcmp(tokens+i, json_chunk, "INDICES") == 0)
+ {
+ out_meshopt_compression->mode = cgltf_meshopt_compression_mode_indices;
+ }
+ ++i;
+ }
+ else if (cgltf_json_strcmp(tokens+i, json_chunk, "filter") == 0)
+ {
+ ++i;
+ if (cgltf_json_strcmp(tokens+i, json_chunk, "NONE") == 0)
+ {
+ out_meshopt_compression->filter = cgltf_meshopt_compression_filter_none;
+ }
+ else if (cgltf_json_strcmp(tokens+i, json_chunk, "OCTAHEDRAL") == 0)
+ {
+ out_meshopt_compression->filter = cgltf_meshopt_compression_filter_octahedral;
+ }
+ else if (cgltf_json_strcmp(tokens+i, json_chunk, "QUATERNION") == 0)
+ {
+ out_meshopt_compression->filter = cgltf_meshopt_compression_filter_quaternion;
+ }
+ else if (cgltf_json_strcmp(tokens+i, json_chunk, "EXPONENTIAL") == 0)
+ {
+ out_meshopt_compression->filter = cgltf_meshopt_compression_filter_exponential;
+ }
+ ++i;
+ }
+ else
+ {
+ i = cgltf_skip_json(tokens, i+1);
+ }
+
+ if (i < 0)
+ {
+ return i;
+ }
+ }
+
+ return i;
+}
+
+static int cgltf_parse_json_buffer_view(cgltf_options* options, jsmntok_t const* tokens, int i, const uint8_t* json_chunk, cgltf_buffer_view* out_buffer_view)
+{
+ 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, "name") == 0)
+ {
+ i = cgltf_parse_json_string(options, tokens, i + 1, json_chunk, &out_buffer_view->name);
+ }
+ else if (cgltf_json_strcmp(tokens+i, json_chunk, "buffer") == 0)
+ {
+ ++i;
out_buffer_view->buffer = CGLTF_PTRINDEX(cgltf_buffer, cgltf_json_to_int(tokens + i, json_chunk));
++i;
}
@@ -3287,6 +4330,46 @@ static int cgltf_parse_json_buffer_view(jsmntok_t const* tokens, int i, const ui
{
i = cgltf_parse_json_extras(tokens, i + 1, json_chunk, &out_buffer_view->extras);
}
+ else if (cgltf_json_strcmp(tokens + i, json_chunk, "extensions") == 0)
+ {
+ ++i;
+
+ CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
+ if(out_buffer_view->extensions)
+ {
+ return CGLTF_ERROR_JSON;
+ }
+
+ int extensions_size = tokens[i].size;
+ out_buffer_view->extensions_count = 0;
+ out_buffer_view->extensions = (cgltf_extension*)cgltf_calloc(options, sizeof(cgltf_extension), extensions_size);
+
+ if (!out_buffer_view->extensions)
+ {
+ return CGLTF_ERROR_NOMEM;
+ }
+
+ ++i;
+ for (int k = 0; k < extensions_size; ++k)
+ {
+ CGLTF_CHECK_KEY(tokens[i]);
+
+ if (cgltf_json_strcmp(tokens+i, json_chunk, "EXT_meshopt_compression") == 0)
+ {
+ 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
+ {
+ i = cgltf_parse_json_unprocessed_extension(options, tokens, i, json_chunk, &(out_buffer_view->extensions[out_buffer_view->extensions_count++]));
+ }
+
+ if (i < 0)
+ {
+ return i;
+ }
+ }
+ }
else
{
i = cgltf_skip_json(tokens, i+1);
@@ -3311,7 +4394,7 @@ static int cgltf_parse_json_buffer_views(cgltf_options* options, jsmntok_t const
for (cgltf_size j = 0; j < out_data->buffer_views_count; ++j)
{
- i = cgltf_parse_json_buffer_view(tokens, i, json_chunk, &out_data->buffer_views[j]);
+ i = cgltf_parse_json_buffer_view(options, tokens, i, json_chunk, &out_data->buffer_views[j]);
if (i < 0)
{
return i;
@@ -3331,7 +4414,11 @@ static int cgltf_parse_json_buffer(cgltf_options* options, jsmntok_t const* toke
{
CGLTF_CHECK_KEY(tokens[i]);
- if (cgltf_json_strcmp(tokens+i, json_chunk, "byteLength") == 0)
+ if (cgltf_json_strcmp(tokens + i, json_chunk, "name") == 0)
+ {
+ i = cgltf_parse_json_string(options, tokens, i + 1, json_chunk, &out_buffer->name);
+ }
+ else if (cgltf_json_strcmp(tokens+i, json_chunk, "byteLength") == 0)
{
++i;
out_buffer->size =
@@ -3346,6 +4433,10 @@ static int cgltf_parse_json_buffer(cgltf_options* options, jsmntok_t const* toke
{
i = cgltf_parse_json_extras(tokens, i + 1, json_chunk, &out_buffer->extras);
}
+ else if (cgltf_json_strcmp(tokens + i, json_chunk, "extensions") == 0)
+ {
+ i = cgltf_parse_json_unprocessed_extensions(options, tokens, i, json_chunk, &out_buffer->extensions_count, &out_buffer->extensions);
+ }
else
{
i = cgltf_skip_json(tokens, i+1);
@@ -3426,6 +4517,10 @@ static int cgltf_parse_json_skin(cgltf_options* options, jsmntok_t const* tokens
{
i = cgltf_parse_json_extras(tokens, i + 1, json_chunk, &out_skin->extras);
}
+ else if (cgltf_json_strcmp(tokens + i, json_chunk, "extensions") == 0)
+ {
+ i = cgltf_parse_json_unprocessed_extensions(options, tokens, i, json_chunk, &out_skin->extensions_count, &out_skin->extensions);
+ }
else
{
i = cgltf_skip_json(tokens, i+1);
@@ -3505,6 +4600,7 @@ static int cgltf_parse_json_camera(cgltf_options* options, jsmntok_t const* toke
if (cgltf_json_strcmp(tokens+i, json_chunk, "aspectRatio") == 0)
{
++i;
+ out_camera->data.perspective.has_aspect_ratio = 1;
out_camera->data.perspective.aspect_ratio = cgltf_json_to_float(tokens + i, json_chunk);
++i;
}
@@ -3517,6 +4613,7 @@ static int cgltf_parse_json_camera(cgltf_options* options, jsmntok_t const* toke
else if (cgltf_json_strcmp(tokens+i, json_chunk, "zfar") == 0)
{
++i;
+ out_camera->data.perspective.has_zfar = 1;
out_camera->data.perspective.zfar = cgltf_json_to_float(tokens + i, json_chunk);
++i;
}
@@ -3599,6 +4696,10 @@ static int cgltf_parse_json_camera(cgltf_options* options, jsmntok_t const* toke
{
i = cgltf_parse_json_extras(tokens, i + 1, json_chunk, &out_camera->extras);
}
+ else if (cgltf_json_strcmp(tokens + i, json_chunk, "extensions") == 0)
+ {
+ i = cgltf_parse_json_unprocessed_extensions(options, tokens, i, json_chunk, &out_camera->extensions_count, &out_camera->extensions);
+ }
else
{
i = cgltf_skip_json(tokens, i+1);
@@ -3847,8 +4948,20 @@ static int cgltf_parse_json_node(cgltf_options* options, jsmntok_t const* tokens
++i;
CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
+ if(out_node->extensions)
+ {
+ return CGLTF_ERROR_JSON;
+ }
int extensions_size = tokens[i].size;
+ out_node->extensions_count= 0;
+ out_node->extensions = (cgltf_extension*)cgltf_calloc(options, sizeof(cgltf_extension), extensions_size);
+
+ if (!out_node->extensions)
+ {
+ return CGLTF_ERROR_NOMEM;
+ }
+
++i;
for (int k = 0; k < extensions_size; ++k)
@@ -3888,7 +5001,7 @@ static int cgltf_parse_json_node(cgltf_options* options, jsmntok_t const* tokens
}
else
{
- i = cgltf_skip_json(tokens, i+1);
+ i = cgltf_parse_json_unprocessed_extension(options, tokens, i, json_chunk, &(out_node->extensions[out_node->extensions_count++]));
}
if (i < 0)
@@ -3963,6 +5076,10 @@ static int cgltf_parse_json_scene(cgltf_options* options, jsmntok_t const* token
{
i = cgltf_parse_json_extras(tokens, i + 1, json_chunk, &out_scene->extras);
}
+ else if (cgltf_json_strcmp(tokens + i, json_chunk, "extensions") == 0)
+ {
+ i = cgltf_parse_json_unprocessed_extensions(options, tokens, i, json_chunk, &out_scene->extensions_count, &out_scene->extensions);
+ }
else
{
i = cgltf_skip_json(tokens, i+1);
@@ -4041,6 +5158,10 @@ static int cgltf_parse_json_animation_sampler(cgltf_options* options, jsmntok_t
{
i = cgltf_parse_json_extras(tokens, i + 1, json_chunk, &out_sampler->extras);
}
+ else if (cgltf_json_strcmp(tokens + i, json_chunk, "extensions") == 0)
+ {
+ i = cgltf_parse_json_unprocessed_extensions(options, tokens, i, json_chunk, &out_sampler->extensions_count, &out_sampler->extensions);
+ }
else
{
i = cgltf_skip_json(tokens, i+1);
@@ -4117,6 +5238,10 @@ static int cgltf_parse_json_animation_channel(cgltf_options* options, jsmntok_t
{
i = cgltf_parse_json_extras(tokens, i + 1, json_chunk, &out_channel->extras);
}
+ else if (cgltf_json_strcmp(tokens + i, json_chunk, "extensions") == 0)
+ {
+ i = cgltf_parse_json_unprocessed_extensions(options, tokens, i, json_chunk, &out_channel->extensions_count, &out_channel->extensions);
+ }
else
{
i = cgltf_skip_json(tokens, i+1);
@@ -4195,6 +5320,10 @@ static int cgltf_parse_json_animation(cgltf_options* options, jsmntok_t const* t
{
i = cgltf_parse_json_extras(tokens, i + 1, json_chunk, &out_animation->extras);
}
+ else if (cgltf_json_strcmp(tokens + i, json_chunk, "extensions") == 0)
+ {
+ i = cgltf_parse_json_unprocessed_extensions(options, tokens, i, json_chunk, &out_animation->extensions_count, &out_animation->extensions);
+ }
else
{
i = cgltf_skip_json(tokens, i+1);
@@ -4228,6 +5357,58 @@ static int cgltf_parse_json_animations(cgltf_options* options, jsmntok_t const*
return i;
}
+static int cgltf_parse_json_variant(cgltf_options* options, jsmntok_t const* tokens, int i, const uint8_t* json_chunk, cgltf_material_variant* out_variant)
+{
+ 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, "name") == 0)
+ {
+ i = cgltf_parse_json_string(options, tokens, i + 1, json_chunk, &out_variant->name);
+ }
+ else if (cgltf_json_strcmp(tokens + i, json_chunk, "extras") == 0)
+ {
+ i = cgltf_parse_json_extras(tokens, i + 1, json_chunk, &out_variant->extras);
+ }
+ else
+ {
+ i = cgltf_skip_json(tokens, i+1);
+ }
+
+ if (i < 0)
+ {
+ return i;
+ }
+ }
+
+ return i;
+}
+
+static int cgltf_parse_json_variants(cgltf_options* options, jsmntok_t const* tokens, int i, const uint8_t* json_chunk, cgltf_data* out_data)
+{
+ i = cgltf_parse_json_array(options, tokens, i, json_chunk, sizeof(cgltf_material_variant), (void**)&out_data->variants, &out_data->variants_count);
+ if (i < 0)
+ {
+ return i;
+ }
+
+ for (cgltf_size j = 0; j < out_data->variants_count; ++j)
+ {
+ i = cgltf_parse_json_variant(options, tokens, i, json_chunk, &out_data->variants[j]);
+ if (i < 0)
+ {
+ return i;
+ }
+ }
+ return i;
+}
+
static int cgltf_parse_json_asset(cgltf_options* options, jsmntok_t const* tokens, int i, const uint8_t* json_chunk, cgltf_asset* out_asset)
{
CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
@@ -4259,6 +5440,10 @@ static int cgltf_parse_json_asset(cgltf_options* options, jsmntok_t const* token
{
i = cgltf_parse_json_extras(tokens, i + 1, json_chunk, &out_asset->extras);
}
+ else if (cgltf_json_strcmp(tokens + i, json_chunk, "extensions") == 0)
+ {
+ i = cgltf_parse_json_unprocessed_extensions(options, tokens, i, json_chunk, &out_asset->extensions_count, &out_asset->extensions);
+ }
else
{
i = cgltf_skip_json(tokens, i+1);
@@ -4416,8 +5601,20 @@ static int cgltf_parse_json_root(cgltf_options* options, jsmntok_t const* tokens
++i;
CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
+ if(out_data->data_extensions)
+ {
+ return CGLTF_ERROR_JSON;
+ }
int extensions_size = tokens[i].size;
+ out_data->data_extensions_count = 0;
+ out_data->data_extensions = (cgltf_extension*)cgltf_calloc(options, sizeof(cgltf_extension), extensions_size);
+
+ if (!out_data->data_extensions)
+ {
+ return CGLTF_ERROR_NOMEM;
+ }
+
++i;
for (int k = 0; k < extensions_size; ++k)
@@ -4452,9 +5649,37 @@ static int cgltf_parse_json_root(cgltf_options* options, jsmntok_t const* tokens
}
}
}
+ else if (cgltf_json_strcmp(tokens+i, json_chunk, "KHR_materials_variants") == 0)
+ {
+ ++i;
+
+ CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
+
+ int data_size = tokens[i].size;
+ ++i;
+
+ for (int m = 0; m < data_size; ++m)
+ {
+ CGLTF_CHECK_KEY(tokens[i]);
+
+ if (cgltf_json_strcmp(tokens + i, json_chunk, "variants") == 0)
+ {
+ i = cgltf_parse_json_variants(options, tokens, i + 1, json_chunk, out_data);
+ }
+ else
+ {
+ i = cgltf_skip_json(tokens, i + 1);
+ }
+
+ if (i < 0)
+ {
+ return i;
+ }
+ }
+ }
else
{
- i = cgltf_skip_json(tokens, i + 1);
+ i = cgltf_parse_json_unprocessed_extension(options, tokens, i, json_chunk, &(out_data->data_extensions[out_data->data_extensions_count++]));
}
if (i < 0)
@@ -4585,6 +5810,20 @@ 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);
+ }
+ }
+
+ for (cgltf_size k = 0; k < data->meshes[i].primitives[j].mappings_count; ++k)
+ {
+ CGLTF_PTRFIXUP_REQ(data->meshes[i].primitives[j].mappings[k].material, data->materials, data->materials_count);
+ }
}
}
@@ -4631,11 +5870,30 @@ 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);
+
+ CGLTF_PTRFIXUP(data->materials[i].specular.specular_texture.texture, data->textures, data->textures_count);
+ CGLTF_PTRFIXUP(data->materials[i].specular.specular_color_texture.texture, data->textures, data->textures_count);
+
+ CGLTF_PTRFIXUP(data->materials[i].transmission.transmission_texture.texture, data->textures, data->textures_count);
+
+ CGLTF_PTRFIXUP(data->materials[i].volume.thickness_texture.texture, data->textures, data->textures_count);
+
+ CGLTF_PTRFIXUP(data->materials[i].sheen.sheen_color_texture.texture, data->textures, data->textures_count);
+ CGLTF_PTRFIXUP(data->materials[i].sheen.sheen_roughness_texture.texture, data->textures, data->textures_count);
}
for (cgltf_size i = 0; i < data->buffer_views_count; ++i)
{
CGLTF_PTRFIXUP_REQ(data->buffer_views[i].buffer, data->buffers, data->buffers_count);
+
+ if (data->buffer_views[i].has_meshopt_compression)
+ {
+ CGLTF_PTRFIXUP_REQ(data->buffer_views[i].meshopt_compression.buffer, data->buffers, data->buffers_count);
+ }
}
for (cgltf_size i = 0; i < data->skins_count; ++i)
@@ -4750,7 +6008,7 @@ static jsmntok_t *jsmn_alloc_token(jsmn_parser *parser,
* Fills token type and boundaries.
*/
static void jsmn_fill_token(jsmntok_t *token, jsmntype_t type,
- int start, int end) {
+ int start, int end) {
token->type = type;
token->start = start;
token->end = end;
@@ -4810,7 +6068,7 @@ found:
* Fills next token with JSON string.
*/
static int jsmn_parse_string(jsmn_parser *parser, const char *js,
- size_t len, jsmntok_t *tokens, size_t num_tokens) {
+ size_t len, jsmntok_t *tokens, size_t num_tokens) {
jsmntok_t *token;
int start = parser->pos;
@@ -4853,8 +6111,8 @@ static int jsmn_parse_string(jsmn_parser *parser, const char *js,
for(i = 0; i < 4 && parser->pos < len && js[parser->pos] != '\0'; i++) {
/* If it isn't a hex character we have an error */
if(!((js[parser->pos] >= 48 && js[parser->pos] <= 57) || /* 0-9 */
- (js[parser->pos] >= 65 && js[parser->pos] <= 70) || /* A-F */
- (js[parser->pos] >= 97 && js[parser->pos] <= 102))) { /* a-f */
+ (js[parser->pos] >= 65 && js[parser->pos] <= 70) || /* A-F */
+ (js[parser->pos] >= 97 && js[parser->pos] <= 102))) { /* a-f */
parser->pos = start;
return JSMN_ERROR_INVAL;
}
@@ -4877,7 +6135,7 @@ static int jsmn_parse_string(jsmn_parser *parser, const char *js,
* Parse JSON string and fill tokens.
*/
static int jsmn_parse(jsmn_parser *parser, const char *js, size_t len,
- jsmntok_t *tokens, size_t num_tokens) {
+ jsmntok_t *tokens, size_t num_tokens) {
int r;
int i;
jsmntok_t *token;