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