github.com/Konstantin8105/c4go@v0.0.0-20240505174241-768bb1c65a51/tests/raylib/external/cgltf.h (about)

     1  /**
     2   * cgltf - a single-file glTF 2.0 parser written in C99.
     3   *
     4   * Version: 1.12
     5   *
     6   * Website: https://github.com/jkuhlmann/cgltf
     7   *
     8   * Distributed under the MIT License, see notice at the end of this file.
     9   *
    10   * Building:
    11   * Include this file where you need the struct and function
    12   * declarations. Have exactly one source file where you define
    13   * `CGLTF_IMPLEMENTATION` before including this file to get the
    14   * function definitions.
    15   *
    16   * Reference:
    17   * `cgltf_result cgltf_parse(const cgltf_options*, const void*,
    18   * cgltf_size, cgltf_data**)` parses both glTF and GLB data. If
    19   * this function returns `cgltf_result_success`, you have to call
    20   * `cgltf_free()` on the created `cgltf_data*` variable.
    21   * Note that contents of external files for buffers and images are not
    22   * automatically loaded. You'll need to read these files yourself using
    23   * URIs in the `cgltf_data` structure.
    24   *
    25   * `cgltf_options` is the struct passed to `cgltf_parse()` to control
    26   * parts of the parsing process. You can use it to force the file type
    27   * and provide memory allocation as well as file operation callbacks.
    28   * Should be zero-initialized to trigger default behavior.
    29   *
    30   * `cgltf_data` is the struct allocated and filled by `cgltf_parse()`.
    31   * It generally mirrors the glTF format as described by the spec (see
    32   * https://github.com/KhronosGroup/glTF/tree/master/specification/2.0).
    33   *
    34   * `void cgltf_free(cgltf_data*)` frees the allocated `cgltf_data`
    35   * variable.
    36   *
    37   * `cgltf_result cgltf_load_buffers(const cgltf_options*, cgltf_data*,
    38   * const char* gltf_path)` can be optionally called to open and read buffer
    39   * files using the `FILE*` APIs. The `gltf_path` argument is the path to
    40   * the original glTF file, which allows the parser to resolve the path to
    41   * buffer files.
    42   *
    43   * `cgltf_result cgltf_load_buffer_base64(const cgltf_options* options,
    44   * cgltf_size size, const char* base64, void** out_data)` decodes
    45   * base64-encoded data content. Used internally by `cgltf_load_buffers()`.
    46   * This is useful when decoding data URIs in images.
    47   *
    48   * `cgltf_result cgltf_parse_file(const cgltf_options* options, const
    49   * char* path, cgltf_data** out_data)` can be used to open the given
    50   * file using `FILE*` APIs and parse the data using `cgltf_parse()`.
    51   *
    52   * `cgltf_result cgltf_validate(cgltf_data*)` can be used to do additional
    53   * checks to make sure the parsed glTF data is valid.
    54   *
    55   * `cgltf_node_transform_local` converts the translation / rotation / scale properties of a node
    56   * into a mat4.
    57   *
    58   * `cgltf_node_transform_world` calls `cgltf_node_transform_local` on every ancestor in order
    59   * to compute the root-to-node transformation.
    60   *
    61   * `cgltf_accessor_unpack_floats` reads in the data from an accessor, applies sparse data (if any),
    62   * and converts them to floating point. Assumes that `cgltf_load_buffers` has already been called.
    63   * By passing null for the output pointer, users can find out how many floats are required in the
    64   * output buffer.
    65   *
    66   * `cgltf_num_components` is a tiny utility that tells you the dimensionality of
    67   * a certain accessor type. This can be used before `cgltf_accessor_unpack_floats` to help allocate
    68   * the necessary amount of memory.
    69   *
    70   * `cgltf_accessor_read_float` reads a certain element from a non-sparse accessor and converts it to
    71   * floating point, assuming that `cgltf_load_buffers` has already been called. The passed-in element
    72   * size is the number of floats in the output buffer, which should be in the range [1, 16]. Returns
    73   * false if the passed-in element_size is too small, or if the accessor is sparse.
    74   *
    75   * `cgltf_accessor_read_uint` is similar to its floating-point counterpart, but limited to reading
    76   * vector types and does not support matrix types. The passed-in element size is the number of uints
    77   * in the output buffer, which should be in the range [1, 4]. Returns false if the passed-in 
    78   * element_size is too small, or if the accessor is sparse.
    79   *
    80   * `cgltf_accessor_read_index` is similar to its floating-point counterpart, but it returns size_t
    81   * and only works with single-component data types.
    82   *
    83   * `cgltf_result cgltf_copy_extras_json(const cgltf_data*, const cgltf_extras*,
    84   * char* dest, cgltf_size* dest_size)` allows users to retrieve the "extras" data that
    85   * can be attached to many glTF objects (which can be arbitrary JSON data). The
    86   * `cgltf_extras` struct stores the offsets of the start and end of the extras JSON data
    87   * as it appears in the complete glTF JSON data. This function copies the extras data
    88   * into the provided buffer. If `dest` is NULL, the length of the data is written into
    89   * `dest_size`. You can then parse this data using your own JSON parser
    90   * or, if you've included the cgltf implementation using the integrated JSMN JSON parser.
    91   */
    92  #ifndef CGLTF_H_INCLUDED__
    93  #define CGLTF_H_INCLUDED__
    94  
    95  #include <stddef.h>
    96  
    97  #ifdef __cplusplus
    98  extern "C" {
    99  #endif
   100  
   101  typedef size_t cgltf_size;
   102  typedef long long int cgltf_ssize;
   103  typedef float cgltf_float;
   104  typedef int cgltf_int;
   105  typedef unsigned int cgltf_uint;
   106  typedef int cgltf_bool;
   107  
   108  typedef enum cgltf_file_type
   109  {
   110  	cgltf_file_type_invalid,
   111  	cgltf_file_type_gltf,
   112  	cgltf_file_type_glb,
   113  	cgltf_file_type_max_enum
   114  } cgltf_file_type;
   115  
   116  typedef enum cgltf_result
   117  {
   118  	cgltf_result_success,
   119  	cgltf_result_data_too_short,
   120  	cgltf_result_unknown_format,
   121  	cgltf_result_invalid_json,
   122  	cgltf_result_invalid_gltf,
   123  	cgltf_result_invalid_options,
   124  	cgltf_result_file_not_found,
   125  	cgltf_result_io_error,
   126  	cgltf_result_out_of_memory,
   127  	cgltf_result_legacy_gltf,
   128      cgltf_result_max_enum
   129  } cgltf_result;
   130  
   131  typedef struct cgltf_memory_options
   132  {
   133  	void* (*alloc_func)(void* user, cgltf_size size);
   134  	void (*free_func) (void* user, void* ptr);
   135  	void* user_data;
   136  } cgltf_memory_options;
   137  
   138  typedef struct cgltf_file_options
   139  {
   140  	cgltf_result(*read)(const struct cgltf_memory_options* memory_options, const struct cgltf_file_options* file_options, const char* path, cgltf_size* size, void** data);
   141  	void (*release)(const struct cgltf_memory_options* memory_options, const struct cgltf_file_options* file_options, void* data);
   142  	void* user_data;
   143  } cgltf_file_options;
   144  
   145  typedef struct cgltf_options
   146  {
   147  	cgltf_file_type type; /* invalid == auto detect */
   148  	cgltf_size json_token_count; /* 0 == auto */
   149  	cgltf_memory_options memory;
   150  	cgltf_file_options file;
   151  } cgltf_options;
   152  
   153  typedef enum cgltf_buffer_view_type
   154  {
   155  	cgltf_buffer_view_type_invalid,
   156  	cgltf_buffer_view_type_indices,
   157  	cgltf_buffer_view_type_vertices,
   158  	cgltf_buffer_view_type_max_enum
   159  } cgltf_buffer_view_type;
   160  
   161  typedef enum cgltf_attribute_type
   162  {
   163  	cgltf_attribute_type_invalid,
   164  	cgltf_attribute_type_position,
   165  	cgltf_attribute_type_normal,
   166  	cgltf_attribute_type_tangent,
   167  	cgltf_attribute_type_texcoord,
   168  	cgltf_attribute_type_color,
   169  	cgltf_attribute_type_joints,
   170  	cgltf_attribute_type_weights,
   171  	cgltf_attribute_type_custom,
   172  	cgltf_attribute_type_max_enum
   173  } cgltf_attribute_type;
   174  
   175  typedef enum cgltf_component_type
   176  {
   177  	cgltf_component_type_invalid,
   178  	cgltf_component_type_r_8, /* BYTE */
   179  	cgltf_component_type_r_8u, /* UNSIGNED_BYTE */
   180  	cgltf_component_type_r_16, /* SHORT */
   181  	cgltf_component_type_r_16u, /* UNSIGNED_SHORT */
   182  	cgltf_component_type_r_32u, /* UNSIGNED_INT */
   183  	cgltf_component_type_r_32f, /* FLOAT */
   184      cgltf_component_type_max_enum
   185  } cgltf_component_type;
   186  
   187  typedef enum cgltf_type
   188  {
   189  	cgltf_type_invalid,
   190  	cgltf_type_scalar,
   191  	cgltf_type_vec2,
   192  	cgltf_type_vec3,
   193  	cgltf_type_vec4,
   194  	cgltf_type_mat2,
   195  	cgltf_type_mat3,
   196  	cgltf_type_mat4,
   197  	cgltf_type_max_enum
   198  } cgltf_type;
   199  
   200  typedef enum cgltf_primitive_type
   201  {
   202  	cgltf_primitive_type_points,
   203  	cgltf_primitive_type_lines,
   204  	cgltf_primitive_type_line_loop,
   205  	cgltf_primitive_type_line_strip,
   206  	cgltf_primitive_type_triangles,
   207  	cgltf_primitive_type_triangle_strip,
   208  	cgltf_primitive_type_triangle_fan,
   209  	cgltf_primitive_type_max_enum
   210  } cgltf_primitive_type;
   211  
   212  typedef enum cgltf_alpha_mode
   213  {
   214  	cgltf_alpha_mode_opaque,
   215  	cgltf_alpha_mode_mask,
   216  	cgltf_alpha_mode_blend,
   217  	cgltf_alpha_mode_max_enum
   218  } cgltf_alpha_mode;
   219  
   220  typedef enum cgltf_animation_path_type {
   221  	cgltf_animation_path_type_invalid,
   222  	cgltf_animation_path_type_translation,
   223  	cgltf_animation_path_type_rotation,
   224  	cgltf_animation_path_type_scale,
   225  	cgltf_animation_path_type_weights,
   226  	cgltf_animation_path_type_max_enum
   227  } cgltf_animation_path_type;
   228  
   229  typedef enum cgltf_interpolation_type {
   230  	cgltf_interpolation_type_linear,
   231  	cgltf_interpolation_type_step,
   232  	cgltf_interpolation_type_cubic_spline,
   233  	cgltf_interpolation_type_max_enum
   234  } cgltf_interpolation_type;
   235  
   236  typedef enum cgltf_camera_type {
   237  	cgltf_camera_type_invalid,
   238  	cgltf_camera_type_perspective,
   239  	cgltf_camera_type_orthographic,
   240  	cgltf_camera_type_max_enum
   241  } cgltf_camera_type;
   242  
   243  typedef enum cgltf_light_type {
   244  	cgltf_light_type_invalid,
   245  	cgltf_light_type_directional,
   246  	cgltf_light_type_point,
   247  	cgltf_light_type_spot,
   248  	cgltf_light_type_max_enum
   249  } cgltf_light_type;
   250  
   251  typedef enum cgltf_data_free_method {
   252  	cgltf_data_free_method_none,
   253  	cgltf_data_free_method_file_release,
   254  	cgltf_data_free_method_memory_free,
   255  	cgltf_data_free_method_max_enum
   256  } cgltf_data_free_method;
   257  
   258  typedef struct cgltf_extras {
   259  	cgltf_size start_offset;
   260  	cgltf_size end_offset;
   261  } cgltf_extras;
   262  
   263  typedef struct cgltf_extension {
   264  	char* name;
   265  	char* data;
   266  } cgltf_extension;
   267  
   268  typedef struct cgltf_buffer
   269  {
   270  	char* name;
   271  	cgltf_size size;
   272  	char* uri;
   273  	void* data; /* loaded by cgltf_load_buffers */
   274  	cgltf_data_free_method data_free_method;
   275  	cgltf_extras extras;
   276  	cgltf_size extensions_count;
   277  	cgltf_extension* extensions;
   278  } cgltf_buffer;
   279  
   280  typedef enum cgltf_meshopt_compression_mode {
   281  	cgltf_meshopt_compression_mode_invalid,
   282  	cgltf_meshopt_compression_mode_attributes,
   283  	cgltf_meshopt_compression_mode_triangles,
   284  	cgltf_meshopt_compression_mode_indices,
   285  	cgltf_meshopt_compression_mode_max_enum
   286  } cgltf_meshopt_compression_mode;
   287  
   288  typedef enum cgltf_meshopt_compression_filter {
   289  	cgltf_meshopt_compression_filter_none,
   290  	cgltf_meshopt_compression_filter_octahedral,
   291  	cgltf_meshopt_compression_filter_quaternion,
   292  	cgltf_meshopt_compression_filter_exponential,
   293  	cgltf_meshopt_compression_filter_max_enum
   294  } cgltf_meshopt_compression_filter;
   295  
   296  typedef struct cgltf_meshopt_compression
   297  {
   298  	cgltf_buffer* buffer;
   299  	cgltf_size offset;
   300  	cgltf_size size;
   301  	cgltf_size stride;
   302  	cgltf_size count;
   303  	cgltf_meshopt_compression_mode mode;
   304  	cgltf_meshopt_compression_filter filter;
   305  } cgltf_meshopt_compression;
   306  
   307  typedef struct cgltf_buffer_view
   308  {
   309  	char *name;
   310  	cgltf_buffer* buffer;
   311  	cgltf_size offset;
   312  	cgltf_size size;
   313  	cgltf_size stride; /* 0 == automatically determined by accessor */
   314  	cgltf_buffer_view_type type;
   315  	void* data; /* overrides buffer->data if present, filled by extensions */
   316  	cgltf_bool has_meshopt_compression;
   317  	cgltf_meshopt_compression meshopt_compression;
   318  	cgltf_extras extras;
   319  	cgltf_size extensions_count;
   320  	cgltf_extension* extensions;
   321  } cgltf_buffer_view;
   322  
   323  typedef struct cgltf_accessor_sparse
   324  {
   325  	cgltf_size count;
   326  	cgltf_buffer_view* indices_buffer_view;
   327  	cgltf_size indices_byte_offset;
   328  	cgltf_component_type indices_component_type;
   329  	cgltf_buffer_view* values_buffer_view;
   330  	cgltf_size values_byte_offset;
   331  	cgltf_extras extras;
   332  	cgltf_extras indices_extras;
   333  	cgltf_extras values_extras;
   334  	cgltf_size extensions_count;
   335  	cgltf_extension* extensions;
   336  	cgltf_size indices_extensions_count;
   337  	cgltf_extension* indices_extensions;
   338  	cgltf_size values_extensions_count;
   339  	cgltf_extension* values_extensions;
   340  } cgltf_accessor_sparse;
   341  
   342  typedef struct cgltf_accessor
   343  {
   344  	char* name;
   345  	cgltf_component_type component_type;
   346  	cgltf_bool normalized;
   347  	cgltf_type type;
   348  	cgltf_size offset;
   349  	cgltf_size count;
   350  	cgltf_size stride;
   351  	cgltf_buffer_view* buffer_view;
   352  	cgltf_bool has_min;
   353  	cgltf_float min[16];
   354  	cgltf_bool has_max;
   355  	cgltf_float max[16];
   356  	cgltf_bool is_sparse;
   357  	cgltf_accessor_sparse sparse;
   358  	cgltf_extras extras;
   359  	cgltf_size extensions_count;
   360  	cgltf_extension* extensions;
   361  } cgltf_accessor;
   362  
   363  typedef struct cgltf_attribute
   364  {
   365  	char* name;
   366  	cgltf_attribute_type type;
   367  	cgltf_int index;
   368  	cgltf_accessor* data;
   369  } cgltf_attribute;
   370  
   371  typedef struct cgltf_image
   372  {
   373  	char* name;
   374  	char* uri;
   375  	cgltf_buffer_view* buffer_view;
   376  	char* mime_type;
   377  	cgltf_extras extras;
   378  	cgltf_size extensions_count;
   379  	cgltf_extension* extensions;
   380  } cgltf_image;
   381  
   382  typedef struct cgltf_sampler
   383  {
   384  	char* name;
   385  	cgltf_int mag_filter;
   386  	cgltf_int min_filter;
   387  	cgltf_int wrap_s;
   388  	cgltf_int wrap_t;
   389  	cgltf_extras extras;
   390  	cgltf_size extensions_count;
   391  	cgltf_extension* extensions;
   392  } cgltf_sampler;
   393  
   394  typedef struct cgltf_texture
   395  {
   396  	char* name;
   397  	cgltf_image* image;
   398  	cgltf_sampler* sampler;
   399  	cgltf_bool has_basisu;
   400  	cgltf_image* basisu_image;
   401  	cgltf_extras extras;
   402  	cgltf_size extensions_count;
   403  	cgltf_extension* extensions;
   404  } cgltf_texture;
   405  
   406  typedef struct cgltf_texture_transform
   407  {
   408  	cgltf_float offset[2];
   409  	cgltf_float rotation;
   410  	cgltf_float scale[2];
   411  	cgltf_bool has_texcoord;
   412  	cgltf_int texcoord;
   413  } cgltf_texture_transform;
   414  
   415  typedef struct cgltf_texture_view
   416  {
   417  	cgltf_texture* texture;
   418  	cgltf_int texcoord;
   419  	cgltf_float scale; /* equivalent to strength for occlusion_texture */
   420  	cgltf_bool has_transform;
   421  	cgltf_texture_transform transform;
   422  	cgltf_extras extras;
   423  	cgltf_size extensions_count;
   424  	cgltf_extension* extensions;
   425  } cgltf_texture_view;
   426  
   427  typedef struct cgltf_pbr_metallic_roughness
   428  {
   429  	cgltf_texture_view base_color_texture;
   430  	cgltf_texture_view metallic_roughness_texture;
   431  
   432  	cgltf_float base_color_factor[4];
   433  	cgltf_float metallic_factor;
   434  	cgltf_float roughness_factor;
   435  
   436  	cgltf_extras extras;
   437  } cgltf_pbr_metallic_roughness;
   438  
   439  typedef struct cgltf_pbr_specular_glossiness
   440  {
   441  	cgltf_texture_view diffuse_texture;
   442  	cgltf_texture_view specular_glossiness_texture;
   443  
   444  	cgltf_float diffuse_factor[4];
   445  	cgltf_float specular_factor[3];
   446  	cgltf_float glossiness_factor;
   447  } cgltf_pbr_specular_glossiness;
   448  
   449  typedef struct cgltf_clearcoat
   450  {
   451  	cgltf_texture_view clearcoat_texture;
   452  	cgltf_texture_view clearcoat_roughness_texture;
   453  	cgltf_texture_view clearcoat_normal_texture;
   454  
   455  	cgltf_float clearcoat_factor;
   456  	cgltf_float clearcoat_roughness_factor;
   457  } cgltf_clearcoat;
   458  
   459  typedef struct cgltf_transmission
   460  {
   461  	cgltf_texture_view transmission_texture;
   462  	cgltf_float transmission_factor;
   463  } cgltf_transmission;
   464  
   465  typedef struct cgltf_ior
   466  {
   467  	cgltf_float ior;
   468  } cgltf_ior;
   469  
   470  typedef struct cgltf_specular
   471  {
   472  	cgltf_texture_view specular_texture;
   473  	cgltf_texture_view specular_color_texture;
   474  	cgltf_float specular_color_factor[3];
   475  	cgltf_float specular_factor;
   476  } cgltf_specular;
   477  
   478  typedef struct cgltf_volume
   479  {
   480  	cgltf_texture_view thickness_texture;
   481  	cgltf_float thickness_factor;
   482  	cgltf_float attenuation_color[3];
   483  	cgltf_float attenuation_distance;
   484  } cgltf_volume;
   485  
   486  typedef struct cgltf_sheen
   487  {
   488  	cgltf_texture_view sheen_color_texture;
   489  	cgltf_float sheen_color_factor[3];
   490  	cgltf_texture_view sheen_roughness_texture;
   491  	cgltf_float sheen_roughness_factor;
   492  } cgltf_sheen;
   493  
   494  typedef struct cgltf_emissive_strength
   495  {
   496  	cgltf_float emissive_strength;
   497  } cgltf_emissive_strength;
   498  
   499  typedef struct cgltf_iridescence
   500  {
   501  	cgltf_float iridescence_factor;
   502  	cgltf_texture_view iridescence_texture;
   503  	cgltf_float iridescence_ior;
   504  	cgltf_float iridescence_thickness_min;
   505  	cgltf_float iridescence_thickness_max;
   506  	cgltf_texture_view iridescence_thickness_texture;
   507  } cgltf_iridescence;
   508  
   509  typedef struct cgltf_material
   510  {
   511  	char* name;
   512  	cgltf_bool has_pbr_metallic_roughness;
   513  	cgltf_bool has_pbr_specular_glossiness;
   514  	cgltf_bool has_clearcoat;
   515  	cgltf_bool has_transmission;
   516  	cgltf_bool has_volume;
   517  	cgltf_bool has_ior;
   518  	cgltf_bool has_specular;
   519  	cgltf_bool has_sheen;
   520  	cgltf_bool has_emissive_strength;
   521  	cgltf_bool has_iridescence;
   522  	cgltf_pbr_metallic_roughness pbr_metallic_roughness;
   523  	cgltf_pbr_specular_glossiness pbr_specular_glossiness;
   524  	cgltf_clearcoat clearcoat;
   525  	cgltf_ior ior;
   526  	cgltf_specular specular;
   527  	cgltf_sheen sheen;
   528  	cgltf_transmission transmission;
   529  	cgltf_volume volume;
   530  	cgltf_emissive_strength emissive_strength;
   531  	cgltf_iridescence iridescence;
   532  	cgltf_texture_view normal_texture;
   533  	cgltf_texture_view occlusion_texture;
   534  	cgltf_texture_view emissive_texture;
   535  	cgltf_float emissive_factor[3];
   536  	cgltf_alpha_mode alpha_mode;
   537  	cgltf_float alpha_cutoff;
   538  	cgltf_bool double_sided;
   539  	cgltf_bool unlit;
   540  	cgltf_extras extras;
   541  	cgltf_size extensions_count;
   542  	cgltf_extension* extensions;
   543  } cgltf_material;
   544  
   545  typedef struct cgltf_material_mapping
   546  {
   547  	cgltf_size variant;
   548  	cgltf_material* material;
   549  	cgltf_extras extras;
   550  } cgltf_material_mapping;
   551  
   552  typedef struct cgltf_morph_target {
   553  	cgltf_attribute* attributes;
   554  	cgltf_size attributes_count;
   555  } cgltf_morph_target;
   556  
   557  typedef struct cgltf_draco_mesh_compression {
   558  	cgltf_buffer_view* buffer_view;
   559  	cgltf_attribute* attributes;
   560  	cgltf_size attributes_count;
   561  } cgltf_draco_mesh_compression;
   562  
   563  typedef struct cgltf_mesh_gpu_instancing {
   564  	cgltf_buffer_view* buffer_view;
   565  	cgltf_attribute* attributes;
   566  	cgltf_size attributes_count;
   567  } cgltf_mesh_gpu_instancing;
   568  
   569  typedef struct cgltf_primitive {
   570  	cgltf_primitive_type type;
   571  	cgltf_accessor* indices;
   572  	cgltf_material* material;
   573  	cgltf_attribute* attributes;
   574  	cgltf_size attributes_count;
   575  	cgltf_morph_target* targets;
   576  	cgltf_size targets_count;
   577  	cgltf_extras extras;
   578  	cgltf_bool has_draco_mesh_compression;
   579  	cgltf_draco_mesh_compression draco_mesh_compression;
   580  	cgltf_material_mapping* mappings;
   581  	cgltf_size mappings_count;
   582  	cgltf_size extensions_count;
   583  	cgltf_extension* extensions;
   584  } cgltf_primitive;
   585  
   586  typedef struct cgltf_mesh {
   587  	char* name;
   588  	cgltf_primitive* primitives;
   589  	cgltf_size primitives_count;
   590  	cgltf_float* weights;
   591  	cgltf_size weights_count;
   592  	char** target_names;
   593  	cgltf_size target_names_count;
   594  	cgltf_extras extras;
   595  	cgltf_size extensions_count;
   596  	cgltf_extension* extensions;
   597  } cgltf_mesh;
   598  
   599  typedef struct cgltf_node cgltf_node;
   600  
   601  typedef struct cgltf_skin {
   602  	char* name;
   603  	cgltf_node** joints;
   604  	cgltf_size joints_count;
   605  	cgltf_node* skeleton;
   606  	cgltf_accessor* inverse_bind_matrices;
   607  	cgltf_extras extras;
   608  	cgltf_size extensions_count;
   609  	cgltf_extension* extensions;
   610  } cgltf_skin;
   611  
   612  typedef struct cgltf_camera_perspective {
   613  	cgltf_bool has_aspect_ratio;
   614  	cgltf_float aspect_ratio;
   615  	cgltf_float yfov;
   616  	cgltf_bool has_zfar;
   617  	cgltf_float zfar;
   618  	cgltf_float znear;
   619  	cgltf_extras extras;
   620  } cgltf_camera_perspective;
   621  
   622  typedef struct cgltf_camera_orthographic {
   623  	cgltf_float xmag;
   624  	cgltf_float ymag;
   625  	cgltf_float zfar;
   626  	cgltf_float znear;
   627  	cgltf_extras extras;
   628  } cgltf_camera_orthographic;
   629  
   630  typedef struct cgltf_camera {
   631  	char* name;
   632  	cgltf_camera_type type;
   633  	union {
   634  		cgltf_camera_perspective perspective;
   635  		cgltf_camera_orthographic orthographic;
   636  	} data;
   637  	cgltf_extras extras;
   638  	cgltf_size extensions_count;
   639  	cgltf_extension* extensions;
   640  } cgltf_camera;
   641  
   642  typedef struct cgltf_light {
   643  	char* name;
   644  	cgltf_float color[3];
   645  	cgltf_float intensity;
   646  	cgltf_light_type type;
   647  	cgltf_float range;
   648  	cgltf_float spot_inner_cone_angle;
   649  	cgltf_float spot_outer_cone_angle;
   650  	cgltf_extras extras;
   651  } cgltf_light;
   652  
   653  struct cgltf_node {
   654  	char* name;
   655  	cgltf_node* parent;
   656  	cgltf_node** children;
   657  	cgltf_size children_count;
   658  	cgltf_skin* skin;
   659  	cgltf_mesh* mesh;
   660  	cgltf_camera* camera;
   661  	cgltf_light* light;
   662  	cgltf_float* weights;
   663  	cgltf_size weights_count;
   664  	cgltf_bool has_translation;
   665  	cgltf_bool has_rotation;
   666  	cgltf_bool has_scale;
   667  	cgltf_bool has_matrix;
   668  	cgltf_float translation[3];
   669  	cgltf_float rotation[4];
   670  	cgltf_float scale[3];
   671  	cgltf_float matrix[16];
   672  	cgltf_extras extras;
   673  	cgltf_bool has_mesh_gpu_instancing;
   674  	cgltf_mesh_gpu_instancing mesh_gpu_instancing;
   675  	cgltf_size extensions_count;
   676  	cgltf_extension* extensions;
   677  };
   678  
   679  typedef struct cgltf_scene {
   680  	char* name;
   681  	cgltf_node** nodes;
   682  	cgltf_size nodes_count;
   683  	cgltf_extras extras;
   684  	cgltf_size extensions_count;
   685  	cgltf_extension* extensions;
   686  } cgltf_scene;
   687  
   688  typedef struct cgltf_animation_sampler {
   689  	cgltf_accessor* input;
   690  	cgltf_accessor* output;
   691  	cgltf_interpolation_type interpolation;
   692  	cgltf_extras extras;
   693  	cgltf_size extensions_count;
   694  	cgltf_extension* extensions;
   695  } cgltf_animation_sampler;
   696  
   697  typedef struct cgltf_animation_channel {
   698  	cgltf_animation_sampler* sampler;
   699  	cgltf_node* target_node;
   700  	cgltf_animation_path_type target_path;
   701  	cgltf_extras extras;
   702  	cgltf_size extensions_count;
   703  	cgltf_extension* extensions;
   704  } cgltf_animation_channel;
   705  
   706  typedef struct cgltf_animation {
   707  	char* name;
   708  	cgltf_animation_sampler* samplers;
   709  	cgltf_size samplers_count;
   710  	cgltf_animation_channel* channels;
   711  	cgltf_size channels_count;
   712  	cgltf_extras extras;
   713  	cgltf_size extensions_count;
   714  	cgltf_extension* extensions;
   715  } cgltf_animation;
   716  
   717  typedef struct cgltf_material_variant
   718  {
   719  	char* name;
   720  	cgltf_extras extras;
   721  } cgltf_material_variant;
   722  
   723  typedef struct cgltf_asset {
   724  	char* copyright;
   725  	char* generator;
   726  	char* version;
   727  	char* min_version;
   728  	cgltf_extras extras;
   729  	cgltf_size extensions_count;
   730  	cgltf_extension* extensions;
   731  } cgltf_asset;
   732  
   733  typedef struct cgltf_data
   734  {
   735  	cgltf_file_type file_type;
   736  	void* file_data;
   737  
   738  	cgltf_asset asset;
   739  
   740  	cgltf_mesh* meshes;
   741  	cgltf_size meshes_count;
   742  
   743  	cgltf_material* materials;
   744  	cgltf_size materials_count;
   745  
   746  	cgltf_accessor* accessors;
   747  	cgltf_size accessors_count;
   748  
   749  	cgltf_buffer_view* buffer_views;
   750  	cgltf_size buffer_views_count;
   751  
   752  	cgltf_buffer* buffers;
   753  	cgltf_size buffers_count;
   754  
   755  	cgltf_image* images;
   756  	cgltf_size images_count;
   757  
   758  	cgltf_texture* textures;
   759  	cgltf_size textures_count;
   760  
   761  	cgltf_sampler* samplers;
   762  	cgltf_size samplers_count;
   763  
   764  	cgltf_skin* skins;
   765  	cgltf_size skins_count;
   766  
   767  	cgltf_camera* cameras;
   768  	cgltf_size cameras_count;
   769  
   770  	cgltf_light* lights;
   771  	cgltf_size lights_count;
   772  
   773  	cgltf_node* nodes;
   774  	cgltf_size nodes_count;
   775  
   776  	cgltf_scene* scenes;
   777  	cgltf_size scenes_count;
   778  
   779  	cgltf_scene* scene;
   780  
   781  	cgltf_animation* animations;
   782  	cgltf_size animations_count;
   783  
   784  	cgltf_material_variant* variants;
   785  	cgltf_size variants_count;
   786  
   787  	cgltf_extras extras;
   788  
   789  	cgltf_size data_extensions_count;
   790  	cgltf_extension* data_extensions;
   791  
   792  	char** extensions_used;
   793  	cgltf_size extensions_used_count;
   794  
   795  	char** extensions_required;
   796  	cgltf_size extensions_required_count;
   797  
   798  	const char* json;
   799  	cgltf_size json_size;
   800  
   801  	const void* bin;
   802  	cgltf_size bin_size;
   803  
   804  	cgltf_memory_options memory;
   805  	cgltf_file_options file;
   806  } cgltf_data;
   807  
   808  cgltf_result cgltf_parse(
   809  		const cgltf_options* options,
   810  		const void* data,
   811  		cgltf_size size,
   812  		cgltf_data** out_data);
   813  
   814  cgltf_result cgltf_parse_file(
   815  		const cgltf_options* options,
   816  		const char* path,
   817  		cgltf_data** out_data);
   818  
   819  cgltf_result cgltf_load_buffers(
   820  		const cgltf_options* options,
   821  		cgltf_data* data,
   822  		const char* gltf_path);
   823  
   824  cgltf_result cgltf_load_buffer_base64(const cgltf_options* options, cgltf_size size, const char* base64, void** out_data);
   825  
   826  cgltf_size cgltf_decode_string(char* string);
   827  cgltf_size cgltf_decode_uri(char* uri);
   828  
   829  cgltf_result cgltf_validate(cgltf_data* data);
   830  
   831  void cgltf_free(cgltf_data* data);
   832  
   833  void cgltf_node_transform_local(const cgltf_node* node, cgltf_float* out_matrix);
   834  void cgltf_node_transform_world(const cgltf_node* node, cgltf_float* out_matrix);
   835  
   836  cgltf_bool cgltf_accessor_read_float(const cgltf_accessor* accessor, cgltf_size index, cgltf_float* out, cgltf_size element_size);
   837  cgltf_bool cgltf_accessor_read_uint(const cgltf_accessor* accessor, cgltf_size index, cgltf_uint* out, cgltf_size element_size);
   838  cgltf_size cgltf_accessor_read_index(const cgltf_accessor* accessor, cgltf_size index);
   839  
   840  cgltf_size cgltf_num_components(cgltf_type type);
   841  
   842  cgltf_size cgltf_accessor_unpack_floats(const cgltf_accessor* accessor, cgltf_float* out, cgltf_size float_count);
   843  
   844  cgltf_result cgltf_copy_extras_json(const cgltf_data* data, const cgltf_extras* extras, char* dest, cgltf_size* dest_size);
   845  
   846  #ifdef __cplusplus
   847  }
   848  #endif
   849  
   850  #endif /* #ifndef CGLTF_H_INCLUDED__ */
   851  
   852  /*
   853   *
   854   * Stop now, if you are only interested in the API.
   855   * Below, you find the implementation.
   856   *
   857   */
   858  
   859  #if defined(__INTELLISENSE__) || defined(__JETBRAINS_IDE__)
   860  /* This makes MSVC/CLion intellisense work. */
   861  #define CGLTF_IMPLEMENTATION
   862  #endif
   863  
   864  #ifdef CGLTF_IMPLEMENTATION
   865  
   866  #include <stdint.h> /* For uint8_t, uint32_t */
   867  #include <string.h> /* For strncpy */
   868  #include <stdio.h>  /* For fopen */
   869  #include <limits.h> /* For UINT_MAX etc */
   870  #include <float.h>  /* For FLT_MAX */
   871  
   872  #if !defined(CGLTF_MALLOC) || !defined(CGLTF_FREE) || !defined(CGLTF_ATOI) || !defined(CGLTF_ATOF) || !defined(CGLTF_ATOLL)
   873  #include <stdlib.h> /* For malloc, free, atoi, atof */
   874  #endif
   875  
   876  #if CGLTF_VALIDATE_ENABLE_ASSERTS
   877  #include <assert.h>
   878  #endif
   879  
   880  /* JSMN_PARENT_LINKS is necessary to make parsing large structures linear in input size */
   881  #define JSMN_PARENT_LINKS
   882  
   883  /* JSMN_STRICT is necessary to reject invalid JSON documents */
   884  #define JSMN_STRICT
   885  
   886  /*
   887   * -- jsmn.h start --
   888   * Source: https://github.com/zserge/jsmn
   889   * License: MIT
   890   */
   891  typedef enum {
   892  	JSMN_UNDEFINED = 0,
   893  	JSMN_OBJECT = 1,
   894  	JSMN_ARRAY = 2,
   895  	JSMN_STRING = 3,
   896  	JSMN_PRIMITIVE = 4
   897  } jsmntype_t;
   898  enum jsmnerr {
   899  	/* Not enough tokens were provided */
   900  	JSMN_ERROR_NOMEM = -1,
   901  	/* Invalid character inside JSON string */
   902  	JSMN_ERROR_INVAL = -2,
   903  	/* The string is not a full JSON packet, more bytes expected */
   904  	JSMN_ERROR_PART = -3
   905  };
   906  typedef struct {
   907  	jsmntype_t type;
   908  	int start;
   909  	int end;
   910  	int size;
   911  #ifdef JSMN_PARENT_LINKS
   912  	int parent;
   913  #endif
   914  } jsmntok_t;
   915  typedef struct {
   916  	unsigned int pos; /* offset in the JSON string */
   917  	unsigned int toknext; /* next token to allocate */
   918  	int toksuper; /* superior token node, e.g parent object or array */
   919  } jsmn_parser;
   920  static void jsmn_init(jsmn_parser *parser);
   921  static int jsmn_parse(jsmn_parser *parser, const char *js, size_t len, jsmntok_t *tokens, size_t num_tokens);
   922  /*
   923   * -- jsmn.h end --
   924   */
   925  
   926  
   927  static const cgltf_size GlbHeaderSize = 12;
   928  static const cgltf_size GlbChunkHeaderSize = 8;
   929  static const uint32_t GlbVersion = 2;
   930  static const uint32_t GlbMagic = 0x46546C67;
   931  static const uint32_t GlbMagicJsonChunk = 0x4E4F534A;
   932  static const uint32_t GlbMagicBinChunk = 0x004E4942;
   933  
   934  #ifndef CGLTF_MALLOC
   935  #define CGLTF_MALLOC(size) malloc(size)
   936  #endif
   937  #ifndef CGLTF_FREE
   938  #define CGLTF_FREE(ptr) free(ptr)
   939  #endif
   940  #ifndef CGLTF_ATOI
   941  #define CGLTF_ATOI(str) atoi(str)
   942  #endif
   943  #ifndef CGLTF_ATOF
   944  #define CGLTF_ATOF(str) atof(str)
   945  #endif
   946  #ifndef CGLTF_ATOLL
   947  #define CGLTF_ATOLL(str) atoll(str)
   948  #endif
   949  #ifndef CGLTF_VALIDATE_ENABLE_ASSERTS
   950  #define CGLTF_VALIDATE_ENABLE_ASSERTS 0
   951  #endif
   952  
   953  static void* cgltf_default_alloc(void* user, cgltf_size size)
   954  {
   955  	(void)user;
   956  	return CGLTF_MALLOC(size);
   957  }
   958  
   959  static void cgltf_default_free(void* user, void* ptr)
   960  {
   961  	(void)user;
   962  	CGLTF_FREE(ptr);
   963  }
   964  
   965  static void* cgltf_calloc(cgltf_options* options, size_t element_size, cgltf_size count)
   966  {
   967  	if (SIZE_MAX / element_size < count)
   968  	{
   969  		return NULL;
   970  	}
   971  	void* result = options->memory.alloc_func(options->memory.user_data, element_size * count);
   972  	if (!result)
   973  	{
   974  		return NULL;
   975  	}
   976  	memset(result, 0, element_size * count);
   977  	return result;
   978  }
   979  
   980  static cgltf_result cgltf_default_file_read(const struct cgltf_memory_options* memory_options, const struct cgltf_file_options* file_options, const char* path, cgltf_size* size, void** data)
   981  {
   982  	(void)file_options;
   983  	void* (*memory_alloc)(void*, cgltf_size) = memory_options->alloc_func ? memory_options->alloc_func : &cgltf_default_alloc;
   984  	void (*memory_free)(void*, void*) = memory_options->free_func ? memory_options->free_func : &cgltf_default_free;
   985  
   986  	FILE* file = fopen(path, "rb");
   987  	if (!file)
   988  	{
   989  		return cgltf_result_file_not_found;
   990  	}
   991  
   992  	cgltf_size file_size = size ? *size : 0;
   993  
   994  	if (file_size == 0)
   995  	{
   996  		fseek(file, 0, SEEK_END);
   997  
   998  #ifdef _WIN32
   999  		__int64 length = _ftelli64(file);
  1000  #else
  1001  		long length = ftell(file);
  1002  #endif
  1003  
  1004  		if (length < 0)
  1005  		{
  1006  			fclose(file);
  1007  			return cgltf_result_io_error;
  1008  		}
  1009  
  1010  		fseek(file, 0, SEEK_SET);
  1011  		file_size = (cgltf_size)length;
  1012  	}
  1013  
  1014  	char* file_data = (char*)memory_alloc(memory_options->user_data, file_size);
  1015  	if (!file_data)
  1016  	{
  1017  		fclose(file);
  1018  		return cgltf_result_out_of_memory;
  1019  	}
  1020  	
  1021  	cgltf_size read_size = fread(file_data, 1, file_size, file);
  1022  
  1023  	fclose(file);
  1024  
  1025  	if (read_size != file_size)
  1026  	{
  1027  		memory_free(memory_options->user_data, file_data);
  1028  		return cgltf_result_io_error;
  1029  	}
  1030  
  1031  	if (size)
  1032  	{
  1033  		*size = file_size;
  1034  	}
  1035  	if (data)
  1036  	{
  1037  		*data = file_data;
  1038  	}
  1039  
  1040  	return cgltf_result_success;
  1041  }
  1042  
  1043  static void cgltf_default_file_release(const struct cgltf_memory_options* memory_options, const struct cgltf_file_options* file_options, void* data)
  1044  {
  1045  	(void)file_options;
  1046  	void (*memfree)(void*, void*) = memory_options->free_func ? memory_options->free_func : &cgltf_default_free;
  1047  	memfree(memory_options->user_data, data);
  1048  }
  1049  
  1050  static cgltf_result cgltf_parse_json(cgltf_options* options, const uint8_t* json_chunk, cgltf_size size, cgltf_data** out_data);
  1051  
  1052  cgltf_result cgltf_parse(const cgltf_options* options, const void* data, cgltf_size size, cgltf_data** out_data)
  1053  {
  1054  	if (size < GlbHeaderSize)
  1055  	{
  1056  		return cgltf_result_data_too_short;
  1057  	}
  1058  
  1059  	if (options == NULL)
  1060  	{
  1061  		return cgltf_result_invalid_options;
  1062  	}
  1063  
  1064  	cgltf_options fixed_options = *options;
  1065  	if (fixed_options.memory.alloc_func == NULL)
  1066  	{
  1067  		fixed_options.memory.alloc_func = &cgltf_default_alloc;
  1068  	}
  1069  	if (fixed_options.memory.free_func == NULL)
  1070  	{
  1071  		fixed_options.memory.free_func = &cgltf_default_free;
  1072  	}
  1073  
  1074  	uint32_t tmp;
  1075  	// Magic
  1076  	memcpy(&tmp, data, 4);
  1077  	if (tmp != GlbMagic)
  1078  	{
  1079  		if (fixed_options.type == cgltf_file_type_invalid)
  1080  		{
  1081  			fixed_options.type = cgltf_file_type_gltf;
  1082  		}
  1083  		else if (fixed_options.type == cgltf_file_type_glb)
  1084  		{
  1085  			return cgltf_result_unknown_format;
  1086  		}
  1087  	}
  1088  
  1089  	if (fixed_options.type == cgltf_file_type_gltf)
  1090  	{
  1091  		cgltf_result json_result = cgltf_parse_json(&fixed_options, (const uint8_t*)data, size, out_data);
  1092  		if (json_result != cgltf_result_success)
  1093  		{
  1094  			return json_result;
  1095  		}
  1096  
  1097  		(*out_data)->file_type = cgltf_file_type_gltf;
  1098  
  1099  		return cgltf_result_success;
  1100  	}
  1101  
  1102  	const uint8_t* ptr = (const uint8_t*)data;
  1103  	// Version
  1104  	memcpy(&tmp, ptr + 4, 4);
  1105  	uint32_t version = tmp;
  1106  	if (version != GlbVersion)
  1107  	{
  1108  		return version < GlbVersion ? cgltf_result_legacy_gltf : cgltf_result_unknown_format;
  1109  	}
  1110  
  1111  	// Total length
  1112  	memcpy(&tmp, ptr + 8, 4);
  1113  	if (tmp > size)
  1114  	{
  1115  		return cgltf_result_data_too_short;
  1116  	}
  1117  
  1118  	const uint8_t* json_chunk = ptr + GlbHeaderSize;
  1119  
  1120  	if (GlbHeaderSize + GlbChunkHeaderSize > size)
  1121  	{
  1122  		return cgltf_result_data_too_short;
  1123  	}
  1124  
  1125  	// JSON chunk: length
  1126  	uint32_t json_length;
  1127  	memcpy(&json_length, json_chunk, 4);
  1128  	if (GlbHeaderSize + GlbChunkHeaderSize + json_length > size)
  1129  	{
  1130  		return cgltf_result_data_too_short;
  1131  	}
  1132  
  1133  	// JSON chunk: magic
  1134  	memcpy(&tmp, json_chunk + 4, 4);
  1135  	if (tmp != GlbMagicJsonChunk)
  1136  	{
  1137  		return cgltf_result_unknown_format;
  1138  	}
  1139  
  1140  	json_chunk += GlbChunkHeaderSize;
  1141  
  1142  	const void* bin = 0;
  1143  	cgltf_size bin_size = 0;
  1144  
  1145  	if (GlbHeaderSize + GlbChunkHeaderSize + json_length + GlbChunkHeaderSize <= size)
  1146  	{
  1147  		// We can read another chunk
  1148  		const uint8_t* bin_chunk = json_chunk + json_length;
  1149  
  1150  		// Bin chunk: length
  1151  		uint32_t bin_length;
  1152  		memcpy(&bin_length, bin_chunk, 4);
  1153  		if (GlbHeaderSize + GlbChunkHeaderSize + json_length + GlbChunkHeaderSize + bin_length > size)
  1154  		{
  1155  			return cgltf_result_data_too_short;
  1156  		}
  1157  
  1158  		// Bin chunk: magic
  1159  		memcpy(&tmp, bin_chunk + 4, 4);
  1160  		if (tmp != GlbMagicBinChunk)
  1161  		{
  1162  			return cgltf_result_unknown_format;
  1163  		}
  1164  
  1165  		bin_chunk += GlbChunkHeaderSize;
  1166  
  1167  		bin = bin_chunk;
  1168  		bin_size = bin_length;
  1169  	}
  1170  
  1171  	cgltf_result json_result = cgltf_parse_json(&fixed_options, json_chunk, json_length, out_data);
  1172  	if (json_result != cgltf_result_success)
  1173  	{
  1174  		return json_result;
  1175  	}
  1176  
  1177  	(*out_data)->file_type = cgltf_file_type_glb;
  1178  	(*out_data)->bin = bin;
  1179  	(*out_data)->bin_size = bin_size;
  1180  
  1181  	return cgltf_result_success;
  1182  }
  1183  
  1184  cgltf_result cgltf_parse_file(const cgltf_options* options, const char* path, cgltf_data** out_data)
  1185  {
  1186  	if (options == NULL)
  1187  	{
  1188  		return cgltf_result_invalid_options;
  1189  	}
  1190  
  1191  	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;
  1192  	void (*file_release)(const struct cgltf_memory_options*, const struct cgltf_file_options*, void* data) = options->file.release ? options->file.release : cgltf_default_file_release;
  1193  
  1194  	void* file_data = NULL;
  1195  	cgltf_size file_size = 0;
  1196  	cgltf_result result = file_read(&options->memory, &options->file, path, &file_size, &file_data);
  1197  	if (result != cgltf_result_success)
  1198  	{
  1199  		return result;
  1200  	}
  1201  
  1202  	result = cgltf_parse(options, file_data, file_size, out_data);
  1203  
  1204  	if (result != cgltf_result_success)
  1205  	{
  1206  		file_release(&options->memory, &options->file, file_data);
  1207  		return result;
  1208  	}
  1209  
  1210  	(*out_data)->file_data = file_data;
  1211  
  1212  	return cgltf_result_success;
  1213  }
  1214  
  1215  static void cgltf_combine_paths(char* path, const char* base, const char* uri)
  1216  {
  1217  	const char* s0 = strrchr(base, '/');
  1218  	const char* s1 = strrchr(base, '\\');
  1219  	const char* slash = s0 ? (s1 && s1 > s0 ? s1 : s0) : s1;
  1220  
  1221  	if (slash)
  1222  	{
  1223  		size_t prefix = slash - base + 1;
  1224  
  1225  		strncpy(path, base, prefix);
  1226  		strcpy(path + prefix, uri);
  1227  	}
  1228  	else
  1229  	{
  1230  		strcpy(path, uri);
  1231  	}
  1232  }
  1233  
  1234  static cgltf_result cgltf_load_buffer_file(const cgltf_options* options, cgltf_size size, const char* uri, const char* gltf_path, void** out_data)
  1235  {
  1236  	void* (*memory_alloc)(void*, cgltf_size) = options->memory.alloc_func ? options->memory.alloc_func : &cgltf_default_alloc;
  1237  	void (*memory_free)(void*, void*) = options->memory.free_func ? options->memory.free_func : &cgltf_default_free;
  1238  	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;
  1239  
  1240  	char* path = (char*)memory_alloc(options->memory.user_data, strlen(uri) + strlen(gltf_path) + 1);
  1241  	if (!path)
  1242  	{
  1243  		return cgltf_result_out_of_memory;
  1244  	}
  1245  
  1246  	cgltf_combine_paths(path, gltf_path, uri);
  1247  
  1248  	// after combining, the tail of the resulting path is a uri; decode_uri converts it into path
  1249  	cgltf_decode_uri(path + strlen(path) - strlen(uri));
  1250  
  1251  	void* file_data = NULL;
  1252  	cgltf_result result = file_read(&options->memory, &options->file, path, &size, &file_data);
  1253  
  1254  	memory_free(options->memory.user_data, path);
  1255  
  1256  	*out_data = (result == cgltf_result_success) ? file_data : NULL;
  1257  
  1258  	return result;
  1259  }
  1260  
  1261  cgltf_result cgltf_load_buffer_base64(const cgltf_options* options, cgltf_size size, const char* base64, void** out_data)
  1262  {
  1263  	void* (*memory_alloc)(void*, cgltf_size) = options->memory.alloc_func ? options->memory.alloc_func : &cgltf_default_alloc;
  1264  	void (*memory_free)(void*, void*) = options->memory.free_func ? options->memory.free_func : &cgltf_default_free;
  1265  
  1266  	unsigned char* data = (unsigned char*)memory_alloc(options->memory.user_data, size);
  1267  	if (!data)
  1268  	{
  1269  		return cgltf_result_out_of_memory;
  1270  	}
  1271  
  1272  	unsigned int buffer = 0;
  1273  	unsigned int buffer_bits = 0;
  1274  
  1275  	for (cgltf_size i = 0; i < size; ++i)
  1276  	{
  1277  		while (buffer_bits < 8)
  1278  		{
  1279  			char ch = *base64++;
  1280  
  1281  			int index =
  1282  				(unsigned)(ch - 'A') < 26 ? (ch - 'A') :
  1283  				(unsigned)(ch - 'a') < 26 ? (ch - 'a') + 26 :
  1284  				(unsigned)(ch - '0') < 10 ? (ch - '0') + 52 :
  1285  				ch == '+' ? 62 :
  1286  				ch == '/' ? 63 :
  1287  				-1;
  1288  
  1289  			if (index < 0)
  1290  			{
  1291  				memory_free(options->memory.user_data, data);
  1292  				return cgltf_result_io_error;
  1293  			}
  1294  
  1295  			buffer = (buffer << 6) | index;
  1296  			buffer_bits += 6;
  1297  		}
  1298  
  1299  		data[i] = (unsigned char)(buffer >> (buffer_bits - 8));
  1300  		buffer_bits -= 8;
  1301  	}
  1302  
  1303  	*out_data = data;
  1304  
  1305  	return cgltf_result_success;
  1306  }
  1307  
  1308  static int cgltf_unhex(char ch)
  1309  {
  1310  	return
  1311  		(unsigned)(ch - '0') < 10 ? (ch - '0') :
  1312  		(unsigned)(ch - 'A') < 6 ? (ch - 'A') + 10 :
  1313  		(unsigned)(ch - 'a') < 6 ? (ch - 'a') + 10 :
  1314  		-1;
  1315  }
  1316  
  1317  cgltf_size cgltf_decode_string(char* string)
  1318  {
  1319  	char* read = string + strcspn(string, "\\");
  1320  	if (*read == 0)
  1321  	{
  1322  		return read - string;
  1323  	}
  1324  	char* write = string;
  1325  	char* last = string;
  1326  
  1327  	for (;;)
  1328  	{
  1329  		// Copy characters since last escaped sequence
  1330  		cgltf_size written = read - last;
  1331  		memmove(write, last, written);
  1332  		write += written;
  1333  
  1334  		if (*read++ == 0)
  1335  		{
  1336  			break;
  1337  		}
  1338  
  1339  		// jsmn already checked that all escape sequences are valid
  1340  		switch (*read++)
  1341  		{
  1342  		case '\"': *write++ = '\"'; break;
  1343  		case '/':  *write++ = '/';  break;
  1344  		case '\\': *write++ = '\\'; break;
  1345  		case 'b':  *write++ = '\b'; break;
  1346  		case 'f':  *write++ = '\f'; break;
  1347  		case 'r':  *write++ = '\r'; break;
  1348  		case 'n':  *write++ = '\n'; break;
  1349  		case 't':  *write++ = '\t'; break;
  1350  		case 'u':
  1351  		{
  1352  			// UCS-2 codepoint \uXXXX to UTF-8
  1353  			int character = 0;
  1354  			for (cgltf_size i = 0; i < 4; ++i)
  1355  			{
  1356  				character = (character << 4) + cgltf_unhex(*read++);
  1357  			}
  1358  
  1359  			if (character <= 0x7F)
  1360  			{
  1361  				*write++ = character & 0xFF;
  1362  			}
  1363  			else if (character <= 0x7FF)
  1364  			{
  1365  				*write++ = 0xC0 | ((character >> 6) & 0xFF);
  1366  				*write++ = 0x80 | (character & 0x3F);
  1367  			}
  1368  			else
  1369  			{
  1370  				*write++ = 0xE0 | ((character >> 12) & 0xFF);
  1371  				*write++ = 0x80 | ((character >> 6) & 0x3F);
  1372  				*write++ = 0x80 | (character & 0x3F);
  1373  			}
  1374  			break;
  1375  		}
  1376  		default:
  1377  			break;
  1378  		}
  1379  
  1380  		last = read;
  1381  		read += strcspn(read, "\\");
  1382  	}
  1383  
  1384  	*write = 0;
  1385  	return write - string;
  1386  }
  1387  
  1388  cgltf_size cgltf_decode_uri(char* uri)
  1389  {
  1390  	char* write = uri;
  1391  	char* i = uri;
  1392  
  1393  	while (*i)
  1394  	{
  1395  		if (*i == '%')
  1396  		{
  1397  			int ch1 = cgltf_unhex(i[1]);
  1398  
  1399  			if (ch1 >= 0)
  1400  			{
  1401  				int ch2 = cgltf_unhex(i[2]);
  1402  
  1403  				if (ch2 >= 0)
  1404  				{
  1405  					*write++ = (char)(ch1 * 16 + ch2);
  1406  					i += 3;
  1407  					continue;
  1408  				}
  1409  			}
  1410  		}
  1411  
  1412  		*write++ = *i++;
  1413  	}
  1414  
  1415  	*write = 0;
  1416  	return write - uri;
  1417  }
  1418  
  1419  cgltf_result cgltf_load_buffers(const cgltf_options* options, cgltf_data* data, const char* gltf_path)
  1420  {
  1421  	if (options == NULL)
  1422  	{
  1423  		return cgltf_result_invalid_options;
  1424  	}
  1425  
  1426  	if (data->buffers_count && data->buffers[0].data == NULL && data->buffers[0].uri == NULL && data->bin)
  1427  	{
  1428  		if (data->bin_size < data->buffers[0].size)
  1429  		{
  1430  			return cgltf_result_data_too_short;
  1431  		}
  1432  
  1433  		data->buffers[0].data = (void*)data->bin;
  1434  		data->buffers[0].data_free_method = cgltf_data_free_method_none;
  1435  	}
  1436  
  1437  	for (cgltf_size i = 0; i < data->buffers_count; ++i)
  1438  	{
  1439  		if (data->buffers[i].data)
  1440  		{
  1441  			continue;
  1442  		}
  1443  
  1444  		const char* uri = data->buffers[i].uri;
  1445  
  1446  		if (uri == NULL)
  1447  		{
  1448  			continue;
  1449  		}
  1450  
  1451  		if (strncmp(uri, "data:", 5) == 0)
  1452  		{
  1453  			const char* comma = strchr(uri, ',');
  1454  
  1455  			if (comma && comma - uri >= 7 && strncmp(comma - 7, ";base64", 7) == 0)
  1456  			{
  1457  				cgltf_result res = cgltf_load_buffer_base64(options, data->buffers[i].size, comma + 1, &data->buffers[i].data);
  1458  				data->buffers[i].data_free_method = cgltf_data_free_method_memory_free;
  1459  
  1460  				if (res != cgltf_result_success)
  1461  				{
  1462  					return res;
  1463  				}
  1464  			}
  1465  			else
  1466  			{
  1467  				return cgltf_result_unknown_format;
  1468  			}
  1469  		}
  1470  		else if (strstr(uri, "://") == NULL && gltf_path)
  1471  		{
  1472  			cgltf_result res = cgltf_load_buffer_file(options, data->buffers[i].size, uri, gltf_path, &data->buffers[i].data);
  1473  			data->buffers[i].data_free_method = cgltf_data_free_method_file_release;
  1474  
  1475  			if (res != cgltf_result_success)
  1476  			{
  1477  				return res;
  1478  			}
  1479  		}
  1480  		else
  1481  		{
  1482  			return cgltf_result_unknown_format;
  1483  		}
  1484  	}
  1485  
  1486  	return cgltf_result_success;
  1487  }
  1488  
  1489  static cgltf_size cgltf_calc_size(cgltf_type type, cgltf_component_type component_type);
  1490  
  1491  static cgltf_size cgltf_calc_index_bound(cgltf_buffer_view* buffer_view, cgltf_size offset, cgltf_component_type component_type, cgltf_size count)
  1492  {
  1493  	char* data = (char*)buffer_view->buffer->data + offset + buffer_view->offset;
  1494  	cgltf_size bound = 0;
  1495  
  1496  	switch (component_type)
  1497  	{
  1498  	case cgltf_component_type_r_8u:
  1499  		for (size_t i = 0; i < count; ++i)
  1500  		{
  1501  			cgltf_size v = ((unsigned char*)data)[i];
  1502  			bound = bound > v ? bound : v;
  1503  		}
  1504  		break;
  1505  
  1506  	case cgltf_component_type_r_16u:
  1507  		for (size_t i = 0; i < count; ++i)
  1508  		{
  1509  			cgltf_size v = ((unsigned short*)data)[i];
  1510  			bound = bound > v ? bound : v;
  1511  		}
  1512  		break;
  1513  
  1514  	case cgltf_component_type_r_32u:
  1515  		for (size_t i = 0; i < count; ++i)
  1516  		{
  1517  			cgltf_size v = ((unsigned int*)data)[i];
  1518  			bound = bound > v ? bound : v;
  1519  		}
  1520  		break;
  1521  
  1522  	default:
  1523  		;
  1524  	}
  1525  
  1526  	return bound;
  1527  }
  1528  
  1529  #if CGLTF_VALIDATE_ENABLE_ASSERTS
  1530  #define CGLTF_ASSERT_IF(cond, result) assert(!(cond)); if (cond) return result;
  1531  #else
  1532  #define CGLTF_ASSERT_IF(cond, result) if (cond) return result;
  1533  #endif
  1534  
  1535  cgltf_result cgltf_validate(cgltf_data* data)
  1536  {
  1537  	for (cgltf_size i = 0; i < data->accessors_count; ++i)
  1538  	{
  1539  		cgltf_accessor* accessor = &data->accessors[i];
  1540  
  1541  		cgltf_size element_size = cgltf_calc_size(accessor->type, accessor->component_type);
  1542  
  1543  		if (accessor->buffer_view)
  1544  		{
  1545  			cgltf_size req_size = accessor->offset + accessor->stride * (accessor->count - 1) + element_size;
  1546  
  1547  			CGLTF_ASSERT_IF(accessor->buffer_view->size < req_size, cgltf_result_data_too_short);
  1548  		}
  1549  
  1550  		if (accessor->is_sparse)
  1551  		{
  1552  			cgltf_accessor_sparse* sparse = &accessor->sparse;
  1553  
  1554  			cgltf_size indices_component_size = cgltf_calc_size(cgltf_type_scalar, sparse->indices_component_type);
  1555  			cgltf_size indices_req_size = sparse->indices_byte_offset + indices_component_size * sparse->count;
  1556  			cgltf_size values_req_size = sparse->values_byte_offset + element_size * sparse->count;
  1557  
  1558  			CGLTF_ASSERT_IF(sparse->indices_buffer_view->size < indices_req_size ||
  1559  							sparse->values_buffer_view->size < values_req_size, cgltf_result_data_too_short);
  1560  
  1561  			CGLTF_ASSERT_IF(sparse->indices_component_type != cgltf_component_type_r_8u &&
  1562  							sparse->indices_component_type != cgltf_component_type_r_16u &&
  1563  							sparse->indices_component_type != cgltf_component_type_r_32u, cgltf_result_invalid_gltf);
  1564  
  1565  			if (sparse->indices_buffer_view->buffer->data)
  1566  			{
  1567  				cgltf_size index_bound = cgltf_calc_index_bound(sparse->indices_buffer_view, sparse->indices_byte_offset, sparse->indices_component_type, sparse->count);
  1568  
  1569  				CGLTF_ASSERT_IF(index_bound >= accessor->count, cgltf_result_data_too_short);
  1570  			}
  1571  		}
  1572  	}
  1573  
  1574  	for (cgltf_size i = 0; i < data->buffer_views_count; ++i)
  1575  	{
  1576  		cgltf_size req_size = data->buffer_views[i].offset + data->buffer_views[i].size;
  1577  
  1578  		CGLTF_ASSERT_IF(data->buffer_views[i].buffer && data->buffer_views[i].buffer->size < req_size, cgltf_result_data_too_short);
  1579  
  1580  		if (data->buffer_views[i].has_meshopt_compression)
  1581  		{
  1582  			cgltf_meshopt_compression* mc = &data->buffer_views[i].meshopt_compression;
  1583  
  1584  			CGLTF_ASSERT_IF(mc->buffer == NULL || mc->buffer->size < mc->offset + mc->size, cgltf_result_data_too_short);
  1585  
  1586  			CGLTF_ASSERT_IF(data->buffer_views[i].stride && mc->stride != data->buffer_views[i].stride, cgltf_result_invalid_gltf);
  1587  
  1588  			CGLTF_ASSERT_IF(data->buffer_views[i].size != mc->stride * mc->count, cgltf_result_invalid_gltf);
  1589  
  1590  			CGLTF_ASSERT_IF(mc->mode == cgltf_meshopt_compression_mode_invalid, cgltf_result_invalid_gltf);
  1591  
  1592  			CGLTF_ASSERT_IF(mc->mode == cgltf_meshopt_compression_mode_attributes && !(mc->stride % 4 == 0 && mc->stride <= 256), cgltf_result_invalid_gltf);
  1593  
  1594  			CGLTF_ASSERT_IF(mc->mode == cgltf_meshopt_compression_mode_triangles && mc->count % 3 != 0, cgltf_result_invalid_gltf);
  1595  
  1596  			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);
  1597  
  1598  			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);
  1599  
  1600  			CGLTF_ASSERT_IF(mc->filter == cgltf_meshopt_compression_filter_octahedral && mc->stride != 4 && mc->stride != 8, cgltf_result_invalid_gltf);
  1601  
  1602  			CGLTF_ASSERT_IF(mc->filter == cgltf_meshopt_compression_filter_quaternion && mc->stride != 8, cgltf_result_invalid_gltf);
  1603  		}
  1604  	}
  1605  
  1606  	for (cgltf_size i = 0; i < data->meshes_count; ++i)
  1607  	{
  1608  		if (data->meshes[i].weights)
  1609  		{
  1610  			CGLTF_ASSERT_IF(data->meshes[i].primitives_count && data->meshes[i].primitives[0].targets_count != data->meshes[i].weights_count, cgltf_result_invalid_gltf);
  1611  		}
  1612  
  1613  		if (data->meshes[i].target_names)
  1614  		{
  1615  			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);
  1616  		}
  1617  
  1618  		for (cgltf_size j = 0; j < data->meshes[i].primitives_count; ++j)
  1619  		{
  1620  			CGLTF_ASSERT_IF(data->meshes[i].primitives[j].targets_count != data->meshes[i].primitives[0].targets_count, cgltf_result_invalid_gltf);
  1621  
  1622  			if (data->meshes[i].primitives[j].attributes_count)
  1623  			{
  1624  				cgltf_accessor* first = data->meshes[i].primitives[j].attributes[0].data;
  1625  
  1626  				for (cgltf_size k = 0; k < data->meshes[i].primitives[j].attributes_count; ++k)
  1627  				{
  1628  					CGLTF_ASSERT_IF(data->meshes[i].primitives[j].attributes[k].data->count != first->count, cgltf_result_invalid_gltf);
  1629  				}
  1630  
  1631  				for (cgltf_size k = 0; k < data->meshes[i].primitives[j].targets_count; ++k)
  1632  				{
  1633  					for (cgltf_size m = 0; m < data->meshes[i].primitives[j].targets[k].attributes_count; ++m)
  1634  					{
  1635  						CGLTF_ASSERT_IF(data->meshes[i].primitives[j].targets[k].attributes[m].data->count != first->count, cgltf_result_invalid_gltf);
  1636  					}
  1637  				}
  1638  
  1639  				cgltf_accessor* indices = data->meshes[i].primitives[j].indices;
  1640  
  1641  				CGLTF_ASSERT_IF(indices &&
  1642  					indices->component_type != cgltf_component_type_r_8u &&
  1643  					indices->component_type != cgltf_component_type_r_16u &&
  1644  					indices->component_type != cgltf_component_type_r_32u, cgltf_result_invalid_gltf);
  1645  
  1646  				if (indices && indices->buffer_view && indices->buffer_view->buffer->data)
  1647  				{
  1648  					cgltf_size index_bound = cgltf_calc_index_bound(indices->buffer_view, indices->offset, indices->component_type, indices->count);
  1649  
  1650  					CGLTF_ASSERT_IF(index_bound >= first->count, cgltf_result_data_too_short);
  1651  				}
  1652  
  1653  				for (cgltf_size k = 0; k < data->meshes[i].primitives[j].mappings_count; ++k)
  1654  				{
  1655  					CGLTF_ASSERT_IF(data->meshes[i].primitives[j].mappings[k].variant >= data->variants_count, cgltf_result_invalid_gltf);
  1656  				}
  1657  			}
  1658  		}
  1659  	}
  1660  
  1661  	for (cgltf_size i = 0; i < data->nodes_count; ++i)
  1662  	{
  1663  		if (data->nodes[i].weights && data->nodes[i].mesh)
  1664  		{
  1665  			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);
  1666  		}
  1667  	}
  1668  
  1669  	for (cgltf_size i = 0; i < data->nodes_count; ++i)
  1670  	{
  1671  		cgltf_node* p1 = data->nodes[i].parent;
  1672  		cgltf_node* p2 = p1 ? p1->parent : NULL;
  1673  
  1674  		while (p1 && p2)
  1675  		{
  1676  			CGLTF_ASSERT_IF(p1 == p2, cgltf_result_invalid_gltf);
  1677  
  1678  			p1 = p1->parent;
  1679  			p2 = p2->parent ? p2->parent->parent : NULL;
  1680  		}
  1681  	}
  1682  
  1683  	for (cgltf_size i = 0; i < data->scenes_count; ++i)
  1684  	{
  1685  		for (cgltf_size j = 0; j < data->scenes[i].nodes_count; ++j)
  1686  		{
  1687  			CGLTF_ASSERT_IF(data->scenes[i].nodes[j]->parent, cgltf_result_invalid_gltf);
  1688  		}
  1689  	}
  1690  
  1691  	for (cgltf_size i = 0; i < data->animations_count; ++i)
  1692  	{
  1693  		for (cgltf_size j = 0; j < data->animations[i].channels_count; ++j)
  1694  		{
  1695  			cgltf_animation_channel* channel = &data->animations[i].channels[j];
  1696  
  1697  			if (!channel->target_node)
  1698  			{
  1699  				continue;
  1700  			}
  1701  
  1702  			cgltf_size components = 1;
  1703  
  1704  			if (channel->target_path == cgltf_animation_path_type_weights)
  1705  			{
  1706  				CGLTF_ASSERT_IF(!channel->target_node->mesh || !channel->target_node->mesh->primitives_count, cgltf_result_invalid_gltf);
  1707  
  1708  				components = channel->target_node->mesh->primitives[0].targets_count;
  1709  			}
  1710  
  1711  			cgltf_size values = channel->sampler->interpolation == cgltf_interpolation_type_cubic_spline ? 3 : 1;
  1712  
  1713  			CGLTF_ASSERT_IF(channel->sampler->input->count * components * values != channel->sampler->output->count, cgltf_result_data_too_short);
  1714  		}
  1715  	}
  1716  
  1717  	return cgltf_result_success;
  1718  }
  1719  
  1720  cgltf_result cgltf_copy_extras_json(const cgltf_data* data, const cgltf_extras* extras, char* dest, cgltf_size* dest_size)
  1721  {
  1722  	cgltf_size json_size = extras->end_offset - extras->start_offset;
  1723  
  1724  	if (!dest)
  1725  	{
  1726  		if (dest_size)
  1727  		{
  1728  			*dest_size = json_size + 1;
  1729  			return cgltf_result_success;
  1730  		}
  1731  		return cgltf_result_invalid_options;
  1732  	}
  1733  
  1734  	if (*dest_size + 1 < json_size)
  1735  	{
  1736  		strncpy(dest, data->json + extras->start_offset, *dest_size - 1);
  1737  		dest[*dest_size - 1] = 0;
  1738  	}
  1739  	else
  1740  	{
  1741  		strncpy(dest, data->json + extras->start_offset, json_size);
  1742  		dest[json_size] = 0;
  1743  	}
  1744  
  1745  	return cgltf_result_success;
  1746  }
  1747  
  1748  void cgltf_free_extensions(cgltf_data* data, cgltf_extension* extensions, cgltf_size extensions_count)
  1749  {
  1750  	for (cgltf_size i = 0; i < extensions_count; ++i)
  1751  	{
  1752  		data->memory.free_func(data->memory.user_data, extensions[i].name);
  1753  		data->memory.free_func(data->memory.user_data, extensions[i].data);
  1754  	}
  1755  	data->memory.free_func(data->memory.user_data, extensions);
  1756  }
  1757  
  1758  void cgltf_free(cgltf_data* data)
  1759  {
  1760  	if (!data)
  1761  	{
  1762  		return;
  1763  	}
  1764  
  1765  	void (*file_release)(const struct cgltf_memory_options*, const struct cgltf_file_options*, void* data) = data->file.release ? data->file.release : cgltf_default_file_release;
  1766  
  1767  	data->memory.free_func(data->memory.user_data, data->asset.copyright);
  1768  	data->memory.free_func(data->memory.user_data, data->asset.generator);
  1769  	data->memory.free_func(data->memory.user_data, data->asset.version);
  1770  	data->memory.free_func(data->memory.user_data, data->asset.min_version);
  1771  
  1772  	cgltf_free_extensions(data, data->asset.extensions, data->asset.extensions_count);
  1773  
  1774  	for (cgltf_size i = 0; i < data->accessors_count; ++i)
  1775  	{
  1776  		data->memory.free_func(data->memory.user_data, data->accessors[i].name);
  1777  
  1778  		if(data->accessors[i].is_sparse)
  1779  		{
  1780  			cgltf_free_extensions(data, data->accessors[i].sparse.extensions, data->accessors[i].sparse.extensions_count);
  1781  			cgltf_free_extensions(data, data->accessors[i].sparse.indices_extensions, data->accessors[i].sparse.indices_extensions_count);
  1782  			cgltf_free_extensions(data, data->accessors[i].sparse.values_extensions, data->accessors[i].sparse.values_extensions_count);
  1783  		}
  1784  		cgltf_free_extensions(data, data->accessors[i].extensions, data->accessors[i].extensions_count);
  1785  	}
  1786  	data->memory.free_func(data->memory.user_data, data->accessors);
  1787  
  1788  	for (cgltf_size i = 0; i < data->buffer_views_count; ++i)
  1789  	{
  1790  		data->memory.free_func(data->memory.user_data, data->buffer_views[i].name);
  1791  		data->memory.free_func(data->memory.user_data, data->buffer_views[i].data);
  1792  
  1793  		cgltf_free_extensions(data, data->buffer_views[i].extensions, data->buffer_views[i].extensions_count);
  1794  	}
  1795  	data->memory.free_func(data->memory.user_data, data->buffer_views);
  1796  
  1797  	for (cgltf_size i = 0; i < data->buffers_count; ++i)
  1798  	{
  1799  		data->memory.free_func(data->memory.user_data, data->buffers[i].name);
  1800  
  1801  		if (data->buffers[i].data_free_method == cgltf_data_free_method_file_release)
  1802  		{
  1803  			file_release(&data->memory, &data->file, data->buffers[i].data);
  1804  		}
  1805  		else if (data->buffers[i].data_free_method == cgltf_data_free_method_memory_free)
  1806  		{
  1807  			data->memory.free_func(data->memory.user_data, data->buffers[i].data);
  1808  		}
  1809  
  1810  		data->memory.free_func(data->memory.user_data, data->buffers[i].uri);
  1811  
  1812  		cgltf_free_extensions(data, data->buffers[i].extensions, data->buffers[i].extensions_count);
  1813  	}
  1814  
  1815  	data->memory.free_func(data->memory.user_data, data->buffers);
  1816  
  1817  	for (cgltf_size i = 0; i < data->meshes_count; ++i)
  1818  	{
  1819  		data->memory.free_func(data->memory.user_data, data->meshes[i].name);
  1820  
  1821  		for (cgltf_size j = 0; j < data->meshes[i].primitives_count; ++j)
  1822  		{
  1823  			for (cgltf_size k = 0; k < data->meshes[i].primitives[j].attributes_count; ++k)
  1824  			{
  1825  				data->memory.free_func(data->memory.user_data, data->meshes[i].primitives[j].attributes[k].name);
  1826  			}
  1827  
  1828  			data->memory.free_func(data->memory.user_data, data->meshes[i].primitives[j].attributes);
  1829  
  1830  			for (cgltf_size k = 0; k < data->meshes[i].primitives[j].targets_count; ++k)
  1831  			{
  1832  				for (cgltf_size m = 0; m < data->meshes[i].primitives[j].targets[k].attributes_count; ++m)
  1833  				{
  1834  					data->memory.free_func(data->memory.user_data, data->meshes[i].primitives[j].targets[k].attributes[m].name);
  1835  				}
  1836  
  1837  				data->memory.free_func(data->memory.user_data, data->meshes[i].primitives[j].targets[k].attributes);
  1838  			}
  1839  
  1840  			data->memory.free_func(data->memory.user_data, data->meshes[i].primitives[j].targets);
  1841  
  1842  			if (data->meshes[i].primitives[j].has_draco_mesh_compression)
  1843  			{
  1844  				for (cgltf_size k = 0; k < data->meshes[i].primitives[j].draco_mesh_compression.attributes_count; ++k)
  1845  				{
  1846  					data->memory.free_func(data->memory.user_data, data->meshes[i].primitives[j].draco_mesh_compression.attributes[k].name);
  1847  				}
  1848  
  1849  				data->memory.free_func(data->memory.user_data, data->meshes[i].primitives[j].draco_mesh_compression.attributes);
  1850  			}
  1851  
  1852  			data->memory.free_func(data->memory.user_data, data->meshes[i].primitives[j].mappings);
  1853  
  1854  			cgltf_free_extensions(data, data->meshes[i].primitives[j].extensions, data->meshes[i].primitives[j].extensions_count);
  1855  		}
  1856  
  1857  		data->memory.free_func(data->memory.user_data, data->meshes[i].primitives);
  1858  		data->memory.free_func(data->memory.user_data, data->meshes[i].weights);
  1859  
  1860  		for (cgltf_size j = 0; j < data->meshes[i].target_names_count; ++j)
  1861  		{
  1862  			data->memory.free_func(data->memory.user_data, data->meshes[i].target_names[j]);
  1863  		}
  1864  
  1865  		cgltf_free_extensions(data, data->meshes[i].extensions, data->meshes[i].extensions_count);
  1866  
  1867  		data->memory.free_func(data->memory.user_data, data->meshes[i].target_names);
  1868  	}
  1869  
  1870  	data->memory.free_func(data->memory.user_data, data->meshes);
  1871  
  1872  	for (cgltf_size i = 0; i < data->materials_count; ++i)
  1873  	{
  1874  		data->memory.free_func(data->memory.user_data, data->materials[i].name);
  1875  
  1876  		if(data->materials[i].has_pbr_metallic_roughness)
  1877  		{
  1878  			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);
  1879  			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);
  1880  		}
  1881  		if(data->materials[i].has_pbr_specular_glossiness)
  1882  		{
  1883  			cgltf_free_extensions(data, data->materials[i].pbr_specular_glossiness.diffuse_texture.extensions, data->materials[i].pbr_specular_glossiness.diffuse_texture.extensions_count);
  1884  			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);
  1885  		}
  1886  		if(data->materials[i].has_clearcoat)
  1887  		{
  1888  			cgltf_free_extensions(data, data->materials[i].clearcoat.clearcoat_texture.extensions, data->materials[i].clearcoat.clearcoat_texture.extensions_count);
  1889  			cgltf_free_extensions(data, data->materials[i].clearcoat.clearcoat_roughness_texture.extensions, data->materials[i].clearcoat.clearcoat_roughness_texture.extensions_count);
  1890  			cgltf_free_extensions(data, data->materials[i].clearcoat.clearcoat_normal_texture.extensions, data->materials[i].clearcoat.clearcoat_normal_texture.extensions_count);
  1891  		}
  1892  		if(data->materials[i].has_specular)
  1893  		{
  1894  			cgltf_free_extensions(data, data->materials[i].specular.specular_texture.extensions, data->materials[i].specular.specular_texture.extensions_count);
  1895  			cgltf_free_extensions(data, data->materials[i].specular.specular_color_texture.extensions, data->materials[i].specular.specular_color_texture.extensions_count);
  1896  		}
  1897  		if(data->materials[i].has_transmission)
  1898  		{
  1899  			cgltf_free_extensions(data, data->materials[i].transmission.transmission_texture.extensions, data->materials[i].transmission.transmission_texture.extensions_count);
  1900  		}
  1901  		if (data->materials[i].has_volume)
  1902  		{
  1903  			cgltf_free_extensions(data, data->materials[i].volume.thickness_texture.extensions, data->materials[i].volume.thickness_texture.extensions_count);
  1904  		}
  1905  		if(data->materials[i].has_sheen)
  1906  		{
  1907  			cgltf_free_extensions(data, data->materials[i].sheen.sheen_color_texture.extensions, data->materials[i].sheen.sheen_color_texture.extensions_count);
  1908  			cgltf_free_extensions(data, data->materials[i].sheen.sheen_roughness_texture.extensions, data->materials[i].sheen.sheen_roughness_texture.extensions_count);
  1909  		}
  1910  		if(data->materials[i].has_iridescence)
  1911  		{
  1912  			cgltf_free_extensions(data, data->materials[i].iridescence.iridescence_texture.extensions, data->materials[i].iridescence.iridescence_texture.extensions_count);
  1913  			cgltf_free_extensions(data, data->materials[i].iridescence.iridescence_thickness_texture.extensions, data->materials[i].iridescence.iridescence_thickness_texture.extensions_count);
  1914  		}
  1915  
  1916  		cgltf_free_extensions(data, data->materials[i].normal_texture.extensions, data->materials[i].normal_texture.extensions_count);
  1917  		cgltf_free_extensions(data, data->materials[i].occlusion_texture.extensions, data->materials[i].occlusion_texture.extensions_count);
  1918  		cgltf_free_extensions(data, data->materials[i].emissive_texture.extensions, data->materials[i].emissive_texture.extensions_count);
  1919  
  1920  		cgltf_free_extensions(data, data->materials[i].extensions, data->materials[i].extensions_count);
  1921  	}
  1922  
  1923  	data->memory.free_func(data->memory.user_data, data->materials);
  1924  
  1925  	for (cgltf_size i = 0; i < data->images_count; ++i) 
  1926  	{
  1927  		data->memory.free_func(data->memory.user_data, data->images[i].name);
  1928  		data->memory.free_func(data->memory.user_data, data->images[i].uri);
  1929  		data->memory.free_func(data->memory.user_data, data->images[i].mime_type);
  1930  
  1931  		cgltf_free_extensions(data, data->images[i].extensions, data->images[i].extensions_count);
  1932  	}
  1933  
  1934  	data->memory.free_func(data->memory.user_data, data->images);
  1935  
  1936  	for (cgltf_size i = 0; i < data->textures_count; ++i)
  1937  	{
  1938  		data->memory.free_func(data->memory.user_data, data->textures[i].name);
  1939  		cgltf_free_extensions(data, data->textures[i].extensions, data->textures[i].extensions_count);
  1940  	}
  1941  
  1942  	data->memory.free_func(data->memory.user_data, data->textures);
  1943  
  1944  	for (cgltf_size i = 0; i < data->samplers_count; ++i)
  1945  	{
  1946  		data->memory.free_func(data->memory.user_data, data->samplers[i].name);
  1947  		cgltf_free_extensions(data, data->samplers[i].extensions, data->samplers[i].extensions_count);
  1948  	}
  1949  
  1950  	data->memory.free_func(data->memory.user_data, data->samplers);
  1951  
  1952  	for (cgltf_size i = 0; i < data->skins_count; ++i)
  1953  	{
  1954  		data->memory.free_func(data->memory.user_data, data->skins[i].name);
  1955  		data->memory.free_func(data->memory.user_data, data->skins[i].joints);
  1956  
  1957  		cgltf_free_extensions(data, data->skins[i].extensions, data->skins[i].extensions_count);
  1958  	}
  1959  
  1960  	data->memory.free_func(data->memory.user_data, data->skins);
  1961  
  1962  	for (cgltf_size i = 0; i < data->cameras_count; ++i)
  1963  	{
  1964  		data->memory.free_func(data->memory.user_data, data->cameras[i].name);
  1965  		cgltf_free_extensions(data, data->cameras[i].extensions, data->cameras[i].extensions_count);
  1966  	}
  1967  
  1968  	data->memory.free_func(data->memory.user_data, data->cameras);
  1969  
  1970  	for (cgltf_size i = 0; i < data->lights_count; ++i)
  1971  	{
  1972  		data->memory.free_func(data->memory.user_data, data->lights[i].name);
  1973  	}
  1974  
  1975  	data->memory.free_func(data->memory.user_data, data->lights);
  1976  
  1977  	for (cgltf_size i = 0; i < data->nodes_count; ++i)
  1978  	{
  1979  		data->memory.free_func(data->memory.user_data, data->nodes[i].name);
  1980  		data->memory.free_func(data->memory.user_data, data->nodes[i].children);
  1981  		data->memory.free_func(data->memory.user_data, data->nodes[i].weights);
  1982  		cgltf_free_extensions(data, data->nodes[i].extensions, data->nodes[i].extensions_count);
  1983  	}
  1984  
  1985  	data->memory.free_func(data->memory.user_data, data->nodes);
  1986  
  1987  	for (cgltf_size i = 0; i < data->scenes_count; ++i)
  1988  	{
  1989  		data->memory.free_func(data->memory.user_data, data->scenes[i].name);
  1990  		data->memory.free_func(data->memory.user_data, data->scenes[i].nodes);
  1991  
  1992  		cgltf_free_extensions(data, data->scenes[i].extensions, data->scenes[i].extensions_count);
  1993  	}
  1994  
  1995  	data->memory.free_func(data->memory.user_data, data->scenes);
  1996  
  1997  	for (cgltf_size i = 0; i < data->animations_count; ++i)
  1998  	{
  1999  		data->memory.free_func(data->memory.user_data, data->animations[i].name);
  2000  		for (cgltf_size j = 0; j <  data->animations[i].samplers_count; ++j)
  2001  		{
  2002  			cgltf_free_extensions(data, data->animations[i].samplers[j].extensions, data->animations[i].samplers[j].extensions_count);
  2003  		}
  2004  		data->memory.free_func(data->memory.user_data, data->animations[i].samplers);
  2005  
  2006  		for (cgltf_size j = 0; j <  data->animations[i].channels_count; ++j)
  2007  		{
  2008  			cgltf_free_extensions(data, data->animations[i].channels[j].extensions, data->animations[i].channels[j].extensions_count);
  2009  		}
  2010  		data->memory.free_func(data->memory.user_data, data->animations[i].channels);
  2011  
  2012  		cgltf_free_extensions(data, data->animations[i].extensions, data->animations[i].extensions_count);
  2013  	}
  2014  
  2015  	data->memory.free_func(data->memory.user_data, data->animations);
  2016  
  2017  	for (cgltf_size i = 0; i < data->variants_count; ++i)
  2018  	{
  2019  		data->memory.free_func(data->memory.user_data, data->variants[i].name);
  2020  	}
  2021  
  2022  	data->memory.free_func(data->memory.user_data, data->variants);
  2023  
  2024  	cgltf_free_extensions(data, data->data_extensions, data->data_extensions_count);
  2025  
  2026  	for (cgltf_size i = 0; i < data->extensions_used_count; ++i)
  2027  	{
  2028  		data->memory.free_func(data->memory.user_data, data->extensions_used[i]);
  2029  	}
  2030  
  2031  	data->memory.free_func(data->memory.user_data, data->extensions_used);
  2032  
  2033  	for (cgltf_size i = 0; i < data->extensions_required_count; ++i)
  2034  	{
  2035  		data->memory.free_func(data->memory.user_data, data->extensions_required[i]);
  2036  	}
  2037  
  2038  	data->memory.free_func(data->memory.user_data, data->extensions_required);
  2039  
  2040  	file_release(&data->memory, &data->file, data->file_data);
  2041  
  2042  	data->memory.free_func(data->memory.user_data, data);
  2043  }
  2044  
  2045  void cgltf_node_transform_local(const cgltf_node* node, cgltf_float* out_matrix)
  2046  {
  2047  	cgltf_float* lm = out_matrix;
  2048  
  2049  	if (node->has_matrix)
  2050  	{
  2051  		memcpy(lm, node->matrix, sizeof(float) * 16);
  2052  	}
  2053  	else
  2054  	{
  2055  		float tx = node->translation[0];
  2056  		float ty = node->translation[1];
  2057  		float tz = node->translation[2];
  2058  
  2059  		float qx = node->rotation[0];
  2060  		float qy = node->rotation[1];
  2061  		float qz = node->rotation[2];
  2062  		float qw = node->rotation[3];
  2063  
  2064  		float sx = node->scale[0];
  2065  		float sy = node->scale[1];
  2066  		float sz = node->scale[2];
  2067  
  2068  		lm[0] = (1 - 2 * qy*qy - 2 * qz*qz) * sx;
  2069  		lm[1] = (2 * qx*qy + 2 * qz*qw) * sx;
  2070  		lm[2] = (2 * qx*qz - 2 * qy*qw) * sx;
  2071  		lm[3] = 0.f;
  2072  
  2073  		lm[4] = (2 * qx*qy - 2 * qz*qw) * sy;
  2074  		lm[5] = (1 - 2 * qx*qx - 2 * qz*qz) * sy;
  2075  		lm[6] = (2 * qy*qz + 2 * qx*qw) * sy;
  2076  		lm[7] = 0.f;
  2077  
  2078  		lm[8] = (2 * qx*qz + 2 * qy*qw) * sz;
  2079  		lm[9] = (2 * qy*qz - 2 * qx*qw) * sz;
  2080  		lm[10] = (1 - 2 * qx*qx - 2 * qy*qy) * sz;
  2081  		lm[11] = 0.f;
  2082  
  2083  		lm[12] = tx;
  2084  		lm[13] = ty;
  2085  		lm[14] = tz;
  2086  		lm[15] = 1.f;
  2087  	}
  2088  }
  2089  
  2090  void cgltf_node_transform_world(const cgltf_node* node, cgltf_float* out_matrix)
  2091  {
  2092  	cgltf_float* lm = out_matrix;
  2093  	cgltf_node_transform_local(node, lm);
  2094  
  2095  	const cgltf_node* parent = node->parent;
  2096  
  2097  	while (parent)
  2098  	{
  2099  		float pm[16];
  2100  		cgltf_node_transform_local(parent, pm);
  2101  
  2102  		for (int i = 0; i < 4; ++i)
  2103  		{
  2104  			float l0 = lm[i * 4 + 0];
  2105  			float l1 = lm[i * 4 + 1];
  2106  			float l2 = lm[i * 4 + 2];
  2107  
  2108  			float r0 = l0 * pm[0] + l1 * pm[4] + l2 * pm[8];
  2109  			float r1 = l0 * pm[1] + l1 * pm[5] + l2 * pm[9];
  2110  			float r2 = l0 * pm[2] + l1 * pm[6] + l2 * pm[10];
  2111  
  2112  			lm[i * 4 + 0] = r0;
  2113  			lm[i * 4 + 1] = r1;
  2114  			lm[i * 4 + 2] = r2;
  2115  		}
  2116  
  2117  		lm[12] += pm[12];
  2118  		lm[13] += pm[13];
  2119  		lm[14] += pm[14];
  2120  
  2121  		parent = parent->parent;
  2122  	}
  2123  }
  2124  
  2125  static cgltf_ssize cgltf_component_read_integer(const void* in, cgltf_component_type component_type)
  2126  {
  2127  	switch (component_type)
  2128  	{
  2129  		case cgltf_component_type_r_16:
  2130  			return *((const int16_t*) in);
  2131  		case cgltf_component_type_r_16u:
  2132  			return *((const uint16_t*) in);
  2133  		case cgltf_component_type_r_32u:
  2134  			return *((const uint32_t*) in);
  2135  		case cgltf_component_type_r_32f:
  2136  			return (cgltf_ssize)*((const float*) in);
  2137  		case cgltf_component_type_r_8:
  2138  			return *((const int8_t*) in);
  2139  		case cgltf_component_type_r_8u:
  2140  			return *((const uint8_t*) in);
  2141  		default:
  2142  			return 0;
  2143  	}
  2144  }
  2145  
  2146  static cgltf_size cgltf_component_read_index(const void* in, cgltf_component_type component_type)
  2147  {
  2148  	switch (component_type)
  2149  	{
  2150  		case cgltf_component_type_r_16u:
  2151  			return *((const uint16_t*) in);
  2152  		case cgltf_component_type_r_32u:
  2153  			return *((const uint32_t*) in);
  2154  		case cgltf_component_type_r_32f:
  2155  			return (cgltf_size)*((const float*) in);
  2156  		case cgltf_component_type_r_8u:
  2157  			return *((const uint8_t*) in);
  2158  		default:
  2159  			return 0;
  2160  	}
  2161  }
  2162  
  2163  static cgltf_float cgltf_component_read_float(const void* in, cgltf_component_type component_type, cgltf_bool normalized)
  2164  {
  2165  	if (component_type == cgltf_component_type_r_32f)
  2166  	{
  2167  		return *((const float*) in);
  2168  	}
  2169  
  2170  	if (normalized)
  2171  	{
  2172  		switch (component_type)
  2173  		{
  2174  			// note: glTF spec doesn't currently define normalized conversions for 32-bit integers
  2175  			case cgltf_component_type_r_16:
  2176  				return *((const int16_t*) in) / (cgltf_float)32767;
  2177  			case cgltf_component_type_r_16u:
  2178  				return *((const uint16_t*) in) / (cgltf_float)65535;
  2179  			case cgltf_component_type_r_8:
  2180  				return *((const int8_t*) in) / (cgltf_float)127;
  2181  			case cgltf_component_type_r_8u:
  2182  				return *((const uint8_t*) in) / (cgltf_float)255;
  2183  			default:
  2184  				return 0;
  2185  		}
  2186  	}
  2187  
  2188  	return (cgltf_float)cgltf_component_read_integer(in, component_type);
  2189  }
  2190  
  2191  static cgltf_size cgltf_component_size(cgltf_component_type component_type);
  2192  
  2193  static cgltf_bool cgltf_element_read_float(const uint8_t* element, cgltf_type type, cgltf_component_type component_type, cgltf_bool normalized, cgltf_float* out, cgltf_size element_size)
  2194  {
  2195  	cgltf_size num_components = cgltf_num_components(type);
  2196  
  2197  	if (element_size < num_components) {
  2198  		return 0;
  2199  	}
  2200  
  2201  	// There are three special cases for component extraction, see #data-alignment in the 2.0 spec.
  2202  
  2203  	cgltf_size component_size = cgltf_component_size(component_type);
  2204  
  2205  	if (type == cgltf_type_mat2 && component_size == 1)
  2206  	{
  2207  		out[0] = cgltf_component_read_float(element, component_type, normalized);
  2208  		out[1] = cgltf_component_read_float(element + 1, component_type, normalized);
  2209  		out[2] = cgltf_component_read_float(element + 4, component_type, normalized);
  2210  		out[3] = cgltf_component_read_float(element + 5, component_type, normalized);
  2211  		return 1;
  2212  	}
  2213  
  2214  	if (type == cgltf_type_mat3 && component_size == 1)
  2215  	{
  2216  		out[0] = cgltf_component_read_float(element, component_type, normalized);
  2217  		out[1] = cgltf_component_read_float(element + 1, component_type, normalized);
  2218  		out[2] = cgltf_component_read_float(element + 2, component_type, normalized);
  2219  		out[3] = cgltf_component_read_float(element + 4, component_type, normalized);
  2220  		out[4] = cgltf_component_read_float(element + 5, component_type, normalized);
  2221  		out[5] = cgltf_component_read_float(element + 6, component_type, normalized);
  2222  		out[6] = cgltf_component_read_float(element + 8, component_type, normalized);
  2223  		out[7] = cgltf_component_read_float(element + 9, component_type, normalized);
  2224  		out[8] = cgltf_component_read_float(element + 10, component_type, normalized);
  2225  		return 1;
  2226  	}
  2227  
  2228  	if (type == cgltf_type_mat3 && component_size == 2)
  2229  	{
  2230  		out[0] = cgltf_component_read_float(element, component_type, normalized);
  2231  		out[1] = cgltf_component_read_float(element + 2, component_type, normalized);
  2232  		out[2] = cgltf_component_read_float(element + 4, component_type, normalized);
  2233  		out[3] = cgltf_component_read_float(element + 8, component_type, normalized);
  2234  		out[4] = cgltf_component_read_float(element + 10, component_type, normalized);
  2235  		out[5] = cgltf_component_read_float(element + 12, component_type, normalized);
  2236  		out[6] = cgltf_component_read_float(element + 16, component_type, normalized);
  2237  		out[7] = cgltf_component_read_float(element + 18, component_type, normalized);
  2238  		out[8] = cgltf_component_read_float(element + 20, component_type, normalized);
  2239  		return 1;
  2240  	}
  2241  
  2242  	for (cgltf_size i = 0; i < num_components; ++i)
  2243  	{
  2244  		out[i] = cgltf_component_read_float(element + component_size * i, component_type, normalized);
  2245  	}
  2246  	return 1;
  2247  }
  2248  
  2249  const uint8_t* cgltf_buffer_view_data(const cgltf_buffer_view* view)
  2250  {
  2251  	if (view->data)
  2252  		return (const uint8_t*)view->data;
  2253  
  2254  	if (!view->buffer->data)
  2255  		return NULL;
  2256  
  2257  	const uint8_t* result = (const uint8_t*)view->buffer->data;
  2258  	result += view->offset;
  2259  	return result;
  2260  }
  2261  
  2262  cgltf_bool cgltf_accessor_read_float(const cgltf_accessor* accessor, cgltf_size index, cgltf_float* out, cgltf_size element_size)
  2263  {
  2264  	if (accessor->is_sparse)
  2265  	{
  2266  		return 0;
  2267  	}
  2268  	if (accessor->buffer_view == NULL)
  2269  	{
  2270  		memset(out, 0, element_size * sizeof(cgltf_float));
  2271  		return 1;
  2272  	}
  2273  	const uint8_t* element = cgltf_buffer_view_data(accessor->buffer_view);
  2274  	if (element == NULL)
  2275  	{
  2276  		return 0;
  2277  	}
  2278  	element += accessor->offset + accessor->stride * index;
  2279  	return cgltf_element_read_float(element, accessor->type, accessor->component_type, accessor->normalized, out, element_size);
  2280  }
  2281  
  2282  cgltf_size cgltf_accessor_unpack_floats(const cgltf_accessor* accessor, cgltf_float* out, cgltf_size float_count)
  2283  {
  2284  	cgltf_size floats_per_element = cgltf_num_components(accessor->type);
  2285  	cgltf_size available_floats = accessor->count * floats_per_element;
  2286  	if (out == NULL)
  2287  	{
  2288  		return available_floats;
  2289  	}
  2290  
  2291  	float_count = available_floats < float_count ? available_floats : float_count;
  2292  	cgltf_size element_count = float_count / floats_per_element;
  2293  
  2294  	// First pass: convert each element in the base accessor.
  2295  	cgltf_float* dest = out;
  2296  	cgltf_accessor dense = *accessor;
  2297  	dense.is_sparse = 0;
  2298  	for (cgltf_size index = 0; index < element_count; index++, dest += floats_per_element)
  2299  	{
  2300  		if (!cgltf_accessor_read_float(&dense, index, dest, floats_per_element))
  2301  		{
  2302  			return 0;
  2303  		}
  2304  	}
  2305  
  2306  	// Second pass: write out each element in the sparse accessor.
  2307  	if (accessor->is_sparse)
  2308  	{
  2309  		const cgltf_accessor_sparse* sparse = &dense.sparse;
  2310  
  2311  		const uint8_t* index_data = cgltf_buffer_view_data(sparse->indices_buffer_view);
  2312  		const uint8_t* reader_head = cgltf_buffer_view_data(sparse->values_buffer_view);
  2313  
  2314  		if (index_data == NULL || reader_head == NULL)
  2315  		{
  2316  			return 0;
  2317  		}
  2318  
  2319  		index_data += sparse->indices_byte_offset;
  2320  		reader_head += sparse->values_byte_offset;
  2321  
  2322  		cgltf_size index_stride = cgltf_component_size(sparse->indices_component_type);
  2323  		for (cgltf_size reader_index = 0; reader_index < sparse->count; reader_index++, index_data += index_stride)
  2324  		{
  2325  			size_t writer_index = cgltf_component_read_index(index_data, sparse->indices_component_type);
  2326  			float* writer_head = out + writer_index * floats_per_element;
  2327  
  2328  			if (!cgltf_element_read_float(reader_head, dense.type, dense.component_type, dense.normalized, writer_head, floats_per_element))
  2329  			{
  2330  				return 0;
  2331  			}
  2332  
  2333  			reader_head += dense.stride;
  2334  		}
  2335  	}
  2336  
  2337  	return element_count * floats_per_element;
  2338  }
  2339  
  2340  static cgltf_uint cgltf_component_read_uint(const void* in, cgltf_component_type component_type)
  2341  {
  2342  	switch (component_type)
  2343  	{
  2344  		case cgltf_component_type_r_8:
  2345  			return *((const int8_t*) in);
  2346  
  2347  		case cgltf_component_type_r_8u:
  2348  			return *((const uint8_t*) in);
  2349  
  2350  		case cgltf_component_type_r_16:
  2351  			return *((const int16_t*) in);
  2352  
  2353  		case cgltf_component_type_r_16u:
  2354  			return *((const uint16_t*) in);
  2355  
  2356  		case cgltf_component_type_r_32u:
  2357  			return *((const uint32_t*) in);
  2358  
  2359  		default:
  2360  			return 0;
  2361  	}
  2362  }
  2363  
  2364  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)
  2365  {
  2366  	cgltf_size num_components = cgltf_num_components(type);
  2367  
  2368  	if (element_size < num_components)
  2369  	{
  2370  		return 0;
  2371  	}
  2372  
  2373  	// Reading integer matrices is not a valid use case
  2374  	if (type == cgltf_type_mat2 || type == cgltf_type_mat3 || type == cgltf_type_mat4)
  2375  	{
  2376  		return 0;
  2377  	}
  2378  
  2379  	cgltf_size component_size = cgltf_component_size(component_type);
  2380  
  2381  	for (cgltf_size i = 0; i < num_components; ++i)
  2382  	{
  2383  		out[i] = cgltf_component_read_uint(element + component_size * i, component_type);
  2384  	}
  2385  	return 1;
  2386  }
  2387  
  2388  cgltf_bool cgltf_accessor_read_uint(const cgltf_accessor* accessor, cgltf_size index, cgltf_uint* out, cgltf_size element_size)
  2389  {
  2390  	if (accessor->is_sparse)
  2391  	{
  2392  		return 0;
  2393  	}
  2394  	if (accessor->buffer_view == NULL)
  2395  	{
  2396  		memset(out, 0, element_size * sizeof( cgltf_uint ));
  2397  		return 1;
  2398  	}
  2399  	const uint8_t* element = cgltf_buffer_view_data(accessor->buffer_view);
  2400  	if (element == NULL)
  2401  	{
  2402  		return 0;
  2403  	}
  2404  	element += accessor->offset + accessor->stride * index;
  2405  	return cgltf_element_read_uint(element, accessor->type, accessor->component_type, out, element_size);
  2406  }
  2407  
  2408  cgltf_size cgltf_accessor_read_index(const cgltf_accessor* accessor, cgltf_size index)
  2409  {
  2410  	if (accessor->is_sparse)
  2411  	{
  2412  		return 0; // This is an error case, but we can't communicate the error with existing interface.
  2413  	}
  2414  	if (accessor->buffer_view == NULL)
  2415  	{
  2416  		return 0;
  2417  	}
  2418  	const uint8_t* element = cgltf_buffer_view_data(accessor->buffer_view);
  2419  	if (element == NULL)
  2420  	{
  2421  		return 0; // This is an error case, but we can't communicate the error with existing interface.
  2422  	}
  2423  	element += accessor->offset + accessor->stride * index;
  2424  	return cgltf_component_read_index(element, accessor->component_type);
  2425  }
  2426  
  2427  #define CGLTF_ERROR_JSON -1
  2428  #define CGLTF_ERROR_NOMEM -2
  2429  #define CGLTF_ERROR_LEGACY -3
  2430  
  2431  #define CGLTF_CHECK_TOKTYPE(tok_, type_) if ((tok_).type != (type_)) { return CGLTF_ERROR_JSON; }
  2432  #define CGLTF_CHECK_TOKTYPE_RETTYPE(tok_, type_, ret_) if ((tok_).type != (type_)) { return (ret_)CGLTF_ERROR_JSON; }
  2433  #define CGLTF_CHECK_KEY(tok_) if ((tok_).type != JSMN_STRING || (tok_).size == 0) { return CGLTF_ERROR_JSON; } /* checking size for 0 verifies that a value follows the key */
  2434  
  2435  #define CGLTF_PTRINDEX(type, idx) (type*)((cgltf_size)idx + 1)
  2436  #define CGLTF_PTRFIXUP(var, data, size) if (var) { if ((cgltf_size)var > size) { return CGLTF_ERROR_JSON; } var = &data[(cgltf_size)var-1]; }
  2437  #define CGLTF_PTRFIXUP_REQ(var, data, size) if (!var || (cgltf_size)var > size) { return CGLTF_ERROR_JSON; } var = &data[(cgltf_size)var-1];
  2438  
  2439  static int cgltf_json_strcmp(jsmntok_t const* tok, const uint8_t* json_chunk, const char* str)
  2440  {
  2441  	CGLTF_CHECK_TOKTYPE(*tok, JSMN_STRING);
  2442  	size_t const str_len = strlen(str);
  2443  	size_t const name_length = tok->end - tok->start;
  2444  	return (str_len == name_length) ? strncmp((const char*)json_chunk + tok->start, str, str_len) : 128;
  2445  }
  2446  
  2447  static int cgltf_json_to_int(jsmntok_t const* tok, const uint8_t* json_chunk)
  2448  {
  2449  	CGLTF_CHECK_TOKTYPE(*tok, JSMN_PRIMITIVE);
  2450  	char tmp[128];
  2451  	int size = (cgltf_size)(tok->end - tok->start) < sizeof(tmp) ? tok->end - tok->start : (int)(sizeof(tmp) - 1);
  2452  	strncpy(tmp, (const char*)json_chunk + tok->start, size);
  2453  	tmp[size] = 0;
  2454  	return CGLTF_ATOI(tmp);
  2455  }
  2456  
  2457  static cgltf_size cgltf_json_to_size(jsmntok_t const* tok, const uint8_t* json_chunk)
  2458  {
  2459  	CGLTF_CHECK_TOKTYPE_RETTYPE(*tok, JSMN_PRIMITIVE, cgltf_size);
  2460  	char tmp[128];
  2461  	int size = (cgltf_size)(tok->end - tok->start) < sizeof(tmp) ? tok->end - tok->start : (int)(sizeof(tmp) - 1);
  2462  	strncpy(tmp, (const char*)json_chunk + tok->start, size);
  2463  	tmp[size] = 0;
  2464  	return (cgltf_size)CGLTF_ATOLL(tmp);
  2465  }
  2466  
  2467  static cgltf_float cgltf_json_to_float(jsmntok_t const* tok, const uint8_t* json_chunk)
  2468  {
  2469  	CGLTF_CHECK_TOKTYPE(*tok, JSMN_PRIMITIVE);
  2470  	char tmp[128];
  2471  	int size = (cgltf_size)(tok->end - tok->start) < sizeof(tmp) ? tok->end - tok->start : (int)(sizeof(tmp) - 1);
  2472  	strncpy(tmp, (const char*)json_chunk + tok->start, size);
  2473  	tmp[size] = 0;
  2474  	return (cgltf_float)CGLTF_ATOF(tmp);
  2475  }
  2476  
  2477  static cgltf_bool cgltf_json_to_bool(jsmntok_t const* tok, const uint8_t* json_chunk)
  2478  {
  2479  	int size = tok->end - tok->start;
  2480  	return size == 4 && memcmp(json_chunk + tok->start, "true", 4) == 0;
  2481  }
  2482  
  2483  static int cgltf_skip_json(jsmntok_t const* tokens, int i)
  2484  {
  2485  	int end = i + 1;
  2486  
  2487  	while (i < end)
  2488  	{
  2489  		switch (tokens[i].type)
  2490  		{
  2491  		case JSMN_OBJECT:
  2492  			end += tokens[i].size * 2;
  2493  			break;
  2494  
  2495  		case JSMN_ARRAY:
  2496  			end += tokens[i].size;
  2497  			break;
  2498  
  2499  		case JSMN_PRIMITIVE:
  2500  		case JSMN_STRING:
  2501  			break;
  2502  
  2503  		default:
  2504  			return -1;
  2505  		}
  2506  
  2507  		i++;
  2508  	}
  2509  
  2510  	return i;
  2511  }
  2512  
  2513  static void cgltf_fill_float_array(float* out_array, int size, float value)
  2514  {
  2515  	for (int j = 0; j < size; ++j)
  2516  	{
  2517  		out_array[j] = value;
  2518  	}
  2519  }
  2520  
  2521  static int cgltf_parse_json_float_array(jsmntok_t const* tokens, int i, const uint8_t* json_chunk, float* out_array, int size)
  2522  {
  2523  	CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_ARRAY);
  2524  	if (tokens[i].size != size)
  2525  	{
  2526  		return CGLTF_ERROR_JSON;
  2527  	}
  2528  	++i;
  2529  	for (int j = 0; j < size; ++j)
  2530  	{
  2531  		CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_PRIMITIVE);
  2532  		out_array[j] = cgltf_json_to_float(tokens + i, json_chunk);
  2533  		++i;
  2534  	}
  2535  	return i;
  2536  }
  2537  
  2538  static int cgltf_parse_json_string(cgltf_options* options, jsmntok_t const* tokens, int i, const uint8_t* json_chunk, char** out_string)
  2539  {
  2540  	CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_STRING);
  2541  	if (*out_string)
  2542  	{
  2543  		return CGLTF_ERROR_JSON;
  2544  	}
  2545  	int size = tokens[i].end - tokens[i].start;
  2546  	char* result = (char*)options->memory.alloc_func(options->memory.user_data, size + 1);
  2547  	if (!result)
  2548  	{
  2549  		return CGLTF_ERROR_NOMEM;
  2550  	}
  2551  	strncpy(result, (const char*)json_chunk + tokens[i].start, size);
  2552  	result[size] = 0;
  2553  	*out_string = result;
  2554  	return i + 1;
  2555  }
  2556  
  2557  static int cgltf_parse_json_array(cgltf_options* options, jsmntok_t const* tokens, int i, const uint8_t* json_chunk, size_t element_size, void** out_array, cgltf_size* out_size)
  2558  {
  2559  	(void)json_chunk;
  2560  	if (tokens[i].type != JSMN_ARRAY)
  2561  	{
  2562  		return tokens[i].type == JSMN_OBJECT ? CGLTF_ERROR_LEGACY : CGLTF_ERROR_JSON;
  2563  	}
  2564  	if (*out_array)
  2565  	{
  2566  		return CGLTF_ERROR_JSON;
  2567  	}
  2568  	int size = tokens[i].size;
  2569  	void* result = cgltf_calloc(options, element_size, size);
  2570  	if (!result)
  2571  	{
  2572  		return CGLTF_ERROR_NOMEM;
  2573  	}
  2574  	*out_array = result;
  2575  	*out_size = size;
  2576  	return i + 1;
  2577  }
  2578  
  2579  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)
  2580  {
  2581  	CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_ARRAY);
  2582  	i = cgltf_parse_json_array(options, tokens, i, json_chunk, sizeof(char*), (void**)out_array, out_size);
  2583  	if (i < 0)
  2584  	{
  2585  		return i;
  2586  	}
  2587  
  2588  	for (cgltf_size j = 0; j < *out_size; ++j)
  2589  	{
  2590  		i = cgltf_parse_json_string(options, tokens, i, json_chunk, j + (*out_array));
  2591  		if (i < 0)
  2592  		{
  2593  			return i;
  2594  		}
  2595  	}
  2596  	return i;
  2597  }
  2598  
  2599  static void cgltf_parse_attribute_type(const char* name, cgltf_attribute_type* out_type, int* out_index)
  2600  {
  2601  	if (*name == '_')
  2602  	{
  2603  		*out_type = cgltf_attribute_type_custom;
  2604  		return;
  2605  	}
  2606  
  2607  	const char* us = strchr(name, '_');
  2608  	size_t len = us ? (size_t)(us - name) : strlen(name);
  2609  
  2610  	if (len == 8 && strncmp(name, "POSITION", 8) == 0)
  2611  	{
  2612  		*out_type = cgltf_attribute_type_position;
  2613  	}
  2614  	else if (len == 6 && strncmp(name, "NORMAL", 6) == 0)
  2615  	{
  2616  		*out_type = cgltf_attribute_type_normal;
  2617  	}
  2618  	else if (len == 7 && strncmp(name, "TANGENT", 7) == 0)
  2619  	{
  2620  		*out_type = cgltf_attribute_type_tangent;
  2621  	}
  2622  	else if (len == 8 && strncmp(name, "TEXCOORD", 8) == 0)
  2623  	{
  2624  		*out_type = cgltf_attribute_type_texcoord;
  2625  	}
  2626  	else if (len == 5 && strncmp(name, "COLOR", 5) == 0)
  2627  	{
  2628  		*out_type = cgltf_attribute_type_color;
  2629  	}
  2630  	else if (len == 6 && strncmp(name, "JOINTS", 6) == 0)
  2631  	{
  2632  		*out_type = cgltf_attribute_type_joints;
  2633  	}
  2634  	else if (len == 7 && strncmp(name, "WEIGHTS", 7) == 0)
  2635  	{
  2636  		*out_type = cgltf_attribute_type_weights;
  2637  	}
  2638  	else
  2639  	{
  2640  		*out_type = cgltf_attribute_type_invalid;
  2641  	}
  2642  
  2643  	if (us && *out_type != cgltf_attribute_type_invalid)
  2644  	{
  2645  		*out_index = CGLTF_ATOI(us + 1);
  2646  	}
  2647  }
  2648  
  2649  static int cgltf_parse_json_attribute_list(cgltf_options* options, jsmntok_t const* tokens, int i, const uint8_t* json_chunk, cgltf_attribute** out_attributes, cgltf_size* out_attributes_count)
  2650  {
  2651  	CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
  2652  
  2653  	if (*out_attributes)
  2654  	{
  2655  		return CGLTF_ERROR_JSON;
  2656  	}
  2657  
  2658  	*out_attributes_count = tokens[i].size;
  2659  	*out_attributes = (cgltf_attribute*)cgltf_calloc(options, sizeof(cgltf_attribute), *out_attributes_count);
  2660  	++i;
  2661  
  2662  	if (!*out_attributes)
  2663  	{
  2664  		return CGLTF_ERROR_NOMEM;
  2665  	}
  2666  
  2667  	for (cgltf_size j = 0; j < *out_attributes_count; ++j)
  2668  	{
  2669  		CGLTF_CHECK_KEY(tokens[i]);
  2670  
  2671  		i = cgltf_parse_json_string(options, tokens, i, json_chunk, &(*out_attributes)[j].name);
  2672  		if (i < 0)
  2673  		{
  2674  			return CGLTF_ERROR_JSON;
  2675  		}
  2676  
  2677  		cgltf_parse_attribute_type((*out_attributes)[j].name, &(*out_attributes)[j].type, &(*out_attributes)[j].index);
  2678  
  2679  		(*out_attributes)[j].data = CGLTF_PTRINDEX(cgltf_accessor, cgltf_json_to_int(tokens + i, json_chunk));
  2680  		++i;
  2681  	}
  2682  
  2683  	return i;
  2684  }
  2685  
  2686  static int cgltf_parse_json_extras(jsmntok_t const* tokens, int i, const uint8_t* json_chunk, cgltf_extras* out_extras)
  2687  {
  2688  	(void)json_chunk;
  2689  	out_extras->start_offset = tokens[i].start;
  2690  	out_extras->end_offset = tokens[i].end;
  2691  	i = cgltf_skip_json(tokens, i);
  2692  	return i;
  2693  }
  2694  
  2695  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)
  2696  {
  2697  	CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_STRING);
  2698  	CGLTF_CHECK_TOKTYPE(tokens[i+1], JSMN_OBJECT);
  2699  	if (out_extension->name)
  2700  	{
  2701  		return CGLTF_ERROR_JSON;
  2702  	}
  2703  
  2704  	cgltf_size name_length = tokens[i].end - tokens[i].start;
  2705  	out_extension->name = (char*)options->memory.alloc_func(options->memory.user_data, name_length + 1);
  2706  	if (!out_extension->name)
  2707  	{
  2708  		return CGLTF_ERROR_NOMEM;
  2709  	}
  2710  	strncpy(out_extension->name, (const char*)json_chunk + tokens[i].start, name_length);
  2711  	out_extension->name[name_length] = 0;
  2712  	i++;
  2713  
  2714  	size_t start = tokens[i].start;
  2715  	size_t size = tokens[i].end - start;
  2716  	out_extension->data = (char*)options->memory.alloc_func(options->memory.user_data, size + 1);
  2717  	if (!out_extension->data)
  2718  	{
  2719  		return CGLTF_ERROR_NOMEM;
  2720  	}
  2721  	strncpy(out_extension->data, (const char*)json_chunk + start, size);
  2722  	out_extension->data[size] = '\0';
  2723  
  2724  	i = cgltf_skip_json(tokens, i);
  2725  
  2726  	return i;
  2727  }
  2728  
  2729  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)
  2730  {
  2731  	++i;
  2732  
  2733  	CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
  2734  	if(*out_extensions)
  2735  	{
  2736  		return CGLTF_ERROR_JSON;
  2737  	}
  2738  
  2739  	int extensions_size = tokens[i].size;
  2740  	*out_extensions_count = 0;
  2741  	*out_extensions = (cgltf_extension*)cgltf_calloc(options, sizeof(cgltf_extension), extensions_size);
  2742  
  2743  	if (!*out_extensions)
  2744  	{
  2745  		return CGLTF_ERROR_NOMEM;
  2746  	}
  2747  
  2748  	++i;
  2749  
  2750  	for (int j = 0; j < extensions_size; ++j)
  2751  	{
  2752  		CGLTF_CHECK_KEY(tokens[i]);
  2753  
  2754  		cgltf_size extension_index = (*out_extensions_count)++;
  2755  		cgltf_extension* extension = &((*out_extensions)[extension_index]);
  2756  		i = cgltf_parse_json_unprocessed_extension(options, tokens, i, json_chunk, extension);
  2757  
  2758  		if (i < 0)
  2759  		{
  2760  			return i;
  2761  		}
  2762  	}
  2763  	return i;
  2764  }
  2765  
  2766  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)
  2767  {
  2768  	CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
  2769  
  2770  	int size = tokens[i].size;
  2771  	++i;
  2772  
  2773  	for (int j = 0; j < size; ++j)
  2774  	{
  2775  		CGLTF_CHECK_KEY(tokens[i]);
  2776  
  2777  		if (cgltf_json_strcmp(tokens + i, json_chunk, "attributes") == 0)
  2778  		{
  2779  			i = cgltf_parse_json_attribute_list(options, tokens, i + 1, json_chunk, &out_draco_mesh_compression->attributes, &out_draco_mesh_compression->attributes_count);
  2780  		}
  2781  		else if (cgltf_json_strcmp(tokens + i, json_chunk, "bufferView") == 0)
  2782  		{
  2783  			++i;
  2784  			out_draco_mesh_compression->buffer_view = CGLTF_PTRINDEX(cgltf_buffer_view, cgltf_json_to_int(tokens + i, json_chunk));
  2785  			++i;
  2786  		}
  2787  
  2788  		if (i < 0)
  2789  		{
  2790  			return i;
  2791  		}
  2792  	}
  2793  
  2794  	return i;
  2795  }
  2796  
  2797  static int cgltf_parse_json_mesh_gpu_instancing(cgltf_options* options, jsmntok_t const* tokens, int i, const uint8_t* json_chunk, cgltf_mesh_gpu_instancing* out_mesh_gpu_instancing)
  2798  {
  2799  	CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
  2800  
  2801  	int size = tokens[i].size;
  2802  	++i;
  2803  
  2804  	for (int j = 0; j < size; ++j)
  2805  	{
  2806  		CGLTF_CHECK_KEY(tokens[i]);
  2807  
  2808  		if (cgltf_json_strcmp(tokens + i, json_chunk, "attributes") == 0)
  2809  		{
  2810  			i = cgltf_parse_json_attribute_list(options, tokens, i + 1, json_chunk, &out_mesh_gpu_instancing->attributes, &out_mesh_gpu_instancing->attributes_count);
  2811  		}
  2812  		else if (cgltf_json_strcmp(tokens + i, json_chunk, "bufferView") == 0)
  2813  		{
  2814  			++i;
  2815  			out_mesh_gpu_instancing->buffer_view = CGLTF_PTRINDEX(cgltf_buffer_view, cgltf_json_to_int(tokens + i, json_chunk));
  2816  			++i;
  2817  		}
  2818  
  2819  		if (i < 0)
  2820  		{
  2821  			return i;
  2822  		}
  2823  	}
  2824  
  2825  	return i;
  2826  }
  2827  
  2828  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)
  2829  {
  2830  	(void)options;
  2831  	CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_ARRAY);
  2832  
  2833  	int size = tokens[i].size;
  2834  	++i;
  2835  
  2836  	for (int j = 0; j < size; ++j)
  2837  	{
  2838  		CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
  2839  
  2840  		int obj_size = tokens[i].size;
  2841  		++i;
  2842  
  2843  		int material = -1;
  2844  		int variants_tok = -1;
  2845  		cgltf_extras extras = {0, 0};
  2846  
  2847  		for (int k = 0; k < obj_size; ++k)
  2848  		{
  2849  			CGLTF_CHECK_KEY(tokens[i]);
  2850  
  2851  			if (cgltf_json_strcmp(tokens + i, json_chunk, "material") == 0)
  2852  			{
  2853  				++i;
  2854  				material = cgltf_json_to_int(tokens + i, json_chunk);
  2855  				++i;
  2856  			}
  2857  			else if (cgltf_json_strcmp(tokens + i, json_chunk, "variants") == 0)
  2858  			{
  2859  				variants_tok = i+1;
  2860  				CGLTF_CHECK_TOKTYPE(tokens[variants_tok], JSMN_ARRAY);
  2861  
  2862  				i = cgltf_skip_json(tokens, i+1);
  2863  			}
  2864  			else if (cgltf_json_strcmp(tokens + i, json_chunk, "extras") == 0)
  2865  			{
  2866  				i = cgltf_parse_json_extras(tokens, i + 1, json_chunk, &extras);
  2867  			}
  2868  			else
  2869  			{
  2870  				i = cgltf_skip_json(tokens, i+1);
  2871  			}
  2872  
  2873  			if (i < 0)
  2874  			{
  2875  				return i;
  2876  			}
  2877  		}
  2878  
  2879  		if (material < 0 || variants_tok < 0)
  2880  		{
  2881  			return CGLTF_ERROR_JSON;
  2882  		}
  2883  
  2884  		if (out_mappings)
  2885  		{
  2886  			for (int k = 0; k < tokens[variants_tok].size; ++k)
  2887  			{
  2888  				int variant = cgltf_json_to_int(&tokens[variants_tok + 1 + k], json_chunk);
  2889  				if (variant < 0)
  2890  					return variant;
  2891  
  2892  				out_mappings[*offset].material = CGLTF_PTRINDEX(cgltf_material, material);
  2893  				out_mappings[*offset].variant = variant;
  2894  				out_mappings[*offset].extras = extras;
  2895  
  2896  				(*offset)++;
  2897  			}
  2898  		}
  2899  		else
  2900  		{
  2901  			(*offset) += tokens[variants_tok].size;
  2902  		}
  2903  	}
  2904  
  2905  	return i;
  2906  }
  2907  
  2908  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)
  2909  {
  2910  	CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
  2911  
  2912  	int size = tokens[i].size;
  2913  	++i;
  2914  
  2915  	for (int j = 0; j < size; ++j)
  2916  	{
  2917  		CGLTF_CHECK_KEY(tokens[i]);
  2918  
  2919  		if (cgltf_json_strcmp(tokens + i, json_chunk, "mappings") == 0)
  2920  		{
  2921  			if (out_prim->mappings)
  2922  			{
  2923  				return CGLTF_ERROR_JSON;
  2924  			}
  2925  
  2926  			cgltf_size mappings_offset = 0;
  2927  			int k = cgltf_parse_json_material_mapping_data(options, tokens, i + 1, json_chunk, NULL, &mappings_offset);
  2928  			if (k < 0)
  2929  			{
  2930  				return k;
  2931  			}
  2932  
  2933  			out_prim->mappings_count = mappings_offset;
  2934  			out_prim->mappings = (cgltf_material_mapping*)cgltf_calloc(options, sizeof(cgltf_material_mapping), out_prim->mappings_count);
  2935  
  2936  			mappings_offset = 0;
  2937  			i = cgltf_parse_json_material_mapping_data(options, tokens, i + 1, json_chunk, out_prim->mappings, &mappings_offset);
  2938  		}
  2939  		else
  2940  		{
  2941  			i = cgltf_skip_json(tokens, i+1);
  2942  		}
  2943  
  2944  		if (i < 0)
  2945  		{
  2946  			return i;
  2947  		}
  2948  	}
  2949  
  2950  	return i;
  2951  }
  2952  
  2953  static int cgltf_parse_json_primitive(cgltf_options* options, jsmntok_t const* tokens, int i, const uint8_t* json_chunk, cgltf_primitive* out_prim)
  2954  {
  2955  	CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
  2956  
  2957  	out_prim->type = cgltf_primitive_type_triangles;
  2958  
  2959  	int size = tokens[i].size;
  2960  	++i;
  2961  
  2962  	for (int j = 0; j < size; ++j)
  2963  	{
  2964  		CGLTF_CHECK_KEY(tokens[i]);
  2965  
  2966  		if (cgltf_json_strcmp(tokens+i, json_chunk, "mode") == 0)
  2967  		{
  2968  			++i;
  2969  			out_prim->type
  2970  					= (cgltf_primitive_type)
  2971  					cgltf_json_to_int(tokens+i, json_chunk);
  2972  			++i;
  2973  		}
  2974  		else if (cgltf_json_strcmp(tokens+i, json_chunk, "indices") == 0)
  2975  		{
  2976  			++i;
  2977  			out_prim->indices = CGLTF_PTRINDEX(cgltf_accessor, cgltf_json_to_int(tokens + i, json_chunk));
  2978  			++i;
  2979  		}
  2980  		else if (cgltf_json_strcmp(tokens+i, json_chunk, "material") == 0)
  2981  		{
  2982  			++i;
  2983  			out_prim->material = CGLTF_PTRINDEX(cgltf_material, cgltf_json_to_int(tokens + i, json_chunk));
  2984  			++i;
  2985  		}
  2986  		else if (cgltf_json_strcmp(tokens+i, json_chunk, "attributes") == 0)
  2987  		{
  2988  			i = cgltf_parse_json_attribute_list(options, tokens, i + 1, json_chunk, &out_prim->attributes, &out_prim->attributes_count);
  2989  		}
  2990  		else if (cgltf_json_strcmp(tokens+i, json_chunk, "targets") == 0)
  2991  		{
  2992  			i = cgltf_parse_json_array(options, tokens, i + 1, json_chunk, sizeof(cgltf_morph_target), (void**)&out_prim->targets, &out_prim->targets_count);
  2993  			if (i < 0)
  2994  			{
  2995  				return i;
  2996  			}
  2997  
  2998  			for (cgltf_size k = 0; k < out_prim->targets_count; ++k)
  2999  			{
  3000  				i = cgltf_parse_json_attribute_list(options, tokens, i, json_chunk, &out_prim->targets[k].attributes, &out_prim->targets[k].attributes_count);
  3001  				if (i < 0)
  3002  				{
  3003  					return i;
  3004  				}
  3005  			}
  3006  		}
  3007  		else if (cgltf_json_strcmp(tokens + i, json_chunk, "extras") == 0)
  3008  		{
  3009  			i = cgltf_parse_json_extras(tokens, i + 1, json_chunk, &out_prim->extras);
  3010  		}
  3011  		else if (cgltf_json_strcmp(tokens + i, json_chunk, "extensions") == 0)
  3012  		{
  3013  			++i;
  3014  
  3015  			CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
  3016  			if(out_prim->extensions)
  3017  			{
  3018  				return CGLTF_ERROR_JSON;
  3019  			}
  3020  
  3021  			int extensions_size = tokens[i].size;
  3022  			out_prim->extensions_count = 0;
  3023  			out_prim->extensions = (cgltf_extension*)cgltf_calloc(options, sizeof(cgltf_extension), extensions_size);
  3024  
  3025  			if (!out_prim->extensions)
  3026  			{
  3027  				return CGLTF_ERROR_NOMEM;
  3028  			}
  3029  
  3030  			++i;
  3031  			for (int k = 0; k < extensions_size; ++k)
  3032  			{
  3033  				CGLTF_CHECK_KEY(tokens[i]);
  3034  
  3035  				if (cgltf_json_strcmp(tokens+i, json_chunk, "KHR_draco_mesh_compression") == 0)
  3036  				{
  3037  					out_prim->has_draco_mesh_compression = 1;
  3038  					i = cgltf_parse_json_draco_mesh_compression(options, tokens, i + 1, json_chunk, &out_prim->draco_mesh_compression);
  3039  				}
  3040  				else if (cgltf_json_strcmp(tokens+i, json_chunk, "KHR_materials_variants") == 0)
  3041  				{
  3042  					i = cgltf_parse_json_material_mappings(options, tokens, i + 1, json_chunk, out_prim);
  3043  				}
  3044  				else
  3045  				{
  3046  					i = cgltf_parse_json_unprocessed_extension(options, tokens, i, json_chunk, &(out_prim->extensions[out_prim->extensions_count++]));
  3047  				}
  3048  
  3049  				if (i < 0)
  3050  				{
  3051  					return i;
  3052  				}
  3053  			}
  3054  		}
  3055  		else
  3056  		{
  3057  			i = cgltf_skip_json(tokens, i+1);
  3058  		}
  3059  
  3060  		if (i < 0)
  3061  		{
  3062  			return i;
  3063  		}
  3064  	}
  3065  
  3066  	return i;
  3067  }
  3068  
  3069  static int cgltf_parse_json_mesh(cgltf_options* options, jsmntok_t const* tokens, int i, const uint8_t* json_chunk, cgltf_mesh* out_mesh)
  3070  {
  3071  	CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
  3072  
  3073  	int size = tokens[i].size;
  3074  	++i;
  3075  
  3076  	for (int j = 0; j < size; ++j)
  3077  	{
  3078  		CGLTF_CHECK_KEY(tokens[i]);
  3079  
  3080  		if (cgltf_json_strcmp(tokens+i, json_chunk, "name") == 0)
  3081  		{
  3082  			i = cgltf_parse_json_string(options, tokens, i + 1, json_chunk, &out_mesh->name);
  3083  		}
  3084  		else if (cgltf_json_strcmp(tokens+i, json_chunk, "primitives") == 0)
  3085  		{
  3086  			i = cgltf_parse_json_array(options, tokens, i + 1, json_chunk, sizeof(cgltf_primitive), (void**)&out_mesh->primitives, &out_mesh->primitives_count);
  3087  			if (i < 0)
  3088  			{
  3089  				return i;
  3090  			}
  3091  
  3092  			for (cgltf_size prim_index = 0; prim_index < out_mesh->primitives_count; ++prim_index)
  3093  			{
  3094  				i = cgltf_parse_json_primitive(options, tokens, i, json_chunk, &out_mesh->primitives[prim_index]);
  3095  				if (i < 0)
  3096  				{
  3097  					return i;
  3098  				}
  3099  			}
  3100  		}
  3101  		else if (cgltf_json_strcmp(tokens + i, json_chunk, "weights") == 0)
  3102  		{
  3103  			i = cgltf_parse_json_array(options, tokens, i + 1, json_chunk, sizeof(cgltf_float), (void**)&out_mesh->weights, &out_mesh->weights_count);
  3104  			if (i < 0)
  3105  			{
  3106  				return i;
  3107  			}
  3108  
  3109  			i = cgltf_parse_json_float_array(tokens, i - 1, json_chunk, out_mesh->weights, (int)out_mesh->weights_count);
  3110  		}
  3111  		else if (cgltf_json_strcmp(tokens + i, json_chunk, "extras") == 0)
  3112  		{
  3113  			++i;
  3114  
  3115  			out_mesh->extras.start_offset = tokens[i].start;
  3116  			out_mesh->extras.end_offset = tokens[i].end;
  3117  
  3118  			if (tokens[i].type == JSMN_OBJECT)
  3119  			{
  3120  				int extras_size = tokens[i].size;
  3121  				++i;
  3122  
  3123  				for (int k = 0; k < extras_size; ++k)
  3124  				{
  3125  					CGLTF_CHECK_KEY(tokens[i]);
  3126  
  3127  					if (cgltf_json_strcmp(tokens+i, json_chunk, "targetNames") == 0 && tokens[i+1].type == JSMN_ARRAY)
  3128  					{
  3129  						i = cgltf_parse_json_string_array(options, tokens, i + 1, json_chunk, &out_mesh->target_names, &out_mesh->target_names_count);
  3130  					}
  3131  					else
  3132  					{
  3133  						i = cgltf_skip_json(tokens, i+1);
  3134  					}
  3135  
  3136  					if (i < 0)
  3137  					{
  3138  						return i;
  3139  					}
  3140  				}
  3141  			}
  3142  			else
  3143  			{
  3144  				i = cgltf_skip_json(tokens, i);
  3145  			}
  3146  		}
  3147  		else if (cgltf_json_strcmp(tokens + i, json_chunk, "extensions") == 0)
  3148  		{
  3149  			i = cgltf_parse_json_unprocessed_extensions(options, tokens, i, json_chunk, &out_mesh->extensions_count, &out_mesh->extensions);
  3150  		}
  3151  		else
  3152  		{
  3153  			i = cgltf_skip_json(tokens, i+1);
  3154  		}
  3155  
  3156  		if (i < 0)
  3157  		{
  3158  			return i;
  3159  		}
  3160  	}
  3161  
  3162  	return i;
  3163  }
  3164  
  3165  static int cgltf_parse_json_meshes(cgltf_options* options, jsmntok_t const* tokens, int i, const uint8_t* json_chunk, cgltf_data* out_data)
  3166  {
  3167  	i = cgltf_parse_json_array(options, tokens, i, json_chunk, sizeof(cgltf_mesh), (void**)&out_data->meshes, &out_data->meshes_count);
  3168  	if (i < 0)
  3169  	{
  3170  		return i;
  3171  	}
  3172  
  3173  	for (cgltf_size j = 0; j < out_data->meshes_count; ++j)
  3174  	{
  3175  		i = cgltf_parse_json_mesh(options, tokens, i, json_chunk, &out_data->meshes[j]);
  3176  		if (i < 0)
  3177  		{
  3178  			return i;
  3179  		}
  3180  	}
  3181  	return i;
  3182  }
  3183  
  3184  static cgltf_component_type cgltf_json_to_component_type(jsmntok_t const* tok, const uint8_t* json_chunk)
  3185  {
  3186  	int type = cgltf_json_to_int(tok, json_chunk);
  3187  
  3188  	switch (type)
  3189  	{
  3190  	case 5120:
  3191  		return cgltf_component_type_r_8;
  3192  	case 5121:
  3193  		return cgltf_component_type_r_8u;
  3194  	case 5122:
  3195  		return cgltf_component_type_r_16;
  3196  	case 5123:
  3197  		return cgltf_component_type_r_16u;
  3198  	case 5125:
  3199  		return cgltf_component_type_r_32u;
  3200  	case 5126:
  3201  		return cgltf_component_type_r_32f;
  3202  	default:
  3203  		return cgltf_component_type_invalid;
  3204  	}
  3205  }
  3206  
  3207  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)
  3208  {
  3209  	CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
  3210  
  3211  	int size = tokens[i].size;
  3212  	++i;
  3213  
  3214  	for (int j = 0; j < size; ++j)
  3215  	{
  3216  		CGLTF_CHECK_KEY(tokens[i]);
  3217  
  3218  		if (cgltf_json_strcmp(tokens+i, json_chunk, "count") == 0)
  3219  		{
  3220  			++i;
  3221  			out_sparse->count = cgltf_json_to_int(tokens + i, json_chunk);
  3222  			++i;
  3223  		}
  3224  		else if (cgltf_json_strcmp(tokens+i, json_chunk, "indices") == 0)
  3225  		{
  3226  			++i;
  3227  			CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
  3228  
  3229  			int indices_size = tokens[i].size;
  3230  			++i;
  3231  
  3232  			for (int k = 0; k < indices_size; ++k)
  3233  			{
  3234  				CGLTF_CHECK_KEY(tokens[i]);
  3235  
  3236  				if (cgltf_json_strcmp(tokens+i, json_chunk, "bufferView") == 0)
  3237  				{
  3238  					++i;
  3239  					out_sparse->indices_buffer_view = CGLTF_PTRINDEX(cgltf_buffer_view, cgltf_json_to_int(tokens + i, json_chunk));
  3240  					++i;
  3241  				}
  3242  				else if (cgltf_json_strcmp(tokens+i, json_chunk, "byteOffset") == 0)
  3243  				{
  3244  					++i;
  3245  					out_sparse->indices_byte_offset = cgltf_json_to_size(tokens + i, json_chunk);
  3246  					++i;
  3247  				}
  3248  				else if (cgltf_json_strcmp(tokens+i, json_chunk, "componentType") == 0)
  3249  				{
  3250  					++i;
  3251  					out_sparse->indices_component_type = cgltf_json_to_component_type(tokens + i, json_chunk);
  3252  					++i;
  3253  				}
  3254  				else if (cgltf_json_strcmp(tokens + i, json_chunk, "extras") == 0)
  3255  				{
  3256  					i = cgltf_parse_json_extras(tokens, i + 1, json_chunk, &out_sparse->indices_extras);
  3257  				}
  3258  				else if (cgltf_json_strcmp(tokens + i, json_chunk, "extensions") == 0)
  3259  				{
  3260  					i = cgltf_parse_json_unprocessed_extensions(options, tokens, i, json_chunk, &out_sparse->indices_extensions_count, &out_sparse->indices_extensions);
  3261  				}
  3262  				else
  3263  				{
  3264  					i = cgltf_skip_json(tokens, i+1);
  3265  				}
  3266  
  3267  				if (i < 0)
  3268  				{
  3269  					return i;
  3270  				}
  3271  			}
  3272  		}
  3273  		else if (cgltf_json_strcmp(tokens+i, json_chunk, "values") == 0)
  3274  		{
  3275  			++i;
  3276  			CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
  3277  
  3278  			int values_size = tokens[i].size;
  3279  			++i;
  3280  
  3281  			for (int k = 0; k < values_size; ++k)
  3282  			{
  3283  				CGLTF_CHECK_KEY(tokens[i]);
  3284  
  3285  				if (cgltf_json_strcmp(tokens+i, json_chunk, "bufferView") == 0)
  3286  				{
  3287  					++i;
  3288  					out_sparse->values_buffer_view = CGLTF_PTRINDEX(cgltf_buffer_view, cgltf_json_to_int(tokens + i, json_chunk));
  3289  					++i;
  3290  				}
  3291  				else if (cgltf_json_strcmp(tokens+i, json_chunk, "byteOffset") == 0)
  3292  				{
  3293  					++i;
  3294  					out_sparse->values_byte_offset = cgltf_json_to_size(tokens + i, json_chunk);
  3295  					++i;
  3296  				}
  3297  				else if (cgltf_json_strcmp(tokens + i, json_chunk, "extras") == 0)
  3298  				{
  3299  					i = cgltf_parse_json_extras(tokens, i + 1, json_chunk, &out_sparse->values_extras);
  3300  				}
  3301  				else if (cgltf_json_strcmp(tokens + i, json_chunk, "extensions") == 0)
  3302  				{
  3303  					i = cgltf_parse_json_unprocessed_extensions(options, tokens, i, json_chunk, &out_sparse->values_extensions_count, &out_sparse->values_extensions);
  3304  				}
  3305  				else
  3306  				{
  3307  					i = cgltf_skip_json(tokens, i+1);
  3308  				}
  3309  
  3310  				if (i < 0)
  3311  				{
  3312  					return i;
  3313  				}
  3314  			}
  3315  		}
  3316  		else if (cgltf_json_strcmp(tokens + i, json_chunk, "extras") == 0)
  3317  		{
  3318  			i = cgltf_parse_json_extras(tokens, i + 1, json_chunk, &out_sparse->extras);
  3319  		}
  3320  		else if (cgltf_json_strcmp(tokens + i, json_chunk, "extensions") == 0)
  3321  		{
  3322  			i = cgltf_parse_json_unprocessed_extensions(options, tokens, i, json_chunk, &out_sparse->extensions_count, &out_sparse->extensions);
  3323  		}
  3324  		else
  3325  		{
  3326  			i = cgltf_skip_json(tokens, i+1);
  3327  		}
  3328  
  3329  		if (i < 0)
  3330  		{
  3331  			return i;
  3332  		}
  3333  	}
  3334  
  3335  	return i;
  3336  }
  3337  
  3338  static int cgltf_parse_json_accessor(cgltf_options* options, jsmntok_t const* tokens, int i, const uint8_t* json_chunk, cgltf_accessor* out_accessor)
  3339  {
  3340  	CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
  3341  
  3342  	int size = tokens[i].size;
  3343  	++i;
  3344  
  3345  	for (int j = 0; j < size; ++j)
  3346  	{
  3347  		CGLTF_CHECK_KEY(tokens[i]);
  3348  
  3349  		if (cgltf_json_strcmp(tokens + i, json_chunk, "name") == 0)
  3350  		{
  3351  			i = cgltf_parse_json_string(options, tokens, i + 1, json_chunk, &out_accessor->name);
  3352  		}
  3353  		else if (cgltf_json_strcmp(tokens+i, json_chunk, "bufferView") == 0)
  3354  		{
  3355  			++i;
  3356  			out_accessor->buffer_view = CGLTF_PTRINDEX(cgltf_buffer_view, cgltf_json_to_int(tokens + i, json_chunk));
  3357  			++i;
  3358  		}
  3359  		else if (cgltf_json_strcmp(tokens+i, json_chunk, "byteOffset") == 0)
  3360  		{
  3361  			++i;
  3362  			out_accessor->offset =
  3363  					cgltf_json_to_size(tokens+i, json_chunk);
  3364  			++i;
  3365  		}
  3366  		else if (cgltf_json_strcmp(tokens+i, json_chunk, "componentType") == 0)
  3367  		{
  3368  			++i;
  3369  			out_accessor->component_type = cgltf_json_to_component_type(tokens + i, json_chunk);
  3370  			++i;
  3371  		}
  3372  		else if (cgltf_json_strcmp(tokens+i, json_chunk, "normalized") == 0)
  3373  		{
  3374  			++i;
  3375  			out_accessor->normalized = cgltf_json_to_bool(tokens+i, json_chunk);
  3376  			++i;
  3377  		}
  3378  		else if (cgltf_json_strcmp(tokens+i, json_chunk, "count") == 0)
  3379  		{
  3380  			++i;
  3381  			out_accessor->count =
  3382  					cgltf_json_to_int(tokens+i, json_chunk);
  3383  			++i;
  3384  		}
  3385  		else if (cgltf_json_strcmp(tokens+i, json_chunk, "type") == 0)
  3386  		{
  3387  			++i;
  3388  			if (cgltf_json_strcmp(tokens+i, json_chunk, "SCALAR") == 0)
  3389  			{
  3390  				out_accessor->type = cgltf_type_scalar;
  3391  			}
  3392  			else if (cgltf_json_strcmp(tokens+i, json_chunk, "VEC2") == 0)
  3393  			{
  3394  				out_accessor->type = cgltf_type_vec2;
  3395  			}
  3396  			else if (cgltf_json_strcmp(tokens+i, json_chunk, "VEC3") == 0)
  3397  			{
  3398  				out_accessor->type = cgltf_type_vec3;
  3399  			}
  3400  			else if (cgltf_json_strcmp(tokens+i, json_chunk, "VEC4") == 0)
  3401  			{
  3402  				out_accessor->type = cgltf_type_vec4;
  3403  			}
  3404  			else if (cgltf_json_strcmp(tokens+i, json_chunk, "MAT2") == 0)
  3405  			{
  3406  				out_accessor->type = cgltf_type_mat2;
  3407  			}
  3408  			else if (cgltf_json_strcmp(tokens+i, json_chunk, "MAT3") == 0)
  3409  			{
  3410  				out_accessor->type = cgltf_type_mat3;
  3411  			}
  3412  			else if (cgltf_json_strcmp(tokens+i, json_chunk, "MAT4") == 0)
  3413  			{
  3414  				out_accessor->type = cgltf_type_mat4;
  3415  			}
  3416  			++i;
  3417  		}
  3418  		else if (cgltf_json_strcmp(tokens + i, json_chunk, "min") == 0)
  3419  		{
  3420  			++i;
  3421  			out_accessor->has_min = 1;
  3422  			// note: we can't parse the precise number of elements since type may not have been computed yet
  3423  			int min_size = tokens[i].size > 16 ? 16 : tokens[i].size;
  3424  			i = cgltf_parse_json_float_array(tokens, i, json_chunk, out_accessor->min, min_size);
  3425  		}
  3426  		else if (cgltf_json_strcmp(tokens + i, json_chunk, "max") == 0)
  3427  		{
  3428  			++i;
  3429  			out_accessor->has_max = 1;
  3430  			// note: we can't parse the precise number of elements since type may not have been computed yet
  3431  			int max_size = tokens[i].size > 16 ? 16 : tokens[i].size;
  3432  			i = cgltf_parse_json_float_array(tokens, i, json_chunk, out_accessor->max, max_size);
  3433  		}
  3434  		else if (cgltf_json_strcmp(tokens + i, json_chunk, "sparse") == 0)
  3435  		{
  3436  			out_accessor->is_sparse = 1;
  3437  			i = cgltf_parse_json_accessor_sparse(options, tokens, i + 1, json_chunk, &out_accessor->sparse);
  3438  		}
  3439  		else if (cgltf_json_strcmp(tokens + i, json_chunk, "extras") == 0)
  3440  		{
  3441  			i = cgltf_parse_json_extras(tokens, i + 1, json_chunk, &out_accessor->extras);
  3442  		}
  3443  		else if (cgltf_json_strcmp(tokens + i, json_chunk, "extensions") == 0)
  3444  		{
  3445  			i = cgltf_parse_json_unprocessed_extensions(options, tokens, i, json_chunk, &out_accessor->extensions_count, &out_accessor->extensions);
  3446  		}
  3447  		else
  3448  		{
  3449  			i = cgltf_skip_json(tokens, i+1);
  3450  		}
  3451  
  3452  		if (i < 0)
  3453  		{
  3454  			return i;
  3455  		}
  3456  	}
  3457  
  3458  	return i;
  3459  }
  3460  
  3461  static int cgltf_parse_json_texture_transform(jsmntok_t const* tokens, int i, const uint8_t* json_chunk, cgltf_texture_transform* out_texture_transform)
  3462  {
  3463  	CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
  3464  
  3465  	int size = tokens[i].size;
  3466  	++i;
  3467  
  3468  	for (int j = 0; j < size; ++j)
  3469  	{
  3470  		CGLTF_CHECK_KEY(tokens[i]);
  3471  
  3472  		if (cgltf_json_strcmp(tokens + i, json_chunk, "offset") == 0)
  3473  		{
  3474  			i = cgltf_parse_json_float_array(tokens, i + 1, json_chunk, out_texture_transform->offset, 2);
  3475  		}
  3476  		else if (cgltf_json_strcmp(tokens + i, json_chunk, "rotation") == 0)
  3477  		{
  3478  			++i;
  3479  			out_texture_transform->rotation = cgltf_json_to_float(tokens + i, json_chunk);
  3480  			++i;
  3481  		}
  3482  		else if (cgltf_json_strcmp(tokens + i, json_chunk, "scale") == 0)
  3483  		{
  3484  			i = cgltf_parse_json_float_array(tokens, i + 1, json_chunk, out_texture_transform->scale, 2);
  3485  		}
  3486  		else if (cgltf_json_strcmp(tokens + i, json_chunk, "texCoord") == 0)
  3487  		{
  3488  			++i;
  3489  			out_texture_transform->has_texcoord = 1;
  3490  			out_texture_transform->texcoord = cgltf_json_to_int(tokens + i, json_chunk);
  3491  			++i;
  3492  		}
  3493  		else
  3494  		{
  3495  			i = cgltf_skip_json(tokens, i + 1);
  3496  		}
  3497  
  3498  		if (i < 0)
  3499  		{
  3500  			return i;
  3501  		}
  3502  	}
  3503  
  3504  	return i;
  3505  }
  3506  
  3507  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)
  3508  {
  3509  	CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
  3510  
  3511  	out_texture_view->scale = 1.0f;
  3512  	cgltf_fill_float_array(out_texture_view->transform.scale, 2, 1.0f);
  3513  
  3514  	int size = tokens[i].size;
  3515  	++i;
  3516  
  3517  	for (int j = 0; j < size; ++j)
  3518  	{
  3519  		CGLTF_CHECK_KEY(tokens[i]);
  3520  
  3521  		if (cgltf_json_strcmp(tokens + i, json_chunk, "index") == 0)
  3522  		{
  3523  			++i;
  3524  			out_texture_view->texture = CGLTF_PTRINDEX(cgltf_texture, cgltf_json_to_int(tokens + i, json_chunk));
  3525  			++i;
  3526  		}
  3527  		else if (cgltf_json_strcmp(tokens + i, json_chunk, "texCoord") == 0)
  3528  		{
  3529  			++i;
  3530  			out_texture_view->texcoord = cgltf_json_to_int(tokens + i, json_chunk);
  3531  			++i;
  3532  		}
  3533  		else if (cgltf_json_strcmp(tokens + i, json_chunk, "scale") == 0) 
  3534  		{
  3535  			++i;
  3536  			out_texture_view->scale = cgltf_json_to_float(tokens + i, json_chunk);
  3537  			++i;
  3538  		}
  3539  		else if (cgltf_json_strcmp(tokens + i, json_chunk, "strength") == 0)
  3540  		{
  3541  			++i;
  3542  			out_texture_view->scale = cgltf_json_to_float(tokens + i, json_chunk);
  3543  			++i;
  3544  		}
  3545  		else if (cgltf_json_strcmp(tokens + i, json_chunk, "extras") == 0)
  3546  		{
  3547  			i = cgltf_parse_json_extras(tokens, i + 1, json_chunk, &out_texture_view->extras);
  3548  		}
  3549  		else if (cgltf_json_strcmp(tokens + i, json_chunk, "extensions") == 0)
  3550  		{
  3551  			++i;
  3552  
  3553  			CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
  3554  			if(out_texture_view->extensions)
  3555  			{
  3556  				return CGLTF_ERROR_JSON;
  3557  			}
  3558  
  3559  			int extensions_size = tokens[i].size;
  3560  			out_texture_view->extensions_count = 0;
  3561  			out_texture_view->extensions = (cgltf_extension*)cgltf_calloc(options, sizeof(cgltf_extension), extensions_size);
  3562  
  3563  			if (!out_texture_view->extensions)
  3564  			{
  3565  				return CGLTF_ERROR_NOMEM;
  3566  			}
  3567  
  3568  			++i;
  3569  
  3570  			for (int k = 0; k < extensions_size; ++k)
  3571  			{
  3572  				CGLTF_CHECK_KEY(tokens[i]);
  3573  
  3574  				if (cgltf_json_strcmp(tokens+i, json_chunk, "KHR_texture_transform") == 0)
  3575  				{
  3576  					out_texture_view->has_transform = 1;
  3577  					i = cgltf_parse_json_texture_transform(tokens, i + 1, json_chunk, &out_texture_view->transform);
  3578  				}
  3579  				else
  3580  				{
  3581  					i = cgltf_parse_json_unprocessed_extension(options, tokens, i, json_chunk, &(out_texture_view->extensions[out_texture_view->extensions_count++]));
  3582  				}
  3583  
  3584  				if (i < 0)
  3585  				{
  3586  					return i;
  3587  				}
  3588  			}
  3589  		}
  3590  		else
  3591  		{
  3592  			i = cgltf_skip_json(tokens, i + 1);
  3593  		}
  3594  
  3595  		if (i < 0)
  3596  		{
  3597  			return i;
  3598  		}
  3599  	}
  3600  
  3601  	return i;
  3602  }
  3603  
  3604  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)
  3605  {
  3606  	CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
  3607  
  3608  	int size = tokens[i].size;
  3609  	++i;
  3610  
  3611  	for (int j = 0; j < size; ++j)
  3612  	{
  3613  		CGLTF_CHECK_KEY(tokens[i]);
  3614  
  3615  		if (cgltf_json_strcmp(tokens+i, json_chunk, "metallicFactor") == 0)
  3616  		{
  3617  			++i;
  3618  			out_pbr->metallic_factor = 
  3619  				cgltf_json_to_float(tokens + i, json_chunk);
  3620  			++i;
  3621  		}
  3622  		else if (cgltf_json_strcmp(tokens+i, json_chunk, "roughnessFactor") == 0) 
  3623  		{
  3624  			++i;
  3625  			out_pbr->roughness_factor =
  3626  				cgltf_json_to_float(tokens+i, json_chunk);
  3627  			++i;
  3628  		}
  3629  		else if (cgltf_json_strcmp(tokens+i, json_chunk, "baseColorFactor") == 0)
  3630  		{
  3631  			i = cgltf_parse_json_float_array(tokens, i + 1, json_chunk, out_pbr->base_color_factor, 4);
  3632  		}
  3633  		else if (cgltf_json_strcmp(tokens+i, json_chunk, "baseColorTexture") == 0)
  3634  		{
  3635  			i = cgltf_parse_json_texture_view(options, tokens, i + 1, json_chunk,
  3636  				&out_pbr->base_color_texture);
  3637  		}
  3638  		else if (cgltf_json_strcmp(tokens + i, json_chunk, "metallicRoughnessTexture") == 0)
  3639  		{
  3640  			i = cgltf_parse_json_texture_view(options, tokens, i + 1, json_chunk,
  3641  				&out_pbr->metallic_roughness_texture);
  3642  		}
  3643  		else if (cgltf_json_strcmp(tokens + i, json_chunk, "extras") == 0)
  3644  		{
  3645  			i = cgltf_parse_json_extras(tokens, i + 1, json_chunk, &out_pbr->extras);
  3646  		}
  3647  		else
  3648  		{
  3649  			i = cgltf_skip_json(tokens, i+1);
  3650  		}
  3651  
  3652  		if (i < 0)
  3653  		{
  3654  			return i;
  3655  		}
  3656  	}
  3657  
  3658  	return i;
  3659  }
  3660  
  3661  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)
  3662  {
  3663  	CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
  3664  	int size = tokens[i].size;
  3665  	++i;
  3666  
  3667  	for (int j = 0; j < size; ++j)
  3668  	{
  3669  		CGLTF_CHECK_KEY(tokens[i]);
  3670  
  3671  		if (cgltf_json_strcmp(tokens+i, json_chunk, "diffuseFactor") == 0)
  3672  		{
  3673  			i = cgltf_parse_json_float_array(tokens, i + 1, json_chunk, out_pbr->diffuse_factor, 4);
  3674  		}
  3675  		else if (cgltf_json_strcmp(tokens+i, json_chunk, "specularFactor") == 0)
  3676  		{
  3677  			i = cgltf_parse_json_float_array(tokens, i + 1, json_chunk, out_pbr->specular_factor, 3);
  3678  		}
  3679  		else if (cgltf_json_strcmp(tokens+i, json_chunk, "glossinessFactor") == 0)
  3680  		{
  3681  			++i;
  3682  			out_pbr->glossiness_factor = cgltf_json_to_float(tokens + i, json_chunk);
  3683  			++i;
  3684  		}
  3685  		else if (cgltf_json_strcmp(tokens+i, json_chunk, "diffuseTexture") == 0)
  3686  		{
  3687  			i = cgltf_parse_json_texture_view(options, tokens, i + 1, json_chunk, &out_pbr->diffuse_texture);
  3688  		}
  3689  		else if (cgltf_json_strcmp(tokens+i, json_chunk, "specularGlossinessTexture") == 0)
  3690  		{
  3691  			i = cgltf_parse_json_texture_view(options, tokens, i + 1, json_chunk, &out_pbr->specular_glossiness_texture);
  3692  		}
  3693  		else
  3694  		{
  3695  			i = cgltf_skip_json(tokens, i+1);
  3696  		}
  3697  
  3698  		if (i < 0)
  3699  		{
  3700  			return i;
  3701  		}
  3702  	}
  3703  
  3704  	return i;
  3705  }
  3706  
  3707  static int cgltf_parse_json_clearcoat(cgltf_options* options, jsmntok_t const* tokens, int i, const uint8_t* json_chunk, cgltf_clearcoat* out_clearcoat)
  3708  {
  3709  	CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
  3710  	int size = tokens[i].size;
  3711  	++i;
  3712  
  3713  	for (int j = 0; j < size; ++j)
  3714  	{
  3715  		CGLTF_CHECK_KEY(tokens[i]);
  3716  
  3717  		if (cgltf_json_strcmp(tokens+i, json_chunk, "clearcoatFactor") == 0)
  3718  		{
  3719  			++i;
  3720  			out_clearcoat->clearcoat_factor = cgltf_json_to_float(tokens + i, json_chunk);
  3721  			++i;
  3722  		}
  3723  		else if (cgltf_json_strcmp(tokens+i, json_chunk, "clearcoatRoughnessFactor") == 0)
  3724  		{
  3725  			++i;
  3726  			out_clearcoat->clearcoat_roughness_factor = cgltf_json_to_float(tokens + i, json_chunk);
  3727  			++i;
  3728  		}
  3729  		else if (cgltf_json_strcmp(tokens+i, json_chunk, "clearcoatTexture") == 0)
  3730  		{
  3731  			i = cgltf_parse_json_texture_view(options, tokens, i + 1, json_chunk, &out_clearcoat->clearcoat_texture);
  3732  		}
  3733  		else if (cgltf_json_strcmp(tokens+i, json_chunk, "clearcoatRoughnessTexture") == 0)
  3734  		{
  3735  			i = cgltf_parse_json_texture_view(options, tokens, i + 1, json_chunk, &out_clearcoat->clearcoat_roughness_texture);
  3736  		}
  3737  		else if (cgltf_json_strcmp(tokens+i, json_chunk, "clearcoatNormalTexture") == 0)
  3738  		{
  3739  			i = cgltf_parse_json_texture_view(options, tokens, i + 1, json_chunk, &out_clearcoat->clearcoat_normal_texture);
  3740  		}
  3741  		else
  3742  		{
  3743  			i = cgltf_skip_json(tokens, i+1);
  3744  		}
  3745  
  3746  		if (i < 0)
  3747  		{
  3748  			return i;
  3749  		}
  3750  	}
  3751  
  3752  	return i;
  3753  }
  3754  
  3755  static int cgltf_parse_json_ior(jsmntok_t const* tokens, int i, const uint8_t* json_chunk, cgltf_ior* out_ior)
  3756  {
  3757  	CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
  3758  	int size = tokens[i].size;
  3759  	++i;
  3760  
  3761  	// Default values
  3762  	out_ior->ior = 1.5f;
  3763  
  3764  	for (int j = 0; j < size; ++j)
  3765  	{
  3766  		CGLTF_CHECK_KEY(tokens[i]);
  3767  
  3768  		if (cgltf_json_strcmp(tokens+i, json_chunk, "ior") == 0)
  3769  		{
  3770  			++i;
  3771  			out_ior->ior = cgltf_json_to_float(tokens + i, json_chunk);
  3772  			++i;
  3773  		}
  3774  		else
  3775  		{
  3776  			i = cgltf_skip_json(tokens, i+1);
  3777  		}
  3778  
  3779  		if (i < 0)
  3780  		{
  3781  			return i;
  3782  		}
  3783  	}
  3784  
  3785  	return i;
  3786  }
  3787  
  3788  static int cgltf_parse_json_specular(cgltf_options* options, jsmntok_t const* tokens, int i, const uint8_t* json_chunk, cgltf_specular* out_specular)
  3789  {
  3790  	CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
  3791  	int size = tokens[i].size;
  3792  	++i;
  3793  
  3794  	// Default values
  3795  	out_specular->specular_factor = 1.0f;
  3796  	cgltf_fill_float_array(out_specular->specular_color_factor, 3, 1.0f);
  3797  
  3798  	for (int j = 0; j < size; ++j)
  3799  	{
  3800  		CGLTF_CHECK_KEY(tokens[i]);
  3801  
  3802  		if (cgltf_json_strcmp(tokens+i, json_chunk, "specularFactor") == 0)
  3803  		{
  3804  			++i;
  3805  			out_specular->specular_factor = cgltf_json_to_float(tokens + i, json_chunk);
  3806  			++i;
  3807  		}
  3808  		else if (cgltf_json_strcmp(tokens+i, json_chunk, "specularColorFactor") == 0)
  3809  		{
  3810  			i = cgltf_parse_json_float_array(tokens, i + 1, json_chunk, out_specular->specular_color_factor, 3);
  3811  		}
  3812  		else if (cgltf_json_strcmp(tokens+i, json_chunk, "specularTexture") == 0)
  3813  		{
  3814  			i = cgltf_parse_json_texture_view(options, tokens, i + 1, json_chunk, &out_specular->specular_texture);
  3815  		}
  3816  		else if (cgltf_json_strcmp(tokens + i, json_chunk, "specularColorTexture") == 0)
  3817  		{
  3818  			i = cgltf_parse_json_texture_view(options, tokens, i + 1, json_chunk, &out_specular->specular_color_texture);
  3819  		}
  3820  		else
  3821  		{
  3822  			i = cgltf_skip_json(tokens, i+1);
  3823  		}
  3824  
  3825  		if (i < 0)
  3826  		{
  3827  			return i;
  3828  		}
  3829  	}
  3830  
  3831  	return i;
  3832  }
  3833  
  3834  static int cgltf_parse_json_transmission(cgltf_options* options, jsmntok_t const* tokens, int i, const uint8_t* json_chunk, cgltf_transmission* out_transmission)
  3835  {
  3836  	CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
  3837  	int size = tokens[i].size;
  3838  	++i;
  3839  
  3840  	for (int j = 0; j < size; ++j)
  3841  	{
  3842  		CGLTF_CHECK_KEY(tokens[i]);
  3843  
  3844  		if (cgltf_json_strcmp(tokens+i, json_chunk, "transmissionFactor") == 0)
  3845  		{
  3846  			++i;
  3847  			out_transmission->transmission_factor = cgltf_json_to_float(tokens + i, json_chunk);
  3848  			++i;
  3849  		}
  3850  		else if (cgltf_json_strcmp(tokens+i, json_chunk, "transmissionTexture") == 0)
  3851  		{
  3852  			i = cgltf_parse_json_texture_view(options, tokens, i + 1, json_chunk, &out_transmission->transmission_texture);
  3853  		}
  3854  		else
  3855  		{
  3856  			i = cgltf_skip_json(tokens, i+1);
  3857  		}
  3858  
  3859  		if (i < 0)
  3860  		{
  3861  			return i;
  3862  		}
  3863  	}
  3864  
  3865  	return i;
  3866  }
  3867  
  3868  static int cgltf_parse_json_volume(cgltf_options* options, jsmntok_t const* tokens, int i, const uint8_t* json_chunk, cgltf_volume* out_volume)
  3869  {
  3870  	CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
  3871  	int size = tokens[i].size;
  3872  	++i;
  3873  
  3874  	for (int j = 0; j < size; ++j)
  3875  	{
  3876  		CGLTF_CHECK_KEY(tokens[i]);
  3877  
  3878  		if (cgltf_json_strcmp(tokens + i, json_chunk, "thicknessFactor") == 0)
  3879  		{
  3880  			++i;
  3881  			out_volume->thickness_factor = cgltf_json_to_float(tokens + i, json_chunk);
  3882  			++i;
  3883  		}
  3884  		else if (cgltf_json_strcmp(tokens + i, json_chunk, "thicknessTexture") == 0)
  3885  		{
  3886  			i = cgltf_parse_json_texture_view(options, tokens, i + 1, json_chunk, &out_volume->thickness_texture);
  3887  		}
  3888  		else if (cgltf_json_strcmp(tokens + i, json_chunk, "attenuationColor") == 0)
  3889  		{
  3890  			i = cgltf_parse_json_float_array(tokens, i + 1, json_chunk, out_volume->attenuation_color, 3);
  3891  		}
  3892  		else if (cgltf_json_strcmp(tokens + i, json_chunk, "attenuationDistance") == 0)
  3893  		{
  3894  			++i;
  3895  			out_volume->attenuation_distance = cgltf_json_to_float(tokens + i, json_chunk);
  3896  			++i;
  3897  		}
  3898  		else
  3899  		{
  3900  			i = cgltf_skip_json(tokens, i + 1);
  3901  		}
  3902  
  3903  		if (i < 0)
  3904  		{
  3905  			return i;
  3906  		}
  3907  	}
  3908  
  3909  	return i;
  3910  }
  3911  
  3912  static int cgltf_parse_json_sheen(cgltf_options* options, jsmntok_t const* tokens, int i, const uint8_t* json_chunk, cgltf_sheen* out_sheen)
  3913  {
  3914  	CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
  3915  	int size = tokens[i].size;
  3916  	++i;
  3917  
  3918  	for (int j = 0; j < size; ++j)
  3919  	{
  3920  		CGLTF_CHECK_KEY(tokens[i]);
  3921  
  3922  		if (cgltf_json_strcmp(tokens+i, json_chunk, "sheenColorFactor") == 0)
  3923  		{
  3924  			i = cgltf_parse_json_float_array(tokens, i + 1, json_chunk, out_sheen->sheen_color_factor, 3);
  3925  		}
  3926  		else if (cgltf_json_strcmp(tokens+i, json_chunk, "sheenColorTexture") == 0)
  3927  		{
  3928  			i = cgltf_parse_json_texture_view(options, tokens, i + 1, json_chunk, &out_sheen->sheen_color_texture);
  3929  		}
  3930  		else if (cgltf_json_strcmp(tokens+i, json_chunk, "sheenRoughnessFactor") == 0)
  3931  		{
  3932  			++i;
  3933  			out_sheen->sheen_roughness_factor = cgltf_json_to_float(tokens + i, json_chunk);
  3934  			++i;
  3935  		}
  3936  		else if (cgltf_json_strcmp(tokens+i, json_chunk, "sheenRoughnessTexture") == 0)
  3937  		{
  3938  			i = cgltf_parse_json_texture_view(options, tokens, i + 1, json_chunk, &out_sheen->sheen_roughness_texture);
  3939  		}
  3940  		else
  3941  		{
  3942  			i = cgltf_skip_json(tokens, i+1);
  3943  		}
  3944  
  3945  		if (i < 0)
  3946  		{
  3947  			return i;
  3948  		}
  3949  	}
  3950  
  3951  	return i;
  3952  }
  3953  
  3954  static int cgltf_parse_json_emissive_strength(jsmntok_t const* tokens, int i, const uint8_t* json_chunk, cgltf_emissive_strength* out_emissive_strength)
  3955  {
  3956  	CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
  3957  	int size = tokens[i].size;
  3958  	++i;
  3959  
  3960  	// Default
  3961  	out_emissive_strength->emissive_strength = 1.f;
  3962  
  3963  	for (int j = 0; j < size; ++j)
  3964  	{
  3965  		CGLTF_CHECK_KEY(tokens[i]);
  3966  
  3967  		if (cgltf_json_strcmp(tokens + i, json_chunk, "emissiveStrength") == 0)
  3968  		{
  3969  			++i;
  3970  			out_emissive_strength->emissive_strength = cgltf_json_to_float(tokens + i, json_chunk);
  3971  			++i;
  3972  		}
  3973  		else
  3974  		{
  3975  			i = cgltf_skip_json(tokens, i + 1);
  3976  		}
  3977  
  3978  		if (i < 0)
  3979  		{
  3980  			return i;
  3981  		}
  3982  	}
  3983  
  3984  	return i;
  3985  }
  3986  
  3987  static int cgltf_parse_json_iridescence(cgltf_options* options, jsmntok_t const* tokens, int i, const uint8_t* json_chunk, cgltf_iridescence* out_iridescence)
  3988  {
  3989  	CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
  3990  	int size = tokens[i].size;
  3991  	++i;
  3992  
  3993  	// Default
  3994  	out_iridescence->iridescence_ior = 1.3f;
  3995  	out_iridescence->iridescence_thickness_min = 100.f;
  3996  	out_iridescence->iridescence_thickness_max = 400.f;
  3997  
  3998  	for (int j = 0; j < size; ++j)
  3999  	{
  4000  		CGLTF_CHECK_KEY(tokens[i]);
  4001  
  4002  		if (cgltf_json_strcmp(tokens + i, json_chunk, "iridescenceFactor") == 0)
  4003  		{
  4004  			++i;
  4005  			out_iridescence->iridescence_factor = cgltf_json_to_float(tokens + i, json_chunk);
  4006  			++i;
  4007  		}
  4008  		else if (cgltf_json_strcmp(tokens + i, json_chunk, "iridescenceTexture") == 0)
  4009  		{
  4010  			i = cgltf_parse_json_texture_view(options, tokens, i + 1, json_chunk, &out_iridescence->iridescence_texture);
  4011  		}
  4012  		else if (cgltf_json_strcmp(tokens + i, json_chunk, "iridescenceIor") == 0)
  4013  		{
  4014  			++i;
  4015  			out_iridescence->iridescence_ior = cgltf_json_to_float(tokens + i, json_chunk);
  4016  			++i;
  4017  		}
  4018  		else if (cgltf_json_strcmp(tokens + i, json_chunk, "iridescenceThicknessMinimum") == 0)
  4019  		{
  4020  			++i;
  4021  			out_iridescence->iridescence_thickness_min = cgltf_json_to_float(tokens + i, json_chunk);
  4022  			++i;
  4023  		}
  4024  		else if (cgltf_json_strcmp(tokens + i, json_chunk, "iridescenceThicknessMaximum") == 0)
  4025  		{
  4026  			++i;
  4027  			out_iridescence->iridescence_thickness_max = cgltf_json_to_float(tokens + i, json_chunk);
  4028  			++i;
  4029  		}
  4030  		else if (cgltf_json_strcmp(tokens + i, json_chunk, "iridescenceThicknessTexture") == 0)
  4031  		{
  4032  			i = cgltf_parse_json_texture_view(options, tokens, i + 1, json_chunk, &out_iridescence->iridescence_thickness_texture);
  4033  		}
  4034  		else
  4035  		{
  4036  			i = cgltf_skip_json(tokens, i + 1);
  4037  		}
  4038  
  4039  		if (i < 0)
  4040  		{
  4041  			return i;
  4042  		}
  4043  	}
  4044  
  4045  	return i;
  4046  }
  4047  
  4048  static int cgltf_parse_json_image(cgltf_options* options, jsmntok_t const* tokens, int i, const uint8_t* json_chunk, cgltf_image* out_image)
  4049  {
  4050  	CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
  4051  
  4052  	int size = tokens[i].size;
  4053  	++i;
  4054  
  4055  	for (int j = 0; j < size; ++j) 
  4056  	{
  4057  		CGLTF_CHECK_KEY(tokens[i]);
  4058  
  4059  		if (cgltf_json_strcmp(tokens + i, json_chunk, "uri") == 0) 
  4060  		{
  4061  			i = cgltf_parse_json_string(options, tokens, i + 1, json_chunk, &out_image->uri);
  4062  		}
  4063  		else if (cgltf_json_strcmp(tokens+i, json_chunk, "bufferView") == 0)
  4064  		{
  4065  			++i;
  4066  			out_image->buffer_view = CGLTF_PTRINDEX(cgltf_buffer_view, cgltf_json_to_int(tokens + i, json_chunk));
  4067  			++i;
  4068  		}
  4069  		else if (cgltf_json_strcmp(tokens + i, json_chunk, "mimeType") == 0)
  4070  		{
  4071  			i = cgltf_parse_json_string(options, tokens, i + 1, json_chunk, &out_image->mime_type);
  4072  		}
  4073  		else if (cgltf_json_strcmp(tokens + i, json_chunk, "name") == 0)
  4074  		{
  4075  			i = cgltf_parse_json_string(options, tokens, i + 1, json_chunk, &out_image->name);
  4076  		}
  4077  		else if (cgltf_json_strcmp(tokens + i, json_chunk, "extras") == 0)
  4078  		{
  4079  			i = cgltf_parse_json_extras(tokens, i + 1, json_chunk, &out_image->extras);
  4080  		}
  4081  		else if (cgltf_json_strcmp(tokens + i, json_chunk, "extensions") == 0)
  4082  		{
  4083  			i = cgltf_parse_json_unprocessed_extensions(options, tokens, i, json_chunk, &out_image->extensions_count, &out_image->extensions);
  4084  		}
  4085  		else
  4086  		{
  4087  			i = cgltf_skip_json(tokens, i + 1);
  4088  		}
  4089  
  4090  		if (i < 0)
  4091  		{
  4092  			return i;
  4093  		}
  4094  	}
  4095  
  4096  	return i;
  4097  }
  4098  
  4099  static int cgltf_parse_json_sampler(cgltf_options* options, jsmntok_t const* tokens, int i, const uint8_t* json_chunk, cgltf_sampler* out_sampler)
  4100  {
  4101  	(void)options;
  4102  	CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
  4103  
  4104  	out_sampler->wrap_s = 10497;
  4105  	out_sampler->wrap_t = 10497;
  4106  
  4107  	int size = tokens[i].size;
  4108  	++i;
  4109  
  4110  	for (int j = 0; j < size; ++j)
  4111  	{
  4112  		CGLTF_CHECK_KEY(tokens[i]);
  4113  
  4114  		if (cgltf_json_strcmp(tokens + i, json_chunk, "name") == 0)
  4115  		{
  4116  			i = cgltf_parse_json_string(options, tokens, i + 1, json_chunk, &out_sampler->name);
  4117  		}
  4118  		else if (cgltf_json_strcmp(tokens + i, json_chunk, "magFilter") == 0)
  4119  		{
  4120  			++i;
  4121  			out_sampler->mag_filter
  4122  				= cgltf_json_to_int(tokens + i, json_chunk);
  4123  			++i;
  4124  		}
  4125  		else if (cgltf_json_strcmp(tokens + i, json_chunk, "minFilter") == 0)
  4126  		{
  4127  			++i;
  4128  			out_sampler->min_filter
  4129  				= cgltf_json_to_int(tokens + i, json_chunk);
  4130  			++i;
  4131  		}
  4132  		else if (cgltf_json_strcmp(tokens + i, json_chunk, "wrapS") == 0)
  4133  		{
  4134  			++i;
  4135  			out_sampler->wrap_s
  4136  				= cgltf_json_to_int(tokens + i, json_chunk);
  4137  			++i;
  4138  		}
  4139  		else if (cgltf_json_strcmp(tokens + i, json_chunk, "wrapT") == 0) 
  4140  		{
  4141  			++i;
  4142  			out_sampler->wrap_t
  4143  				= cgltf_json_to_int(tokens + i, json_chunk);
  4144  			++i;
  4145  		}
  4146  		else if (cgltf_json_strcmp(tokens + i, json_chunk, "extras") == 0)
  4147  		{
  4148  			i = cgltf_parse_json_extras(tokens, i + 1, json_chunk, &out_sampler->extras);
  4149  		}
  4150  		else if (cgltf_json_strcmp(tokens + i, json_chunk, "extensions") == 0)
  4151  		{
  4152  			i = cgltf_parse_json_unprocessed_extensions(options, tokens, i, json_chunk, &out_sampler->extensions_count, &out_sampler->extensions);
  4153  		}
  4154  		else
  4155  		{
  4156  			i = cgltf_skip_json(tokens, i + 1);
  4157  		}
  4158  
  4159  		if (i < 0)
  4160  		{
  4161  			return i;
  4162  		}
  4163  	}
  4164  
  4165  	return i;
  4166  }
  4167  
  4168  static int cgltf_parse_json_texture(cgltf_options* options, jsmntok_t const* tokens, int i, const uint8_t* json_chunk, cgltf_texture* out_texture)
  4169  {
  4170  	CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
  4171  
  4172  	int size = tokens[i].size;
  4173  	++i;
  4174  
  4175  	for (int j = 0; j < size; ++j)
  4176  	{
  4177  		CGLTF_CHECK_KEY(tokens[i]);
  4178  
  4179  		if (cgltf_json_strcmp(tokens+i, json_chunk, "name") == 0)
  4180  		{
  4181  			i = cgltf_parse_json_string(options, tokens, i + 1, json_chunk, &out_texture->name);
  4182  		}
  4183  		else if (cgltf_json_strcmp(tokens + i, json_chunk, "sampler") == 0)
  4184  		{
  4185  			++i;
  4186  			out_texture->sampler = CGLTF_PTRINDEX(cgltf_sampler, cgltf_json_to_int(tokens + i, json_chunk));
  4187  			++i;
  4188  		}
  4189  		else if (cgltf_json_strcmp(tokens + i, json_chunk, "source") == 0) 
  4190  		{
  4191  			++i;
  4192  			out_texture->image = CGLTF_PTRINDEX(cgltf_image, cgltf_json_to_int(tokens + i, json_chunk));
  4193  			++i;
  4194  		}
  4195  		else if (cgltf_json_strcmp(tokens + i, json_chunk, "extras") == 0)
  4196  		{
  4197  			i = cgltf_parse_json_extras(tokens, i + 1, json_chunk, &out_texture->extras);
  4198  		}
  4199  		else if (cgltf_json_strcmp(tokens + i, json_chunk, "extensions") == 0)
  4200  		{
  4201  			++i;
  4202  
  4203  			CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
  4204  			if (out_texture->extensions)
  4205  			{
  4206  				return CGLTF_ERROR_JSON;
  4207  			}
  4208  
  4209  			int extensions_size = tokens[i].size;
  4210  			++i;
  4211  			out_texture->extensions = (cgltf_extension*)cgltf_calloc(options, sizeof(cgltf_extension), extensions_size);
  4212  			out_texture->extensions_count = 0;
  4213  
  4214  			if (!out_texture->extensions)
  4215  			{
  4216  				return CGLTF_ERROR_NOMEM;
  4217  			}
  4218  
  4219  			for (int k = 0; k < extensions_size; ++k)
  4220  			{
  4221  				CGLTF_CHECK_KEY(tokens[i]);
  4222  
  4223  				if (cgltf_json_strcmp(tokens + i, json_chunk, "KHR_texture_basisu") == 0)
  4224  				{
  4225  					out_texture->has_basisu = 1;
  4226  					++i;
  4227  					CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
  4228  					int num_properties = tokens[i].size;
  4229  					++i;
  4230  
  4231  					for (int t = 0; t < num_properties; ++t)
  4232  					{
  4233  						CGLTF_CHECK_KEY(tokens[i]);
  4234  
  4235  						if (cgltf_json_strcmp(tokens + i, json_chunk, "source") == 0)
  4236  						{
  4237  							++i;
  4238  							out_texture->basisu_image = CGLTF_PTRINDEX(cgltf_image, cgltf_json_to_int(tokens + i, json_chunk));
  4239  							++i;
  4240  						}
  4241  						else
  4242  						{
  4243  							i = cgltf_skip_json(tokens, i + 1);
  4244  						}
  4245  						if (i < 0)
  4246  						{
  4247  							return i;
  4248  						}
  4249  					}
  4250  				}
  4251  				else
  4252  				{
  4253  					i = cgltf_parse_json_unprocessed_extension(options, tokens, i, json_chunk, &(out_texture->extensions[out_texture->extensions_count++]));
  4254  				}
  4255  
  4256  				if (i < 0)
  4257  				{
  4258  					return i;
  4259  				}
  4260  			}
  4261  		}
  4262  		else
  4263  		{
  4264  			i = cgltf_skip_json(tokens, i + 1);
  4265  		}
  4266  
  4267  		if (i < 0)
  4268  		{
  4269  			return i;
  4270  		}
  4271  	}
  4272  
  4273  	return i;
  4274  }
  4275  
  4276  static int cgltf_parse_json_material(cgltf_options* options, jsmntok_t const* tokens, int i, const uint8_t* json_chunk, cgltf_material* out_material)
  4277  {
  4278  	CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
  4279  
  4280  	cgltf_fill_float_array(out_material->pbr_metallic_roughness.base_color_factor, 4, 1.0f);
  4281  	out_material->pbr_metallic_roughness.metallic_factor = 1.0f;
  4282  	out_material->pbr_metallic_roughness.roughness_factor = 1.0f;
  4283  
  4284  	cgltf_fill_float_array(out_material->pbr_specular_glossiness.diffuse_factor, 4, 1.0f);
  4285  	cgltf_fill_float_array(out_material->pbr_specular_glossiness.specular_factor, 3, 1.0f);
  4286  	out_material->pbr_specular_glossiness.glossiness_factor = 1.0f;
  4287  
  4288  	cgltf_fill_float_array(out_material->volume.attenuation_color, 3, 1.0f);
  4289  	out_material->volume.attenuation_distance = FLT_MAX;
  4290  
  4291  	out_material->alpha_cutoff = 0.5f;
  4292  
  4293  	int size = tokens[i].size;
  4294  	++i;
  4295  
  4296  	for (int j = 0; j < size; ++j)
  4297  	{
  4298  		CGLTF_CHECK_KEY(tokens[i]);
  4299  
  4300  		if (cgltf_json_strcmp(tokens+i, json_chunk, "name") == 0)
  4301  		{
  4302  			i = cgltf_parse_json_string(options, tokens, i + 1, json_chunk, &out_material->name);
  4303  		}
  4304  		else if (cgltf_json_strcmp(tokens+i, json_chunk, "pbrMetallicRoughness") == 0)
  4305  		{
  4306  			out_material->has_pbr_metallic_roughness = 1;
  4307  			i = cgltf_parse_json_pbr_metallic_roughness(options, tokens, i + 1, json_chunk, &out_material->pbr_metallic_roughness);
  4308  		}
  4309  		else if (cgltf_json_strcmp(tokens+i, json_chunk, "emissiveFactor") == 0)
  4310  		{
  4311  			i = cgltf_parse_json_float_array(tokens, i + 1, json_chunk, out_material->emissive_factor, 3);
  4312  		}
  4313  		else if (cgltf_json_strcmp(tokens + i, json_chunk, "normalTexture") == 0)
  4314  		{
  4315  			i = cgltf_parse_json_texture_view(options, tokens, i + 1, json_chunk,
  4316  				&out_material->normal_texture);
  4317  		}
  4318  		else if (cgltf_json_strcmp(tokens + i, json_chunk, "occlusionTexture") == 0)
  4319  		{
  4320  			i = cgltf_parse_json_texture_view(options, tokens, i + 1, json_chunk,
  4321  				&out_material->occlusion_texture);
  4322  		}
  4323  		else if (cgltf_json_strcmp(tokens + i, json_chunk, "emissiveTexture") == 0)
  4324  		{
  4325  			i = cgltf_parse_json_texture_view(options, tokens, i + 1, json_chunk,
  4326  				&out_material->emissive_texture);
  4327  		}
  4328  		else if (cgltf_json_strcmp(tokens + i, json_chunk, "alphaMode") == 0)
  4329  		{
  4330  			++i;
  4331  			if (cgltf_json_strcmp(tokens + i, json_chunk, "OPAQUE") == 0)
  4332  			{
  4333  				out_material->alpha_mode = cgltf_alpha_mode_opaque;
  4334  			}
  4335  			else if (cgltf_json_strcmp(tokens + i, json_chunk, "MASK") == 0)
  4336  			{
  4337  				out_material->alpha_mode = cgltf_alpha_mode_mask;
  4338  			}
  4339  			else if (cgltf_json_strcmp(tokens + i, json_chunk, "BLEND") == 0)
  4340  			{
  4341  				out_material->alpha_mode = cgltf_alpha_mode_blend;
  4342  			}
  4343  			++i;
  4344  		}
  4345  		else if (cgltf_json_strcmp(tokens + i, json_chunk, "alphaCutoff") == 0)
  4346  		{
  4347  			++i;
  4348  			out_material->alpha_cutoff = cgltf_json_to_float(tokens + i, json_chunk);
  4349  			++i;
  4350  		}
  4351  		else if (cgltf_json_strcmp(tokens + i, json_chunk, "doubleSided") == 0)
  4352  		{
  4353  			++i;
  4354  			out_material->double_sided =
  4355  				cgltf_json_to_bool(tokens + i, json_chunk);
  4356  			++i;
  4357  		}
  4358  		else if (cgltf_json_strcmp(tokens + i, json_chunk, "extras") == 0)
  4359  		{
  4360  			i = cgltf_parse_json_extras(tokens, i + 1, json_chunk, &out_material->extras);
  4361  		}
  4362  		else if (cgltf_json_strcmp(tokens + i, json_chunk, "extensions") == 0)
  4363  		{
  4364  			++i;
  4365  
  4366  			CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
  4367  			if(out_material->extensions)
  4368  			{
  4369  				return CGLTF_ERROR_JSON;
  4370  			}
  4371  
  4372  			int extensions_size = tokens[i].size;
  4373  			++i;
  4374  			out_material->extensions = (cgltf_extension*)cgltf_calloc(options, sizeof(cgltf_extension), extensions_size);
  4375  			out_material->extensions_count= 0;
  4376  
  4377  			if (!out_material->extensions)
  4378  			{
  4379  				return CGLTF_ERROR_NOMEM;
  4380  			}
  4381  
  4382  			for (int k = 0; k < extensions_size; ++k)
  4383  			{
  4384  				CGLTF_CHECK_KEY(tokens[i]);
  4385  
  4386  				if (cgltf_json_strcmp(tokens+i, json_chunk, "KHR_materials_pbrSpecularGlossiness") == 0)
  4387  				{
  4388  					out_material->has_pbr_specular_glossiness = 1;
  4389  					i = cgltf_parse_json_pbr_specular_glossiness(options, tokens, i + 1, json_chunk, &out_material->pbr_specular_glossiness);
  4390  				}
  4391  				else if (cgltf_json_strcmp(tokens+i, json_chunk, "KHR_materials_unlit") == 0)
  4392  				{
  4393  					out_material->unlit = 1;
  4394  					i = cgltf_skip_json(tokens, i+1);
  4395  				}
  4396  				else if (cgltf_json_strcmp(tokens+i, json_chunk, "KHR_materials_clearcoat") == 0)
  4397  				{
  4398  					out_material->has_clearcoat = 1;
  4399  					i = cgltf_parse_json_clearcoat(options, tokens, i + 1, json_chunk, &out_material->clearcoat);
  4400  				}
  4401  				else if (cgltf_json_strcmp(tokens+i, json_chunk, "KHR_materials_ior") == 0)
  4402  				{
  4403  					out_material->has_ior = 1;
  4404  					i = cgltf_parse_json_ior(tokens, i + 1, json_chunk, &out_material->ior);
  4405  				}
  4406  				else if (cgltf_json_strcmp(tokens+i, json_chunk, "KHR_materials_specular") == 0)
  4407  				{
  4408  					out_material->has_specular = 1;
  4409  					i = cgltf_parse_json_specular(options, tokens, i + 1, json_chunk, &out_material->specular);
  4410  				}
  4411  				else if (cgltf_json_strcmp(tokens+i, json_chunk, "KHR_materials_transmission") == 0)
  4412  				{
  4413  					out_material->has_transmission = 1;
  4414  					i = cgltf_parse_json_transmission(options, tokens, i + 1, json_chunk, &out_material->transmission);
  4415  				}
  4416  				else if (cgltf_json_strcmp(tokens + i, json_chunk, "KHR_materials_volume") == 0)
  4417  				{
  4418  					out_material->has_volume = 1;
  4419  					i = cgltf_parse_json_volume(options, tokens, i + 1, json_chunk, &out_material->volume);
  4420  				}
  4421  				else if (cgltf_json_strcmp(tokens+i, json_chunk, "KHR_materials_sheen") == 0)
  4422  				{
  4423  					out_material->has_sheen = 1;
  4424  					i = cgltf_parse_json_sheen(options, tokens, i + 1, json_chunk, &out_material->sheen);
  4425  				}
  4426  				else if (cgltf_json_strcmp(tokens + i, json_chunk, "KHR_materials_emissive_strength") == 0)
  4427  				{
  4428  					out_material->has_emissive_strength = 1;
  4429  					i = cgltf_parse_json_emissive_strength(tokens, i + 1, json_chunk, &out_material->emissive_strength);
  4430  				}
  4431  				else if (cgltf_json_strcmp(tokens + i, json_chunk, "KHR_materials_iridescence") == 0)
  4432  				{
  4433  					out_material->has_iridescence = 1;
  4434  					i = cgltf_parse_json_iridescence(options, tokens, i + 1, json_chunk, &out_material->iridescence);
  4435  				}
  4436  				else
  4437  				{
  4438  					i = cgltf_parse_json_unprocessed_extension(options, tokens, i, json_chunk, &(out_material->extensions[out_material->extensions_count++]));
  4439  				}
  4440  
  4441  				if (i < 0)
  4442  				{
  4443  					return i;
  4444  				}
  4445  			}
  4446  		}
  4447  		else
  4448  		{
  4449  			i = cgltf_skip_json(tokens, i+1);
  4450  		}
  4451  
  4452  		if (i < 0)
  4453  		{
  4454  			return i;
  4455  		}
  4456  	}
  4457  
  4458  	return i;
  4459  }
  4460  
  4461  static int cgltf_parse_json_accessors(cgltf_options* options, jsmntok_t const* tokens, int i, const uint8_t* json_chunk, cgltf_data* out_data)
  4462  {
  4463  	i = cgltf_parse_json_array(options, tokens, i, json_chunk, sizeof(cgltf_accessor), (void**)&out_data->accessors, &out_data->accessors_count);
  4464  	if (i < 0)
  4465  	{
  4466  		return i;
  4467  	}
  4468  
  4469  	for (cgltf_size j = 0; j < out_data->accessors_count; ++j)
  4470  	{
  4471  		i = cgltf_parse_json_accessor(options, tokens, i, json_chunk, &out_data->accessors[j]);
  4472  		if (i < 0)
  4473  		{
  4474  			return i;
  4475  		}
  4476  	}
  4477  	return i;
  4478  }
  4479  
  4480  static int cgltf_parse_json_materials(cgltf_options* options, jsmntok_t const* tokens, int i, const uint8_t* json_chunk, cgltf_data* out_data)
  4481  {
  4482  	i = cgltf_parse_json_array(options, tokens, i, json_chunk, sizeof(cgltf_material), (void**)&out_data->materials, &out_data->materials_count);
  4483  	if (i < 0)
  4484  	{
  4485  		return i;
  4486  	}
  4487  
  4488  	for (cgltf_size j = 0; j < out_data->materials_count; ++j)
  4489  	{
  4490  		i = cgltf_parse_json_material(options, tokens, i, json_chunk, &out_data->materials[j]);
  4491  		if (i < 0)
  4492  		{
  4493  			return i;
  4494  		}
  4495  	}
  4496  	return i;
  4497  }
  4498  
  4499  static int cgltf_parse_json_images(cgltf_options* options, jsmntok_t const* tokens, int i, const uint8_t* json_chunk, cgltf_data* out_data)
  4500  {
  4501  	i = cgltf_parse_json_array(options, tokens, i, json_chunk, sizeof(cgltf_image), (void**)&out_data->images, &out_data->images_count);
  4502  	if (i < 0)
  4503  	{
  4504  		return i;
  4505  	}
  4506  
  4507  	for (cgltf_size j = 0; j < out_data->images_count; ++j)
  4508  	{
  4509  		i = cgltf_parse_json_image(options, tokens, i, json_chunk, &out_data->images[j]);
  4510  		if (i < 0)
  4511  		{
  4512  			return i;
  4513  		}
  4514  	}
  4515  	return i;
  4516  }
  4517  
  4518  static int cgltf_parse_json_textures(cgltf_options* options, jsmntok_t const* tokens, int i, const uint8_t* json_chunk, cgltf_data* out_data)
  4519  {
  4520  	i = cgltf_parse_json_array(options, tokens, i, json_chunk, sizeof(cgltf_texture), (void**)&out_data->textures, &out_data->textures_count);
  4521  	if (i < 0)
  4522  	{
  4523  		return i;
  4524  	}
  4525  
  4526  	for (cgltf_size j = 0; j < out_data->textures_count; ++j)
  4527  	{
  4528  		i = cgltf_parse_json_texture(options, tokens, i, json_chunk, &out_data->textures[j]);
  4529  		if (i < 0)
  4530  		{
  4531  			return i;
  4532  		}
  4533  	}
  4534  	return i;
  4535  }
  4536  
  4537  static int cgltf_parse_json_samplers(cgltf_options* options, jsmntok_t const* tokens, int i, const uint8_t* json_chunk, cgltf_data* out_data)
  4538  {
  4539  	i = cgltf_parse_json_array(options, tokens, i, json_chunk, sizeof(cgltf_sampler), (void**)&out_data->samplers, &out_data->samplers_count);
  4540  	if (i < 0)
  4541  	{
  4542  		return i;
  4543  	}
  4544  
  4545  	for (cgltf_size j = 0; j < out_data->samplers_count; ++j)
  4546  	{
  4547  		i = cgltf_parse_json_sampler(options, tokens, i, json_chunk, &out_data->samplers[j]);
  4548  		if (i < 0)
  4549  		{
  4550  			return i;
  4551  		}
  4552  	}
  4553  	return i;
  4554  }
  4555  
  4556  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)
  4557  {
  4558  	(void)options;
  4559  	CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
  4560  
  4561  	int size = tokens[i].size;
  4562  	++i;
  4563  
  4564  	for (int j = 0; j < size; ++j)
  4565  	{
  4566  		CGLTF_CHECK_KEY(tokens[i]);
  4567  
  4568  		if (cgltf_json_strcmp(tokens+i, json_chunk, "buffer") == 0)
  4569  		{
  4570  			++i;
  4571  			out_meshopt_compression->buffer = CGLTF_PTRINDEX(cgltf_buffer, cgltf_json_to_int(tokens + i, json_chunk));
  4572  			++i;
  4573  		}
  4574  		else if (cgltf_json_strcmp(tokens+i, json_chunk, "byteOffset") == 0)
  4575  		{
  4576  			++i;
  4577  			out_meshopt_compression->offset = cgltf_json_to_size(tokens+i, json_chunk);
  4578  			++i;
  4579  		}
  4580  		else if (cgltf_json_strcmp(tokens+i, json_chunk, "byteLength") == 0)
  4581  		{
  4582  			++i;
  4583  			out_meshopt_compression->size = cgltf_json_to_size(tokens+i, json_chunk);
  4584  			++i;
  4585  		}
  4586  		else if (cgltf_json_strcmp(tokens+i, json_chunk, "byteStride") == 0)
  4587  		{
  4588  			++i;
  4589  			out_meshopt_compression->stride = cgltf_json_to_size(tokens+i, json_chunk);
  4590  			++i;
  4591  		}
  4592  		else if (cgltf_json_strcmp(tokens+i, json_chunk, "count") == 0)
  4593  		{
  4594  			++i;
  4595  			out_meshopt_compression->count = cgltf_json_to_int(tokens+i, json_chunk);
  4596  			++i;
  4597  		}
  4598  		else if (cgltf_json_strcmp(tokens+i, json_chunk, "mode") == 0)
  4599  		{
  4600  			++i;
  4601  			if (cgltf_json_strcmp(tokens+i, json_chunk, "ATTRIBUTES") == 0)
  4602  			{
  4603  				out_meshopt_compression->mode = cgltf_meshopt_compression_mode_attributes;
  4604  			}
  4605  			else if (cgltf_json_strcmp(tokens+i, json_chunk, "TRIANGLES") == 0)
  4606  			{
  4607  				out_meshopt_compression->mode = cgltf_meshopt_compression_mode_triangles;
  4608  			}
  4609  			else if (cgltf_json_strcmp(tokens+i, json_chunk, "INDICES") == 0)
  4610  			{
  4611  				out_meshopt_compression->mode = cgltf_meshopt_compression_mode_indices;
  4612  			}
  4613  			++i;
  4614  		}
  4615  		else if (cgltf_json_strcmp(tokens+i, json_chunk, "filter") == 0)
  4616  		{
  4617  			++i;
  4618  			if (cgltf_json_strcmp(tokens+i, json_chunk, "NONE") == 0)
  4619  			{
  4620  				out_meshopt_compression->filter = cgltf_meshopt_compression_filter_none;
  4621  			}
  4622  			else if (cgltf_json_strcmp(tokens+i, json_chunk, "OCTAHEDRAL") == 0)
  4623  			{
  4624  				out_meshopt_compression->filter = cgltf_meshopt_compression_filter_octahedral;
  4625  			}
  4626  			else if (cgltf_json_strcmp(tokens+i, json_chunk, "QUATERNION") == 0)
  4627  			{
  4628  				out_meshopt_compression->filter = cgltf_meshopt_compression_filter_quaternion;
  4629  			}
  4630  			else if (cgltf_json_strcmp(tokens+i, json_chunk, "EXPONENTIAL") == 0)
  4631  			{
  4632  				out_meshopt_compression->filter = cgltf_meshopt_compression_filter_exponential;
  4633  			}
  4634  			++i;
  4635  		}
  4636  		else
  4637  		{
  4638  			i = cgltf_skip_json(tokens, i+1);
  4639  		}
  4640  
  4641  		if (i < 0)
  4642  		{
  4643  			return i;
  4644  		}
  4645  	}
  4646  
  4647  	return i;
  4648  }
  4649  
  4650  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)
  4651  {
  4652  	CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
  4653  
  4654  	int size = tokens[i].size;
  4655  	++i;
  4656  
  4657  	for (int j = 0; j < size; ++j)
  4658  	{
  4659  		CGLTF_CHECK_KEY(tokens[i]);
  4660  
  4661  		if (cgltf_json_strcmp(tokens + i, json_chunk, "name") == 0)
  4662  		{
  4663  			i = cgltf_parse_json_string(options, tokens, i + 1, json_chunk, &out_buffer_view->name);
  4664  		}
  4665  		else if (cgltf_json_strcmp(tokens+i, json_chunk, "buffer") == 0)
  4666  		{
  4667  			++i;
  4668  			out_buffer_view->buffer = CGLTF_PTRINDEX(cgltf_buffer, cgltf_json_to_int(tokens + i, json_chunk));
  4669  			++i;
  4670  		}
  4671  		else if (cgltf_json_strcmp(tokens+i, json_chunk, "byteOffset") == 0)
  4672  		{
  4673  			++i;
  4674  			out_buffer_view->offset =
  4675  					cgltf_json_to_size(tokens+i, json_chunk);
  4676  			++i;
  4677  		}
  4678  		else if (cgltf_json_strcmp(tokens+i, json_chunk, "byteLength") == 0)
  4679  		{
  4680  			++i;
  4681  			out_buffer_view->size =
  4682  					cgltf_json_to_size(tokens+i, json_chunk);
  4683  			++i;
  4684  		}
  4685  		else if (cgltf_json_strcmp(tokens+i, json_chunk, "byteStride") == 0)
  4686  		{
  4687  			++i;
  4688  			out_buffer_view->stride =
  4689  					cgltf_json_to_size(tokens+i, json_chunk);
  4690  			++i;
  4691  		}
  4692  		else if (cgltf_json_strcmp(tokens+i, json_chunk, "target") == 0)
  4693  		{
  4694  			++i;
  4695  			int type = cgltf_json_to_int(tokens+i, json_chunk);
  4696  			switch (type)
  4697  			{
  4698  			case 34962:
  4699  				type = cgltf_buffer_view_type_vertices;
  4700  				break;
  4701  			case 34963:
  4702  				type = cgltf_buffer_view_type_indices;
  4703  				break;
  4704  			default:
  4705  				type = cgltf_buffer_view_type_invalid;
  4706  				break;
  4707  			}
  4708  			out_buffer_view->type = (cgltf_buffer_view_type)type;
  4709  			++i;
  4710  		}
  4711  		else if (cgltf_json_strcmp(tokens + i, json_chunk, "extras") == 0)
  4712  		{
  4713  			i = cgltf_parse_json_extras(tokens, i + 1, json_chunk, &out_buffer_view->extras);
  4714  		}
  4715  		else if (cgltf_json_strcmp(tokens + i, json_chunk, "extensions") == 0)
  4716  		{
  4717  			++i;
  4718  
  4719  			CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
  4720  			if(out_buffer_view->extensions)
  4721  			{
  4722  				return CGLTF_ERROR_JSON;
  4723  			}
  4724  
  4725  			int extensions_size = tokens[i].size;
  4726  			out_buffer_view->extensions_count = 0;
  4727  			out_buffer_view->extensions = (cgltf_extension*)cgltf_calloc(options, sizeof(cgltf_extension), extensions_size);
  4728  
  4729  			if (!out_buffer_view->extensions)
  4730  			{
  4731  				return CGLTF_ERROR_NOMEM;
  4732  			}
  4733  
  4734  			++i;
  4735  			for (int k = 0; k < extensions_size; ++k)
  4736  			{
  4737  				CGLTF_CHECK_KEY(tokens[i]);
  4738  
  4739  				if (cgltf_json_strcmp(tokens+i, json_chunk, "EXT_meshopt_compression") == 0)
  4740  				{
  4741  					out_buffer_view->has_meshopt_compression = 1;
  4742  					i = cgltf_parse_json_meshopt_compression(options, tokens, i + 1, json_chunk, &out_buffer_view->meshopt_compression);
  4743  				}
  4744  				else
  4745  				{
  4746  					i = cgltf_parse_json_unprocessed_extension(options, tokens, i, json_chunk, &(out_buffer_view->extensions[out_buffer_view->extensions_count++]));
  4747  				}
  4748  
  4749  				if (i < 0)
  4750  				{
  4751  					return i;
  4752  				}
  4753  			}
  4754  		}
  4755  		else
  4756  		{
  4757  			i = cgltf_skip_json(tokens, i+1);
  4758  		}
  4759  
  4760  		if (i < 0)
  4761  		{
  4762  			return i;
  4763  		}
  4764  	}
  4765  
  4766  	return i;
  4767  }
  4768  
  4769  static int cgltf_parse_json_buffer_views(cgltf_options* options, jsmntok_t const* tokens, int i, const uint8_t* json_chunk, cgltf_data* out_data)
  4770  {
  4771  	i = cgltf_parse_json_array(options, tokens, i, json_chunk, sizeof(cgltf_buffer_view), (void**)&out_data->buffer_views, &out_data->buffer_views_count);
  4772  	if (i < 0)
  4773  	{
  4774  		return i;
  4775  	}
  4776  
  4777  	for (cgltf_size j = 0; j < out_data->buffer_views_count; ++j)
  4778  	{
  4779  		i = cgltf_parse_json_buffer_view(options, tokens, i, json_chunk, &out_data->buffer_views[j]);
  4780  		if (i < 0)
  4781  		{
  4782  			return i;
  4783  		}
  4784  	}
  4785  	return i;
  4786  }
  4787  
  4788  static int cgltf_parse_json_buffer(cgltf_options* options, jsmntok_t const* tokens, int i, const uint8_t* json_chunk, cgltf_buffer* out_buffer)
  4789  {
  4790  	CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
  4791  
  4792  	int size = tokens[i].size;
  4793  	++i;
  4794  
  4795  	for (int j = 0; j < size; ++j)
  4796  	{
  4797  		CGLTF_CHECK_KEY(tokens[i]);
  4798  
  4799  		if (cgltf_json_strcmp(tokens + i, json_chunk, "name") == 0)
  4800  		{
  4801  			i = cgltf_parse_json_string(options, tokens, i + 1, json_chunk, &out_buffer->name);
  4802  		}
  4803  		else if (cgltf_json_strcmp(tokens+i, json_chunk, "byteLength") == 0)
  4804  		{
  4805  			++i;
  4806  			out_buffer->size =
  4807  					cgltf_json_to_size(tokens+i, json_chunk);
  4808  			++i;
  4809  		}
  4810  		else if (cgltf_json_strcmp(tokens+i, json_chunk, "uri") == 0)
  4811  		{
  4812  			i = cgltf_parse_json_string(options, tokens, i + 1, json_chunk, &out_buffer->uri);
  4813  		}
  4814  		else if (cgltf_json_strcmp(tokens + i, json_chunk, "extras") == 0)
  4815  		{
  4816  			i = cgltf_parse_json_extras(tokens, i + 1, json_chunk, &out_buffer->extras);
  4817  		}
  4818  		else if (cgltf_json_strcmp(tokens + i, json_chunk, "extensions") == 0)
  4819  		{
  4820  			i = cgltf_parse_json_unprocessed_extensions(options, tokens, i, json_chunk, &out_buffer->extensions_count, &out_buffer->extensions);
  4821  		}
  4822  		else
  4823  		{
  4824  			i = cgltf_skip_json(tokens, i+1);
  4825  		}
  4826  
  4827  		if (i < 0)
  4828  		{
  4829  			return i;
  4830  		}
  4831  	}
  4832  
  4833  	return i;
  4834  }
  4835  
  4836  static int cgltf_parse_json_buffers(cgltf_options* options, jsmntok_t const* tokens, int i, const uint8_t* json_chunk, cgltf_data* out_data)
  4837  {
  4838  	i = cgltf_parse_json_array(options, tokens, i, json_chunk, sizeof(cgltf_buffer), (void**)&out_data->buffers, &out_data->buffers_count);
  4839  	if (i < 0)
  4840  	{
  4841  		return i;
  4842  	}
  4843  
  4844  	for (cgltf_size j = 0; j < out_data->buffers_count; ++j)
  4845  	{
  4846  		i = cgltf_parse_json_buffer(options, tokens, i, json_chunk, &out_data->buffers[j]);
  4847  		if (i < 0)
  4848  		{
  4849  			return i;
  4850  		}
  4851  	}
  4852  	return i;
  4853  }
  4854  
  4855  static int cgltf_parse_json_skin(cgltf_options* options, jsmntok_t const* tokens, int i, const uint8_t* json_chunk, cgltf_skin* out_skin)
  4856  {
  4857  	CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
  4858  
  4859  	int size = tokens[i].size;
  4860  	++i;
  4861  
  4862  	for (int j = 0; j < size; ++j)
  4863  	{
  4864  		CGLTF_CHECK_KEY(tokens[i]);
  4865  
  4866  		if (cgltf_json_strcmp(tokens+i, json_chunk, "name") == 0)
  4867  		{
  4868  			i = cgltf_parse_json_string(options, tokens, i + 1, json_chunk, &out_skin->name);
  4869  		}
  4870  		else if (cgltf_json_strcmp(tokens+i, json_chunk, "joints") == 0)
  4871  		{
  4872  			i = cgltf_parse_json_array(options, tokens, i + 1, json_chunk, sizeof(cgltf_node*), (void**)&out_skin->joints, &out_skin->joints_count);
  4873  			if (i < 0)
  4874  			{
  4875  				return i;
  4876  			}
  4877  
  4878  			for (cgltf_size k = 0; k < out_skin->joints_count; ++k)
  4879  			{
  4880  				out_skin->joints[k] = CGLTF_PTRINDEX(cgltf_node, cgltf_json_to_int(tokens + i, json_chunk));
  4881  				++i;
  4882  			}
  4883  		}
  4884  		else if (cgltf_json_strcmp(tokens+i, json_chunk, "skeleton") == 0)
  4885  		{
  4886  			++i;
  4887  			CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_PRIMITIVE);
  4888  			out_skin->skeleton = CGLTF_PTRINDEX(cgltf_node, cgltf_json_to_int(tokens + i, json_chunk));
  4889  			++i;
  4890  		}
  4891  		else if (cgltf_json_strcmp(tokens+i, json_chunk, "inverseBindMatrices") == 0)
  4892  		{
  4893  			++i;
  4894  			CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_PRIMITIVE);
  4895  			out_skin->inverse_bind_matrices = CGLTF_PTRINDEX(cgltf_accessor, cgltf_json_to_int(tokens + i, json_chunk));
  4896  			++i;
  4897  		}
  4898  		else if (cgltf_json_strcmp(tokens + i, json_chunk, "extras") == 0)
  4899  		{
  4900  			i = cgltf_parse_json_extras(tokens, i + 1, json_chunk, &out_skin->extras);
  4901  		}
  4902  		else if (cgltf_json_strcmp(tokens + i, json_chunk, "extensions") == 0)
  4903  		{
  4904  			i = cgltf_parse_json_unprocessed_extensions(options, tokens, i, json_chunk, &out_skin->extensions_count, &out_skin->extensions);
  4905  		}
  4906  		else
  4907  		{
  4908  			i = cgltf_skip_json(tokens, i+1);
  4909  		}
  4910  
  4911  		if (i < 0)
  4912  		{
  4913  			return i;
  4914  		}
  4915  	}
  4916  
  4917  	return i;
  4918  }
  4919  
  4920  static int cgltf_parse_json_skins(cgltf_options* options, jsmntok_t const* tokens, int i, const uint8_t* json_chunk, cgltf_data* out_data)
  4921  {
  4922  	i = cgltf_parse_json_array(options, tokens, i, json_chunk, sizeof(cgltf_skin), (void**)&out_data->skins, &out_data->skins_count);
  4923  	if (i < 0)
  4924  	{
  4925  		return i;
  4926  	}
  4927  
  4928  	for (cgltf_size j = 0; j < out_data->skins_count; ++j)
  4929  	{
  4930  		i = cgltf_parse_json_skin(options, tokens, i, json_chunk, &out_data->skins[j]);
  4931  		if (i < 0)
  4932  		{
  4933  			return i;
  4934  		}
  4935  	}
  4936  	return i;
  4937  }
  4938  
  4939  static int cgltf_parse_json_camera(cgltf_options* options, jsmntok_t const* tokens, int i, const uint8_t* json_chunk, cgltf_camera* out_camera)
  4940  {
  4941  	CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
  4942  
  4943  	int size = tokens[i].size;
  4944  	++i;
  4945  
  4946  	for (int j = 0; j < size; ++j)
  4947  	{
  4948  		CGLTF_CHECK_KEY(tokens[i]);
  4949  
  4950  		if (cgltf_json_strcmp(tokens+i, json_chunk, "name") == 0)
  4951  		{
  4952  			i = cgltf_parse_json_string(options, tokens, i + 1, json_chunk, &out_camera->name);
  4953  		}
  4954  		else if (cgltf_json_strcmp(tokens+i, json_chunk, "type") == 0)
  4955  		{
  4956  			++i;
  4957  			if (cgltf_json_strcmp(tokens + i, json_chunk, "perspective") == 0)
  4958  			{
  4959  				out_camera->type = cgltf_camera_type_perspective;
  4960  			}
  4961  			else if (cgltf_json_strcmp(tokens + i, json_chunk, "orthographic") == 0)
  4962  			{
  4963  				out_camera->type = cgltf_camera_type_orthographic;
  4964  			}
  4965  			++i;
  4966  		}
  4967  		else if (cgltf_json_strcmp(tokens+i, json_chunk, "perspective") == 0)
  4968  		{
  4969  			++i;
  4970  
  4971  			CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
  4972  
  4973  			int data_size = tokens[i].size;
  4974  			++i;
  4975  
  4976  			out_camera->type = cgltf_camera_type_perspective;
  4977  
  4978  			for (int k = 0; k < data_size; ++k)
  4979  			{
  4980  				CGLTF_CHECK_KEY(tokens[i]);
  4981  
  4982  				if (cgltf_json_strcmp(tokens+i, json_chunk, "aspectRatio") == 0)
  4983  				{
  4984  					++i;
  4985  					out_camera->data.perspective.has_aspect_ratio = 1;
  4986  					out_camera->data.perspective.aspect_ratio = cgltf_json_to_float(tokens + i, json_chunk);
  4987  					++i;
  4988  				}
  4989  				else if (cgltf_json_strcmp(tokens+i, json_chunk, "yfov") == 0)
  4990  				{
  4991  					++i;
  4992  					out_camera->data.perspective.yfov = cgltf_json_to_float(tokens + i, json_chunk);
  4993  					++i;
  4994  				}
  4995  				else if (cgltf_json_strcmp(tokens+i, json_chunk, "zfar") == 0)
  4996  				{
  4997  					++i;
  4998  					out_camera->data.perspective.has_zfar = 1;
  4999  					out_camera->data.perspective.zfar = cgltf_json_to_float(tokens + i, json_chunk);
  5000  					++i;
  5001  				}
  5002  				else if (cgltf_json_strcmp(tokens+i, json_chunk, "znear") == 0)
  5003  				{
  5004  					++i;
  5005  					out_camera->data.perspective.znear = cgltf_json_to_float(tokens + i, json_chunk);
  5006  					++i;
  5007  				}
  5008  				else if (cgltf_json_strcmp(tokens + i, json_chunk, "extras") == 0)
  5009  				{
  5010  					i = cgltf_parse_json_extras(tokens, i + 1, json_chunk, &out_camera->data.perspective.extras);
  5011  				}
  5012  				else
  5013  				{
  5014  					i = cgltf_skip_json(tokens, i+1);
  5015  				}
  5016  
  5017  				if (i < 0)
  5018  				{
  5019  					return i;
  5020  				}
  5021  			}
  5022  		}
  5023  		else if (cgltf_json_strcmp(tokens+i, json_chunk, "orthographic") == 0)
  5024  		{
  5025  			++i;
  5026  
  5027  			CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
  5028  
  5029  			int data_size = tokens[i].size;
  5030  			++i;
  5031  
  5032  			out_camera->type = cgltf_camera_type_orthographic;
  5033  
  5034  			for (int k = 0; k < data_size; ++k)
  5035  			{
  5036  				CGLTF_CHECK_KEY(tokens[i]);
  5037  
  5038  				if (cgltf_json_strcmp(tokens+i, json_chunk, "xmag") == 0)
  5039  				{
  5040  					++i;
  5041  					out_camera->data.orthographic.xmag = cgltf_json_to_float(tokens + i, json_chunk);
  5042  					++i;
  5043  				}
  5044  				else if (cgltf_json_strcmp(tokens+i, json_chunk, "ymag") == 0)
  5045  				{
  5046  					++i;
  5047  					out_camera->data.orthographic.ymag = cgltf_json_to_float(tokens + i, json_chunk);
  5048  					++i;
  5049  				}
  5050  				else if (cgltf_json_strcmp(tokens+i, json_chunk, "zfar") == 0)
  5051  				{
  5052  					++i;
  5053  					out_camera->data.orthographic.zfar = cgltf_json_to_float(tokens + i, json_chunk);
  5054  					++i;
  5055  				}
  5056  				else if (cgltf_json_strcmp(tokens+i, json_chunk, "znear") == 0)
  5057  				{
  5058  					++i;
  5059  					out_camera->data.orthographic.znear = cgltf_json_to_float(tokens + i, json_chunk);
  5060  					++i;
  5061  				}
  5062  				else if (cgltf_json_strcmp(tokens + i, json_chunk, "extras") == 0)
  5063  				{
  5064  					i = cgltf_parse_json_extras(tokens, i + 1, json_chunk, &out_camera->data.orthographic.extras);
  5065  				}
  5066  				else
  5067  				{
  5068  					i = cgltf_skip_json(tokens, i+1);
  5069  				}
  5070  
  5071  				if (i < 0)
  5072  				{
  5073  					return i;
  5074  				}
  5075  			}
  5076  		}
  5077  		else if (cgltf_json_strcmp(tokens + i, json_chunk, "extras") == 0)
  5078  		{
  5079  			i = cgltf_parse_json_extras(tokens, i + 1, json_chunk, &out_camera->extras);
  5080  		}
  5081  		else if (cgltf_json_strcmp(tokens + i, json_chunk, "extensions") == 0)
  5082  		{
  5083  			i = cgltf_parse_json_unprocessed_extensions(options, tokens, i, json_chunk, &out_camera->extensions_count, &out_camera->extensions);
  5084  		}
  5085  		else
  5086  		{
  5087  			i = cgltf_skip_json(tokens, i+1);
  5088  		}
  5089  
  5090  		if (i < 0)
  5091  		{
  5092  			return i;
  5093  		}
  5094  	}
  5095  
  5096  	return i;
  5097  }
  5098  
  5099  static int cgltf_parse_json_cameras(cgltf_options* options, jsmntok_t const* tokens, int i, const uint8_t* json_chunk, cgltf_data* out_data)
  5100  {
  5101  	i = cgltf_parse_json_array(options, tokens, i, json_chunk, sizeof(cgltf_camera), (void**)&out_data->cameras, &out_data->cameras_count);
  5102  	if (i < 0)
  5103  	{
  5104  		return i;
  5105  	}
  5106  
  5107  	for (cgltf_size j = 0; j < out_data->cameras_count; ++j)
  5108  	{
  5109  		i = cgltf_parse_json_camera(options, tokens, i, json_chunk, &out_data->cameras[j]);
  5110  		if (i < 0)
  5111  		{
  5112  			return i;
  5113  		}
  5114  	}
  5115  	return i;
  5116  }
  5117  
  5118  static int cgltf_parse_json_light(cgltf_options* options, jsmntok_t const* tokens, int i, const uint8_t* json_chunk, cgltf_light* out_light)
  5119  {
  5120  	CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
  5121  
  5122  	out_light->color[0] = 1.f;
  5123  	out_light->color[1] = 1.f;
  5124  	out_light->color[2] = 1.f;
  5125  	out_light->intensity = 1.f;
  5126  
  5127  	out_light->spot_inner_cone_angle = 0.f;
  5128  	out_light->spot_outer_cone_angle = 3.1415926535f / 4.0f;
  5129  
  5130  	int size = tokens[i].size;
  5131  	++i;
  5132  
  5133  	for (int j = 0; j < size; ++j)
  5134  	{
  5135  		CGLTF_CHECK_KEY(tokens[i]);
  5136  
  5137  		if (cgltf_json_strcmp(tokens+i, json_chunk, "name") == 0)
  5138  		{
  5139  			i = cgltf_parse_json_string(options, tokens, i + 1, json_chunk, &out_light->name);
  5140  		}
  5141  		else if (cgltf_json_strcmp(tokens + i, json_chunk, "color") == 0)
  5142  		{
  5143  			i = cgltf_parse_json_float_array(tokens, i + 1, json_chunk, out_light->color, 3);
  5144  		}
  5145  		else if (cgltf_json_strcmp(tokens + i, json_chunk, "intensity") == 0)
  5146  		{
  5147  			++i;
  5148  			out_light->intensity = cgltf_json_to_float(tokens + i, json_chunk);
  5149  			++i;
  5150  		}
  5151  		else if (cgltf_json_strcmp(tokens+i, json_chunk, "type") == 0)
  5152  		{
  5153  			++i;
  5154  			if (cgltf_json_strcmp(tokens + i, json_chunk, "directional") == 0)
  5155  			{
  5156  				out_light->type = cgltf_light_type_directional;
  5157  			}
  5158  			else if (cgltf_json_strcmp(tokens + i, json_chunk, "point") == 0)
  5159  			{
  5160  				out_light->type = cgltf_light_type_point;
  5161  			}
  5162  			else if (cgltf_json_strcmp(tokens + i, json_chunk, "spot") == 0)
  5163  			{
  5164  				out_light->type = cgltf_light_type_spot;
  5165  			}
  5166  			++i;
  5167  		}
  5168  		else if (cgltf_json_strcmp(tokens + i, json_chunk, "range") == 0)
  5169  		{
  5170  			++i;
  5171  			out_light->range = cgltf_json_to_float(tokens + i, json_chunk);
  5172  			++i;
  5173  		}
  5174  		else if (cgltf_json_strcmp(tokens+i, json_chunk, "spot") == 0)
  5175  		{
  5176  			++i;
  5177  
  5178  			CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
  5179  
  5180  			int data_size = tokens[i].size;
  5181  			++i;
  5182  
  5183  			for (int k = 0; k < data_size; ++k)
  5184  			{
  5185  				CGLTF_CHECK_KEY(tokens[i]);
  5186  
  5187  				if (cgltf_json_strcmp(tokens+i, json_chunk, "innerConeAngle") == 0)
  5188  				{
  5189  					++i;
  5190  					out_light->spot_inner_cone_angle = cgltf_json_to_float(tokens + i, json_chunk);
  5191  					++i;
  5192  				}
  5193  				else if (cgltf_json_strcmp(tokens+i, json_chunk, "outerConeAngle") == 0)
  5194  				{
  5195  					++i;
  5196  					out_light->spot_outer_cone_angle = cgltf_json_to_float(tokens + i, json_chunk);
  5197  					++i;
  5198  				}
  5199  				else
  5200  				{
  5201  					i = cgltf_skip_json(tokens, i+1);
  5202  				}
  5203  
  5204  				if (i < 0)
  5205  				{
  5206  					return i;
  5207  				}
  5208  			}
  5209  		}
  5210  		else if (cgltf_json_strcmp(tokens + i, json_chunk, "extras") == 0)
  5211  		{
  5212  			i = cgltf_parse_json_extras(tokens, i + 1, json_chunk, &out_light->extras);
  5213  		}
  5214  		else
  5215  		{
  5216  			i = cgltf_skip_json(tokens, i+1);
  5217  		}
  5218  
  5219  		if (i < 0)
  5220  		{
  5221  			return i;
  5222  		}
  5223  	}
  5224  
  5225  	return i;
  5226  }
  5227  
  5228  static int cgltf_parse_json_lights(cgltf_options* options, jsmntok_t const* tokens, int i, const uint8_t* json_chunk, cgltf_data* out_data)
  5229  {
  5230  	i = cgltf_parse_json_array(options, tokens, i, json_chunk, sizeof(cgltf_light), (void**)&out_data->lights, &out_data->lights_count);
  5231  	if (i < 0)
  5232  	{
  5233  		return i;
  5234  	}
  5235  
  5236  	for (cgltf_size j = 0; j < out_data->lights_count; ++j)
  5237  	{
  5238  		i = cgltf_parse_json_light(options, tokens, i, json_chunk, &out_data->lights[j]);
  5239  		if (i < 0)
  5240  		{
  5241  			return i;
  5242  		}
  5243  	}
  5244  	return i;
  5245  }
  5246  
  5247  static int cgltf_parse_json_node(cgltf_options* options, jsmntok_t const* tokens, int i, const uint8_t* json_chunk, cgltf_node* out_node)
  5248  {
  5249  	CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
  5250  
  5251  	out_node->rotation[3] = 1.0f;
  5252  	out_node->scale[0] = 1.0f;
  5253  	out_node->scale[1] = 1.0f;
  5254  	out_node->scale[2] = 1.0f;
  5255  	out_node->matrix[0] = 1.0f;
  5256  	out_node->matrix[5] = 1.0f;
  5257  	out_node->matrix[10] = 1.0f;
  5258  	out_node->matrix[15] = 1.0f;
  5259  
  5260  	int size = tokens[i].size;
  5261  	++i;
  5262  
  5263  	for (int j = 0; j < size; ++j)
  5264  	{
  5265  		CGLTF_CHECK_KEY(tokens[i]);
  5266  
  5267  		if (cgltf_json_strcmp(tokens+i, json_chunk, "name") == 0)
  5268  		{
  5269  			i = cgltf_parse_json_string(options, tokens, i + 1, json_chunk, &out_node->name);
  5270  		}
  5271  		else if (cgltf_json_strcmp(tokens+i, json_chunk, "children") == 0)
  5272  		{
  5273  			i = cgltf_parse_json_array(options, tokens, i + 1, json_chunk, sizeof(cgltf_node*), (void**)&out_node->children, &out_node->children_count);
  5274  			if (i < 0)
  5275  			{
  5276  				return i;
  5277  			}
  5278  
  5279  			for (cgltf_size k = 0; k < out_node->children_count; ++k)
  5280  			{
  5281  				out_node->children[k] = CGLTF_PTRINDEX(cgltf_node, cgltf_json_to_int(tokens + i, json_chunk));
  5282  				++i;
  5283  			}
  5284  		}
  5285  		else if (cgltf_json_strcmp(tokens+i, json_chunk, "mesh") == 0)
  5286  		{
  5287  			++i;
  5288  			CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_PRIMITIVE);
  5289  			out_node->mesh = CGLTF_PTRINDEX(cgltf_mesh, cgltf_json_to_int(tokens + i, json_chunk));
  5290  			++i;
  5291  		}
  5292  		else if (cgltf_json_strcmp(tokens+i, json_chunk, "skin") == 0)
  5293  		{
  5294  			++i;
  5295  			CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_PRIMITIVE);
  5296  			out_node->skin = CGLTF_PTRINDEX(cgltf_skin, cgltf_json_to_int(tokens + i, json_chunk));
  5297  			++i;
  5298  		}
  5299  		else if (cgltf_json_strcmp(tokens+i, json_chunk, "camera") == 0)
  5300  		{
  5301  			++i;
  5302  			CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_PRIMITIVE);
  5303  			out_node->camera = CGLTF_PTRINDEX(cgltf_camera, cgltf_json_to_int(tokens + i, json_chunk));
  5304  			++i;
  5305  		}
  5306  		else if (cgltf_json_strcmp(tokens+i, json_chunk, "translation") == 0)
  5307  		{
  5308  			out_node->has_translation = 1;
  5309  			i = cgltf_parse_json_float_array(tokens, i + 1, json_chunk, out_node->translation, 3);
  5310  		}
  5311  		else if (cgltf_json_strcmp(tokens+i, json_chunk, "rotation") == 0)
  5312  		{
  5313  			out_node->has_rotation = 1;
  5314  			i = cgltf_parse_json_float_array(tokens, i + 1, json_chunk, out_node->rotation, 4);
  5315  		}
  5316  		else if (cgltf_json_strcmp(tokens+i, json_chunk, "scale") == 0)
  5317  		{
  5318  			out_node->has_scale = 1;
  5319  			i = cgltf_parse_json_float_array(tokens, i + 1, json_chunk, out_node->scale, 3);
  5320  		}
  5321  		else if (cgltf_json_strcmp(tokens+i, json_chunk, "matrix") == 0)
  5322  		{
  5323  			out_node->has_matrix = 1;
  5324  			i = cgltf_parse_json_float_array(tokens, i + 1, json_chunk, out_node->matrix, 16);
  5325  		}
  5326  		else if (cgltf_json_strcmp(tokens + i, json_chunk, "weights") == 0)
  5327  		{
  5328  			i = cgltf_parse_json_array(options, tokens, i + 1, json_chunk, sizeof(cgltf_float), (void**)&out_node->weights, &out_node->weights_count);
  5329  			if (i < 0)
  5330  			{
  5331  				return i;
  5332  			}
  5333  
  5334  			i = cgltf_parse_json_float_array(tokens, i - 1, json_chunk, out_node->weights, (int)out_node->weights_count);
  5335  		}
  5336  		else if (cgltf_json_strcmp(tokens + i, json_chunk, "extras") == 0)
  5337  		{
  5338  			i = cgltf_parse_json_extras(tokens, i + 1, json_chunk, &out_node->extras);
  5339  		}
  5340  		else if (cgltf_json_strcmp(tokens + i, json_chunk, "extensions") == 0)
  5341  		{
  5342  			++i;
  5343  
  5344  			CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
  5345  			if(out_node->extensions)
  5346  			{
  5347  				return CGLTF_ERROR_JSON;
  5348  			}
  5349  
  5350  			int extensions_size = tokens[i].size;
  5351  			out_node->extensions_count= 0;
  5352  			out_node->extensions = (cgltf_extension*)cgltf_calloc(options, sizeof(cgltf_extension), extensions_size);
  5353  
  5354  			if (!out_node->extensions)
  5355  			{
  5356  				return CGLTF_ERROR_NOMEM;
  5357  			}
  5358  
  5359  			++i;
  5360  
  5361  			for (int k = 0; k < extensions_size; ++k)
  5362  			{
  5363  				CGLTF_CHECK_KEY(tokens[i]);
  5364  
  5365  				if (cgltf_json_strcmp(tokens+i, json_chunk, "KHR_lights_punctual") == 0)
  5366  				{
  5367  					++i;
  5368  
  5369  					CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
  5370  
  5371  					int data_size = tokens[i].size;
  5372  					++i;
  5373  
  5374  					for (int m = 0; m < data_size; ++m)
  5375  					{
  5376  						CGLTF_CHECK_KEY(tokens[i]);
  5377  
  5378  						if (cgltf_json_strcmp(tokens + i, json_chunk, "light") == 0)
  5379  						{
  5380  							++i;
  5381  							CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_PRIMITIVE);
  5382  							out_node->light = CGLTF_PTRINDEX(cgltf_light, cgltf_json_to_int(tokens + i, json_chunk));
  5383  							++i;
  5384  						}
  5385  						else
  5386  						{
  5387  							i = cgltf_skip_json(tokens, i + 1);
  5388  						}
  5389  
  5390  						if (i < 0)
  5391  						{
  5392  							return i;
  5393  						}
  5394  					}
  5395  				}
  5396  				else if (cgltf_json_strcmp(tokens + i, json_chunk, "EXT_mesh_gpu_instancing") == 0)
  5397  				{
  5398  					out_node->has_mesh_gpu_instancing = 1;
  5399  					i = cgltf_parse_json_mesh_gpu_instancing(options, tokens, i + 1, json_chunk, &out_node->mesh_gpu_instancing);
  5400  				}
  5401  				else
  5402  				{
  5403  					i = cgltf_parse_json_unprocessed_extension(options, tokens, i, json_chunk, &(out_node->extensions[out_node->extensions_count++]));
  5404  				}
  5405  
  5406  				if (i < 0)
  5407  				{
  5408  					return i;
  5409  				}
  5410  			}
  5411  		}
  5412  		else
  5413  		{
  5414  			i = cgltf_skip_json(tokens, i+1);
  5415  		}
  5416  
  5417  		if (i < 0)
  5418  		{
  5419  			return i;
  5420  		}
  5421  	}
  5422  
  5423  	return i;
  5424  }
  5425  
  5426  static int cgltf_parse_json_nodes(cgltf_options* options, jsmntok_t const* tokens, int i, const uint8_t* json_chunk, cgltf_data* out_data)
  5427  {
  5428  	i = cgltf_parse_json_array(options, tokens, i, json_chunk, sizeof(cgltf_node), (void**)&out_data->nodes, &out_data->nodes_count);
  5429  	if (i < 0)
  5430  	{
  5431  		return i;
  5432  	}
  5433  
  5434  	for (cgltf_size j = 0; j < out_data->nodes_count; ++j)
  5435  	{
  5436  		i = cgltf_parse_json_node(options, tokens, i, json_chunk, &out_data->nodes[j]);
  5437  		if (i < 0)
  5438  		{
  5439  			return i;
  5440  		}
  5441  	}
  5442  	return i;
  5443  }
  5444  
  5445  static int cgltf_parse_json_scene(cgltf_options* options, jsmntok_t const* tokens, int i, const uint8_t* json_chunk, cgltf_scene* out_scene)
  5446  {
  5447  	CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
  5448  
  5449  	int size = tokens[i].size;
  5450  	++i;
  5451  
  5452  	for (int j = 0; j < size; ++j)
  5453  	{
  5454  		CGLTF_CHECK_KEY(tokens[i]);
  5455  
  5456  		if (cgltf_json_strcmp(tokens+i, json_chunk, "name") == 0)
  5457  		{
  5458  			i = cgltf_parse_json_string(options, tokens, i + 1, json_chunk, &out_scene->name);
  5459  		}
  5460  		else if (cgltf_json_strcmp(tokens+i, json_chunk, "nodes") == 0)
  5461  		{
  5462  			i = cgltf_parse_json_array(options, tokens, i + 1, json_chunk, sizeof(cgltf_node*), (void**)&out_scene->nodes, &out_scene->nodes_count);
  5463  			if (i < 0)
  5464  			{
  5465  				return i;
  5466  			}
  5467  
  5468  			for (cgltf_size k = 0; k < out_scene->nodes_count; ++k)
  5469  			{
  5470  				out_scene->nodes[k] = CGLTF_PTRINDEX(cgltf_node, cgltf_json_to_int(tokens + i, json_chunk));
  5471  				++i;
  5472  			}
  5473  		}
  5474  		else if (cgltf_json_strcmp(tokens + i, json_chunk, "extras") == 0)
  5475  		{
  5476  			i = cgltf_parse_json_extras(tokens, i + 1, json_chunk, &out_scene->extras);
  5477  		}
  5478  		else if (cgltf_json_strcmp(tokens + i, json_chunk, "extensions") == 0)
  5479  		{
  5480  			i = cgltf_parse_json_unprocessed_extensions(options, tokens, i, json_chunk, &out_scene->extensions_count, &out_scene->extensions);
  5481  		}
  5482  		else
  5483  		{
  5484  			i = cgltf_skip_json(tokens, i+1);
  5485  		}
  5486  
  5487  		if (i < 0)
  5488  		{
  5489  			return i;
  5490  		}
  5491  	}
  5492  
  5493  	return i;
  5494  }
  5495  
  5496  static int cgltf_parse_json_scenes(cgltf_options* options, jsmntok_t const* tokens, int i, const uint8_t* json_chunk, cgltf_data* out_data)
  5497  {
  5498  	i = cgltf_parse_json_array(options, tokens, i, json_chunk, sizeof(cgltf_scene), (void**)&out_data->scenes, &out_data->scenes_count);
  5499  	if (i < 0)
  5500  	{
  5501  		return i;
  5502  	}
  5503  
  5504  	for (cgltf_size j = 0; j < out_data->scenes_count; ++j)
  5505  	{
  5506  		i = cgltf_parse_json_scene(options, tokens, i, json_chunk, &out_data->scenes[j]);
  5507  		if (i < 0)
  5508  		{
  5509  			return i;
  5510  		}
  5511  	}
  5512  	return i;
  5513  }
  5514  
  5515  static int cgltf_parse_json_animation_sampler(cgltf_options* options, jsmntok_t const* tokens, int i, const uint8_t* json_chunk, cgltf_animation_sampler* out_sampler)
  5516  {
  5517  	(void)options;
  5518  	CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
  5519  
  5520  	int size = tokens[i].size;
  5521  	++i;
  5522  
  5523  	for (int j = 0; j < size; ++j)
  5524  	{
  5525  		CGLTF_CHECK_KEY(tokens[i]);
  5526  
  5527  		if (cgltf_json_strcmp(tokens+i, json_chunk, "input") == 0)
  5528  		{
  5529  			++i;
  5530  			out_sampler->input = CGLTF_PTRINDEX(cgltf_accessor, cgltf_json_to_int(tokens + i, json_chunk));
  5531  			++i;
  5532  		}
  5533  		else if (cgltf_json_strcmp(tokens+i, json_chunk, "output") == 0)
  5534  		{
  5535  			++i;
  5536  			out_sampler->output = CGLTF_PTRINDEX(cgltf_accessor, cgltf_json_to_int(tokens + i, json_chunk));
  5537  			++i;
  5538  		}
  5539  		else if (cgltf_json_strcmp(tokens+i, json_chunk, "interpolation") == 0)
  5540  		{
  5541  			++i;
  5542  			if (cgltf_json_strcmp(tokens + i, json_chunk, "LINEAR") == 0)
  5543  			{
  5544  				out_sampler->interpolation = cgltf_interpolation_type_linear;
  5545  			}
  5546  			else if (cgltf_json_strcmp(tokens + i, json_chunk, "STEP") == 0)
  5547  			{
  5548  				out_sampler->interpolation = cgltf_interpolation_type_step;
  5549  			}
  5550  			else if (cgltf_json_strcmp(tokens + i, json_chunk, "CUBICSPLINE") == 0)
  5551  			{
  5552  				out_sampler->interpolation = cgltf_interpolation_type_cubic_spline;
  5553  			}
  5554  			++i;
  5555  		}
  5556  		else if (cgltf_json_strcmp(tokens + i, json_chunk, "extras") == 0)
  5557  		{
  5558  			i = cgltf_parse_json_extras(tokens, i + 1, json_chunk, &out_sampler->extras);
  5559  		}
  5560  		else if (cgltf_json_strcmp(tokens + i, json_chunk, "extensions") == 0)
  5561  		{
  5562  			i = cgltf_parse_json_unprocessed_extensions(options, tokens, i, json_chunk, &out_sampler->extensions_count, &out_sampler->extensions);
  5563  		}
  5564  		else
  5565  		{
  5566  			i = cgltf_skip_json(tokens, i+1);
  5567  		}
  5568  
  5569  		if (i < 0)
  5570  		{
  5571  			return i;
  5572  		}
  5573  	}
  5574  
  5575  	return i;
  5576  }
  5577  
  5578  static int cgltf_parse_json_animation_channel(cgltf_options* options, jsmntok_t const* tokens, int i, const uint8_t* json_chunk, cgltf_animation_channel* out_channel)
  5579  {
  5580  	(void)options;
  5581  	CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
  5582  
  5583  	int size = tokens[i].size;
  5584  	++i;
  5585  
  5586  	for (int j = 0; j < size; ++j)
  5587  	{
  5588  		CGLTF_CHECK_KEY(tokens[i]);
  5589  
  5590  		if (cgltf_json_strcmp(tokens+i, json_chunk, "sampler") == 0)
  5591  		{
  5592  			++i;
  5593  			out_channel->sampler = CGLTF_PTRINDEX(cgltf_animation_sampler, cgltf_json_to_int(tokens + i, json_chunk));
  5594  			++i;
  5595  		}
  5596  		else if (cgltf_json_strcmp(tokens+i, json_chunk, "target") == 0)
  5597  		{
  5598  			++i;
  5599  
  5600  			CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
  5601  
  5602  			int target_size = tokens[i].size;
  5603  			++i;
  5604  
  5605  			for (int k = 0; k < target_size; ++k)
  5606  			{
  5607  				CGLTF_CHECK_KEY(tokens[i]);
  5608  
  5609  				if (cgltf_json_strcmp(tokens+i, json_chunk, "node") == 0)
  5610  				{
  5611  					++i;
  5612  					out_channel->target_node = CGLTF_PTRINDEX(cgltf_node, cgltf_json_to_int(tokens + i, json_chunk));
  5613  					++i;
  5614  				}
  5615  				else if (cgltf_json_strcmp(tokens+i, json_chunk, "path") == 0)
  5616  				{
  5617  					++i;
  5618  					if (cgltf_json_strcmp(tokens+i, json_chunk, "translation") == 0)
  5619  					{
  5620  						out_channel->target_path = cgltf_animation_path_type_translation;
  5621  					}
  5622  					else if (cgltf_json_strcmp(tokens+i, json_chunk, "rotation") == 0)
  5623  					{
  5624  						out_channel->target_path = cgltf_animation_path_type_rotation;
  5625  					}
  5626  					else if (cgltf_json_strcmp(tokens+i, json_chunk, "scale") == 0)
  5627  					{
  5628  						out_channel->target_path = cgltf_animation_path_type_scale;
  5629  					}
  5630  					else if (cgltf_json_strcmp(tokens+i, json_chunk, "weights") == 0)
  5631  					{
  5632  						out_channel->target_path = cgltf_animation_path_type_weights;
  5633  					}
  5634  					++i;
  5635  				}
  5636  				else if (cgltf_json_strcmp(tokens + i, json_chunk, "extras") == 0)
  5637  				{
  5638  					i = cgltf_parse_json_extras(tokens, i + 1, json_chunk, &out_channel->extras);
  5639  				}
  5640  				else if (cgltf_json_strcmp(tokens + i, json_chunk, "extensions") == 0)
  5641  				{
  5642  					i = cgltf_parse_json_unprocessed_extensions(options, tokens, i, json_chunk, &out_channel->extensions_count, &out_channel->extensions);
  5643  				}
  5644  				else
  5645  				{
  5646  					i = cgltf_skip_json(tokens, i+1);
  5647  				}
  5648  
  5649  				if (i < 0)
  5650  				{
  5651  					return i;
  5652  				}
  5653  			}
  5654  		}
  5655  		else
  5656  		{
  5657  			i = cgltf_skip_json(tokens, i+1);
  5658  		}
  5659  
  5660  		if (i < 0)
  5661  		{
  5662  			return i;
  5663  		}
  5664  	}
  5665  
  5666  	return i;
  5667  }
  5668  
  5669  static int cgltf_parse_json_animation(cgltf_options* options, jsmntok_t const* tokens, int i, const uint8_t* json_chunk, cgltf_animation* out_animation)
  5670  {
  5671  	CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
  5672  
  5673  	int size = tokens[i].size;
  5674  	++i;
  5675  
  5676  	for (int j = 0; j < size; ++j)
  5677  	{
  5678  		CGLTF_CHECK_KEY(tokens[i]);
  5679  
  5680  		if (cgltf_json_strcmp(tokens+i, json_chunk, "name") == 0)
  5681  		{
  5682  			i = cgltf_parse_json_string(options, tokens, i + 1, json_chunk, &out_animation->name);
  5683  		}
  5684  		else if (cgltf_json_strcmp(tokens+i, json_chunk, "samplers") == 0)
  5685  		{
  5686  			i = cgltf_parse_json_array(options, tokens, i + 1, json_chunk, sizeof(cgltf_animation_sampler), (void**)&out_animation->samplers, &out_animation->samplers_count);
  5687  			if (i < 0)
  5688  			{
  5689  				return i;
  5690  			}
  5691  
  5692  			for (cgltf_size k = 0; k < out_animation->samplers_count; ++k)
  5693  			{
  5694  				i = cgltf_parse_json_animation_sampler(options, tokens, i, json_chunk, &out_animation->samplers[k]);
  5695  				if (i < 0)
  5696  				{
  5697  					return i;
  5698  				}
  5699  			}
  5700  		}
  5701  		else if (cgltf_json_strcmp(tokens+i, json_chunk, "channels") == 0)
  5702  		{
  5703  			i = cgltf_parse_json_array(options, tokens, i + 1, json_chunk, sizeof(cgltf_animation_channel), (void**)&out_animation->channels, &out_animation->channels_count);
  5704  			if (i < 0)
  5705  			{
  5706  				return i;
  5707  			}
  5708  
  5709  			for (cgltf_size k = 0; k < out_animation->channels_count; ++k)
  5710  			{
  5711  				i = cgltf_parse_json_animation_channel(options, tokens, i, json_chunk, &out_animation->channels[k]);
  5712  				if (i < 0)
  5713  				{
  5714  					return i;
  5715  				}
  5716  			}
  5717  		}
  5718  		else if (cgltf_json_strcmp(tokens + i, json_chunk, "extras") == 0)
  5719  		{
  5720  			i = cgltf_parse_json_extras(tokens, i + 1, json_chunk, &out_animation->extras);
  5721  		}
  5722  		else if (cgltf_json_strcmp(tokens + i, json_chunk, "extensions") == 0)
  5723  		{
  5724  			i = cgltf_parse_json_unprocessed_extensions(options, tokens, i, json_chunk, &out_animation->extensions_count, &out_animation->extensions);
  5725  		}
  5726  		else
  5727  		{
  5728  			i = cgltf_skip_json(tokens, i+1);
  5729  		}
  5730  
  5731  		if (i < 0)
  5732  		{
  5733  			return i;
  5734  		}
  5735  	}
  5736  
  5737  	return i;
  5738  }
  5739  
  5740  static int cgltf_parse_json_animations(cgltf_options* options, jsmntok_t const* tokens, int i, const uint8_t* json_chunk, cgltf_data* out_data)
  5741  {
  5742  	i = cgltf_parse_json_array(options, tokens, i, json_chunk, sizeof(cgltf_animation), (void**)&out_data->animations, &out_data->animations_count);
  5743  	if (i < 0)
  5744  	{
  5745  		return i;
  5746  	}
  5747  
  5748  	for (cgltf_size j = 0; j < out_data->animations_count; ++j)
  5749  	{
  5750  		i = cgltf_parse_json_animation(options, tokens, i, json_chunk, &out_data->animations[j]);
  5751  		if (i < 0)
  5752  		{
  5753  			return i;
  5754  		}
  5755  	}
  5756  	return i;
  5757  }
  5758  
  5759  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)
  5760  {
  5761  	CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
  5762  
  5763  	int size = tokens[i].size;
  5764  	++i;
  5765  
  5766  	for (int j = 0; j < size; ++j)
  5767  	{
  5768  		CGLTF_CHECK_KEY(tokens[i]);
  5769  
  5770  		if (cgltf_json_strcmp(tokens+i, json_chunk, "name") == 0)
  5771  		{
  5772  			i = cgltf_parse_json_string(options, tokens, i + 1, json_chunk, &out_variant->name);
  5773  		}
  5774  		else if (cgltf_json_strcmp(tokens + i, json_chunk, "extras") == 0)
  5775  		{
  5776  			i = cgltf_parse_json_extras(tokens, i + 1, json_chunk, &out_variant->extras);
  5777  		}
  5778  		else
  5779  		{
  5780  			i = cgltf_skip_json(tokens, i+1);
  5781  		}
  5782  
  5783  		if (i < 0)
  5784  		{
  5785  			return i;
  5786  		}
  5787  	}
  5788  
  5789  	return i;
  5790  }
  5791  
  5792  static int cgltf_parse_json_variants(cgltf_options* options, jsmntok_t const* tokens, int i, const uint8_t* json_chunk, cgltf_data* out_data)
  5793  {
  5794  	i = cgltf_parse_json_array(options, tokens, i, json_chunk, sizeof(cgltf_material_variant), (void**)&out_data->variants, &out_data->variants_count);
  5795  	if (i < 0)
  5796  	{
  5797  		return i;
  5798  	}
  5799  
  5800  	for (cgltf_size j = 0; j < out_data->variants_count; ++j)
  5801  	{
  5802  		i = cgltf_parse_json_variant(options, tokens, i, json_chunk, &out_data->variants[j]);
  5803  		if (i < 0)
  5804  		{
  5805  			return i;
  5806  		}
  5807  	}
  5808  	return i;
  5809  }
  5810  
  5811  static int cgltf_parse_json_asset(cgltf_options* options, jsmntok_t const* tokens, int i, const uint8_t* json_chunk, cgltf_asset* out_asset)
  5812  {
  5813  	CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
  5814  
  5815  	int size = tokens[i].size;
  5816  	++i;
  5817  
  5818  	for (int j = 0; j < size; ++j)
  5819  	{
  5820  		CGLTF_CHECK_KEY(tokens[i]);
  5821  
  5822  		if (cgltf_json_strcmp(tokens+i, json_chunk, "copyright") == 0)
  5823  		{
  5824  			i = cgltf_parse_json_string(options, tokens, i + 1, json_chunk, &out_asset->copyright);
  5825  		}
  5826  		else if (cgltf_json_strcmp(tokens+i, json_chunk, "generator") == 0)
  5827  		{
  5828  			i = cgltf_parse_json_string(options, tokens, i + 1, json_chunk, &out_asset->generator);
  5829  		}
  5830  		else if (cgltf_json_strcmp(tokens+i, json_chunk, "version") == 0)
  5831  		{
  5832  			i = cgltf_parse_json_string(options, tokens, i + 1, json_chunk, &out_asset->version);
  5833  		}
  5834  		else if (cgltf_json_strcmp(tokens+i, json_chunk, "minVersion") == 0)
  5835  		{
  5836  			i = cgltf_parse_json_string(options, tokens, i + 1, json_chunk, &out_asset->min_version);
  5837  		}
  5838  		else if (cgltf_json_strcmp(tokens + i, json_chunk, "extras") == 0)
  5839  		{
  5840  			i = cgltf_parse_json_extras(tokens, i + 1, json_chunk, &out_asset->extras);
  5841  		}
  5842  		else if (cgltf_json_strcmp(tokens + i, json_chunk, "extensions") == 0)
  5843  		{
  5844  			i = cgltf_parse_json_unprocessed_extensions(options, tokens, i, json_chunk, &out_asset->extensions_count, &out_asset->extensions);
  5845  		}
  5846  		else
  5847  		{
  5848  			i = cgltf_skip_json(tokens, i+1);
  5849  		}
  5850  
  5851  		if (i < 0)
  5852  		{
  5853  			return i;
  5854  		}
  5855  	}
  5856  
  5857  	if (out_asset->version && CGLTF_ATOF(out_asset->version) < 2)
  5858  	{
  5859  		return CGLTF_ERROR_LEGACY;
  5860  	}
  5861  
  5862  	return i;
  5863  }
  5864  
  5865  cgltf_size cgltf_num_components(cgltf_type type) {
  5866  	switch (type)
  5867  	{
  5868  	case cgltf_type_vec2:
  5869  		return 2;
  5870  	case cgltf_type_vec3:
  5871  		return 3;
  5872  	case cgltf_type_vec4:
  5873  		return 4;
  5874  	case cgltf_type_mat2:
  5875  		return 4;
  5876  	case cgltf_type_mat3:
  5877  		return 9;
  5878  	case cgltf_type_mat4:
  5879  		return 16;
  5880  	case cgltf_type_invalid:
  5881  	case cgltf_type_scalar:
  5882  	default:
  5883  		return 1;
  5884  	}
  5885  }
  5886  
  5887  static cgltf_size cgltf_component_size(cgltf_component_type component_type) {
  5888  	switch (component_type)
  5889  	{
  5890  	case cgltf_component_type_r_8:
  5891  	case cgltf_component_type_r_8u:
  5892  		return 1;
  5893  	case cgltf_component_type_r_16:
  5894  	case cgltf_component_type_r_16u:
  5895  		return 2;
  5896  	case cgltf_component_type_r_32u:
  5897  	case cgltf_component_type_r_32f:
  5898  		return 4;
  5899  	case cgltf_component_type_invalid:
  5900  	default:
  5901  		return 0;
  5902  	}
  5903  }
  5904  
  5905  static cgltf_size cgltf_calc_size(cgltf_type type, cgltf_component_type component_type)
  5906  {
  5907  	cgltf_size component_size = cgltf_component_size(component_type);
  5908  	if (type == cgltf_type_mat2 && component_size == 1)
  5909  	{
  5910  		return 8 * component_size;
  5911  	}
  5912  	else if (type == cgltf_type_mat3 && (component_size == 1 || component_size == 2))
  5913  	{
  5914  		return 12 * component_size;
  5915  	}
  5916  	return component_size * cgltf_num_components(type);
  5917  }
  5918  
  5919  static int cgltf_fixup_pointers(cgltf_data* out_data);
  5920  
  5921  static int cgltf_parse_json_root(cgltf_options* options, jsmntok_t const* tokens, int i, const uint8_t* json_chunk, cgltf_data* out_data)
  5922  {
  5923  	CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
  5924  
  5925  	int size = tokens[i].size;
  5926  	++i;
  5927  
  5928  	for (int j = 0; j < size; ++j)
  5929  	{
  5930  		CGLTF_CHECK_KEY(tokens[i]);
  5931  
  5932  		if (cgltf_json_strcmp(tokens + i, json_chunk, "asset") == 0)
  5933  		{
  5934  			i = cgltf_parse_json_asset(options, tokens, i + 1, json_chunk, &out_data->asset);
  5935  		}
  5936  		else if (cgltf_json_strcmp(tokens + i, json_chunk, "meshes") == 0)
  5937  		{
  5938  			i = cgltf_parse_json_meshes(options, tokens, i + 1, json_chunk, out_data);
  5939  		}
  5940  		else if (cgltf_json_strcmp(tokens + i, json_chunk, "accessors") == 0)
  5941  		{
  5942  			i = cgltf_parse_json_accessors(options, tokens, i + 1, json_chunk, out_data);
  5943  		}
  5944  		else if (cgltf_json_strcmp(tokens + i, json_chunk, "bufferViews") == 0)
  5945  		{
  5946  			i = cgltf_parse_json_buffer_views(options, tokens, i + 1, json_chunk, out_data);
  5947  		}
  5948  		else if (cgltf_json_strcmp(tokens + i, json_chunk, "buffers") == 0)
  5949  		{
  5950  			i = cgltf_parse_json_buffers(options, tokens, i + 1, json_chunk, out_data);
  5951  		}
  5952  		else if (cgltf_json_strcmp(tokens + i, json_chunk, "materials") == 0)
  5953  		{
  5954  			i = cgltf_parse_json_materials(options, tokens, i + 1, json_chunk, out_data);
  5955  		}
  5956  		else if (cgltf_json_strcmp(tokens + i, json_chunk, "images") == 0)
  5957  		{
  5958  			i = cgltf_parse_json_images(options, tokens, i + 1, json_chunk, out_data);
  5959  		}
  5960  		else if (cgltf_json_strcmp(tokens + i, json_chunk, "textures") == 0)
  5961  		{
  5962  			i = cgltf_parse_json_textures(options, tokens, i + 1, json_chunk, out_data);
  5963  		}
  5964  		else if (cgltf_json_strcmp(tokens + i, json_chunk, "samplers") == 0)
  5965  		{
  5966  			i = cgltf_parse_json_samplers(options, tokens, i + 1, json_chunk, out_data);
  5967  		}
  5968  		else if (cgltf_json_strcmp(tokens + i, json_chunk, "skins") == 0)
  5969  		{
  5970  			i = cgltf_parse_json_skins(options, tokens, i + 1, json_chunk, out_data);
  5971  		}
  5972  		else if (cgltf_json_strcmp(tokens + i, json_chunk, "cameras") == 0)
  5973  		{
  5974  			i = cgltf_parse_json_cameras(options, tokens, i + 1, json_chunk, out_data);
  5975  		}
  5976  		else if (cgltf_json_strcmp(tokens + i, json_chunk, "nodes") == 0)
  5977  		{
  5978  			i = cgltf_parse_json_nodes(options, tokens, i + 1, json_chunk, out_data);
  5979  		}
  5980  		else if (cgltf_json_strcmp(tokens + i, json_chunk, "scenes") == 0)
  5981  		{
  5982  			i = cgltf_parse_json_scenes(options, tokens, i + 1, json_chunk, out_data);
  5983  		}
  5984  		else if (cgltf_json_strcmp(tokens + i, json_chunk, "scene") == 0)
  5985  		{
  5986  			++i;
  5987  			out_data->scene = CGLTF_PTRINDEX(cgltf_scene, cgltf_json_to_int(tokens + i, json_chunk));
  5988  			++i;
  5989  		}
  5990  		else if (cgltf_json_strcmp(tokens + i, json_chunk, "animations") == 0)
  5991  		{
  5992  			i = cgltf_parse_json_animations(options, tokens, i + 1, json_chunk, out_data);
  5993  		}
  5994  		else if (cgltf_json_strcmp(tokens+i, json_chunk, "extras") == 0)
  5995  		{
  5996  			i = cgltf_parse_json_extras(tokens, i + 1, json_chunk, &out_data->extras);
  5997  		}
  5998  		else if (cgltf_json_strcmp(tokens + i, json_chunk, "extensions") == 0)
  5999  		{
  6000  			++i;
  6001  
  6002  			CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
  6003  			if(out_data->data_extensions)
  6004  			{
  6005  				return CGLTF_ERROR_JSON;
  6006  			}
  6007  
  6008  			int extensions_size = tokens[i].size;
  6009  			out_data->data_extensions_count = 0;
  6010  			out_data->data_extensions = (cgltf_extension*)cgltf_calloc(options, sizeof(cgltf_extension), extensions_size);
  6011  
  6012  			if (!out_data->data_extensions)
  6013  			{
  6014  				return CGLTF_ERROR_NOMEM;
  6015  			}
  6016  
  6017  			++i;
  6018  
  6019  			for (int k = 0; k < extensions_size; ++k)
  6020  			{
  6021  				CGLTF_CHECK_KEY(tokens[i]);
  6022  
  6023  				if (cgltf_json_strcmp(tokens+i, json_chunk, "KHR_lights_punctual") == 0)
  6024  				{
  6025  					++i;
  6026  
  6027  					CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
  6028  
  6029  					int data_size = tokens[i].size;
  6030  					++i;
  6031  
  6032  					for (int m = 0; m < data_size; ++m)
  6033  					{
  6034  						CGLTF_CHECK_KEY(tokens[i]);
  6035  
  6036  						if (cgltf_json_strcmp(tokens + i, json_chunk, "lights") == 0)
  6037  						{
  6038  							i = cgltf_parse_json_lights(options, tokens, i + 1, json_chunk, out_data);
  6039  						}
  6040  						else
  6041  						{
  6042  							i = cgltf_skip_json(tokens, i + 1);
  6043  						}
  6044  
  6045  						if (i < 0)
  6046  						{
  6047  							return i;
  6048  						}
  6049  					}
  6050  				}
  6051  				else if (cgltf_json_strcmp(tokens+i, json_chunk, "KHR_materials_variants") == 0)
  6052  				{
  6053  					++i;
  6054  
  6055  					CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
  6056  
  6057  					int data_size = tokens[i].size;
  6058  					++i;
  6059  
  6060  					for (int m = 0; m < data_size; ++m)
  6061  					{
  6062  						CGLTF_CHECK_KEY(tokens[i]);
  6063  
  6064  						if (cgltf_json_strcmp(tokens + i, json_chunk, "variants") == 0)
  6065  						{
  6066  							i = cgltf_parse_json_variants(options, tokens, i + 1, json_chunk, out_data);
  6067  						}
  6068  						else
  6069  						{
  6070  							i = cgltf_skip_json(tokens, i + 1);
  6071  						}
  6072  
  6073  						if (i < 0)
  6074  						{
  6075  							return i;
  6076  						}
  6077  					}
  6078  				}
  6079  				else
  6080  				{
  6081  					i = cgltf_parse_json_unprocessed_extension(options, tokens, i, json_chunk, &(out_data->data_extensions[out_data->data_extensions_count++]));
  6082  				}
  6083  
  6084  				if (i < 0)
  6085  				{
  6086  					return i;
  6087  				}
  6088  			}
  6089  		}
  6090  		else if (cgltf_json_strcmp(tokens + i, json_chunk, "extensionsUsed") == 0)
  6091  		{
  6092  			i = cgltf_parse_json_string_array(options, tokens, i + 1, json_chunk, &out_data->extensions_used, &out_data->extensions_used_count);
  6093  		}
  6094  		else if (cgltf_json_strcmp(tokens + i, json_chunk, "extensionsRequired") == 0)
  6095  		{
  6096  			i = cgltf_parse_json_string_array(options, tokens, i + 1, json_chunk, &out_data->extensions_required, &out_data->extensions_required_count);
  6097  		}
  6098  		else
  6099  		{
  6100  			i = cgltf_skip_json(tokens, i + 1);
  6101  		}
  6102  
  6103  		if (i < 0)
  6104  		{
  6105  			return i;
  6106  		}
  6107  	}
  6108  
  6109  	return i;
  6110  }
  6111  
  6112  cgltf_result cgltf_parse_json(cgltf_options* options, const uint8_t* json_chunk, cgltf_size size, cgltf_data** out_data)
  6113  {
  6114  	jsmn_parser parser = { 0, 0, 0 };
  6115  
  6116  	if (options->json_token_count == 0)
  6117  	{
  6118  		int token_count = jsmn_parse(&parser, (const char*)json_chunk, size, NULL, 0);
  6119  
  6120  		if (token_count <= 0)
  6121  		{
  6122  			return cgltf_result_invalid_json;
  6123  		}
  6124  
  6125  		options->json_token_count = token_count;
  6126  	}
  6127  
  6128  	jsmntok_t* tokens = (jsmntok_t*)options->memory.alloc_func(options->memory.user_data, sizeof(jsmntok_t) * (options->json_token_count + 1));
  6129  
  6130  	if (!tokens)
  6131  	{
  6132  		return cgltf_result_out_of_memory;
  6133  	}
  6134  
  6135  	jsmn_init(&parser);
  6136  
  6137  	int token_count = jsmn_parse(&parser, (const char*)json_chunk, size, tokens, options->json_token_count);
  6138  
  6139  	if (token_count <= 0)
  6140  	{
  6141  		options->memory.free_func(options->memory.user_data, tokens);
  6142  		return cgltf_result_invalid_json;
  6143  	}
  6144  
  6145  	// this makes sure that we always have an UNDEFINED token at the end of the stream
  6146  	// for invalid JSON inputs this makes sure we don't perform out of bound reads of token data
  6147  	tokens[token_count].type = JSMN_UNDEFINED;
  6148  
  6149  	cgltf_data* data = (cgltf_data*)options->memory.alloc_func(options->memory.user_data, sizeof(cgltf_data));
  6150  
  6151  	if (!data)
  6152  	{
  6153  		options->memory.free_func(options->memory.user_data, tokens);
  6154  		return cgltf_result_out_of_memory;
  6155  	}
  6156  
  6157  	memset(data, 0, sizeof(cgltf_data));
  6158  	data->memory = options->memory;
  6159  	data->file = options->file;
  6160  
  6161  	int i = cgltf_parse_json_root(options, tokens, 0, json_chunk, data);
  6162  
  6163  	options->memory.free_func(options->memory.user_data, tokens);
  6164  
  6165  	if (i < 0)
  6166  	{
  6167  		cgltf_free(data);
  6168  
  6169  		switch (i)
  6170  		{
  6171  		case CGLTF_ERROR_NOMEM: return cgltf_result_out_of_memory;
  6172  		case CGLTF_ERROR_LEGACY: return cgltf_result_legacy_gltf;
  6173  		default: return cgltf_result_invalid_gltf;
  6174  		}
  6175  	}
  6176  
  6177  	if (cgltf_fixup_pointers(data) < 0)
  6178  	{
  6179  		cgltf_free(data);
  6180  		return cgltf_result_invalid_gltf;
  6181  	}
  6182  
  6183  	data->json = (const char*)json_chunk;
  6184  	data->json_size = size;
  6185  
  6186  	*out_data = data;
  6187  
  6188  	return cgltf_result_success;
  6189  }
  6190  
  6191  static int cgltf_fixup_pointers(cgltf_data* data)
  6192  {
  6193  	for (cgltf_size i = 0; i < data->meshes_count; ++i)
  6194  	{
  6195  		for (cgltf_size j = 0; j < data->meshes[i].primitives_count; ++j)
  6196  		{
  6197  			CGLTF_PTRFIXUP(data->meshes[i].primitives[j].indices, data->accessors, data->accessors_count);
  6198  			CGLTF_PTRFIXUP(data->meshes[i].primitives[j].material, data->materials, data->materials_count);
  6199  
  6200  			for (cgltf_size k = 0; k < data->meshes[i].primitives[j].attributes_count; ++k)
  6201  			{
  6202  				CGLTF_PTRFIXUP_REQ(data->meshes[i].primitives[j].attributes[k].data, data->accessors, data->accessors_count);
  6203  			}
  6204  
  6205  			for (cgltf_size k = 0; k < data->meshes[i].primitives[j].targets_count; ++k)
  6206  			{
  6207  				for (cgltf_size m = 0; m < data->meshes[i].primitives[j].targets[k].attributes_count; ++m)
  6208  				{
  6209  					CGLTF_PTRFIXUP_REQ(data->meshes[i].primitives[j].targets[k].attributes[m].data, data->accessors, data->accessors_count);
  6210  				}
  6211  			}
  6212  
  6213  			if (data->meshes[i].primitives[j].has_draco_mesh_compression)
  6214  			{
  6215  				CGLTF_PTRFIXUP_REQ(data->meshes[i].primitives[j].draco_mesh_compression.buffer_view, data->buffer_views, data->buffer_views_count);
  6216  				for (cgltf_size m = 0; m < data->meshes[i].primitives[j].draco_mesh_compression.attributes_count; ++m)
  6217  				{
  6218  					CGLTF_PTRFIXUP_REQ(data->meshes[i].primitives[j].draco_mesh_compression.attributes[m].data, data->accessors, data->accessors_count);
  6219  				}
  6220  			}
  6221  
  6222  			for (cgltf_size k = 0; k < data->meshes[i].primitives[j].mappings_count; ++k)
  6223  			{
  6224  				CGLTF_PTRFIXUP_REQ(data->meshes[i].primitives[j].mappings[k].material, data->materials, data->materials_count);
  6225  			}
  6226  		}
  6227  	}
  6228  
  6229  	for (cgltf_size i = 0; i < data->accessors_count; ++i)
  6230  	{
  6231  		CGLTF_PTRFIXUP(data->accessors[i].buffer_view, data->buffer_views, data->buffer_views_count);
  6232  
  6233  		if (data->accessors[i].is_sparse)
  6234  		{
  6235  			CGLTF_PTRFIXUP_REQ(data->accessors[i].sparse.indices_buffer_view, data->buffer_views, data->buffer_views_count);
  6236  			CGLTF_PTRFIXUP_REQ(data->accessors[i].sparse.values_buffer_view, data->buffer_views, data->buffer_views_count);
  6237  		}
  6238  
  6239  		if (data->accessors[i].buffer_view)
  6240  		{
  6241  			data->accessors[i].stride = data->accessors[i].buffer_view->stride;
  6242  		}
  6243  
  6244  		if (data->accessors[i].stride == 0)
  6245  		{
  6246  			data->accessors[i].stride = cgltf_calc_size(data->accessors[i].type, data->accessors[i].component_type);
  6247  		}
  6248  	}
  6249  
  6250  	for (cgltf_size i = 0; i < data->textures_count; ++i)
  6251  	{
  6252  		CGLTF_PTRFIXUP(data->textures[i].image, data->images, data->images_count);
  6253  		CGLTF_PTRFIXUP(data->textures[i].basisu_image, data->images, data->images_count);
  6254  		CGLTF_PTRFIXUP(data->textures[i].sampler, data->samplers, data->samplers_count);
  6255  	}
  6256  
  6257  	for (cgltf_size i = 0; i < data->images_count; ++i)
  6258  	{
  6259  		CGLTF_PTRFIXUP(data->images[i].buffer_view, data->buffer_views, data->buffer_views_count);
  6260  	}
  6261  
  6262  	for (cgltf_size i = 0; i < data->materials_count; ++i)
  6263  	{
  6264  		CGLTF_PTRFIXUP(data->materials[i].normal_texture.texture, data->textures, data->textures_count);
  6265  		CGLTF_PTRFIXUP(data->materials[i].emissive_texture.texture, data->textures, data->textures_count);
  6266  		CGLTF_PTRFIXUP(data->materials[i].occlusion_texture.texture, data->textures, data->textures_count);
  6267  
  6268  		CGLTF_PTRFIXUP(data->materials[i].pbr_metallic_roughness.base_color_texture.texture, data->textures, data->textures_count);
  6269  		CGLTF_PTRFIXUP(data->materials[i].pbr_metallic_roughness.metallic_roughness_texture.texture, data->textures, data->textures_count);
  6270  
  6271  		CGLTF_PTRFIXUP(data->materials[i].pbr_specular_glossiness.diffuse_texture.texture, data->textures, data->textures_count);
  6272  		CGLTF_PTRFIXUP(data->materials[i].pbr_specular_glossiness.specular_glossiness_texture.texture, data->textures, data->textures_count);
  6273  
  6274  		CGLTF_PTRFIXUP(data->materials[i].clearcoat.clearcoat_texture.texture, data->textures, data->textures_count);
  6275  		CGLTF_PTRFIXUP(data->materials[i].clearcoat.clearcoat_roughness_texture.texture, data->textures, data->textures_count);
  6276  		CGLTF_PTRFIXUP(data->materials[i].clearcoat.clearcoat_normal_texture.texture, data->textures, data->textures_count);
  6277  
  6278  		CGLTF_PTRFIXUP(data->materials[i].specular.specular_texture.texture, data->textures, data->textures_count);
  6279  		CGLTF_PTRFIXUP(data->materials[i].specular.specular_color_texture.texture, data->textures, data->textures_count);
  6280  
  6281  		CGLTF_PTRFIXUP(data->materials[i].transmission.transmission_texture.texture, data->textures, data->textures_count);
  6282  
  6283  		CGLTF_PTRFIXUP(data->materials[i].volume.thickness_texture.texture, data->textures, data->textures_count);
  6284  
  6285  		CGLTF_PTRFIXUP(data->materials[i].sheen.sheen_color_texture.texture, data->textures, data->textures_count);
  6286  		CGLTF_PTRFIXUP(data->materials[i].sheen.sheen_roughness_texture.texture, data->textures, data->textures_count);
  6287  
  6288  		CGLTF_PTRFIXUP(data->materials[i].iridescence.iridescence_texture.texture, data->textures, data->textures_count);
  6289  		CGLTF_PTRFIXUP(data->materials[i].iridescence.iridescence_thickness_texture.texture, data->textures, data->textures_count);
  6290  	}
  6291  
  6292  	for (cgltf_size i = 0; i < data->buffer_views_count; ++i)
  6293  	{
  6294  		CGLTF_PTRFIXUP_REQ(data->buffer_views[i].buffer, data->buffers, data->buffers_count);
  6295  
  6296  		if (data->buffer_views[i].has_meshopt_compression)
  6297  		{
  6298  			CGLTF_PTRFIXUP_REQ(data->buffer_views[i].meshopt_compression.buffer, data->buffers, data->buffers_count);
  6299  		}
  6300  	}
  6301  
  6302  	for (cgltf_size i = 0; i < data->skins_count; ++i)
  6303  	{
  6304  		for (cgltf_size j = 0; j < data->skins[i].joints_count; ++j)
  6305  		{
  6306  			CGLTF_PTRFIXUP_REQ(data->skins[i].joints[j], data->nodes, data->nodes_count);
  6307  		}
  6308  
  6309  		CGLTF_PTRFIXUP(data->skins[i].skeleton, data->nodes, data->nodes_count);
  6310  		CGLTF_PTRFIXUP(data->skins[i].inverse_bind_matrices, data->accessors, data->accessors_count);
  6311  	}
  6312  
  6313  	for (cgltf_size i = 0; i < data->nodes_count; ++i)
  6314  	{
  6315  		for (cgltf_size j = 0; j < data->nodes[i].children_count; ++j)
  6316  		{
  6317  			CGLTF_PTRFIXUP_REQ(data->nodes[i].children[j], data->nodes, data->nodes_count);
  6318  
  6319  			if (data->nodes[i].children[j]->parent)
  6320  			{
  6321  				return CGLTF_ERROR_JSON;
  6322  			}
  6323  
  6324  			data->nodes[i].children[j]->parent = &data->nodes[i];
  6325  		}
  6326  
  6327  		CGLTF_PTRFIXUP(data->nodes[i].mesh, data->meshes, data->meshes_count);
  6328  		CGLTF_PTRFIXUP(data->nodes[i].skin, data->skins, data->skins_count);
  6329  		CGLTF_PTRFIXUP(data->nodes[i].camera, data->cameras, data->cameras_count);
  6330  		CGLTF_PTRFIXUP(data->nodes[i].light, data->lights, data->lights_count);
  6331  
  6332  		if (data->nodes[i].has_mesh_gpu_instancing)
  6333  		{
  6334  			CGLTF_PTRFIXUP_REQ(data->nodes[i].mesh_gpu_instancing.buffer_view, data->buffer_views, data->buffer_views_count);
  6335  			for (cgltf_size m = 0; m < data->nodes[i].mesh_gpu_instancing.attributes_count; ++m)
  6336  			{
  6337  				CGLTF_PTRFIXUP_REQ(data->nodes[i].mesh_gpu_instancing.attributes[m].data, data->accessors, data->accessors_count);
  6338  			}
  6339  		}
  6340  	}
  6341  
  6342  	for (cgltf_size i = 0; i < data->scenes_count; ++i)
  6343  	{
  6344  		for (cgltf_size j = 0; j < data->scenes[i].nodes_count; ++j)
  6345  		{
  6346  			CGLTF_PTRFIXUP_REQ(data->scenes[i].nodes[j], data->nodes, data->nodes_count);
  6347  
  6348  			if (data->scenes[i].nodes[j]->parent)
  6349  			{
  6350  				return CGLTF_ERROR_JSON;
  6351  			}
  6352  		}
  6353  	}
  6354  
  6355  	CGLTF_PTRFIXUP(data->scene, data->scenes, data->scenes_count);
  6356  
  6357  	for (cgltf_size i = 0; i < data->animations_count; ++i)
  6358  	{
  6359  		for (cgltf_size j = 0; j < data->animations[i].samplers_count; ++j)
  6360  		{
  6361  			CGLTF_PTRFIXUP_REQ(data->animations[i].samplers[j].input, data->accessors, data->accessors_count);
  6362  			CGLTF_PTRFIXUP_REQ(data->animations[i].samplers[j].output, data->accessors, data->accessors_count);
  6363  		}
  6364  
  6365  		for (cgltf_size j = 0; j < data->animations[i].channels_count; ++j)
  6366  		{
  6367  			CGLTF_PTRFIXUP_REQ(data->animations[i].channels[j].sampler, data->animations[i].samplers, data->animations[i].samplers_count);
  6368  			CGLTF_PTRFIXUP(data->animations[i].channels[j].target_node, data->nodes, data->nodes_count);
  6369  		}
  6370  	}
  6371  
  6372  	return 0;
  6373  }
  6374  
  6375  /*
  6376   * -- jsmn.c start --
  6377   * Source: https://github.com/zserge/jsmn
  6378   * License: MIT
  6379   *
  6380   * Copyright (c) 2010 Serge A. Zaitsev
  6381  
  6382   * Permission is hereby granted, free of charge, to any person obtaining a copy
  6383   * of this software and associated documentation files (the "Software"), to deal
  6384   * in the Software without restriction, including without limitation the rights
  6385   * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  6386   * copies of the Software, and to permit persons to whom the Software is
  6387   * furnished to do so, subject to the following conditions:
  6388  
  6389   * The above copyright notice and this permission notice shall be included in
  6390   * all copies or substantial portions of the Software.
  6391  
  6392   * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  6393   * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  6394   * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  6395   * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  6396   * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  6397   * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  6398   * THE SOFTWARE.
  6399   */
  6400  
  6401  /**
  6402   * Allocates a fresh unused token from the token pull.
  6403   */
  6404  static jsmntok_t *jsmn_alloc_token(jsmn_parser *parser,
  6405  				   jsmntok_t *tokens, size_t num_tokens) {
  6406  	jsmntok_t *tok;
  6407  	if (parser->toknext >= num_tokens) {
  6408  		return NULL;
  6409  	}
  6410  	tok = &tokens[parser->toknext++];
  6411  	tok->start = tok->end = -1;
  6412  	tok->size = 0;
  6413  #ifdef JSMN_PARENT_LINKS
  6414  	tok->parent = -1;
  6415  #endif
  6416  	return tok;
  6417  }
  6418  
  6419  /**
  6420   * Fills token type and boundaries.
  6421   */
  6422  static void jsmn_fill_token(jsmntok_t *token, jsmntype_t type,
  6423  				int start, int end) {
  6424  	token->type = type;
  6425  	token->start = start;
  6426  	token->end = end;
  6427  	token->size = 0;
  6428  }
  6429  
  6430  /**
  6431   * Fills next available token with JSON primitive.
  6432   */
  6433  static int jsmn_parse_primitive(jsmn_parser *parser, const char *js,
  6434  				size_t len, jsmntok_t *tokens, size_t num_tokens) {
  6435  	jsmntok_t *token;
  6436  	int start;
  6437  
  6438  	start = parser->pos;
  6439  
  6440  	for (; parser->pos < len && js[parser->pos] != '\0'; parser->pos++) {
  6441  		switch (js[parser->pos]) {
  6442  #ifndef JSMN_STRICT
  6443  		/* In strict mode primitive must be followed by "," or "}" or "]" */
  6444  		case ':':
  6445  #endif
  6446  		case '\t' : case '\r' : case '\n' : case ' ' :
  6447  		case ','  : case ']'  : case '}' :
  6448  			goto found;
  6449  		}
  6450  		if (js[parser->pos] < 32 || js[parser->pos] >= 127) {
  6451  			parser->pos = start;
  6452  			return JSMN_ERROR_INVAL;
  6453  		}
  6454  	}
  6455  #ifdef JSMN_STRICT
  6456  	/* In strict mode primitive must be followed by a comma/object/array */
  6457  	parser->pos = start;
  6458  	return JSMN_ERROR_PART;
  6459  #endif
  6460  
  6461  found:
  6462  	if (tokens == NULL) {
  6463  		parser->pos--;
  6464  		return 0;
  6465  	}
  6466  	token = jsmn_alloc_token(parser, tokens, num_tokens);
  6467  	if (token == NULL) {
  6468  		parser->pos = start;
  6469  		return JSMN_ERROR_NOMEM;
  6470  	}
  6471  	jsmn_fill_token(token, JSMN_PRIMITIVE, start, parser->pos);
  6472  #ifdef JSMN_PARENT_LINKS
  6473  	token->parent = parser->toksuper;
  6474  #endif
  6475  	parser->pos--;
  6476  	return 0;
  6477  }
  6478  
  6479  /**
  6480   * Fills next token with JSON string.
  6481   */
  6482  static int jsmn_parse_string(jsmn_parser *parser, const char *js,
  6483  				 size_t len, jsmntok_t *tokens, size_t num_tokens) {
  6484  	jsmntok_t *token;
  6485  
  6486  	int start = parser->pos;
  6487  
  6488  	parser->pos++;
  6489  
  6490  	/* Skip starting quote */
  6491  	for (; parser->pos < len && js[parser->pos] != '\0'; parser->pos++) {
  6492  		char c = js[parser->pos];
  6493  
  6494  		/* Quote: end of string */
  6495  		if (c == '\"') {
  6496  			if (tokens == NULL) {
  6497  				return 0;
  6498  			}
  6499  			token = jsmn_alloc_token(parser, tokens, num_tokens);
  6500  			if (token == NULL) {
  6501  				parser->pos = start;
  6502  				return JSMN_ERROR_NOMEM;
  6503  			}
  6504  			jsmn_fill_token(token, JSMN_STRING, start+1, parser->pos);
  6505  #ifdef JSMN_PARENT_LINKS
  6506  			token->parent = parser->toksuper;
  6507  #endif
  6508  			return 0;
  6509  		}
  6510  
  6511  		/* Backslash: Quoted symbol expected */
  6512  		if (c == '\\' && parser->pos + 1 < len) {
  6513  			int i;
  6514  			parser->pos++;
  6515  			switch (js[parser->pos]) {
  6516  			/* Allowed escaped symbols */
  6517  			case '\"': case '/' : case '\\' : case 'b' :
  6518  			case 'f' : case 'r' : case 'n'  : case 't' :
  6519  				break;
  6520  				/* Allows escaped symbol \uXXXX */
  6521  			case 'u':
  6522  				parser->pos++;
  6523  				for(i = 0; i < 4 && parser->pos < len && js[parser->pos] != '\0'; i++) {
  6524  					/* If it isn't a hex character we have an error */
  6525  					if(!((js[parser->pos] >= 48 && js[parser->pos] <= 57) || /* 0-9 */
  6526  						 (js[parser->pos] >= 65 && js[parser->pos] <= 70) || /* A-F */
  6527  						 (js[parser->pos] >= 97 && js[parser->pos] <= 102))) { /* a-f */
  6528  						parser->pos = start;
  6529  						return JSMN_ERROR_INVAL;
  6530  					}
  6531  					parser->pos++;
  6532  				}
  6533  				parser->pos--;
  6534  				break;
  6535  				/* Unexpected symbol */
  6536  			default:
  6537  				parser->pos = start;
  6538  				return JSMN_ERROR_INVAL;
  6539  			}
  6540  		}
  6541  	}
  6542  	parser->pos = start;
  6543  	return JSMN_ERROR_PART;
  6544  }
  6545  
  6546  /**
  6547   * Parse JSON string and fill tokens.
  6548   */
  6549  static int jsmn_parse(jsmn_parser *parser, const char *js, size_t len,
  6550  		   jsmntok_t *tokens, size_t num_tokens) {
  6551  	int r;
  6552  	int i;
  6553  	jsmntok_t *token;
  6554  	int count = parser->toknext;
  6555  
  6556  	for (; parser->pos < len && js[parser->pos] != '\0'; parser->pos++) {
  6557  		char c;
  6558  		jsmntype_t type;
  6559  
  6560  		c = js[parser->pos];
  6561  		switch (c) {
  6562  		case '{': case '[':
  6563  			count++;
  6564  			if (tokens == NULL) {
  6565  				break;
  6566  			}
  6567  			token = jsmn_alloc_token(parser, tokens, num_tokens);
  6568  			if (token == NULL)
  6569  				return JSMN_ERROR_NOMEM;
  6570  			if (parser->toksuper != -1) {
  6571  				tokens[parser->toksuper].size++;
  6572  #ifdef JSMN_PARENT_LINKS
  6573  				token->parent = parser->toksuper;
  6574  #endif
  6575  			}
  6576  			token->type = (c == '{' ? JSMN_OBJECT : JSMN_ARRAY);
  6577  			token->start = parser->pos;
  6578  			parser->toksuper = parser->toknext - 1;
  6579  			break;
  6580  		case '}': case ']':
  6581  			if (tokens == NULL)
  6582  				break;
  6583  			type = (c == '}' ? JSMN_OBJECT : JSMN_ARRAY);
  6584  #ifdef JSMN_PARENT_LINKS
  6585  			if (parser->toknext < 1) {
  6586  				return JSMN_ERROR_INVAL;
  6587  			}
  6588  			token = &tokens[parser->toknext - 1];
  6589  			for (;;) {
  6590  				if (token->start != -1 && token->end == -1) {
  6591  					if (token->type != type) {
  6592  						return JSMN_ERROR_INVAL;
  6593  					}
  6594  					token->end = parser->pos + 1;
  6595  					parser->toksuper = token->parent;
  6596  					break;
  6597  				}
  6598  				if (token->parent == -1) {
  6599  					if(token->type != type || parser->toksuper == -1) {
  6600  						return JSMN_ERROR_INVAL;
  6601  					}
  6602  					break;
  6603  				}
  6604  				token = &tokens[token->parent];
  6605  			}
  6606  #else
  6607  			for (i = parser->toknext - 1; i >= 0; i--) {
  6608  				token = &tokens[i];
  6609  				if (token->start != -1 && token->end == -1) {
  6610  					if (token->type != type) {
  6611  						return JSMN_ERROR_INVAL;
  6612  					}
  6613  					parser->toksuper = -1;
  6614  					token->end = parser->pos + 1;
  6615  					break;
  6616  				}
  6617  			}
  6618  			/* Error if unmatched closing bracket */
  6619  			if (i == -1) return JSMN_ERROR_INVAL;
  6620  			for (; i >= 0; i--) {
  6621  				token = &tokens[i];
  6622  				if (token->start != -1 && token->end == -1) {
  6623  					parser->toksuper = i;
  6624  					break;
  6625  				}
  6626  			}
  6627  #endif
  6628  			break;
  6629  		case '\"':
  6630  			r = jsmn_parse_string(parser, js, len, tokens, num_tokens);
  6631  			if (r < 0) return r;
  6632  			count++;
  6633  			if (parser->toksuper != -1 && tokens != NULL)
  6634  				tokens[parser->toksuper].size++;
  6635  			break;
  6636  		case '\t' : case '\r' : case '\n' : case ' ':
  6637  			break;
  6638  		case ':':
  6639  			parser->toksuper = parser->toknext - 1;
  6640  			break;
  6641  		case ',':
  6642  			if (tokens != NULL && parser->toksuper != -1 &&
  6643  					tokens[parser->toksuper].type != JSMN_ARRAY &&
  6644  					tokens[parser->toksuper].type != JSMN_OBJECT) {
  6645  #ifdef JSMN_PARENT_LINKS
  6646  				parser->toksuper = tokens[parser->toksuper].parent;
  6647  #else
  6648  				for (i = parser->toknext - 1; i >= 0; i--) {
  6649  					if (tokens[i].type == JSMN_ARRAY || tokens[i].type == JSMN_OBJECT) {
  6650  						if (tokens[i].start != -1 && tokens[i].end == -1) {
  6651  							parser->toksuper = i;
  6652  							break;
  6653  						}
  6654  					}
  6655  				}
  6656  #endif
  6657  			}
  6658  			break;
  6659  #ifdef JSMN_STRICT
  6660  			/* In strict mode primitives are: numbers and booleans */
  6661  		case '-': case '0': case '1' : case '2': case '3' : case '4':
  6662  		case '5': case '6': case '7' : case '8': case '9':
  6663  		case 't': case 'f': case 'n' :
  6664  			/* And they must not be keys of the object */
  6665  			if (tokens != NULL && parser->toksuper != -1) {
  6666  				jsmntok_t *t = &tokens[parser->toksuper];
  6667  				if (t->type == JSMN_OBJECT ||
  6668  						(t->type == JSMN_STRING && t->size != 0)) {
  6669  					return JSMN_ERROR_INVAL;
  6670  				}
  6671  			}
  6672  #else
  6673  			/* In non-strict mode every unquoted value is a primitive */
  6674  		default:
  6675  #endif
  6676  			r = jsmn_parse_primitive(parser, js, len, tokens, num_tokens);
  6677  			if (r < 0) return r;
  6678  			count++;
  6679  			if (parser->toksuper != -1 && tokens != NULL)
  6680  				tokens[parser->toksuper].size++;
  6681  			break;
  6682  
  6683  #ifdef JSMN_STRICT
  6684  			/* Unexpected char in strict mode */
  6685  		default:
  6686  			return JSMN_ERROR_INVAL;
  6687  #endif
  6688  		}
  6689  	}
  6690  
  6691  	if (tokens != NULL) {
  6692  		for (i = parser->toknext - 1; i >= 0; i--) {
  6693  			/* Unmatched opened object or array */
  6694  			if (tokens[i].start != -1 && tokens[i].end == -1) {
  6695  				return JSMN_ERROR_PART;
  6696  			}
  6697  		}
  6698  	}
  6699  
  6700  	return count;
  6701  }
  6702  
  6703  /**
  6704   * Creates a new parser based over a given  buffer with an array of tokens
  6705   * available.
  6706   */
  6707  static void jsmn_init(jsmn_parser *parser) {
  6708  	parser->pos = 0;
  6709  	parser->toknext = 0;
  6710  	parser->toksuper = -1;
  6711  }
  6712  /*
  6713   * -- jsmn.c end --
  6714   */
  6715  
  6716  #endif /* #ifdef CGLTF_IMPLEMENTATION */
  6717  
  6718  /* cgltf is distributed under MIT license:
  6719   *
  6720   * Copyright (c) 2018-2021 Johannes Kuhlmann
  6721  
  6722   * Permission is hereby granted, free of charge, to any person obtaining a copy
  6723   * of this software and associated documentation files (the "Software"), to deal
  6724   * in the Software without restriction, including without limitation the rights
  6725   * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  6726   * copies of the Software, and to permit persons to whom the Software is
  6727   * furnished to do so, subject to the following conditions:
  6728  
  6729   * The above copyright notice and this permission notice shall be included in all
  6730   * copies or substantial portions of the Software.
  6731  
  6732   * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  6733   * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  6734   * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  6735   * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  6736   * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  6737   * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
  6738   * SOFTWARE.
  6739   */