HDK
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
cgltf.h
Go to the documentation of this file.
1 /**
2  * cgltf - a single-file glTF 2.0 parser written in C99.
3  *
4  * Version: 1.13
5  *
6  * Website: https://github.com/jkuhlmann/cgltf
7  *
8  * Distributed under the MIT License, see notice at the end of this file.
9  *
10  * Building:
11  * Include this file where you need the struct and function
12  * declarations. Have exactly one source file where you define
13  * `CGLTF_IMPLEMENTATION` before including this file to get the
14  * function definitions.
15  *
16  * Reference:
17  * `cgltf_result cgltf_parse(const cgltf_options*, const void*,
18  * cgltf_size, cgltf_data**)` parses both glTF and GLB data. If
19  * this function returns `cgltf_result_success`, you have to call
20  * `cgltf_free()` on the created `cgltf_data*` variable.
21  * Note that contents of external files for buffers and images are not
22  * automatically loaded. You'll need to read these files yourself using
23  * URIs in the `cgltf_data` structure.
24  *
25  * `cgltf_options` is the struct passed to `cgltf_parse()` to control
26  * parts of the parsing process. You can use it to force the file type
27  * and provide memory allocation as well as file operation callbacks.
28  * Should be zero-initialized to trigger default behavior.
29  *
30  * `cgltf_data` is the struct allocated and filled by `cgltf_parse()`.
31  * It generally mirrors the glTF format as described by the spec (see
32  * https://github.com/KhronosGroup/glTF/tree/master/specification/2.0).
33  *
34  * `void cgltf_free(cgltf_data*)` frees the allocated `cgltf_data`
35  * variable.
36  *
37  * `cgltf_result cgltf_load_buffers(const cgltf_options*, cgltf_data*,
38  * const char* gltf_path)` can be optionally called to open and read buffer
39  * files using the `FILE*` APIs. The `gltf_path` argument is the path to
40  * the original glTF file, which allows the parser to resolve the path to
41  * buffer files.
42  *
43  * `cgltf_result cgltf_load_buffer_base64(const cgltf_options* options,
44  * cgltf_size size, const char* base64, void** out_data)` decodes
45  * base64-encoded data content. Used internally by `cgltf_load_buffers()`.
46  * This is useful when decoding data URIs in images.
47  *
48  * `cgltf_result cgltf_parse_file(const cgltf_options* options, const
49  * char* path, cgltf_data** out_data)` can be used to open the given
50  * file using `FILE*` APIs and parse the data using `cgltf_parse()`.
51  *
52  * `cgltf_result cgltf_validate(cgltf_data*)` can be used to do additional
53  * checks to make sure the parsed glTF data is valid.
54  *
55  * `cgltf_node_transform_local` converts the translation / rotation / scale properties of a node
56  * into a mat4.
57  *
58  * `cgltf_node_transform_world` calls `cgltf_node_transform_local` on every ancestor in order
59  * to compute the root-to-node transformation.
60  *
61  * `cgltf_accessor_unpack_floats` reads in the data from an accessor, applies sparse data (if any),
62  * and converts them to floating point. Assumes that `cgltf_load_buffers` has already been called.
63  * By passing null for the output pointer, users can find out how many floats are required in the
64  * output buffer.
65  *
66  * `cgltf_num_components` is a tiny utility that tells you the dimensionality of
67  * a certain accessor type. This can be used before `cgltf_accessor_unpack_floats` to help allocate
68  * the necessary amount of memory.
69  *
70  * `cgltf_accessor_read_float` reads a certain element from a non-sparse accessor and converts it to
71  * floating point, assuming that `cgltf_load_buffers` has already been called. The passed-in element
72  * size is the number of floats in the output buffer, which should be in the range [1, 16]. Returns
73  * false if the passed-in element_size is too small, or if the accessor is sparse.
74  *
75  * `cgltf_accessor_read_uint` is similar to its floating-point counterpart, but limited to reading
76  * vector types and does not support matrix types. The passed-in element size is the number of uints
77  * in the output buffer, which should be in the range [1, 4]. Returns false if the passed-in
78  * element_size is too small, or if the accessor is sparse.
79  *
80  * `cgltf_accessor_read_index` is similar to its floating-point counterpart, but it returns size_t
81  * and only works with single-component data types.
82  *
83  * `cgltf_result cgltf_copy_extras_json(const cgltf_data*, const cgltf_extras*,
84  * char* dest, cgltf_size* dest_size)` allows users to retrieve the "extras" data that
85  * can be attached to many glTF objects (which can be arbitrary JSON data). The
86  * `cgltf_extras` struct stores the offsets of the start and end of the extras JSON data
87  * as it appears in the complete glTF JSON data. This function copies the extras data
88  * into the provided buffer. If `dest` is NULL, the length of the data is written into
89  * `dest_size`. You can then parse this data using your own JSON parser
90  * or, if you've included the cgltf implementation using the integrated JSMN JSON parser.
91  */
92 #ifndef CGLTF_H_INCLUDED__
93 #define CGLTF_H_INCLUDED__
94 
95 #include <stddef.h>
96 
97 #ifdef __cplusplus
98 extern "C" {
99 #endif
100 
101 typedef size_t cgltf_size;
102 typedef long long int cgltf_ssize;
103 typedef float cgltf_float;
104 typedef int cgltf_int;
105 typedef unsigned int cgltf_uint;
106 typedef int cgltf_bool;
107 
108 typedef enum cgltf_file_type
109 {
115 
116 typedef enum cgltf_result
117 {
129 } cgltf_result;
130 
131 typedef struct cgltf_memory_options
132 {
133  void* (*alloc_func)(void* user, cgltf_size size);
134  void (*free_func) (void* user, void* ptr);
135  void* user_data;
137 
138 typedef struct cgltf_file_options
139 {
140  cgltf_result(*read)(const struct cgltf_memory_options* memory_options, const struct cgltf_file_options* file_options, const char* path, cgltf_size* size, void** data);
141  void (*release)(const struct cgltf_memory_options* memory_options, const struct cgltf_file_options* file_options, void* data);
142  void* user_data;
144 
145 typedef struct cgltf_options
146 {
147  cgltf_file_type type; /* invalid == auto detect */
148  cgltf_size json_token_count; /* 0 == auto */
151 } cgltf_options;
152 
154 {
160 
162 {
174 
176 {
179  cgltf_component_type_r_8u, /* UNSIGNED_BYTE */
181  cgltf_component_type_r_16u, /* UNSIGNED_SHORT */
182  cgltf_component_type_r_32u, /* UNSIGNED_INT */
186 
187 typedef enum cgltf_type
188 {
198 } cgltf_type;
199 
201 {
211 
212 typedef enum cgltf_alpha_mode
213 {
219 
228 
235 
236 typedef enum cgltf_camera_type {
242 
243 typedef enum cgltf_light_type {
250 
257 
258 typedef struct cgltf_extras {
259  cgltf_size start_offset;
260  cgltf_size end_offset;
261 } cgltf_extras;
262 
263 typedef struct cgltf_extension {
264  char* name;
265  char* data;
267 
268 typedef struct cgltf_buffer
269 {
270  char* name;
271  cgltf_size size;
272  char* uri;
273  void* data; /* loaded by cgltf_load_buffers */
276  cgltf_size extensions_count;
278 } cgltf_buffer;
279 
287 
295 
297 {
299  cgltf_size offset;
300  cgltf_size size;
301  cgltf_size stride;
302  cgltf_size count;
306 
307 typedef struct cgltf_buffer_view
308 {
309  char *name;
311  cgltf_size offset;
312  cgltf_size size;
313  cgltf_size stride; /* 0 == automatically determined by accessor */
315  void* data; /* overrides buffer->data if present, filled by extensions */
319  cgltf_size extensions_count;
322 
323 typedef struct cgltf_accessor_sparse
324 {
325  cgltf_size count;
330  cgltf_size values_byte_offset;
334  cgltf_size extensions_count;
341 
342 typedef struct cgltf_accessor
343 {
344  char* name;
346  cgltf_bool normalized;
348  cgltf_size offset;
349  cgltf_size count;
350  cgltf_size stride;
352  cgltf_bool has_min;
353  cgltf_float min[16];
354  cgltf_bool has_max;
355  cgltf_float max[16];
356  cgltf_bool is_sparse;
359  cgltf_size extensions_count;
362 
363 typedef struct cgltf_attribute
364 {
365  char* name;
367  cgltf_int index;
370 
371 typedef struct cgltf_image
372 {
373  char* name;
374  char* uri;
376  char* mime_type;
378  cgltf_size extensions_count;
380 } cgltf_image;
381 
382 typedef struct cgltf_sampler
383 {
384  char* name;
385  cgltf_int mag_filter;
386  cgltf_int min_filter;
387  cgltf_int wrap_s;
388  cgltf_int wrap_t;
390  cgltf_size extensions_count;
392 } cgltf_sampler;
393 
394 typedef struct cgltf_texture
395 {
396  char* name;
399  cgltf_bool has_basisu;
402  cgltf_size extensions_count;
404 } cgltf_texture;
405 
407 {
408  cgltf_float offset[2];
409  cgltf_float rotation;
410  cgltf_float scale[2];
411  cgltf_bool has_texcoord;
412  cgltf_int texcoord;
414 
415 typedef struct cgltf_texture_view
416 {
418  cgltf_int texcoord;
419  cgltf_float scale; /* equivalent to strength for occlusion_texture */
420  cgltf_bool has_transform;
423  cgltf_size extensions_count;
426 
428 {
431 
432  cgltf_float base_color_factor[4];
433  cgltf_float metallic_factor;
434  cgltf_float roughness_factor;
435 
438 
440 {
443 
444  cgltf_float diffuse_factor[4];
445  cgltf_float specular_factor[3];
446  cgltf_float glossiness_factor;
448 
449 typedef struct cgltf_clearcoat
450 {
454 
455  cgltf_float clearcoat_factor;
458 
459 typedef struct cgltf_transmission
460 {
462  cgltf_float transmission_factor;
464 
465 typedef struct cgltf_ior
466 {
467  cgltf_float ior;
468 } cgltf_ior;
469 
470 typedef struct cgltf_specular
471 {
474  cgltf_float specular_color_factor[3];
475  cgltf_float specular_factor;
477 
478 typedef struct cgltf_volume
479 {
481  cgltf_float thickness_factor;
482  cgltf_float attenuation_color[3];
483  cgltf_float attenuation_distance;
484 } cgltf_volume;
485 
486 typedef struct cgltf_sheen
487 {
489  cgltf_float sheen_color_factor[3];
492 } cgltf_sheen;
493 
495 {
496  cgltf_float emissive_strength;
498 
499 typedef struct cgltf_iridescence
500 {
501  cgltf_float iridescence_factor;
503  cgltf_float iridescence_ior;
508 
509 typedef struct cgltf_material
510 {
511  char* name;
514  cgltf_bool has_clearcoat;
515  cgltf_bool has_transmission;
516  cgltf_bool has_volume;
517  cgltf_bool has_ior;
518  cgltf_bool has_specular;
519  cgltf_bool has_sheen;
521  cgltf_bool has_iridescence;
535  cgltf_float emissive_factor[3];
537  cgltf_float alpha_cutoff;
538  cgltf_bool double_sided;
539  cgltf_bool unlit;
541  cgltf_size extensions_count;
544 
546 {
547  cgltf_size variant;
551 
552 typedef struct cgltf_morph_target {
554  cgltf_size attributes_count;
556 
560  cgltf_size attributes_count;
562 
566  cgltf_size attributes_count;
568 
569 typedef struct cgltf_primitive {
574  cgltf_size attributes_count;
576  cgltf_size targets_count;
581  cgltf_size mappings_count;
582  cgltf_size extensions_count;
585 
586 typedef struct cgltf_mesh {
587  char* name;
589  cgltf_size primitives_count;
590  cgltf_float* weights;
591  cgltf_size weights_count;
592  char** target_names;
593  cgltf_size target_names_count;
595  cgltf_size extensions_count;
597 } cgltf_mesh;
598 
599 typedef struct cgltf_node cgltf_node;
600 
601 typedef struct cgltf_skin {
602  char* name;
604  cgltf_size joints_count;
608  cgltf_size extensions_count;
610 } cgltf_skin;
611 
612 typedef struct cgltf_camera_perspective {
613  cgltf_bool has_aspect_ratio;
614  cgltf_float aspect_ratio;
615  cgltf_float yfov;
616  cgltf_bool has_zfar;
617  cgltf_float zfar;
618  cgltf_float znear;
621 
623  cgltf_float xmag;
624  cgltf_float ymag;
625  cgltf_float zfar;
626  cgltf_float znear;
629 
630 typedef struct cgltf_camera {
631  char* name;
633  union {
636  } data;
638  cgltf_size extensions_count;
640 } cgltf_camera;
641 
642 typedef struct cgltf_light {
643  char* name;
644  cgltf_float color[3];
645  cgltf_float intensity;
647  cgltf_float range;
651 } cgltf_light;
652 
653 struct cgltf_node {
654  char* name;
657  cgltf_size children_count;
662  cgltf_float* weights;
663  cgltf_size weights_count;
664  cgltf_bool has_translation;
665  cgltf_bool has_rotation;
666  cgltf_bool has_scale;
667  cgltf_bool has_matrix;
668  cgltf_float translation[3];
669  cgltf_float rotation[4];
670  cgltf_float scale[3];
671  cgltf_float matrix[16];
675  cgltf_size extensions_count;
677 };
678 
679 typedef struct cgltf_scene {
680  char* name;
682  cgltf_size nodes_count;
684  cgltf_size extensions_count;
686 } cgltf_scene;
687 
688 typedef struct cgltf_animation_sampler {
693  cgltf_size extensions_count;
696 
697 typedef struct cgltf_animation_channel {
702  cgltf_size extensions_count;
705 
706 typedef struct cgltf_animation {
707  char* name;
709  cgltf_size samplers_count;
711  cgltf_size channels_count;
713  cgltf_size extensions_count;
716 
718 {
719  char* name;
722 
723 typedef struct cgltf_asset {
724  char* copyright;
725  char* generator;
726  char* version;
727  char* min_version;
729  cgltf_size extensions_count;
731 } cgltf_asset;
732 
733 typedef struct cgltf_data
734 {
736  void* file_data;
737 
739 
741  cgltf_size meshes_count;
742 
744  cgltf_size materials_count;
745 
747  cgltf_size accessors_count;
748 
750  cgltf_size buffer_views_count;
751 
753  cgltf_size buffers_count;
754 
756  cgltf_size images_count;
757 
759  cgltf_size textures_count;
760 
762  cgltf_size samplers_count;
763 
765  cgltf_size skins_count;
766 
768  cgltf_size cameras_count;
769 
771  cgltf_size lights_count;
772 
774  cgltf_size nodes_count;
775 
777  cgltf_size scenes_count;
778 
780 
782  cgltf_size animations_count;
783 
785  cgltf_size variants_count;
786 
788 
791 
794 
797 
798  const char* json;
799  cgltf_size json_size;
800 
801  const void* bin;
802  cgltf_size bin_size;
803 
806 } cgltf_data;
807 
809  const cgltf_options* options,
810  const void* data,
811  cgltf_size size,
812  cgltf_data** out_data);
813 
815  const cgltf_options* options,
816  const char* path,
817  cgltf_data** out_data);
818 
820  const cgltf_options* options,
821  cgltf_data* data,
822  const char* gltf_path);
823 
824 cgltf_result cgltf_load_buffer_base64(const cgltf_options* options, cgltf_size size, const char* base64, void** out_data);
825 
826 cgltf_size cgltf_decode_string(char* string);
827 cgltf_size cgltf_decode_uri(char* uri);
828 
830 
831 void cgltf_free(cgltf_data* data);
832 
833 void cgltf_node_transform_local(const cgltf_node* node, cgltf_float* out_matrix);
834 void cgltf_node_transform_world(const cgltf_node* node, cgltf_float* out_matrix);
835 
836 cgltf_bool cgltf_accessor_read_float(const cgltf_accessor* accessor, cgltf_size index, cgltf_float* out, cgltf_size element_size);
837 cgltf_bool cgltf_accessor_read_uint(const cgltf_accessor* accessor, cgltf_size index, cgltf_uint* out, cgltf_size element_size);
838 cgltf_size cgltf_accessor_read_index(const cgltf_accessor* accessor, cgltf_size index);
839 
841 
842 cgltf_size cgltf_accessor_unpack_floats(const cgltf_accessor* accessor, cgltf_float* out, cgltf_size float_count);
843 
844 cgltf_result cgltf_copy_extras_json(const cgltf_data* data, const cgltf_extras* extras, char* dest, cgltf_size* dest_size);
845 
846 #ifdef __cplusplus
847 }
848 #endif
849 
850 #endif /* #ifndef CGLTF_H_INCLUDED__ */
851 
852 /*
853  *
854  * Stop now, if you are only interested in the API.
855  * Below, you find the implementation.
856  *
857  */
858 
859 #if defined(__INTELLISENSE__) || defined(__JETBRAINS_IDE__)
860 /* This makes MSVC/CLion intellisense work. */
861 #define CGLTF_IMPLEMENTATION
862 #endif
863 
864 #ifdef CGLTF_IMPLEMENTATION
865 
866 #include <stdint.h> /* For uint8_t, uint32_t */
867 #include <string.h> /* For strncpy */
868 #include <stdio.h> /* For fopen */
869 #include <limits.h> /* For UINT_MAX etc */
870 #include <float.h> /* For FLT_MAX */
871 
872 #if !defined(CGLTF_MALLOC) || !defined(CGLTF_FREE) || !defined(CGLTF_ATOI) || !defined(CGLTF_ATOF) || !defined(CGLTF_ATOLL)
873 #include <stdlib.h> /* For malloc, free, atoi, atof */
874 #endif
875 
876 #if CGLTF_VALIDATE_ENABLE_ASSERTS
877 #include <assert.h>
878 #endif
879 
880 /* JSMN_PARENT_LINKS is necessary to make parsing large structures linear in input size */
881 #define JSMN_PARENT_LINKS
882 
883 /* JSMN_STRICT is necessary to reject invalid JSON documents */
884 #define JSMN_STRICT
885 
886 /*
887  * -- jsmn.h start --
888  * Source: https://github.com/zserge/jsmn
889  * License: MIT
890  */
891 typedef enum {
892  JSMN_UNDEFINED = 0,
893  JSMN_OBJECT = 1,
894  JSMN_ARRAY = 2,
895  JSMN_STRING = 3,
896  JSMN_PRIMITIVE = 4
897 } jsmntype_t;
898 enum jsmnerr {
899  /* Not enough tokens were provided */
900  JSMN_ERROR_NOMEM = -1,
901  /* Invalid character inside JSON string */
902  JSMN_ERROR_INVAL = -2,
903  /* The string is not a full JSON packet, more bytes expected */
904  JSMN_ERROR_PART = -3
905 };
906 typedef struct {
907  jsmntype_t type;
908  int start;
909  int end;
910  int size;
911 #ifdef JSMN_PARENT_LINKS
912  int parent;
913 #endif
914 } jsmntok_t;
915 typedef struct {
916  unsigned int pos; /* offset in the JSON string */
917  unsigned int toknext; /* next token to allocate */
918  int toksuper; /* superior token node, e.g parent object or array */
919 } jsmn_parser;
920 static void jsmn_init(jsmn_parser *parser);
921 static int jsmn_parse(jsmn_parser *parser, const char *js, size_t len, jsmntok_t *tokens, size_t num_tokens);
922 /*
923  * -- jsmn.h end --
924  */
925 
926 
927 static const cgltf_size GlbHeaderSize = 12;
928 static const cgltf_size GlbChunkHeaderSize = 8;
929 static const uint32_t GlbVersion = 2;
930 static const uint32_t GlbMagic = 0x46546C67;
931 static const uint32_t GlbMagicJsonChunk = 0x4E4F534A;
932 static const uint32_t GlbMagicBinChunk = 0x004E4942;
933 
934 #ifndef CGLTF_MALLOC
935 #define CGLTF_MALLOC(size) malloc(size)
936 #endif
937 #ifndef CGLTF_FREE
938 #define CGLTF_FREE(ptr) free(ptr)
939 #endif
940 #ifndef CGLTF_ATOI
941 #define CGLTF_ATOI(str) atoi(str)
942 #endif
943 #ifndef CGLTF_ATOF
944 #define CGLTF_ATOF(str) atof(str)
945 #endif
946 #ifndef CGLTF_ATOLL
947 #define CGLTF_ATOLL(str) atoll(str)
948 #endif
949 #ifndef CGLTF_VALIDATE_ENABLE_ASSERTS
950 #define CGLTF_VALIDATE_ENABLE_ASSERTS 0
951 #endif
952 
953 static void* cgltf_default_alloc(void* user, cgltf_size size)
954 {
955  (void)user;
956  return CGLTF_MALLOC(size);
957 }
958 
959 static void cgltf_default_free(void* user, void* ptr)
960 {
961  (void)user;
962  CGLTF_FREE(ptr);
963 }
964 
965 static void* cgltf_calloc(cgltf_options* options, size_t element_size, cgltf_size count)
966 {
967  if (SIZE_MAX / element_size < count)
968  {
969  return NULL;
970  }
971  void* result = options->memory.alloc_func(options->memory.user_data, element_size * count);
972  if (!result)
973  {
974  return NULL;
975  }
976  memset(result, 0, element_size * count);
977  return result;
978 }
979 
980 static cgltf_result cgltf_default_file_read(const struct cgltf_memory_options* memory_options, const struct cgltf_file_options* file_options, const char* path, cgltf_size* size, void** data)
981 {
982  (void)file_options;
983  void* (*memory_alloc)(void*, cgltf_size) = memory_options->alloc_func ? memory_options->alloc_func : &cgltf_default_alloc;
984  void (*memory_free)(void*, void*) = memory_options->free_func ? memory_options->free_func : &cgltf_default_free;
985 
986  FILE* file = fopen(path, "rb");
987  if (!file)
988  {
990  }
991 
992  cgltf_size file_size = size ? *size : 0;
993 
994  if (file_size == 0)
995  {
996  fseek(file, 0, SEEK_END);
997 
998 #ifdef _WIN32
999  __int64 length = _ftelli64(file);
1000 #else
1001  long length = ftell(file);
1002 #endif
1003 
1004  if (length < 0)
1005  {
1006  fclose(file);
1007  return cgltf_result_io_error;
1008  }
1009 
1010  fseek(file, 0, SEEK_SET);
1011  file_size = (cgltf_size)length;
1012  }
1013 
1014  char* file_data = (char*)memory_alloc(memory_options->user_data, file_size);
1015  if (!file_data)
1016  {
1017  fclose(file);
1019  }
1020 
1021  cgltf_size read_size = fread(file_data, 1, file_size, file);
1022 
1023  fclose(file);
1024 
1025  if (read_size != file_size)
1026  {
1027  memory_free(memory_options->user_data, file_data);
1028  return cgltf_result_io_error;
1029  }
1030 
1031  if (size)
1032  {
1033  *size = file_size;
1034  }
1035  if (data)
1036  {
1037  *data = file_data;
1038  }
1039 
1040  return cgltf_result_success;
1041 }
1042 
1043 static void cgltf_default_file_release(const struct cgltf_memory_options* memory_options, const struct cgltf_file_options* file_options, void* data)
1044 {
1045  (void)file_options;
1046  void (*memfree)(void*, void*) = memory_options->free_func ? memory_options->free_func : &cgltf_default_free;
1047  memfree(memory_options->user_data, data);
1048 }
1049 
1050 static cgltf_result cgltf_parse_json(cgltf_options* options, const uint8_t* json_chunk, cgltf_size size, cgltf_data** out_data);
1051 
1052 cgltf_result cgltf_parse(const cgltf_options* options, const void* data, cgltf_size size, cgltf_data** out_data)
1053 {
1054  if (size < GlbHeaderSize)
1055  {
1057  }
1058 
1059  if (options == NULL)
1060  {
1062  }
1063 
1064  cgltf_options fixed_options = *options;
1065  if (fixed_options.memory.alloc_func == NULL)
1066  {
1067  fixed_options.memory.alloc_func = &cgltf_default_alloc;
1068  }
1069  if (fixed_options.memory.free_func == NULL)
1070  {
1071  fixed_options.memory.free_func = &cgltf_default_free;
1072  }
1073 
1074  uint32_t tmp;
1075  // Magic
1076  memcpy(&tmp, data, 4);
1077  if (tmp != GlbMagic)
1078  {
1079  if (fixed_options.type == cgltf_file_type_invalid)
1080  {
1081  fixed_options.type = cgltf_file_type_gltf;
1082  }
1083  else if (fixed_options.type == cgltf_file_type_glb)
1084  {
1086  }
1087  }
1088 
1089  if (fixed_options.type == cgltf_file_type_gltf)
1090  {
1091  cgltf_result json_result = cgltf_parse_json(&fixed_options, (const uint8_t*)data, size, out_data);
1092  if (json_result != cgltf_result_success)
1093  {
1094  return json_result;
1095  }
1096 
1097  (*out_data)->file_type = cgltf_file_type_gltf;
1098 
1099  return cgltf_result_success;
1100  }
1101 
1102  const uint8_t* ptr = (const uint8_t*)data;
1103  // Version
1104  memcpy(&tmp, ptr + 4, 4);
1105  uint32_t version = tmp;
1106  if (version != GlbVersion)
1107  {
1108  return version < GlbVersion ? cgltf_result_legacy_gltf : cgltf_result_unknown_format;
1109  }
1110 
1111  // Total length
1112  memcpy(&tmp, ptr + 8, 4);
1113  if (tmp > size)
1114  {
1116  }
1117 
1118  const uint8_t* json_chunk = ptr + GlbHeaderSize;
1119 
1120  if (GlbHeaderSize + GlbChunkHeaderSize > size)
1121  {
1123  }
1124 
1125  // JSON chunk: length
1126  uint32_t json_length;
1127  memcpy(&json_length, json_chunk, 4);
1128  if (GlbHeaderSize + GlbChunkHeaderSize + json_length > size)
1129  {
1131  }
1132 
1133  // JSON chunk: magic
1134  memcpy(&tmp, json_chunk + 4, 4);
1135  if (tmp != GlbMagicJsonChunk)
1136  {
1138  }
1139 
1140  json_chunk += GlbChunkHeaderSize;
1141 
1142  const void* bin = 0;
1143  cgltf_size bin_size = 0;
1144 
1145  if (GlbHeaderSize + GlbChunkHeaderSize + json_length + GlbChunkHeaderSize <= size)
1146  {
1147  // We can read another chunk
1148  const uint8_t* bin_chunk = json_chunk + json_length;
1149 
1150  // Bin chunk: length
1151  uint32_t bin_length;
1152  memcpy(&bin_length, bin_chunk, 4);
1153  if (GlbHeaderSize + GlbChunkHeaderSize + json_length + GlbChunkHeaderSize + bin_length > size)
1154  {
1156  }
1157 
1158  // Bin chunk: magic
1159  memcpy(&tmp, bin_chunk + 4, 4);
1160  if (tmp != GlbMagicBinChunk)
1161  {
1163  }
1164 
1165  bin_chunk += GlbChunkHeaderSize;
1166 
1167  bin = bin_chunk;
1168  bin_size = bin_length;
1169  }
1170 
1171  cgltf_result json_result = cgltf_parse_json(&fixed_options, json_chunk, json_length, out_data);
1172  if (json_result != cgltf_result_success)
1173  {
1174  return json_result;
1175  }
1176 
1177  (*out_data)->file_type = cgltf_file_type_glb;
1178  (*out_data)->bin = bin;
1179  (*out_data)->bin_size = bin_size;
1180 
1181  return cgltf_result_success;
1182 }
1183 
1184 cgltf_result cgltf_parse_file(const cgltf_options* options, const char* path, cgltf_data** out_data)
1185 {
1186  if (options == NULL)
1187  {
1189  }
1190 
1191  cgltf_result (*file_read)(const struct cgltf_memory_options*, const struct cgltf_file_options*, const char*, cgltf_size*, void**) = options->file.read ? options->file.read : &cgltf_default_file_read;
1192  void (*file_release)(const struct cgltf_memory_options*, const struct cgltf_file_options*, void* data) = options->file.release ? options->file.release : cgltf_default_file_release;
1193 
1194  void* file_data = NULL;
1195  cgltf_size file_size = 0;
1196  cgltf_result result = file_read(&options->memory, &options->file, path, &file_size, &file_data);
1197  if (result != cgltf_result_success)
1198  {
1199  return result;
1200  }
1201 
1202  result = cgltf_parse(options, file_data, file_size, out_data);
1203 
1204  if (result != cgltf_result_success)
1205  {
1206  file_release(&options->memory, &options->file, file_data);
1207  return result;
1208  }
1209 
1210  (*out_data)->file_data = file_data;
1211 
1212  return cgltf_result_success;
1213 }
1214 
1215 static void cgltf_combine_paths(char* path, const char* base, const char* uri)
1216 {
1217  const char* s0 = strrchr(base, '/');
1218  const char* s1 = strrchr(base, '\\');
1219  const char* slash = s0 ? (s1 && s1 > s0 ? s1 : s0) : s1;
1220 
1221  if (slash)
1222  {
1223  size_t prefix = slash - base + 1;
1224 
1225  strncpy(path, base, prefix);
1226  strcpy(path + prefix, uri);
1227  }
1228  else
1229  {
1230  strcpy(path, uri);
1231  }
1232 }
1233 
1234 static cgltf_result cgltf_load_buffer_file(const cgltf_options* options, cgltf_size size, const char* uri, const char* gltf_path, void** out_data)
1235 {
1236  void* (*memory_alloc)(void*, cgltf_size) = options->memory.alloc_func ? options->memory.alloc_func : &cgltf_default_alloc;
1237  void (*memory_free)(void*, void*) = options->memory.free_func ? options->memory.free_func : &cgltf_default_free;
1238  cgltf_result (*file_read)(const struct cgltf_memory_options*, const struct cgltf_file_options*, const char*, cgltf_size*, void**) = options->file.read ? options->file.read : &cgltf_default_file_read;
1239 
1240  char* path = (char*)memory_alloc(options->memory.user_data, strlen(uri) + strlen(gltf_path) + 1);
1241  if (!path)
1242  {
1244  }
1245 
1246  cgltf_combine_paths(path, gltf_path, uri);
1247 
1248  // after combining, the tail of the resulting path is a uri; decode_uri converts it into path
1249  cgltf_decode_uri(path + strlen(path) - strlen(uri));
1250 
1251  void* file_data = NULL;
1252  cgltf_result result = file_read(&options->memory, &options->file, path, &size, &file_data);
1253 
1254  memory_free(options->memory.user_data, path);
1255 
1256  *out_data = (result == cgltf_result_success) ? file_data : NULL;
1257 
1258  return result;
1259 }
1260 
1261 cgltf_result cgltf_load_buffer_base64(const cgltf_options* options, cgltf_size size, const char* base64, void** out_data)
1262 {
1263  void* (*memory_alloc)(void*, cgltf_size) = options->memory.alloc_func ? options->memory.alloc_func : &cgltf_default_alloc;
1264  void (*memory_free)(void*, void*) = options->memory.free_func ? options->memory.free_func : &cgltf_default_free;
1265 
1266  unsigned char* data = (unsigned char*)memory_alloc(options->memory.user_data, size);
1267  if (!data)
1268  {
1270  }
1271 
1272  unsigned int buffer = 0;
1273  unsigned int buffer_bits = 0;
1274 
1275  for (cgltf_size i = 0; i < size; ++i)
1276  {
1277  while (buffer_bits < 8)
1278  {
1279  char ch = *base64++;
1280 
1281  int index =
1282  (unsigned)(ch - 'A') < 26 ? (ch - 'A') :
1283  (unsigned)(ch - 'a') < 26 ? (ch - 'a') + 26 :
1284  (unsigned)(ch - '0') < 10 ? (ch - '0') + 52 :
1285  ch == '+' ? 62 :
1286  ch == '/' ? 63 :
1287  -1;
1288 
1289  if (index < 0)
1290  {
1291  memory_free(options->memory.user_data, data);
1292  return cgltf_result_io_error;
1293  }
1294 
1295  buffer = (buffer << 6) | index;
1296  buffer_bits += 6;
1297  }
1298 
1299  data[i] = (unsigned char)(buffer >> (buffer_bits - 8));
1300  buffer_bits -= 8;
1301  }
1302 
1303  *out_data = data;
1304 
1305  return cgltf_result_success;
1306 }
1307 
1308 static int cgltf_unhex(char ch)
1309 {
1310  return
1311  (unsigned)(ch - '0') < 10 ? (ch - '0') :
1312  (unsigned)(ch - 'A') < 6 ? (ch - 'A') + 10 :
1313  (unsigned)(ch - 'a') < 6 ? (ch - 'a') + 10 :
1314  -1;
1315 }
1316 
1317 cgltf_size cgltf_decode_string(char* string)
1318 {
1319  char* read = string + strcspn(string, "\\");
1320  if (*read == 0)
1321  {
1322  return read - string;
1323  }
1324  char* write = string;
1325  char* last = string;
1326 
1327  for (;;)
1328  {
1329  // Copy characters since last escaped sequence
1330  cgltf_size written = read - last;
1331  memmove(write, last, written);
1332  write += written;
1333 
1334  if (*read++ == 0)
1335  {
1336  break;
1337  }
1338 
1339  // jsmn already checked that all escape sequences are valid
1340  switch (*read++)
1341  {
1342  case '\"': *write++ = '\"'; break;
1343  case '/': *write++ = '/'; break;
1344  case '\\': *write++ = '\\'; break;
1345  case 'b': *write++ = '\b'; break;
1346  case 'f': *write++ = '\f'; break;
1347  case 'r': *write++ = '\r'; break;
1348  case 'n': *write++ = '\n'; break;
1349  case 't': *write++ = '\t'; break;
1350  case 'u':
1351  {
1352  // UCS-2 codepoint \uXXXX to UTF-8
1353  int character = 0;
1354  for (cgltf_size i = 0; i < 4; ++i)
1355  {
1356  character = (character << 4) + cgltf_unhex(*read++);
1357  }
1358 
1359  if (character <= 0x7F)
1360  {
1361  *write++ = character & 0xFF;
1362  }
1363  else if (character <= 0x7FF)
1364  {
1365  *write++ = 0xC0 | ((character >> 6) & 0xFF);
1366  *write++ = 0x80 | (character & 0x3F);
1367  }
1368  else
1369  {
1370  *write++ = 0xE0 | ((character >> 12) & 0xFF);
1371  *write++ = 0x80 | ((character >> 6) & 0x3F);
1372  *write++ = 0x80 | (character & 0x3F);
1373  }
1374  break;
1375  }
1376  default:
1377  break;
1378  }
1379 
1380  last = read;
1381  read += strcspn(read, "\\");
1382  }
1383 
1384  *write = 0;
1385  return write - string;
1386 }
1387 
1388 cgltf_size cgltf_decode_uri(char* uri)
1389 {
1390  char* write = uri;
1391  char* i = uri;
1392 
1393  while (*i)
1394  {
1395  if (*i == '%')
1396  {
1397  int ch1 = cgltf_unhex(i[1]);
1398 
1399  if (ch1 >= 0)
1400  {
1401  int ch2 = cgltf_unhex(i[2]);
1402 
1403  if (ch2 >= 0)
1404  {
1405  *write++ = (char)(ch1 * 16 + ch2);
1406  i += 3;
1407  continue;
1408  }
1409  }
1410  }
1411 
1412  *write++ = *i++;
1413  }
1414 
1415  *write = 0;
1416  return write - uri;
1417 }
1418 
1419 cgltf_result cgltf_load_buffers(const cgltf_options* options, cgltf_data* data, const char* gltf_path)
1420 {
1421  if (options == NULL)
1422  {
1424  }
1425 
1426  if (data->buffers_count && data->buffers[0].data == NULL && data->buffers[0].uri == NULL && data->bin)
1427  {
1428  if (data->bin_size < data->buffers[0].size)
1429  {
1431  }
1432 
1433  data->buffers[0].data = (void*)data->bin;
1435  }
1436 
1437  for (cgltf_size i = 0; i < data->buffers_count; ++i)
1438  {
1439  if (data->buffers[i].data)
1440  {
1441  continue;
1442  }
1443 
1444  const char* uri = data->buffers[i].uri;
1445 
1446  if (uri == NULL)
1447  {
1448  continue;
1449  }
1450 
1451  if (strncmp(uri, "data:", 5) == 0)
1452  {
1453  const char* comma = strchr(uri, ',');
1454 
1455  if (comma && comma - uri >= 7 && strncmp(comma - 7, ";base64", 7) == 0)
1456  {
1457  cgltf_result res = cgltf_load_buffer_base64(options, data->buffers[i].size, comma + 1, &data->buffers[i].data);
1459 
1460  if (res != cgltf_result_success)
1461  {
1462  return res;
1463  }
1464  }
1465  else
1466  {
1468  }
1469  }
1470  else if (strstr(uri, "://") == NULL && gltf_path)
1471  {
1472  cgltf_result res = cgltf_load_buffer_file(options, data->buffers[i].size, uri, gltf_path, &data->buffers[i].data);
1474 
1475  if (res != cgltf_result_success)
1476  {
1477  return res;
1478  }
1479  }
1480  else
1481  {
1483  }
1484  }
1485 
1486  return cgltf_result_success;
1487 }
1488 
1489 static cgltf_size cgltf_calc_size(cgltf_type type, cgltf_component_type component_type);
1490 
1491 static cgltf_size cgltf_calc_index_bound(cgltf_buffer_view* buffer_view, cgltf_size offset, cgltf_component_type component_type, cgltf_size count)
1492 {
1493  char* data = (char*)buffer_view->buffer->data + offset + buffer_view->offset;
1494  cgltf_size bound = 0;
1495 
1496  switch (component_type)
1497  {
1499  for (size_t i = 0; i < count; ++i)
1500  {
1501  cgltf_size v = ((unsigned char*)data)[i];
1502  bound = bound > v ? bound : v;
1503  }
1504  break;
1505 
1507  for (size_t i = 0; i < count; ++i)
1508  {
1509  cgltf_size v = ((unsigned short*)data)[i];
1510  bound = bound > v ? bound : v;
1511  }
1512  break;
1513 
1515  for (size_t i = 0; i < count; ++i)
1516  {
1517  cgltf_size v = ((unsigned int*)data)[i];
1518  bound = bound > v ? bound : v;
1519  }
1520  break;
1521 
1522  default:
1523  ;
1524  }
1525 
1526  return bound;
1527 }
1528 
1529 #if CGLTF_VALIDATE_ENABLE_ASSERTS
1530 #define CGLTF_ASSERT_IF(cond, result) assert(!(cond)); if (cond) return result;
1531 #else
1532 #define CGLTF_ASSERT_IF(cond, result) if (cond) return result;
1533 #endif
1534 
1536 {
1537  for (cgltf_size i = 0; i < data->accessors_count; ++i)
1538  {
1539  cgltf_accessor* accessor = &data->accessors[i];
1540 
1541  cgltf_size element_size = cgltf_calc_size(accessor->type, accessor->component_type);
1542 
1543  if (accessor->buffer_view)
1544  {
1545  cgltf_size req_size = accessor->offset + accessor->stride * (accessor->count - 1) + element_size;
1546 
1547  CGLTF_ASSERT_IF(accessor->buffer_view->size < req_size, cgltf_result_data_too_short);
1548  }
1549 
1550  if (accessor->is_sparse)
1551  {
1552  cgltf_accessor_sparse* sparse = &accessor->sparse;
1553 
1554  cgltf_size indices_component_size = cgltf_calc_size(cgltf_type_scalar, sparse->indices_component_type);
1555  cgltf_size indices_req_size = sparse->indices_byte_offset + indices_component_size * sparse->count;
1556  cgltf_size values_req_size = sparse->values_byte_offset + element_size * sparse->count;
1557 
1558  CGLTF_ASSERT_IF(sparse->indices_buffer_view->size < indices_req_size ||
1559  sparse->values_buffer_view->size < values_req_size, cgltf_result_data_too_short);
1560 
1561  CGLTF_ASSERT_IF(sparse->indices_component_type != cgltf_component_type_r_8u &&
1564 
1565  if (sparse->indices_buffer_view->buffer->data)
1566  {
1567  cgltf_size index_bound = cgltf_calc_index_bound(sparse->indices_buffer_view, sparse->indices_byte_offset, sparse->indices_component_type, sparse->count);
1568 
1569  CGLTF_ASSERT_IF(index_bound >= accessor->count, cgltf_result_data_too_short);
1570  }
1571  }
1572  }
1573 
1574  for (cgltf_size i = 0; i < data->buffer_views_count; ++i)
1575  {
1576  cgltf_size req_size = data->buffer_views[i].offset + data->buffer_views[i].size;
1577 
1578  CGLTF_ASSERT_IF(data->buffer_views[i].buffer && data->buffer_views[i].buffer->size < req_size, cgltf_result_data_too_short);
1579 
1581  {
1583 
1584  CGLTF_ASSERT_IF(mc->buffer == NULL || mc->buffer->size < mc->offset + mc->size, cgltf_result_data_too_short);
1585 
1586  CGLTF_ASSERT_IF(data->buffer_views[i].stride && mc->stride != data->buffer_views[i].stride, cgltf_result_invalid_gltf);
1587 
1588  CGLTF_ASSERT_IF(data->buffer_views[i].size != mc->stride * mc->count, cgltf_result_invalid_gltf);
1589 
1591 
1592  CGLTF_ASSERT_IF(mc->mode == cgltf_meshopt_compression_mode_attributes && !(mc->stride % 4 == 0 && mc->stride <= 256), cgltf_result_invalid_gltf);
1593 
1594  CGLTF_ASSERT_IF(mc->mode == cgltf_meshopt_compression_mode_triangles && mc->count % 3 != 0, cgltf_result_invalid_gltf);
1595 
1597 
1599 
1600  CGLTF_ASSERT_IF(mc->filter == cgltf_meshopt_compression_filter_octahedral && mc->stride != 4 && mc->stride != 8, cgltf_result_invalid_gltf);
1601 
1603  }
1604  }
1605 
1606  for (cgltf_size i = 0; i < data->meshes_count; ++i)
1607  {
1608  if (data->meshes[i].weights)
1609  {
1610  CGLTF_ASSERT_IF(data->meshes[i].primitives_count && data->meshes[i].primitives[0].targets_count != data->meshes[i].weights_count, cgltf_result_invalid_gltf);
1611  }
1612 
1613  if (data->meshes[i].target_names)
1614  {
1615  CGLTF_ASSERT_IF(data->meshes[i].primitives_count && data->meshes[i].primitives[0].targets_count != data->meshes[i].target_names_count, cgltf_result_invalid_gltf);
1616  }
1617 
1618  for (cgltf_size j = 0; j < data->meshes[i].primitives_count; ++j)
1619  {
1620  CGLTF_ASSERT_IF(data->meshes[i].primitives[j].targets_count != data->meshes[i].primitives[0].targets_count, cgltf_result_invalid_gltf);
1621 
1622  if (data->meshes[i].primitives[j].attributes_count)
1623  {
1625 
1626  for (cgltf_size k = 0; k < data->meshes[i].primitives[j].attributes_count; ++k)
1627  {
1628  CGLTF_ASSERT_IF(data->meshes[i].primitives[j].attributes[k].data->count != first->count, cgltf_result_invalid_gltf);
1629  }
1630 
1631  for (cgltf_size k = 0; k < data->meshes[i].primitives[j].targets_count; ++k)
1632  {
1633  for (cgltf_size m = 0; m < data->meshes[i].primitives[j].targets[k].attributes_count; ++m)
1634  {
1635  CGLTF_ASSERT_IF(data->meshes[i].primitives[j].targets[k].attributes[m].data->count != first->count, cgltf_result_invalid_gltf);
1636  }
1637  }
1638 
1640 
1641  CGLTF_ASSERT_IF(indices &&
1645 
1646  if (indices && indices->buffer_view && indices->buffer_view->buffer->data)
1647  {
1648  cgltf_size index_bound = cgltf_calc_index_bound(indices->buffer_view, indices->offset, indices->component_type, indices->count);
1649 
1650  CGLTF_ASSERT_IF(index_bound >= first->count, cgltf_result_data_too_short);
1651  }
1652 
1653  for (cgltf_size k = 0; k < data->meshes[i].primitives[j].mappings_count; ++k)
1654  {
1655  CGLTF_ASSERT_IF(data->meshes[i].primitives[j].mappings[k].variant >= data->variants_count, cgltf_result_invalid_gltf);
1656  }
1657  }
1658  }
1659  }
1660 
1661  for (cgltf_size i = 0; i < data->nodes_count; ++i)
1662  {
1663  if (data->nodes[i].weights && data->nodes[i].mesh)
1664  {
1665  CGLTF_ASSERT_IF (data->nodes[i].mesh->primitives_count && data->nodes[i].mesh->primitives[0].targets_count != data->nodes[i].weights_count, cgltf_result_invalid_gltf);
1666  }
1667  }
1668 
1669  for (cgltf_size i = 0; i < data->nodes_count; ++i)
1670  {
1671  cgltf_node* p1 = data->nodes[i].parent;
1672  cgltf_node* p2 = p1 ? p1->parent : NULL;
1673 
1674  while (p1 && p2)
1675  {
1676  CGLTF_ASSERT_IF(p1 == p2, cgltf_result_invalid_gltf);
1677 
1678  p1 = p1->parent;
1679  p2 = p2->parent ? p2->parent->parent : NULL;
1680  }
1681  }
1682 
1683  for (cgltf_size i = 0; i < data->scenes_count; ++i)
1684  {
1685  for (cgltf_size j = 0; j < data->scenes[i].nodes_count; ++j)
1686  {
1687  CGLTF_ASSERT_IF(data->scenes[i].nodes[j]->parent, cgltf_result_invalid_gltf);
1688  }
1689  }
1690 
1691  for (cgltf_size i = 0; i < data->animations_count; ++i)
1692  {
1693  for (cgltf_size j = 0; j < data->animations[i].channels_count; ++j)
1694  {
1695  cgltf_animation_channel* channel = &data->animations[i].channels[j];
1696 
1697  if (!channel->target_node)
1698  {
1699  continue;
1700  }
1701 
1702  cgltf_size components = 1;
1703 
1705  {
1706  CGLTF_ASSERT_IF(!channel->target_node->mesh || !channel->target_node->mesh->primitives_count, cgltf_result_invalid_gltf);
1707 
1708  components = channel->target_node->mesh->primitives[0].targets_count;
1709  }
1710 
1711  cgltf_size values = channel->sampler->interpolation == cgltf_interpolation_type_cubic_spline ? 3 : 1;
1712 
1713  CGLTF_ASSERT_IF(channel->sampler->input->count * components * values != channel->sampler->output->count, cgltf_result_data_too_short);
1714  }
1715  }
1716 
1717  return cgltf_result_success;
1718 }
1719 
1720 cgltf_result cgltf_copy_extras_json(const cgltf_data* data, const cgltf_extras* extras, char* dest, cgltf_size* dest_size)
1721 {
1722  cgltf_size json_size = extras->end_offset - extras->start_offset;
1723 
1724  if (!dest)
1725  {
1726  if (dest_size)
1727  {
1728  *dest_size = json_size + 1;
1729  return cgltf_result_success;
1730  }
1732  }
1733 
1734  if (*dest_size + 1 < json_size)
1735  {
1736  strncpy(dest, data->json + extras->start_offset, *dest_size - 1);
1737  dest[*dest_size - 1] = 0;
1738  }
1739  else
1740  {
1741  strncpy(dest, data->json + extras->start_offset, json_size);
1742  dest[json_size] = 0;
1743  }
1744 
1745  return cgltf_result_success;
1746 }
1747 
1748 void cgltf_free_extensions(cgltf_data* data, cgltf_extension* extensions, cgltf_size extensions_count)
1749 {
1750  for (cgltf_size i = 0; i < extensions_count; ++i)
1751  {
1752  data->memory.free_func(data->memory.user_data, extensions[i].name);
1753  data->memory.free_func(data->memory.user_data, extensions[i].data);
1754  }
1755  data->memory.free_func(data->memory.user_data, extensions);
1756 }
1757 
1758 void cgltf_free(cgltf_data* data)
1759 {
1760  if (!data)
1761  {
1762  return;
1763  }
1764 
1765  void (*file_release)(const struct cgltf_memory_options*, const struct cgltf_file_options*, void* data) = data->file.release ? data->file.release : cgltf_default_file_release;
1766 
1767  data->memory.free_func(data->memory.user_data, data->asset.copyright);
1768  data->memory.free_func(data->memory.user_data, data->asset.generator);
1769  data->memory.free_func(data->memory.user_data, data->asset.version);
1770  data->memory.free_func(data->memory.user_data, data->asset.min_version);
1771 
1772  cgltf_free_extensions(data, data->asset.extensions, data->asset.extensions_count);
1773 
1774  for (cgltf_size i = 0; i < data->accessors_count; ++i)
1775  {
1776  data->memory.free_func(data->memory.user_data, data->accessors[i].name);
1777 
1778  if(data->accessors[i].is_sparse)
1779  {
1780  cgltf_free_extensions(data, data->accessors[i].sparse.extensions, data->accessors[i].sparse.extensions_count);
1781  cgltf_free_extensions(data, data->accessors[i].sparse.indices_extensions, data->accessors[i].sparse.indices_extensions_count);
1782  cgltf_free_extensions(data, data->accessors[i].sparse.values_extensions, data->accessors[i].sparse.values_extensions_count);
1783  }
1784  cgltf_free_extensions(data, data->accessors[i].extensions, data->accessors[i].extensions_count);
1785  }
1786  data->memory.free_func(data->memory.user_data, data->accessors);
1787 
1788  for (cgltf_size i = 0; i < data->buffer_views_count; ++i)
1789  {
1790  data->memory.free_func(data->memory.user_data, data->buffer_views[i].name);
1791  data->memory.free_func(data->memory.user_data, data->buffer_views[i].data);
1792 
1793  cgltf_free_extensions(data, data->buffer_views[i].extensions, data->buffer_views[i].extensions_count);
1794  }
1795  data->memory.free_func(data->memory.user_data, data->buffer_views);
1796 
1797  for (cgltf_size i = 0; i < data->buffers_count; ++i)
1798  {
1799  data->memory.free_func(data->memory.user_data, data->buffers[i].name);
1800 
1802  {
1803  file_release(&data->memory, &data->file, data->buffers[i].data);
1804  }
1806  {
1807  data->memory.free_func(data->memory.user_data, data->buffers[i].data);
1808  }
1809 
1810  data->memory.free_func(data->memory.user_data, data->buffers[i].uri);
1811 
1812  cgltf_free_extensions(data, data->buffers[i].extensions, data->buffers[i].extensions_count);
1813  }
1814 
1815  data->memory.free_func(data->memory.user_data, data->buffers);
1816 
1817  for (cgltf_size i = 0; i < data->meshes_count; ++i)
1818  {
1819  data->memory.free_func(data->memory.user_data, data->meshes[i].name);
1820 
1821  for (cgltf_size j = 0; j < data->meshes[i].primitives_count; ++j)
1822  {
1823  for (cgltf_size k = 0; k < data->meshes[i].primitives[j].attributes_count; ++k)
1824  {
1825  data->memory.free_func(data->memory.user_data, data->meshes[i].primitives[j].attributes[k].name);
1826  }
1827 
1828  data->memory.free_func(data->memory.user_data, data->meshes[i].primitives[j].attributes);
1829 
1830  for (cgltf_size k = 0; k < data->meshes[i].primitives[j].targets_count; ++k)
1831  {
1832  for (cgltf_size m = 0; m < data->meshes[i].primitives[j].targets[k].attributes_count; ++m)
1833  {
1834  data->memory.free_func(data->memory.user_data, data->meshes[i].primitives[j].targets[k].attributes[m].name);
1835  }
1836 
1837  data->memory.free_func(data->memory.user_data, data->meshes[i].primitives[j].targets[k].attributes);
1838  }
1839 
1840  data->memory.free_func(data->memory.user_data, data->meshes[i].primitives[j].targets);
1841 
1843  {
1844  for (cgltf_size k = 0; k < data->meshes[i].primitives[j].draco_mesh_compression.attributes_count; ++k)
1845  {
1847  }
1848 
1850  }
1851 
1852  data->memory.free_func(data->memory.user_data, data->meshes[i].primitives[j].mappings);
1853 
1854  cgltf_free_extensions(data, data->meshes[i].primitives[j].extensions, data->meshes[i].primitives[j].extensions_count);
1855  }
1856 
1857  data->memory.free_func(data->memory.user_data, data->meshes[i].primitives);
1858  data->memory.free_func(data->memory.user_data, data->meshes[i].weights);
1859 
1860  for (cgltf_size j = 0; j < data->meshes[i].target_names_count; ++j)
1861  {
1862  data->memory.free_func(data->memory.user_data, data->meshes[i].target_names[j]);
1863  }
1864 
1865  cgltf_free_extensions(data, data->meshes[i].extensions, data->meshes[i].extensions_count);
1866 
1867  data->memory.free_func(data->memory.user_data, data->meshes[i].target_names);
1868  }
1869 
1870  data->memory.free_func(data->memory.user_data, data->meshes);
1871 
1872  for (cgltf_size i = 0; i < data->materials_count; ++i)
1873  {
1874  data->memory.free_func(data->memory.user_data, data->materials[i].name);
1875 
1877  {
1880  }
1882  {
1885  }
1886  if(data->materials[i].has_clearcoat)
1887  {
1888  cgltf_free_extensions(data, data->materials[i].clearcoat.clearcoat_texture.extensions, data->materials[i].clearcoat.clearcoat_texture.extensions_count);
1891  }
1892  if(data->materials[i].has_specular)
1893  {
1894  cgltf_free_extensions(data, data->materials[i].specular.specular_texture.extensions, data->materials[i].specular.specular_texture.extensions_count);
1896  }
1897  if(data->materials[i].has_transmission)
1898  {
1900  }
1901  if (data->materials[i].has_volume)
1902  {
1903  cgltf_free_extensions(data, data->materials[i].volume.thickness_texture.extensions, data->materials[i].volume.thickness_texture.extensions_count);
1904  }
1905  if(data->materials[i].has_sheen)
1906  {
1907  cgltf_free_extensions(data, data->materials[i].sheen.sheen_color_texture.extensions, data->materials[i].sheen.sheen_color_texture.extensions_count);
1909  }
1910  if(data->materials[i].has_iridescence)
1911  {
1914  }
1915 
1916  cgltf_free_extensions(data, data->materials[i].normal_texture.extensions, data->materials[i].normal_texture.extensions_count);
1917  cgltf_free_extensions(data, data->materials[i].occlusion_texture.extensions, data->materials[i].occlusion_texture.extensions_count);
1918  cgltf_free_extensions(data, data->materials[i].emissive_texture.extensions, data->materials[i].emissive_texture.extensions_count);
1919 
1920  cgltf_free_extensions(data, data->materials[i].extensions, data->materials[i].extensions_count);
1921  }
1922 
1923  data->memory.free_func(data->memory.user_data, data->materials);
1924 
1925  for (cgltf_size i = 0; i < data->images_count; ++i)
1926  {
1927  data->memory.free_func(data->memory.user_data, data->images[i].name);
1928  data->memory.free_func(data->memory.user_data, data->images[i].uri);
1929  data->memory.free_func(data->memory.user_data, data->images[i].mime_type);
1930 
1931  cgltf_free_extensions(data, data->images[i].extensions, data->images[i].extensions_count);
1932  }
1933 
1934  data->memory.free_func(data->memory.user_data, data->images);
1935 
1936  for (cgltf_size i = 0; i < data->textures_count; ++i)
1937  {
1938  data->memory.free_func(data->memory.user_data, data->textures[i].name);
1939  cgltf_free_extensions(data, data->textures[i].extensions, data->textures[i].extensions_count);
1940  }
1941 
1942  data->memory.free_func(data->memory.user_data, data->textures);
1943 
1944  for (cgltf_size i = 0; i < data->samplers_count; ++i)
1945  {
1946  data->memory.free_func(data->memory.user_data, data->samplers[i].name);
1947  cgltf_free_extensions(data, data->samplers[i].extensions, data->samplers[i].extensions_count);
1948  }
1949 
1950  data->memory.free_func(data->memory.user_data, data->samplers);
1951 
1952  for (cgltf_size i = 0; i < data->skins_count; ++i)
1953  {
1954  data->memory.free_func(data->memory.user_data, data->skins[i].name);
1955  data->memory.free_func(data->memory.user_data, data->skins[i].joints);
1956 
1957  cgltf_free_extensions(data, data->skins[i].extensions, data->skins[i].extensions_count);
1958  }
1959 
1960  data->memory.free_func(data->memory.user_data, data->skins);
1961 
1962  for (cgltf_size i = 0; i < data->cameras_count; ++i)
1963  {
1964  data->memory.free_func(data->memory.user_data, data->cameras[i].name);
1965  cgltf_free_extensions(data, data->cameras[i].extensions, data->cameras[i].extensions_count);
1966  }
1967 
1968  data->memory.free_func(data->memory.user_data, data->cameras);
1969 
1970  for (cgltf_size i = 0; i < data->lights_count; ++i)
1971  {
1972  data->memory.free_func(data->memory.user_data, data->lights[i].name);
1973  }
1974 
1975  data->memory.free_func(data->memory.user_data, data->lights);
1976 
1977  for (cgltf_size i = 0; i < data->nodes_count; ++i)
1978  {
1979  data->memory.free_func(data->memory.user_data, data->nodes[i].name);
1980  data->memory.free_func(data->memory.user_data, data->nodes[i].children);
1981  data->memory.free_func(data->memory.user_data, data->nodes[i].weights);
1982  cgltf_free_extensions(data, data->nodes[i].extensions, data->nodes[i].extensions_count);
1983  }
1984 
1985  data->memory.free_func(data->memory.user_data, data->nodes);
1986 
1987  for (cgltf_size i = 0; i < data->scenes_count; ++i)
1988  {
1989  data->memory.free_func(data->memory.user_data, data->scenes[i].name);
1990  data->memory.free_func(data->memory.user_data, data->scenes[i].nodes);
1991 
1992  cgltf_free_extensions(data, data->scenes[i].extensions, data->scenes[i].extensions_count);
1993  }
1994 
1995  data->memory.free_func(data->memory.user_data, data->scenes);
1996 
1997  for (cgltf_size i = 0; i < data->animations_count; ++i)
1998  {
1999  data->memory.free_func(data->memory.user_data, data->animations[i].name);
2000  for (cgltf_size j = 0; j < data->animations[i].samplers_count; ++j)
2001  {
2002  cgltf_free_extensions(data, data->animations[i].samplers[j].extensions, data->animations[i].samplers[j].extensions_count);
2003  }
2004  data->memory.free_func(data->memory.user_data, data->animations[i].samplers);
2005 
2006  for (cgltf_size j = 0; j < data->animations[i].channels_count; ++j)
2007  {
2008  cgltf_free_extensions(data, data->animations[i].channels[j].extensions, data->animations[i].channels[j].extensions_count);
2009  }
2010  data->memory.free_func(data->memory.user_data, data->animations[i].channels);
2011 
2012  cgltf_free_extensions(data, data->animations[i].extensions, data->animations[i].extensions_count);
2013  }
2014 
2015  data->memory.free_func(data->memory.user_data, data->animations);
2016 
2017  for (cgltf_size i = 0; i < data->variants_count; ++i)
2018  {
2019  data->memory.free_func(data->memory.user_data, data->variants[i].name);
2020  }
2021 
2022  data->memory.free_func(data->memory.user_data, data->variants);
2023 
2024  cgltf_free_extensions(data, data->data_extensions, data->data_extensions_count);
2025 
2026  for (cgltf_size i = 0; i < data->extensions_used_count; ++i)
2027  {
2028  data->memory.free_func(data->memory.user_data, data->extensions_used[i]);
2029  }
2030 
2031  data->memory.free_func(data->memory.user_data, data->extensions_used);
2032 
2033  for (cgltf_size i = 0; i < data->extensions_required_count; ++i)
2034  {
2035  data->memory.free_func(data->memory.user_data, data->extensions_required[i]);
2036  }
2037 
2038  data->memory.free_func(data->memory.user_data, data->extensions_required);
2039 
2040  file_release(&data->memory, &data->file, data->file_data);
2041 
2042  data->memory.free_func(data->memory.user_data, data);
2043 }
2044 
2045 void cgltf_node_transform_local(const cgltf_node* node, cgltf_float* out_matrix)
2046 {
2047  cgltf_float* lm = out_matrix;
2048 
2049  if (node->has_matrix)
2050  {
2051  memcpy(lm, node->matrix, sizeof(float) * 16);
2052  }
2053  else
2054  {
2055  float tx = node->translation[0];
2056  float ty = node->translation[1];
2057  float tz = node->translation[2];
2058 
2059  float qx = node->rotation[0];
2060  float qy = node->rotation[1];
2061  float qz = node->rotation[2];
2062  float qw = node->rotation[3];
2063 
2064  float sx = node->scale[0];
2065  float sy = node->scale[1];
2066  float sz = node->scale[2];
2067 
2068  lm[0] = (1 - 2 * qy*qy - 2 * qz*qz) * sx;
2069  lm[1] = (2 * qx*qy + 2 * qz*qw) * sx;
2070  lm[2] = (2 * qx*qz - 2 * qy*qw) * sx;
2071  lm[3] = 0.f;
2072 
2073  lm[4] = (2 * qx*qy - 2 * qz*qw) * sy;
2074  lm[5] = (1 - 2 * qx*qx - 2 * qz*qz) * sy;
2075  lm[6] = (2 * qy*qz + 2 * qx*qw) * sy;
2076  lm[7] = 0.f;
2077 
2078  lm[8] = (2 * qx*qz + 2 * qy*qw) * sz;
2079  lm[9] = (2 * qy*qz - 2 * qx*qw) * sz;
2080  lm[10] = (1 - 2 * qx*qx - 2 * qy*qy) * sz;
2081  lm[11] = 0.f;
2082 
2083  lm[12] = tx;
2084  lm[13] = ty;
2085  lm[14] = tz;
2086  lm[15] = 1.f;
2087  }
2088 }
2089 
2090 void cgltf_node_transform_world(const cgltf_node* node, cgltf_float* out_matrix)
2091 {
2092  cgltf_float* lm = out_matrix;
2093  cgltf_node_transform_local(node, lm);
2094 
2095  const cgltf_node* parent = node->parent;
2096 
2097  while (parent)
2098  {
2099  float pm[16];
2100  cgltf_node_transform_local(parent, pm);
2101 
2102  for (int i = 0; i < 4; ++i)
2103  {
2104  float l0 = lm[i * 4 + 0];
2105  float l1 = lm[i * 4 + 1];
2106  float l2 = lm[i * 4 + 2];
2107 
2108  float r0 = l0 * pm[0] + l1 * pm[4] + l2 * pm[8];
2109  float r1 = l0 * pm[1] + l1 * pm[5] + l2 * pm[9];
2110  float r2 = l0 * pm[2] + l1 * pm[6] + l2 * pm[10];
2111 
2112  lm[i * 4 + 0] = r0;
2113  lm[i * 4 + 1] = r1;
2114  lm[i * 4 + 2] = r2;
2115  }
2116 
2117  lm[12] += pm[12];
2118  lm[13] += pm[13];
2119  lm[14] += pm[14];
2120 
2121  parent = parent->parent;
2122  }
2123 }
2124 
2125 static cgltf_ssize cgltf_component_read_integer(const void* in, cgltf_component_type component_type)
2126 {
2127  switch (component_type)
2128  {
2130  return *((const int16_t*) in);
2132  return *((const uint16_t*) in);
2134  return *((const uint32_t*) in);
2136  return (cgltf_ssize)*((const float*) in);
2138  return *((const int8_t*) in);
2140  return *((const uint8_t*) in);
2141  default:
2142  return 0;
2143  }
2144 }
2145 
2146 static cgltf_size cgltf_component_read_index(const void* in, cgltf_component_type component_type)
2147 {
2148  switch (component_type)
2149  {
2151  return *((const uint16_t*) in);
2153  return *((const uint32_t*) in);
2155  return (cgltf_size)*((const float*) in);
2157  return *((const uint8_t*) in);
2158  default:
2159  return 0;
2160  }
2161 }
2162 
2163 static cgltf_float cgltf_component_read_float(const void* in, cgltf_component_type component_type, cgltf_bool normalized)
2164 {
2165  if (component_type == cgltf_component_type_r_32f)
2166  {
2167  return *((const float*) in);
2168  }
2169 
2170  if (normalized)
2171  {
2172  switch (component_type)
2173  {
2174  // note: glTF spec doesn't currently define normalized conversions for 32-bit integers
2176  return *((const int16_t*) in) / (cgltf_float)32767;
2178  return *((const uint16_t*) in) / (cgltf_float)65535;
2180  return *((const int8_t*) in) / (cgltf_float)127;
2182  return *((const uint8_t*) in) / (cgltf_float)255;
2183  default:
2184  return 0;
2185  }
2186  }
2187 
2188  return (cgltf_float)cgltf_component_read_integer(in, component_type);
2189 }
2190 
2191 static cgltf_size cgltf_component_size(cgltf_component_type component_type);
2192 
2193 static cgltf_bool cgltf_element_read_float(const uint8_t* element, cgltf_type type, cgltf_component_type component_type, cgltf_bool normalized, cgltf_float* out, cgltf_size element_size)
2194 {
2195  cgltf_size num_components = cgltf_num_components(type);
2196 
2197  if (element_size < num_components) {
2198  return 0;
2199  }
2200 
2201  // There are three special cases for component extraction, see #data-alignment in the 2.0 spec.
2202 
2203  cgltf_size component_size = cgltf_component_size(component_type);
2204 
2205  if (type == cgltf_type_mat2 && component_size == 1)
2206  {
2207  out[0] = cgltf_component_read_float(element, component_type, normalized);
2208  out[1] = cgltf_component_read_float(element + 1, component_type, normalized);
2209  out[2] = cgltf_component_read_float(element + 4, component_type, normalized);
2210  out[3] = cgltf_component_read_float(element + 5, component_type, normalized);
2211  return 1;
2212  }
2213 
2214  if (type == cgltf_type_mat3 && component_size == 1)
2215  {
2216  out[0] = cgltf_component_read_float(element, component_type, normalized);
2217  out[1] = cgltf_component_read_float(element + 1, component_type, normalized);
2218  out[2] = cgltf_component_read_float(element + 2, component_type, normalized);
2219  out[3] = cgltf_component_read_float(element + 4, component_type, normalized);
2220  out[4] = cgltf_component_read_float(element + 5, component_type, normalized);
2221  out[5] = cgltf_component_read_float(element + 6, component_type, normalized);
2222  out[6] = cgltf_component_read_float(element + 8, component_type, normalized);
2223  out[7] = cgltf_component_read_float(element + 9, component_type, normalized);
2224  out[8] = cgltf_component_read_float(element + 10, component_type, normalized);
2225  return 1;
2226  }
2227 
2228  if (type == cgltf_type_mat3 && component_size == 2)
2229  {
2230  out[0] = cgltf_component_read_float(element, component_type, normalized);
2231  out[1] = cgltf_component_read_float(element + 2, component_type, normalized);
2232  out[2] = cgltf_component_read_float(element + 4, component_type, normalized);
2233  out[3] = cgltf_component_read_float(element + 8, component_type, normalized);
2234  out[4] = cgltf_component_read_float(element + 10, component_type, normalized);
2235  out[5] = cgltf_component_read_float(element + 12, component_type, normalized);
2236  out[6] = cgltf_component_read_float(element + 16, component_type, normalized);
2237  out[7] = cgltf_component_read_float(element + 18, component_type, normalized);
2238  out[8] = cgltf_component_read_float(element + 20, component_type, normalized);
2239  return 1;
2240  }
2241 
2242  for (cgltf_size i = 0; i < num_components; ++i)
2243  {
2244  out[i] = cgltf_component_read_float(element + component_size * i, component_type, normalized);
2245  }
2246  return 1;
2247 }
2248 
2249 const uint8_t* cgltf_buffer_view_data(const cgltf_buffer_view* view)
2250 {
2251  if (view->data)
2252  return (const uint8_t*)view->data;
2253 
2254  if (!view->buffer->data)
2255  return NULL;
2256 
2257  const uint8_t* result = (const uint8_t*)view->buffer->data;
2258  result += view->offset;
2259  return result;
2260 }
2261 
2262 cgltf_bool cgltf_accessor_read_float(const cgltf_accessor* accessor, cgltf_size index, cgltf_float* out, cgltf_size element_size)
2263 {
2264  if (accessor->is_sparse)
2265  {
2266  return 0;
2267  }
2268  if (accessor->buffer_view == NULL)
2269  {
2270  memset(out, 0, element_size * sizeof(cgltf_float));
2271  return 1;
2272  }
2273  const uint8_t* element = cgltf_buffer_view_data(accessor->buffer_view);
2274  if (element == NULL)
2275  {
2276  return 0;
2277  }
2278  element += accessor->offset + accessor->stride * index;
2279  return cgltf_element_read_float(element, accessor->type, accessor->component_type, accessor->normalized, out, element_size);
2280 }
2281 
2282 cgltf_size cgltf_accessor_unpack_floats(const cgltf_accessor* accessor, cgltf_float* out, cgltf_size float_count)
2283 {
2284  cgltf_size floats_per_element = cgltf_num_components(accessor->type);
2285  cgltf_size available_floats = accessor->count * floats_per_element;
2286  if (out == NULL)
2287  {
2288  return available_floats;
2289  }
2290 
2291  float_count = available_floats < float_count ? available_floats : float_count;
2292  cgltf_size element_count = float_count / floats_per_element;
2293 
2294  // First pass: convert each element in the base accessor.
2295  cgltf_float* dest = out;
2296  cgltf_accessor dense = *accessor;
2297  dense.is_sparse = 0;
2298  for (cgltf_size index = 0; index < element_count; index++, dest += floats_per_element)
2299  {
2300  if (!cgltf_accessor_read_float(&dense, index, dest, floats_per_element))
2301  {
2302  return 0;
2303  }
2304  }
2305 
2306  // Second pass: write out each element in the sparse accessor.
2307  if (accessor->is_sparse)
2308  {
2309  const cgltf_accessor_sparse* sparse = &dense.sparse;
2310 
2311  const uint8_t* index_data = cgltf_buffer_view_data(sparse->indices_buffer_view);
2312  const uint8_t* reader_head = cgltf_buffer_view_data(sparse->values_buffer_view);
2313 
2314  if (index_data == NULL || reader_head == NULL)
2315  {
2316  return 0;
2317  }
2318 
2319  index_data += sparse->indices_byte_offset;
2320  reader_head += sparse->values_byte_offset;
2321 
2322  cgltf_size index_stride = cgltf_component_size(sparse->indices_component_type);
2323  for (cgltf_size reader_index = 0; reader_index < sparse->count; reader_index++, index_data += index_stride)
2324  {
2325  size_t writer_index = cgltf_component_read_index(index_data, sparse->indices_component_type);
2326  float* writer_head = out + writer_index * floats_per_element;
2327 
2328  if (!cgltf_element_read_float(reader_head, dense.type, dense.component_type, dense.normalized, writer_head, floats_per_element))
2329  {
2330  return 0;
2331  }
2332 
2333  reader_head += dense.stride;
2334  }
2335  }
2336 
2337  return element_count * floats_per_element;
2338 }
2339 
2340 static cgltf_uint cgltf_component_read_uint(const void* in, cgltf_component_type component_type)
2341 {
2342  switch (component_type)
2343  {
2345  return *((const int8_t*) in);
2346 
2348  return *((const uint8_t*) in);
2349 
2351  return *((const int16_t*) in);
2352 
2354  return *((const uint16_t*) in);
2355 
2357  return *((const uint32_t*) in);
2358 
2359  default:
2360  return 0;
2361  }
2362 }
2363 
2364 static cgltf_bool cgltf_element_read_uint(const uint8_t* element, cgltf_type type, cgltf_component_type component_type, cgltf_uint* out, cgltf_size element_size)
2365 {
2366  cgltf_size num_components = cgltf_num_components(type);
2367 
2368  if (element_size < num_components)
2369  {
2370  return 0;
2371  }
2372 
2373  // Reading integer matrices is not a valid use case
2374  if (type == cgltf_type_mat2 || type == cgltf_type_mat3 || type == cgltf_type_mat4)
2375  {
2376  return 0;
2377  }
2378 
2379  cgltf_size component_size = cgltf_component_size(component_type);
2380 
2381  for (cgltf_size i = 0; i < num_components; ++i)
2382  {
2383  out[i] = cgltf_component_read_uint(element + component_size * i, component_type);
2384  }
2385  return 1;
2386 }
2387 
2388 cgltf_bool cgltf_accessor_read_uint(const cgltf_accessor* accessor, cgltf_size index, cgltf_uint* out, cgltf_size element_size)
2389 {
2390  if (accessor->is_sparse)
2391  {
2392  return 0;
2393  }
2394  if (accessor->buffer_view == NULL)
2395  {
2396  memset(out, 0, element_size * sizeof( cgltf_uint ));
2397  return 1;
2398  }
2399  const uint8_t* element = cgltf_buffer_view_data(accessor->buffer_view);
2400  if (element == NULL)
2401  {
2402  return 0;
2403  }
2404  element += accessor->offset + accessor->stride * index;
2405  return cgltf_element_read_uint(element, accessor->type, accessor->component_type, out, element_size);
2406 }
2407 
2408 cgltf_size cgltf_accessor_read_index(const cgltf_accessor* accessor, cgltf_size index)
2409 {
2410  if (accessor->is_sparse)
2411  {
2412  return 0; // This is an error case, but we can't communicate the error with existing interface.
2413  }
2414  if (accessor->buffer_view == NULL)
2415  {
2416  return 0;
2417  }
2418  const uint8_t* element = cgltf_buffer_view_data(accessor->buffer_view);
2419  if (element == NULL)
2420  {
2421  return 0; // This is an error case, but we can't communicate the error with existing interface.
2422  }
2423  element += accessor->offset + accessor->stride * index;
2424  return cgltf_component_read_index(element, accessor->component_type);
2425 }
2426 
2427 #define CGLTF_ERROR_JSON -1
2428 #define CGLTF_ERROR_NOMEM -2
2429 #define CGLTF_ERROR_LEGACY -3
2430 
2431 #define CGLTF_CHECK_TOKTYPE(tok_, type_) if ((tok_).type != (type_)) { return CGLTF_ERROR_JSON; }
2432 #define CGLTF_CHECK_TOKTYPE_RETTYPE(tok_, type_, ret_) if ((tok_).type != (type_)) { return (ret_)CGLTF_ERROR_JSON; }
2433 #define CGLTF_CHECK_KEY(tok_) if ((tok_).type != JSMN_STRING || (tok_).size == 0) { return CGLTF_ERROR_JSON; } /* checking size for 0 verifies that a value follows the key */
2434 
2435 #define CGLTF_PTRINDEX(type, idx) (type*)((cgltf_size)idx + 1)
2436 #define CGLTF_PTRFIXUP(var, data, size) if (var) { if ((cgltf_size)var > size) { return CGLTF_ERROR_JSON; } var = &data[(cgltf_size)var-1]; }
2437 #define CGLTF_PTRFIXUP_REQ(var, data, size) if (!var || (cgltf_size)var > size) { return CGLTF_ERROR_JSON; } var = &data[(cgltf_size)var-1];
2438 
2439 static int cgltf_json_strcmp(jsmntok_t const* tok, const uint8_t* json_chunk, const char* str)
2440 {
2441  CGLTF_CHECK_TOKTYPE(*tok, JSMN_STRING);
2442  size_t const str_len = strlen(str);
2443  size_t const name_length = tok->end - tok->start;
2444  return (str_len == name_length) ? strncmp((const char*)json_chunk + tok->start, str, str_len) : 128;
2445 }
2446 
2447 static int cgltf_json_to_int(jsmntok_t const* tok, const uint8_t* json_chunk)
2448 {
2449  CGLTF_CHECK_TOKTYPE(*tok, JSMN_PRIMITIVE);
2450  char tmp[128];
2451  int size = (cgltf_size)(tok->end - tok->start) < sizeof(tmp) ? tok->end - tok->start : (int)(sizeof(tmp) - 1);
2452  strncpy(tmp, (const char*)json_chunk + tok->start, size);
2453  tmp[size] = 0;
2454  return CGLTF_ATOI(tmp);
2455 }
2456 
2457 static cgltf_size cgltf_json_to_size(jsmntok_t const* tok, const uint8_t* json_chunk)
2458 {
2459  CGLTF_CHECK_TOKTYPE_RETTYPE(*tok, JSMN_PRIMITIVE, cgltf_size);
2460  char tmp[128];
2461  int size = (cgltf_size)(tok->end - tok->start) < sizeof(tmp) ? tok->end - tok->start : (int)(sizeof(tmp) - 1);
2462  strncpy(tmp, (const char*)json_chunk + tok->start, size);
2463  tmp[size] = 0;
2464  return (cgltf_size)CGLTF_ATOLL(tmp);
2465 }
2466 
2467 static cgltf_float cgltf_json_to_float(jsmntok_t const* tok, const uint8_t* json_chunk)
2468 {
2469  CGLTF_CHECK_TOKTYPE(*tok, JSMN_PRIMITIVE);
2470  char tmp[128];
2471  int size = (cgltf_size)(tok->end - tok->start) < sizeof(tmp) ? tok->end - tok->start : (int)(sizeof(tmp) - 1);
2472  strncpy(tmp, (const char*)json_chunk + tok->start, size);
2473  tmp[size] = 0;
2474  return (cgltf_float)CGLTF_ATOF(tmp);
2475 }
2476 
2477 static cgltf_bool cgltf_json_to_bool(jsmntok_t const* tok, const uint8_t* json_chunk)
2478 {
2479  int size = tok->end - tok->start;
2480  return size == 4 && memcmp(json_chunk + tok->start, "true", 4) == 0;
2481 }
2482 
2483 static int cgltf_skip_json(jsmntok_t const* tokens, int i)
2484 {
2485  int end = i + 1;
2486 
2487  while (i < end)
2488  {
2489  switch (tokens[i].type)
2490  {
2491  case JSMN_OBJECT:
2492  end += tokens[i].size * 2;
2493  break;
2494 
2495  case JSMN_ARRAY:
2496  end += tokens[i].size;
2497  break;
2498 
2499  case JSMN_PRIMITIVE:
2500  case JSMN_STRING:
2501  break;
2502 
2503  default:
2504  return -1;
2505  }
2506 
2507  i++;
2508  }
2509 
2510  return i;
2511 }
2512 
2513 static void cgltf_fill_float_array(float* out_array, int size, float value)
2514 {
2515  for (int j = 0; j < size; ++j)
2516  {
2517  out_array[j] = value;
2518  }
2519 }
2520 
2521 static int cgltf_parse_json_float_array(jsmntok_t const* tokens, int i, const uint8_t* json_chunk, float* out_array, int size)
2522 {
2523  CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_ARRAY);
2524  if (tokens[i].size != size)
2525  {
2526  return CGLTF_ERROR_JSON;
2527  }
2528  ++i;
2529  for (int j = 0; j < size; ++j)
2530  {
2531  CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_PRIMITIVE);
2532  out_array[j] = cgltf_json_to_float(tokens + i, json_chunk);
2533  ++i;
2534  }
2535  return i;
2536 }
2537 
2538 static int cgltf_parse_json_string(cgltf_options* options, jsmntok_t const* tokens, int i, const uint8_t* json_chunk, char** out_string)
2539 {
2540  CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_STRING);
2541  if (*out_string)
2542  {
2543  return CGLTF_ERROR_JSON;
2544  }
2545  int size = tokens[i].end - tokens[i].start;
2546  char* result = (char*)options->memory.alloc_func(options->memory.user_data, size + 1);
2547  if (!result)
2548  {
2549  return CGLTF_ERROR_NOMEM;
2550  }
2551  strncpy(result, (const char*)json_chunk + tokens[i].start, size);
2552  result[size] = 0;
2553  *out_string = result;
2554  return i + 1;
2555 }
2556 
2557 static int cgltf_parse_json_array(cgltf_options* options, jsmntok_t const* tokens, int i, const uint8_t* json_chunk, size_t element_size, void** out_array, cgltf_size* out_size)
2558 {
2559  (void)json_chunk;
2560  if (tokens[i].type != JSMN_ARRAY)
2561  {
2562  return tokens[i].type == JSMN_OBJECT ? CGLTF_ERROR_LEGACY : CGLTF_ERROR_JSON;
2563  }
2564  if (*out_array)
2565  {
2566  return CGLTF_ERROR_JSON;
2567  }
2568  int size = tokens[i].size;
2569  void* result = cgltf_calloc(options, element_size, size);
2570  if (!result)
2571  {
2572  return CGLTF_ERROR_NOMEM;
2573  }
2574  *out_array = result;
2575  *out_size = size;
2576  return i + 1;
2577 }
2578 
2579 static int cgltf_parse_json_string_array(cgltf_options* options, jsmntok_t const* tokens, int i, const uint8_t* json_chunk, char*** out_array, cgltf_size* out_size)
2580 {
2581  CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_ARRAY);
2582  i = cgltf_parse_json_array(options, tokens, i, json_chunk, sizeof(char*), (void**)out_array, out_size);
2583  if (i < 0)
2584  {
2585  return i;
2586  }
2587 
2588  for (cgltf_size j = 0; j < *out_size; ++j)
2589  {
2590  i = cgltf_parse_json_string(options, tokens, i, json_chunk, j + (*out_array));
2591  if (i < 0)
2592  {
2593  return i;
2594  }
2595  }
2596  return i;
2597 }
2598 
2599 static void cgltf_parse_attribute_type(const char* name, cgltf_attribute_type* out_type, int* out_index)
2600 {
2601  if (*name == '_')
2602  {
2603  *out_type = cgltf_attribute_type_custom;
2604  return;
2605  }
2606 
2607  const char* us = strchr(name, '_');
2608  size_t len = us ? (size_t)(us - name) : strlen(name);
2609 
2610  if (len == 8 && strncmp(name, "POSITION", 8) == 0)
2611  {
2612  *out_type = cgltf_attribute_type_position;
2613  }
2614  else if (len == 6 && strncmp(name, "NORMAL", 6) == 0)
2615  {
2616  *out_type = cgltf_attribute_type_normal;
2617  }
2618  else if (len == 7 && strncmp(name, "TANGENT", 7) == 0)
2619  {
2620  *out_type = cgltf_attribute_type_tangent;
2621  }
2622  else if (len == 8 && strncmp(name, "TEXCOORD", 8) == 0)
2623  {
2624  *out_type = cgltf_attribute_type_texcoord;
2625  }
2626  else if (len == 5 && strncmp(name, "COLOR", 5) == 0)
2627  {
2628  *out_type = cgltf_attribute_type_color;
2629  }
2630  else if (len == 6 && strncmp(name, "JOINTS", 6) == 0)
2631  {
2632  *out_type = cgltf_attribute_type_joints;
2633  }
2634  else if (len == 7 && strncmp(name, "WEIGHTS", 7) == 0)
2635  {
2636  *out_type = cgltf_attribute_type_weights;
2637  }
2638  else
2639  {
2640  *out_type = cgltf_attribute_type_invalid;
2641  }
2642 
2643  if (us && *out_type != cgltf_attribute_type_invalid)
2644  {
2645  *out_index = CGLTF_ATOI(us + 1);
2646  }
2647 }
2648 
2649 static int cgltf_parse_json_attribute_list(cgltf_options* options, jsmntok_t const* tokens, int i, const uint8_t* json_chunk, cgltf_attribute** out_attributes, cgltf_size* out_attributes_count)
2650 {
2651  CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
2652 
2653  if (*out_attributes)
2654  {
2655  return CGLTF_ERROR_JSON;
2656  }
2657 
2658  *out_attributes_count = tokens[i].size;
2659  *out_attributes = (cgltf_attribute*)cgltf_calloc(options, sizeof(cgltf_attribute), *out_attributes_count);
2660  ++i;
2661 
2662  if (!*out_attributes)
2663  {
2664  return CGLTF_ERROR_NOMEM;
2665  }
2666 
2667  for (cgltf_size j = 0; j < *out_attributes_count; ++j)
2668  {
2669  CGLTF_CHECK_KEY(tokens[i]);
2670 
2671  i = cgltf_parse_json_string(options, tokens, i, json_chunk, &(*out_attributes)[j].name);
2672  if (i < 0)
2673  {
2674  return CGLTF_ERROR_JSON;
2675  }
2676 
2677  cgltf_parse_attribute_type((*out_attributes)[j].name, &(*out_attributes)[j].type, &(*out_attributes)[j].index);
2678 
2679  (*out_attributes)[j].data = CGLTF_PTRINDEX(cgltf_accessor, cgltf_json_to_int(tokens + i, json_chunk));
2680  ++i;
2681  }
2682 
2683  return i;
2684 }
2685 
2686 static int cgltf_parse_json_extras(jsmntok_t const* tokens, int i, const uint8_t* json_chunk, cgltf_extras* out_extras)
2687 {
2688  (void)json_chunk;
2689  out_extras->start_offset = tokens[i].start;
2690  out_extras->end_offset = tokens[i].end;
2691  i = cgltf_skip_json(tokens, i);
2692  return i;
2693 }
2694 
2695 static int cgltf_parse_json_unprocessed_extension(cgltf_options* options, jsmntok_t const* tokens, int i, const uint8_t* json_chunk, cgltf_extension* out_extension)
2696 {
2697  CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_STRING);
2698  CGLTF_CHECK_TOKTYPE(tokens[i+1], JSMN_OBJECT);
2699  if (out_extension->name)
2700  {
2701  return CGLTF_ERROR_JSON;
2702  }
2703 
2704  cgltf_size name_length = tokens[i].end - tokens[i].start;
2705  out_extension->name = (char*)options->memory.alloc_func(options->memory.user_data, name_length + 1);
2706  if (!out_extension->name)
2707  {
2708  return CGLTF_ERROR_NOMEM;
2709  }
2710  strncpy(out_extension->name, (const char*)json_chunk + tokens[i].start, name_length);
2711  out_extension->name[name_length] = 0;
2712  i++;
2713 
2714  size_t start = tokens[i].start;
2715  size_t size = tokens[i].end - start;
2716  out_extension->data = (char*)options->memory.alloc_func(options->memory.user_data, size + 1);
2717  if (!out_extension->data)
2718  {
2719  return CGLTF_ERROR_NOMEM;
2720  }
2721  strncpy(out_extension->data, (const char*)json_chunk + start, size);
2722  out_extension->data[size] = '\0';
2723 
2724  i = cgltf_skip_json(tokens, i);
2725 
2726  return i;
2727 }
2728 
2729 static int cgltf_parse_json_unprocessed_extensions(cgltf_options* options, jsmntok_t const* tokens, int i, const uint8_t* json_chunk, cgltf_size* out_extensions_count, cgltf_extension** out_extensions)
2730 {
2731  ++i;
2732 
2733  CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
2734  if(*out_extensions)
2735  {
2736  return CGLTF_ERROR_JSON;
2737  }
2738 
2739  int extensions_size = tokens[i].size;
2740  *out_extensions_count = 0;
2741  *out_extensions = (cgltf_extension*)cgltf_calloc(options, sizeof(cgltf_extension), extensions_size);
2742 
2743  if (!*out_extensions)
2744  {
2745  return CGLTF_ERROR_NOMEM;
2746  }
2747 
2748  ++i;
2749 
2750  for (int j = 0; j < extensions_size; ++j)
2751  {
2752  CGLTF_CHECK_KEY(tokens[i]);
2753 
2754  cgltf_size extension_index = (*out_extensions_count)++;
2755  cgltf_extension* extension = &((*out_extensions)[extension_index]);
2756  i = cgltf_parse_json_unprocessed_extension(options, tokens, i, json_chunk, extension);
2757 
2758  if (i < 0)
2759  {
2760  return i;
2761  }
2762  }
2763  return i;
2764 }
2765 
2766 static int cgltf_parse_json_draco_mesh_compression(cgltf_options* options, jsmntok_t const* tokens, int i, const uint8_t* json_chunk, cgltf_draco_mesh_compression* out_draco_mesh_compression)
2767 {
2768  CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
2769 
2770  int size = tokens[i].size;
2771  ++i;
2772 
2773  for (int j = 0; j < size; ++j)
2774  {
2775  CGLTF_CHECK_KEY(tokens[i]);
2776 
2777  if (cgltf_json_strcmp(tokens + i, json_chunk, "attributes") == 0)
2778  {
2779  i = cgltf_parse_json_attribute_list(options, tokens, i + 1, json_chunk, &out_draco_mesh_compression->attributes, &out_draco_mesh_compression->attributes_count);
2780  }
2781  else if (cgltf_json_strcmp(tokens + i, json_chunk, "bufferView") == 0)
2782  {
2783  ++i;
2784  out_draco_mesh_compression->buffer_view = CGLTF_PTRINDEX(cgltf_buffer_view, cgltf_json_to_int(tokens + i, json_chunk));
2785  ++i;
2786  }
2787 
2788  if (i < 0)
2789  {
2790  return i;
2791  }
2792  }
2793 
2794  return i;
2795 }
2796 
2797 static int cgltf_parse_json_mesh_gpu_instancing(cgltf_options* options, jsmntok_t const* tokens, int i, const uint8_t* json_chunk, cgltf_mesh_gpu_instancing* out_mesh_gpu_instancing)
2798 {
2799  CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
2800 
2801  int size = tokens[i].size;
2802  ++i;
2803 
2804  for (int j = 0; j < size; ++j)
2805  {
2806  CGLTF_CHECK_KEY(tokens[i]);
2807 
2808  if (cgltf_json_strcmp(tokens + i, json_chunk, "attributes") == 0)
2809  {
2810  i = cgltf_parse_json_attribute_list(options, tokens, i + 1, json_chunk, &out_mesh_gpu_instancing->attributes, &out_mesh_gpu_instancing->attributes_count);
2811  }
2812  else if (cgltf_json_strcmp(tokens + i, json_chunk, "bufferView") == 0)
2813  {
2814  ++i;
2815  out_mesh_gpu_instancing->buffer_view = CGLTF_PTRINDEX(cgltf_buffer_view, cgltf_json_to_int(tokens + i, json_chunk));
2816  ++i;
2817  }
2818 
2819  if (i < 0)
2820  {
2821  return i;
2822  }
2823  }
2824 
2825  return i;
2826 }
2827 
2828 static int cgltf_parse_json_material_mapping_data(cgltf_options* options, jsmntok_t const* tokens, int i, const uint8_t* json_chunk, cgltf_material_mapping* out_mappings, cgltf_size* offset)
2829 {
2830  (void)options;
2831  CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_ARRAY);
2832 
2833  int size = tokens[i].size;
2834  ++i;
2835 
2836  for (int j = 0; j < size; ++j)
2837  {
2838  CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
2839 
2840  int obj_size = tokens[i].size;
2841  ++i;
2842 
2843  int material = -1;
2844  int variants_tok = -1;
2845  cgltf_extras extras = {0, 0};
2846 
2847  for (int k = 0; k < obj_size; ++k)
2848  {
2849  CGLTF_CHECK_KEY(tokens[i]);
2850 
2851  if (cgltf_json_strcmp(tokens + i, json_chunk, "material") == 0)
2852  {
2853  ++i;
2854  material = cgltf_json_to_int(tokens + i, json_chunk);
2855  ++i;
2856  }
2857  else if (cgltf_json_strcmp(tokens + i, json_chunk, "variants") == 0)
2858  {
2859  variants_tok = i+1;
2860  CGLTF_CHECK_TOKTYPE(tokens[variants_tok], JSMN_ARRAY);
2861 
2862  i = cgltf_skip_json(tokens, i+1);
2863  }
2864  else if (cgltf_json_strcmp(tokens + i, json_chunk, "extras") == 0)
2865  {
2866  i = cgltf_parse_json_extras(tokens, i + 1, json_chunk, &extras);
2867  }
2868  else
2869  {
2870  i = cgltf_skip_json(tokens, i+1);
2871  }
2872 
2873  if (i < 0)
2874  {
2875  return i;
2876  }
2877  }
2878 
2879  if (material < 0 || variants_tok < 0)
2880  {
2881  return CGLTF_ERROR_JSON;
2882  }
2883 
2884  if (out_mappings)
2885  {
2886  for (int k = 0; k < tokens[variants_tok].size; ++k)
2887  {
2888  int variant = cgltf_json_to_int(&tokens[variants_tok + 1 + k], json_chunk);
2889  if (variant < 0)
2890  return variant;
2891 
2892  out_mappings[*offset].material = CGLTF_PTRINDEX(cgltf_material, material);
2893  out_mappings[*offset].variant = variant;
2894  out_mappings[*offset].extras = extras;
2895 
2896  (*offset)++;
2897  }
2898  }
2899  else
2900  {
2901  (*offset) += tokens[variants_tok].size;
2902  }
2903  }
2904 
2905  return i;
2906 }
2907 
2908 static int cgltf_parse_json_material_mappings(cgltf_options* options, jsmntok_t const* tokens, int i, const uint8_t* json_chunk, cgltf_primitive* out_prim)
2909 {
2910  CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
2911 
2912  int size = tokens[i].size;
2913  ++i;
2914 
2915  for (int j = 0; j < size; ++j)
2916  {
2917  CGLTF_CHECK_KEY(tokens[i]);
2918 
2919  if (cgltf_json_strcmp(tokens + i, json_chunk, "mappings") == 0)
2920  {
2921  if (out_prim->mappings)
2922  {
2923  return CGLTF_ERROR_JSON;
2924  }
2925 
2926  cgltf_size mappings_offset = 0;
2927  int k = cgltf_parse_json_material_mapping_data(options, tokens, i + 1, json_chunk, NULL, &mappings_offset);
2928  if (k < 0)
2929  {
2930  return k;
2931  }
2932 
2933  out_prim->mappings_count = mappings_offset;
2934  out_prim->mappings = (cgltf_material_mapping*)cgltf_calloc(options, sizeof(cgltf_material_mapping), out_prim->mappings_count);
2935 
2936  mappings_offset = 0;
2937  i = cgltf_parse_json_material_mapping_data(options, tokens, i + 1, json_chunk, out_prim->mappings, &mappings_offset);
2938  }
2939  else
2940  {
2941  i = cgltf_skip_json(tokens, i+1);
2942  }
2943 
2944  if (i < 0)
2945  {
2946  return i;
2947  }
2948  }
2949 
2950  return i;
2951 }
2952 
2953 static int cgltf_parse_json_primitive(cgltf_options* options, jsmntok_t const* tokens, int i, const uint8_t* json_chunk, cgltf_primitive* out_prim)
2954 {
2955  CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
2956 
2958 
2959  int size = tokens[i].size;
2960  ++i;
2961 
2962  for (int j = 0; j < size; ++j)
2963  {
2964  CGLTF_CHECK_KEY(tokens[i]);
2965 
2966  if (cgltf_json_strcmp(tokens+i, json_chunk, "mode") == 0)
2967  {
2968  ++i;
2969  out_prim->type
2971  cgltf_json_to_int(tokens+i, json_chunk);
2972  ++i;
2973  }
2974  else if (cgltf_json_strcmp(tokens+i, json_chunk, "indices") == 0)
2975  {
2976  ++i;
2977  out_prim->indices = CGLTF_PTRINDEX(cgltf_accessor, cgltf_json_to_int(tokens + i, json_chunk));
2978  ++i;
2979  }
2980  else if (cgltf_json_strcmp(tokens+i, json_chunk, "material") == 0)
2981  {
2982  ++i;
2983  out_prim->material = CGLTF_PTRINDEX(cgltf_material, cgltf_json_to_int(tokens + i, json_chunk));
2984  ++i;
2985  }
2986  else if (cgltf_json_strcmp(tokens+i, json_chunk, "attributes") == 0)
2987  {
2988  i = cgltf_parse_json_attribute_list(options, tokens, i + 1, json_chunk, &out_prim->attributes, &out_prim->attributes_count);
2989  }
2990  else if (cgltf_json_strcmp(tokens+i, json_chunk, "targets") == 0)
2991  {
2992  i = cgltf_parse_json_array(options, tokens, i + 1, json_chunk, sizeof(cgltf_morph_target), (void**)&out_prim->targets, &out_prim->targets_count);
2993  if (i < 0)
2994  {
2995  return i;
2996  }
2997 
2998  for (cgltf_size k = 0; k < out_prim->targets_count; ++k)
2999  {
3000  i = cgltf_parse_json_attribute_list(options, tokens, i, json_chunk, &out_prim->targets[k].attributes, &out_prim->targets[k].attributes_count);
3001  if (i < 0)
3002  {
3003  return i;
3004  }
3005  }
3006  }
3007  else if (cgltf_json_strcmp(tokens + i, json_chunk, "extras") == 0)
3008  {
3009  i = cgltf_parse_json_extras(tokens, i + 1, json_chunk, &out_prim->extras);
3010  }
3011  else if (cgltf_json_strcmp(tokens + i, json_chunk, "extensions") == 0)
3012  {
3013  ++i;
3014 
3015  CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
3016  if(out_prim->extensions)
3017  {
3018  return CGLTF_ERROR_JSON;
3019  }
3020 
3021  int extensions_size = tokens[i].size;
3022  out_prim->extensions_count = 0;
3023  out_prim->extensions = (cgltf_extension*)cgltf_calloc(options, sizeof(cgltf_extension), extensions_size);
3024 
3025  if (!out_prim->extensions)
3026  {
3027  return CGLTF_ERROR_NOMEM;
3028  }
3029 
3030  ++i;
3031  for (int k = 0; k < extensions_size; ++k)
3032  {
3033  CGLTF_CHECK_KEY(tokens[i]);
3034 
3035  if (cgltf_json_strcmp(tokens+i, json_chunk, "KHR_draco_mesh_compression") == 0)
3036  {
3037  out_prim->has_draco_mesh_compression = 1;
3038  i = cgltf_parse_json_draco_mesh_compression(options, tokens, i + 1, json_chunk, &out_prim->draco_mesh_compression);
3039  }
3040  else if (cgltf_json_strcmp(tokens+i, json_chunk, "KHR_materials_variants") == 0)
3041  {
3042  i = cgltf_parse_json_material_mappings(options, tokens, i + 1, json_chunk, out_prim);
3043  }
3044  else
3045  {
3046  i = cgltf_parse_json_unprocessed_extension(options, tokens, i, json_chunk, &(out_prim->extensions[out_prim->extensions_count++]));
3047  }
3048 
3049  if (i < 0)
3050  {
3051  return i;
3052  }
3053  }
3054  }
3055  else
3056  {
3057  i = cgltf_skip_json(tokens, i+1);
3058  }
3059 
3060  if (i < 0)
3061  {
3062  return i;
3063  }
3064  }
3065 
3066  return i;
3067 }
3068 
3069 static int cgltf_parse_json_mesh(cgltf_options* options, jsmntok_t const* tokens, int i, const uint8_t* json_chunk, cgltf_mesh* out_mesh)
3070 {
3071  CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
3072 
3073  int size = tokens[i].size;
3074  ++i;
3075 
3076  for (int j = 0; j < size; ++j)
3077  {
3078  CGLTF_CHECK_KEY(tokens[i]);
3079 
3080  if (cgltf_json_strcmp(tokens+i, json_chunk, "name") == 0)
3081  {
3082  i = cgltf_parse_json_string(options, tokens, i + 1, json_chunk, &out_mesh->name);
3083  }
3084  else if (cgltf_json_strcmp(tokens+i, json_chunk, "primitives") == 0)
3085  {
3086  i = cgltf_parse_json_array(options, tokens, i + 1, json_chunk, sizeof(cgltf_primitive), (void**)&out_mesh->primitives, &out_mesh->primitives_count);
3087  if (i < 0)
3088  {
3089  return i;
3090  }
3091 
3092  for (cgltf_size prim_index = 0; prim_index < out_mesh->primitives_count; ++prim_index)
3093  {
3094  i = cgltf_parse_json_primitive(options, tokens, i, json_chunk, &out_mesh->primitives[prim_index]);
3095  if (i < 0)
3096  {
3097  return i;
3098  }
3099  }
3100  }
3101  else if (cgltf_json_strcmp(tokens + i, json_chunk, "weights") == 0)
3102  {
3103  i = cgltf_parse_json_array(options, tokens, i + 1, json_chunk, sizeof(cgltf_float), (void**)&out_mesh->weights, &out_mesh->weights_count);
3104  if (i < 0)
3105  {
3106  return i;
3107  }
3108 
3109  i = cgltf_parse_json_float_array(tokens, i - 1, json_chunk, out_mesh->weights, (int)out_mesh->weights_count);
3110  }
3111  else if (cgltf_json_strcmp(tokens + i, json_chunk, "extras") == 0)
3112  {
3113  ++i;
3114 
3115  out_mesh->extras.start_offset = tokens[i].start;
3116  out_mesh->extras.end_offset = tokens[i].end;
3117 
3118  if (tokens[i].type == JSMN_OBJECT)
3119  {
3120  int extras_size = tokens[i].size;
3121  ++i;
3122 
3123  for (int k = 0; k < extras_size; ++k)
3124  {
3125  CGLTF_CHECK_KEY(tokens[i]);
3126 
3127  if (cgltf_json_strcmp(tokens+i, json_chunk, "targetNames") == 0 && tokens[i+1].type == JSMN_ARRAY)
3128  {
3129  i = cgltf_parse_json_string_array(options, tokens, i + 1, json_chunk, &out_mesh->target_names, &out_mesh->target_names_count);
3130  }
3131  else
3132  {
3133  i = cgltf_skip_json(tokens, i+1);
3134  }
3135 
3136  if (i < 0)
3137  {
3138  return i;
3139  }
3140  }
3141  }
3142  else
3143  {
3144  i = cgltf_skip_json(tokens, i);
3145  }
3146  }
3147  else if (cgltf_json_strcmp(tokens + i, json_chunk, "extensions") == 0)
3148  {
3149  i = cgltf_parse_json_unprocessed_extensions(options, tokens, i, json_chunk, &out_mesh->extensions_count, &out_mesh->extensions);
3150  }
3151  else
3152  {
3153  i = cgltf_skip_json(tokens, i+1);
3154  }
3155 
3156  if (i < 0)
3157  {
3158  return i;
3159  }
3160  }
3161 
3162  return i;
3163 }
3164 
3165 static int cgltf_parse_json_meshes(cgltf_options* options, jsmntok_t const* tokens, int i, const uint8_t* json_chunk, cgltf_data* out_data)
3166 {
3167  i = cgltf_parse_json_array(options, tokens, i, json_chunk, sizeof(cgltf_mesh), (void**)&out_data->meshes, &out_data->meshes_count);
3168  if (i < 0)
3169  {
3170  return i;
3171  }
3172 
3173  for (cgltf_size j = 0; j < out_data->meshes_count; ++j)
3174  {
3175  i = cgltf_parse_json_mesh(options, tokens, i, json_chunk, &out_data->meshes[j]);
3176  if (i < 0)
3177  {
3178  return i;
3179  }
3180  }
3181  return i;
3182 }
3183 
3184 static cgltf_component_type cgltf_json_to_component_type(jsmntok_t const* tok, const uint8_t* json_chunk)
3185 {
3186  int type = cgltf_json_to_int(tok, json_chunk);
3187 
3188  switch (type)
3189  {
3190  case 5120:
3191  return cgltf_component_type_r_8;
3192  case 5121:
3194  case 5122:
3196  case 5123:
3198  case 5125:
3200  case 5126:
3202  default:
3204  }
3205 }
3206 
3207 static int cgltf_parse_json_accessor_sparse(cgltf_options* options, jsmntok_t const* tokens, int i, const uint8_t* json_chunk, cgltf_accessor_sparse* out_sparse)
3208 {
3209  CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
3210 
3211  int size = tokens[i].size;
3212  ++i;
3213 
3214  for (int j = 0; j < size; ++j)
3215  {
3216  CGLTF_CHECK_KEY(tokens[i]);
3217 
3218  if (cgltf_json_strcmp(tokens+i, json_chunk, "count") == 0)
3219  {
3220  ++i;
3221  out_sparse->count = cgltf_json_to_int(tokens + i, json_chunk);
3222  ++i;
3223  }
3224  else if (cgltf_json_strcmp(tokens+i, json_chunk, "indices") == 0)
3225  {
3226  ++i;
3227  CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
3228 
3229  int indices_size = tokens[i].size;
3230  ++i;
3231 
3232  for (int k = 0; k < indices_size; ++k)
3233  {
3234  CGLTF_CHECK_KEY(tokens[i]);
3235 
3236  if (cgltf_json_strcmp(tokens+i, json_chunk, "bufferView") == 0)
3237  {
3238  ++i;
3239  out_sparse->indices_buffer_view = CGLTF_PTRINDEX(cgltf_buffer_view, cgltf_json_to_int(tokens + i, json_chunk));
3240  ++i;
3241  }
3242  else if (cgltf_json_strcmp(tokens+i, json_chunk, "byteOffset") == 0)
3243  {
3244  ++i;
3245  out_sparse->indices_byte_offset = cgltf_json_to_size(tokens + i, json_chunk);
3246  ++i;
3247  }
3248  else if (cgltf_json_strcmp(tokens+i, json_chunk, "componentType") == 0)
3249  {
3250  ++i;
3251  out_sparse->indices_component_type = cgltf_json_to_component_type(tokens + i, json_chunk);
3252  ++i;
3253  }
3254  else if (cgltf_json_strcmp(tokens + i, json_chunk, "extras") == 0)
3255  {
3256  i = cgltf_parse_json_extras(tokens, i + 1, json_chunk, &out_sparse->indices_extras);
3257  }
3258  else if (cgltf_json_strcmp(tokens + i, json_chunk, "extensions") == 0)
3259  {
3260  i = cgltf_parse_json_unprocessed_extensions(options, tokens, i, json_chunk, &out_sparse->indices_extensions_count, &out_sparse->indices_extensions);
3261  }
3262  else
3263  {
3264  i = cgltf_skip_json(tokens, i+1);
3265  }
3266 
3267  if (i < 0)
3268  {
3269  return i;
3270  }
3271  }
3272  }
3273  else if (cgltf_json_strcmp(tokens+i, json_chunk, "values") == 0)
3274  {
3275  ++i;
3276  CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
3277 
3278  int values_size = tokens[i].size;
3279  ++i;
3280 
3281  for (int k = 0; k < values_size; ++k)
3282  {
3283  CGLTF_CHECK_KEY(tokens[i]);
3284 
3285  if (cgltf_json_strcmp(tokens+i, json_chunk, "bufferView") == 0)
3286  {
3287  ++i;
3288  out_sparse->values_buffer_view = CGLTF_PTRINDEX(cgltf_buffer_view, cgltf_json_to_int(tokens + i, json_chunk));
3289  ++i;
3290  }
3291  else if (cgltf_json_strcmp(tokens+i, json_chunk, "byteOffset") == 0)
3292  {
3293  ++i;
3294  out_sparse->values_byte_offset = cgltf_json_to_size(tokens + i, json_chunk);
3295  ++i;
3296  }
3297  else if (cgltf_json_strcmp(tokens + i, json_chunk, "extras") == 0)
3298  {
3299  i = cgltf_parse_json_extras(tokens, i + 1, json_chunk, &out_sparse->values_extras);
3300  }
3301  else if (cgltf_json_strcmp(tokens + i, json_chunk, "extensions") == 0)
3302  {
3303  i = cgltf_parse_json_unprocessed_extensions(options, tokens, i, json_chunk, &out_sparse->values_extensions_count, &out_sparse->values_extensions);
3304  }
3305  else
3306  {
3307  i = cgltf_skip_json(tokens, i+1);
3308  }
3309 
3310  if (i < 0)
3311  {
3312  return i;
3313  }
3314  }
3315  }
3316  else if (cgltf_json_strcmp(tokens + i, json_chunk, "extras") == 0)
3317  {
3318  i = cgltf_parse_json_extras(tokens, i + 1, json_chunk, &out_sparse->extras);
3319  }
3320  else if (cgltf_json_strcmp(tokens + i, json_chunk, "extensions") == 0)
3321  {
3322  i = cgltf_parse_json_unprocessed_extensions(options, tokens, i, json_chunk, &out_sparse->extensions_count, &out_sparse->extensions);
3323  }
3324  else
3325  {
3326  i = cgltf_skip_json(tokens, i+1);
3327  }
3328 
3329  if (i < 0)
3330  {
3331  return i;
3332  }
3333  }
3334 
3335  return i;
3336 }
3337 
3338 static int cgltf_parse_json_accessor(cgltf_options* options, jsmntok_t const* tokens, int i, const uint8_t* json_chunk, cgltf_accessor* out_accessor)
3339 {
3340  CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
3341 
3342  int size = tokens[i].size;
3343  ++i;
3344 
3345  for (int j = 0; j < size; ++j)
3346  {
3347  CGLTF_CHECK_KEY(tokens[i]);
3348 
3349  if (cgltf_json_strcmp(tokens + i, json_chunk, "name") == 0)
3350  {
3351  i = cgltf_parse_json_string(options, tokens, i + 1, json_chunk, &out_accessor->name);
3352  }
3353  else if (cgltf_json_strcmp(tokens+i, json_chunk, "bufferView") == 0)
3354  {
3355  ++i;
3356  out_accessor->buffer_view = CGLTF_PTRINDEX(cgltf_buffer_view, cgltf_json_to_int(tokens + i, json_chunk));
3357  ++i;
3358  }
3359  else if (cgltf_json_strcmp(tokens+i, json_chunk, "byteOffset") == 0)
3360  {
3361  ++i;
3362  out_accessor->offset =
3363  cgltf_json_to_size(tokens+i, json_chunk);
3364  ++i;
3365  }
3366  else if (cgltf_json_strcmp(tokens+i, json_chunk, "componentType") == 0)
3367  {
3368  ++i;
3369  out_accessor->component_type = cgltf_json_to_component_type(tokens + i, json_chunk);
3370  ++i;
3371  }
3372  else if (cgltf_json_strcmp(tokens+i, json_chunk, "normalized") == 0)
3373  {
3374  ++i;
3375  out_accessor->normalized = cgltf_json_to_bool(tokens+i, json_chunk);
3376  ++i;
3377  }
3378  else if (cgltf_json_strcmp(tokens+i, json_chunk, "count") == 0)
3379  {
3380  ++i;
3381  out_accessor->count =
3382  cgltf_json_to_int(tokens+i, json_chunk);
3383  ++i;
3384  }
3385  else if (cgltf_json_strcmp(tokens+i, json_chunk, "type") == 0)
3386  {
3387  ++i;
3388  if (cgltf_json_strcmp(tokens+i, json_chunk, "SCALAR") == 0)
3389  {
3390  out_accessor->type = cgltf_type_scalar;
3391  }
3392  else if (cgltf_json_strcmp(tokens+i, json_chunk, "VEC2") == 0)
3393  {
3394  out_accessor->type = cgltf_type_vec2;
3395  }
3396  else if (cgltf_json_strcmp(tokens+i, json_chunk, "VEC3") == 0)
3397  {
3398  out_accessor->type = cgltf_type_vec3;
3399  }
3400  else if (cgltf_json_strcmp(tokens+i, json_chunk, "VEC4") == 0)
3401  {
3402  out_accessor->type = cgltf_type_vec4;
3403  }
3404  else if (cgltf_json_strcmp(tokens+i, json_chunk, "MAT2") == 0)
3405  {
3406  out_accessor->type = cgltf_type_mat2;
3407  }
3408  else if (cgltf_json_strcmp(tokens+i, json_chunk, "MAT3") == 0)
3409  {
3410  out_accessor->type = cgltf_type_mat3;
3411  }
3412  else if (cgltf_json_strcmp(tokens+i, json_chunk, "MAT4") == 0)
3413  {
3414  out_accessor->type = cgltf_type_mat4;
3415  }
3416  ++i;
3417  }
3418  else if (cgltf_json_strcmp(tokens + i, json_chunk, "min") == 0)
3419  {
3420  ++i;
3421  out_accessor->has_min = 1;
3422  // note: we can't parse the precise number of elements since type may not have been computed yet
3423  int min_size = tokens[i].size > 16 ? 16 : tokens[i].size;
3424  i = cgltf_parse_json_float_array(tokens, i, json_chunk, out_accessor->min, min_size);
3425  }
3426  else if (cgltf_json_strcmp(tokens + i, json_chunk, "max") == 0)
3427  {
3428  ++i;
3429  out_accessor->has_max = 1;
3430  // note: we can't parse the precise number of elements since type may not have been computed yet
3431  int max_size = tokens[i].size > 16 ? 16 : tokens[i].size;
3432  i = cgltf_parse_json_float_array(tokens, i, json_chunk, out_accessor->max, max_size);
3433  }
3434  else if (cgltf_json_strcmp(tokens + i, json_chunk, "sparse") == 0)
3435  {
3436  out_accessor->is_sparse = 1;
3437  i = cgltf_parse_json_accessor_sparse(options, tokens, i + 1, json_chunk, &out_accessor->sparse);
3438  }
3439  else if (cgltf_json_strcmp(tokens + i, json_chunk, "extras") == 0)
3440  {
3441  i = cgltf_parse_json_extras(tokens, i + 1, json_chunk, &out_accessor->extras);
3442  }
3443  else if (cgltf_json_strcmp(tokens + i, json_chunk, "extensions") == 0)
3444  {
3445  i = cgltf_parse_json_unprocessed_extensions(options, tokens, i, json_chunk, &out_accessor->extensions_count, &out_accessor->extensions);
3446  }
3447  else
3448  {
3449  i = cgltf_skip_json(tokens, i+1);
3450  }
3451 
3452  if (i < 0)
3453  {
3454  return i;
3455  }
3456  }
3457 
3458  return i;
3459 }
3460 
3461 static int cgltf_parse_json_texture_transform(jsmntok_t const* tokens, int i, const uint8_t* json_chunk, cgltf_texture_transform* out_texture_transform)
3462 {
3463  CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
3464 
3465  int size = tokens[i].size;
3466  ++i;
3467 
3468  for (int j = 0; j < size; ++j)
3469  {
3470  CGLTF_CHECK_KEY(tokens[i]);
3471 
3472  if (cgltf_json_strcmp(tokens + i, json_chunk, "offset") == 0)
3473  {
3474  i = cgltf_parse_json_float_array(tokens, i + 1, json_chunk, out_texture_transform->offset, 2);
3475  }
3476  else if (cgltf_json_strcmp(tokens + i, json_chunk, "rotation") == 0)
3477  {
3478  ++i;
3479  out_texture_transform->rotation = cgltf_json_to_float(tokens + i, json_chunk);
3480  ++i;
3481  }
3482  else if (cgltf_json_strcmp(tokens + i, json_chunk, "scale") == 0)
3483  {
3484  i = cgltf_parse_json_float_array(tokens, i + 1, json_chunk, out_texture_transform->scale, 2);
3485  }
3486  else if (cgltf_json_strcmp(tokens + i, json_chunk, "texCoord") == 0)
3487  {
3488  ++i;
3489  out_texture_transform->has_texcoord = 1;
3490  out_texture_transform->texcoord = cgltf_json_to_int(tokens + i, json_chunk);
3491  ++i;
3492  }
3493  else
3494  {
3495  i = cgltf_skip_json(tokens, i + 1);
3496  }
3497 
3498  if (i < 0)
3499  {
3500  return i;
3501  }
3502  }
3503 
3504  return i;
3505 }
3506 
3507 static int cgltf_parse_json_texture_view(cgltf_options* options, jsmntok_t const* tokens, int i, const uint8_t* json_chunk, cgltf_texture_view* out_texture_view)
3508 {
3509  CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
3510 
3511  out_texture_view->scale = 1.0f;
3512  cgltf_fill_float_array(out_texture_view->transform.scale, 2, 1.0f);
3513 
3514  int size = tokens[i].size;
3515  ++i;
3516 
3517  for (int j = 0; j < size; ++j)
3518  {
3519  CGLTF_CHECK_KEY(tokens[i]);
3520 
3521  if (cgltf_json_strcmp(tokens + i, json_chunk, "index") == 0)
3522  {
3523  ++i;
3524  out_texture_view->texture = CGLTF_PTRINDEX(cgltf_texture, cgltf_json_to_int(tokens + i, json_chunk));
3525  ++i;
3526  }
3527  else if (cgltf_json_strcmp(tokens + i, json_chunk, "texCoord") == 0)
3528  {
3529  ++i;
3530  out_texture_view->texcoord = cgltf_json_to_int(tokens + i, json_chunk);
3531  ++i;
3532  }
3533  else if (cgltf_json_strcmp(tokens + i, json_chunk, "scale") == 0)
3534  {
3535  ++i;
3536  out_texture_view->scale = cgltf_json_to_float(tokens + i, json_chunk);
3537  ++i;
3538  }
3539  else if (cgltf_json_strcmp(tokens + i, json_chunk, "strength") == 0)
3540  {
3541  ++i;
3542  out_texture_view->scale = cgltf_json_to_float(tokens + i, json_chunk);
3543  ++i;
3544  }
3545  else if (cgltf_json_strcmp(tokens + i, json_chunk, "extras") == 0)
3546  {
3547  i = cgltf_parse_json_extras(tokens, i + 1, json_chunk, &out_texture_view->extras);
3548  }
3549  else if (cgltf_json_strcmp(tokens + i, json_chunk, "extensions") == 0)
3550  {
3551  ++i;
3552 
3553  CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
3554  if(out_texture_view->extensions)
3555  {
3556  return CGLTF_ERROR_JSON;
3557  }
3558 
3559  int extensions_size = tokens[i].size;
3560  out_texture_view->extensions_count = 0;
3561  out_texture_view->extensions = (cgltf_extension*)cgltf_calloc(options, sizeof(cgltf_extension), extensions_size);
3562 
3563  if (!out_texture_view->extensions)
3564  {
3565  return CGLTF_ERROR_NOMEM;
3566  }
3567 
3568  ++i;
3569 
3570  for (int k = 0; k < extensions_size; ++k)
3571  {
3572  CGLTF_CHECK_KEY(tokens[i]);
3573 
3574  if (cgltf_json_strcmp(tokens+i, json_chunk, "KHR_texture_transform") == 0)
3575  {
3576  out_texture_view->has_transform = 1;
3577  i = cgltf_parse_json_texture_transform(tokens, i + 1, json_chunk, &out_texture_view->transform);
3578  }
3579  else
3580  {
3581  i = cgltf_parse_json_unprocessed_extension(options, tokens, i, json_chunk, &(out_texture_view->extensions[out_texture_view->extensions_count++]));
3582  }
3583 
3584  if (i < 0)
3585  {
3586  return i;
3587  }
3588  }
3589  }
3590  else
3591  {
3592  i = cgltf_skip_json(tokens, i + 1);
3593  }
3594 
3595  if (i < 0)
3596  {
3597  return i;
3598  }
3599  }
3600 
3601  return i;
3602 }
3603 
3604 static int cgltf_parse_json_pbr_metallic_roughness(cgltf_options* options, jsmntok_t const* tokens, int i, const uint8_t* json_chunk, cgltf_pbr_metallic_roughness* out_pbr)
3605 {
3606  CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
3607 
3608  int size = tokens[i].size;
3609  ++i;
3610 
3611  for (int j = 0; j < size; ++j)
3612  {
3613  CGLTF_CHECK_KEY(tokens[i]);
3614 
3615  if (cgltf_json_strcmp(tokens+i, json_chunk, "metallicFactor") == 0)
3616  {
3617  ++i;
3618  out_pbr->metallic_factor =
3619  cgltf_json_to_float(tokens + i, json_chunk);
3620  ++i;
3621  }
3622  else if (cgltf_json_strcmp(tokens+i, json_chunk, "roughnessFactor") == 0)
3623  {
3624  ++i;
3625  out_pbr->roughness_factor =
3626  cgltf_json_to_float(tokens+i, json_chunk);
3627  ++i;
3628  }
3629  else if (cgltf_json_strcmp(tokens+i, json_chunk, "baseColorFactor") == 0)
3630  {
3631  i = cgltf_parse_json_float_array(tokens, i + 1, json_chunk, out_pbr->base_color_factor, 4);
3632  }
3633  else if (cgltf_json_strcmp(tokens+i, json_chunk, "baseColorTexture") == 0)
3634  {
3635  i = cgltf_parse_json_texture_view(options, tokens, i + 1, json_chunk,
3636  &out_pbr->base_color_texture);
3637  }
3638  else if (cgltf_json_strcmp(tokens + i, json_chunk, "metallicRoughnessTexture") == 0)
3639  {
3640  i = cgltf_parse_json_texture_view(options, tokens, i + 1, json_chunk,
3641  &out_pbr->metallic_roughness_texture);
3642  }
3643  else if (cgltf_json_strcmp(tokens + i, json_chunk, "extras") == 0)
3644  {
3645  i = cgltf_parse_json_extras(tokens, i + 1, json_chunk, &out_pbr->extras);
3646  }
3647  else
3648  {
3649  i = cgltf_skip_json(tokens, i+1);
3650  }
3651 
3652  if (i < 0)
3653  {
3654  return i;
3655  }
3656  }
3657 
3658  return i;
3659 }
3660 
3661 static int cgltf_parse_json_pbr_specular_glossiness(cgltf_options* options, jsmntok_t const* tokens, int i, const uint8_t* json_chunk, cgltf_pbr_specular_glossiness* out_pbr)
3662 {
3663  CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
3664  int size = tokens[i].size;
3665  ++i;
3666 
3667  for (int j = 0; j < size; ++j)
3668  {
3669  CGLTF_CHECK_KEY(tokens[i]);
3670 
3671  if (cgltf_json_strcmp(tokens+i, json_chunk, "diffuseFactor") == 0)
3672  {
3673  i = cgltf_parse_json_float_array(tokens, i + 1, json_chunk, out_pbr->diffuse_factor, 4);
3674  }
3675  else if (cgltf_json_strcmp(tokens+i, json_chunk, "specularFactor") == 0)
3676  {
3677  i = cgltf_parse_json_float_array(tokens, i + 1, json_chunk, out_pbr->specular_factor, 3);
3678  }
3679  else if (cgltf_json_strcmp(tokens+i, json_chunk, "glossinessFactor") == 0)
3680  {
3681  ++i;
3682  out_pbr->glossiness_factor = cgltf_json_to_float(tokens + i, json_chunk);
3683  ++i;
3684  }
3685  else if (cgltf_json_strcmp(tokens+i, json_chunk, "diffuseTexture") == 0)
3686  {
3687  i = cgltf_parse_json_texture_view(options, tokens, i + 1, json_chunk, &out_pbr->diffuse_texture);
3688  }
3689  else if (cgltf_json_strcmp(tokens+i, json_chunk, "specularGlossinessTexture") == 0)
3690  {
3691  i = cgltf_parse_json_texture_view(options, tokens, i + 1, json_chunk, &out_pbr->specular_glossiness_texture);
3692  }
3693  else
3694  {
3695  i = cgltf_skip_json(tokens, i+1);
3696  }
3697 
3698  if (i < 0)
3699  {
3700  return i;
3701  }
3702  }
3703 
3704  return i;
3705 }
3706 
3707 static int cgltf_parse_json_clearcoat(cgltf_options* options, jsmntok_t const* tokens, int i, const uint8_t* json_chunk, cgltf_clearcoat* out_clearcoat)
3708 {
3709  CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
3710  int size = tokens[i].size;
3711  ++i;
3712 
3713  for (int j = 0; j < size; ++j)
3714  {
3715  CGLTF_CHECK_KEY(tokens[i]);
3716 
3717  if (cgltf_json_strcmp(tokens+i, json_chunk, "clearcoatFactor") == 0)
3718  {
3719  ++i;
3720  out_clearcoat->clearcoat_factor = cgltf_json_to_float(tokens + i, json_chunk);
3721  ++i;
3722  }
3723  else if (cgltf_json_strcmp(tokens+i, json_chunk, "clearcoatRoughnessFactor") == 0)
3724  {
3725  ++i;
3726  out_clearcoat->clearcoat_roughness_factor = cgltf_json_to_float(tokens + i, json_chunk);
3727  ++i;
3728  }
3729  else if (cgltf_json_strcmp(tokens+i, json_chunk, "clearcoatTexture") == 0)
3730  {
3731  i = cgltf_parse_json_texture_view(options, tokens, i + 1, json_chunk, &out_clearcoat->clearcoat_texture);
3732  }
3733  else if (cgltf_json_strcmp(tokens+i, json_chunk, "clearcoatRoughnessTexture") == 0)
3734  {
3735  i = cgltf_parse_json_texture_view(options, tokens, i + 1, json_chunk, &out_clearcoat->clearcoat_roughness_texture);
3736  }
3737  else if (cgltf_json_strcmp(tokens+i, json_chunk, "clearcoatNormalTexture") == 0)
3738  {
3739  i = cgltf_parse_json_texture_view(options, tokens, i + 1, json_chunk, &out_clearcoat->clearcoat_normal_texture);
3740  }
3741  else
3742  {
3743  i = cgltf_skip_json(tokens, i+1);
3744  }
3745 
3746  if (i < 0)
3747  {
3748  return i;
3749  }
3750  }
3751 
3752  return i;
3753 }
3754 
3755 static int cgltf_parse_json_ior(jsmntok_t const* tokens, int i, const uint8_t* json_chunk, cgltf_ior* out_ior)
3756 {
3757  CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
3758  int size = tokens[i].size;
3759  ++i;
3760 
3761  // Default values
3762  out_ior->ior = 1.5f;
3763 
3764  for (int j = 0; j < size; ++j)
3765  {
3766  CGLTF_CHECK_KEY(tokens[i]);
3767 
3768  if (cgltf_json_strcmp(tokens+i, json_chunk, "ior") == 0)
3769  {
3770  ++i;
3771  out_ior->ior = cgltf_json_to_float(tokens + i, json_chunk);
3772  ++i;
3773  }
3774  else
3775  {
3776  i = cgltf_skip_json(tokens, i+1);
3777  }
3778 
3779  if (i < 0)
3780  {
3781  return i;
3782  }
3783  }
3784 
3785  return i;
3786 }
3787 
3788 static int cgltf_parse_json_specular(cgltf_options* options, jsmntok_t const* tokens, int i, const uint8_t* json_chunk, cgltf_specular* out_specular)
3789 {
3790  CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
3791  int size = tokens[i].size;
3792  ++i;
3793 
3794  // Default values
3795  out_specular->specular_factor = 1.0f;
3796  cgltf_fill_float_array(out_specular->specular_color_factor, 3, 1.0f);
3797 
3798  for (int j = 0; j < size; ++j)
3799  {
3800  CGLTF_CHECK_KEY(tokens[i]);
3801 
3802  if (cgltf_json_strcmp(tokens+i, json_chunk, "specularFactor") == 0)
3803  {
3804  ++i;
3805  out_specular->specular_factor = cgltf_json_to_float(tokens + i, json_chunk);
3806  ++i;
3807  }
3808  else if (cgltf_json_strcmp(tokens+i, json_chunk, "specularColorFactor") == 0)
3809  {
3810  i = cgltf_parse_json_float_array(tokens, i + 1, json_chunk, out_specular->specular_color_factor, 3);
3811  }
3812  else if (cgltf_json_strcmp(tokens+i, json_chunk, "specularTexture") == 0)
3813  {
3814  i = cgltf_parse_json_texture_view(options, tokens, i + 1, json_chunk, &out_specular->specular_texture);
3815  }
3816  else if (cgltf_json_strcmp(tokens + i, json_chunk, "specularColorTexture") == 0)
3817  {
3818  i = cgltf_parse_json_texture_view(options, tokens, i + 1, json_chunk, &out_specular->specular_color_texture);
3819  }
3820  else
3821  {
3822  i = cgltf_skip_json(tokens, i+1);
3823  }
3824 
3825  if (i < 0)
3826  {
3827  return i;
3828  }
3829  }
3830 
3831  return i;
3832 }
3833 
3834 static int cgltf_parse_json_transmission(cgltf_options* options, jsmntok_t const* tokens, int i, const uint8_t* json_chunk, cgltf_transmission* out_transmission)
3835 {
3836  CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
3837  int size = tokens[i].size;
3838  ++i;
3839 
3840  for (int j = 0; j < size; ++j)
3841  {
3842  CGLTF_CHECK_KEY(tokens[i]);
3843 
3844  if (cgltf_json_strcmp(tokens+i, json_chunk, "transmissionFactor") == 0)
3845  {
3846  ++i;
3847  out_transmission->transmission_factor = cgltf_json_to_float(tokens + i, json_chunk);
3848  ++i;
3849  }
3850  else if (cgltf_json_strcmp(tokens+i, json_chunk, "transmissionTexture") == 0)
3851  {
3852  i = cgltf_parse_json_texture_view(options, tokens, i + 1, json_chunk, &out_transmission->transmission_texture);
3853  }
3854  else
3855  {
3856  i = cgltf_skip_json(tokens, i+1);
3857  }
3858 
3859  if (i < 0)
3860  {
3861  return i;
3862  }
3863  }
3864 
3865  return i;
3866 }
3867 
3868 static int cgltf_parse_json_volume(cgltf_options* options, jsmntok_t const* tokens, int i, const uint8_t* json_chunk, cgltf_volume* out_volume)
3869 {
3870  CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
3871  int size = tokens[i].size;
3872  ++i;
3873 
3874  for (int j = 0; j < size; ++j)
3875  {
3876  CGLTF_CHECK_KEY(tokens[i]);
3877 
3878  if (cgltf_json_strcmp(tokens + i, json_chunk, "thicknessFactor") == 0)
3879  {
3880  ++i;
3881  out_volume->thickness_factor = cgltf_json_to_float(tokens + i, json_chunk);
3882  ++i;
3883  }
3884  else if (cgltf_json_strcmp(tokens + i, json_chunk, "thicknessTexture") == 0)
3885  {
3886  i = cgltf_parse_json_texture_view(options, tokens, i + 1, json_chunk, &out_volume->thickness_texture);
3887  }
3888  else if (cgltf_json_strcmp(tokens + i, json_chunk, "attenuationColor") == 0)
3889  {
3890  i = cgltf_parse_json_float_array(tokens, i + 1, json_chunk, out_volume->attenuation_color, 3);
3891  }
3892  else if (cgltf_json_strcmp(tokens + i, json_chunk, "attenuationDistance") == 0)
3893  {
3894  ++i;
3895  out_volume->attenuation_distance = cgltf_json_to_float(tokens + i, json_chunk);
3896  ++i;
3897  }
3898  else
3899  {
3900  i = cgltf_skip_json(tokens, i + 1);
3901  }
3902 
3903  if (i < 0)
3904  {
3905  return i;
3906  }
3907  }
3908 
3909  return i;
3910 }
3911 
3912 static int cgltf_parse_json_sheen(cgltf_options* options, jsmntok_t const* tokens, int i, const uint8_t* json_chunk, cgltf_sheen* out_sheen)
3913 {
3914  CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
3915  int size = tokens[i].size;
3916  ++i;
3917 
3918  for (int j = 0; j < size; ++j)
3919  {
3920  CGLTF_CHECK_KEY(tokens[i]);
3921 
3922  if (cgltf_json_strcmp(tokens+i, json_chunk, "sheenColorFactor") == 0)
3923  {
3924  i = cgltf_parse_json_float_array(tokens, i + 1, json_chunk, out_sheen->sheen_color_factor, 3);
3925  }
3926  else if (cgltf_json_strcmp(tokens+i, json_chunk, "sheenColorTexture") == 0)
3927  {
3928  i = cgltf_parse_json_texture_view(options, tokens, i + 1, json_chunk, &out_sheen->sheen_color_texture);
3929  }
3930  else if (cgltf_json_strcmp(tokens+i, json_chunk, "sheenRoughnessFactor") == 0)
3931  {
3932  ++i;
3933  out_sheen->sheen_roughness_factor = cgltf_json_to_float(tokens + i, json_chunk);
3934  ++i;
3935  }
3936  else if (cgltf_json_strcmp(tokens+i, json_chunk, "sheenRoughnessTexture") == 0)
3937  {
3938  i = cgltf_parse_json_texture_view(options, tokens, i + 1, json_chunk, &out_sheen->sheen_roughness_texture);
3939  }
3940  else
3941  {
3942  i = cgltf_skip_json(tokens, i+1);
3943  }
3944 
3945  if (i < 0)
3946  {
3947  return i;
3948  }
3949  }
3950 
3951  return i;
3952 }
3953 
3954 static int cgltf_parse_json_emissive_strength(jsmntok_t const* tokens, int i, const uint8_t* json_chunk, cgltf_emissive_strength* out_emissive_strength)
3955 {
3956  CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
3957  int size = tokens[i].size;
3958  ++i;
3959 
3960  // Default
3961  out_emissive_strength->emissive_strength = 1.f;
3962 
3963  for (int j = 0; j < size; ++j)
3964  {
3965  CGLTF_CHECK_KEY(tokens[i]);
3966 
3967  if (cgltf_json_strcmp(tokens + i, json_chunk, "emissiveStrength") == 0)
3968  {
3969  ++i;
3970  out_emissive_strength->emissive_strength = cgltf_json_to_float(tokens + i, json_chunk);
3971  ++i;
3972  }
3973  else
3974  {
3975  i = cgltf_skip_json(tokens, i + 1);
3976  }
3977 
3978  if (i < 0)
3979  {
3980  return i;
3981  }
3982  }
3983 
3984  return i;
3985 }
3986 
3987 static int cgltf_parse_json_iridescence(cgltf_options* options, jsmntok_t const* tokens, int i, const uint8_t* json_chunk, cgltf_iridescence* out_iridescence)
3988 {
3989  CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
3990  int size = tokens[i].size;
3991  ++i;
3992 
3993  // Default
3994  out_iridescence->iridescence_ior = 1.3f;
3995  out_iridescence->iridescence_thickness_min = 100.f;
3996  out_iridescence->iridescence_thickness_max = 400.f;
3997 
3998  for (int j = 0; j < size; ++j)
3999  {
4000  CGLTF_CHECK_KEY(tokens[i]);
4001 
4002  if (cgltf_json_strcmp(tokens + i, json_chunk, "iridescenceFactor") == 0)
4003  {
4004  ++i;
4005  out_iridescence->iridescence_factor = cgltf_json_to_float(tokens + i, json_chunk);
4006  ++i;
4007  }
4008  else if (cgltf_json_strcmp(tokens + i, json_chunk, "iridescenceTexture") == 0)
4009  {
4010  i = cgltf_parse_json_texture_view(options, tokens, i + 1, json_chunk, &out_iridescence->iridescence_texture);
4011  }
4012  else if (cgltf_json_strcmp(tokens + i, json_chunk, "iridescenceIor") == 0)
4013  {
4014  ++i;
4015  out_iridescence->iridescence_ior = cgltf_json_to_float(tokens + i, json_chunk);
4016  ++i;
4017  }
4018  else if (cgltf_json_strcmp(tokens + i, json_chunk, "iridescenceThicknessMinimum") == 0)
4019  {
4020  ++i;
4021  out_iridescence->iridescence_thickness_min = cgltf_json_to_float(tokens + i, json_chunk);
4022  ++i;
4023  }
4024  else if (cgltf_json_strcmp(tokens + i, json_chunk, "iridescenceThicknessMaximum") == 0)
4025  {
4026  ++i;
4027  out_iridescence->iridescence_thickness_max = cgltf_json_to_float(tokens + i, json_chunk);
4028  ++i;
4029  }
4030  else if (cgltf_json_strcmp(tokens + i, json_chunk, "iridescenceThicknessTexture") == 0)
4031  {
4032  i = cgltf_parse_json_texture_view(options, tokens, i + 1, json_chunk, &out_iridescence->iridescence_thickness_texture);
4033  }
4034  else
4035  {
4036  i = cgltf_skip_json(tokens, i + 1);
4037  }
4038 
4039  if (i < 0)
4040  {
4041  return i;
4042  }
4043  }
4044 
4045  return i;
4046 }
4047 
4048 static int cgltf_parse_json_image(cgltf_options* options, jsmntok_t const* tokens, int i, const uint8_t* json_chunk, cgltf_image* out_image)
4049 {
4050  CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
4051 
4052  int size = tokens[i].size;
4053  ++i;
4054 
4055  for (int j = 0; j < size; ++j)
4056  {
4057  CGLTF_CHECK_KEY(tokens[i]);
4058 
4059  if (cgltf_json_strcmp(tokens + i, json_chunk, "uri") == 0)
4060  {
4061  i = cgltf_parse_json_string(options, tokens, i + 1, json_chunk, &out_image->uri);
4062  }
4063  else if (cgltf_json_strcmp(tokens+i, json_chunk, "bufferView") == 0)
4064  {
4065  ++i;
4066  out_image->buffer_view = CGLTF_PTRINDEX(cgltf_buffer_view, cgltf_json_to_int(tokens + i, json_chunk));
4067  ++i;
4068  }
4069  else if (cgltf_json_strcmp(tokens + i, json_chunk, "mimeType") == 0)
4070  {
4071  i = cgltf_parse_json_string(options, tokens, i + 1, json_chunk, &out_image->mime_type);
4072  }
4073  else if (cgltf_json_strcmp(tokens + i, json_chunk, "name") == 0)
4074  {
4075  i = cgltf_parse_json_string(options, tokens, i + 1, json_chunk, &out_image->name);
4076  }
4077  else if (cgltf_json_strcmp(tokens + i, json_chunk, "extras") == 0)
4078  {
4079  i = cgltf_parse_json_extras(tokens, i + 1, json_chunk, &out_image->extras);
4080  }
4081  else if (cgltf_json_strcmp(tokens + i, json_chunk, "extensions") == 0)
4082  {
4083  i = cgltf_parse_json_unprocessed_extensions(options, tokens, i, json_chunk, &out_image->extensions_count, &out_image->extensions);
4084  }
4085  else
4086  {
4087  i = cgltf_skip_json(tokens, i + 1);
4088  }
4089 
4090  if (i < 0)
4091  {
4092  return i;
4093  }
4094  }
4095 
4096  return i;
4097 }
4098 
4099 static int cgltf_parse_json_sampler(cgltf_options* options, jsmntok_t const* tokens, int i, const uint8_t* json_chunk, cgltf_sampler* out_sampler)
4100 {
4101  (void)options;
4102  CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
4103 
4104  out_sampler->wrap_s = 10497;
4105  out_sampler->wrap_t = 10497;
4106 
4107  int size = tokens[i].size;
4108  ++i;
4109 
4110  for (int j = 0; j < size; ++j)
4111  {
4112  CGLTF_CHECK_KEY(tokens[i]);
4113 
4114  if (cgltf_json_strcmp(tokens + i, json_chunk, "name") == 0)
4115  {
4116  i = cgltf_parse_json_string(options, tokens, i + 1, json_chunk, &out_sampler->name);
4117  }
4118  else if (cgltf_json_strcmp(tokens + i, json_chunk, "magFilter") == 0)
4119  {
4120  ++i;
4121  out_sampler->mag_filter
4122  = cgltf_json_to_int(tokens + i, json_chunk);
4123  ++i;
4124  }
4125  else if (cgltf_json_strcmp(tokens + i, json_chunk, "minFilter") == 0)
4126  {
4127  ++i;
4128  out_sampler->min_filter
4129  = cgltf_json_to_int(tokens + i, json_chunk);
4130  ++i;
4131  }
4132  else if (cgltf_json_strcmp(tokens + i, json_chunk, "wrapS") == 0)
4133  {
4134  ++i;
4135  out_sampler->wrap_s
4136  = cgltf_json_to_int(tokens + i, json_chunk);
4137  ++i;
4138  }
4139  else if (cgltf_json_strcmp(tokens + i, json_chunk, "wrapT") == 0)
4140  {
4141  ++i;
4142  out_sampler->wrap_t
4143  = cgltf_json_to_int(tokens + i, json_chunk);
4144  ++i;
4145  }
4146  else if (cgltf_json_strcmp(tokens + i, json_chunk, "extras") == 0)
4147  {
4148  i = cgltf_parse_json_extras(tokens, i + 1, json_chunk, &out_sampler->extras);
4149  }
4150  else if (cgltf_json_strcmp(tokens + i, json_chunk, "extensions") == 0)
4151  {
4152  i = cgltf_parse_json_unprocessed_extensions(options, tokens, i, json_chunk, &out_sampler->extensions_count, &out_sampler->extensions);
4153  }
4154  else
4155  {
4156  i = cgltf_skip_json(tokens, i + 1);
4157  }
4158 
4159  if (i < 0)
4160  {
4161  return i;
4162  }
4163  }
4164 
4165  return i;
4166 }
4167 
4168 static int cgltf_parse_json_texture(cgltf_options* options, jsmntok_t const* tokens, int i, const uint8_t* json_chunk, cgltf_texture* out_texture)
4169 {
4170  CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
4171 
4172  int size = tokens[i].size;
4173  ++i;
4174 
4175  for (int j = 0; j < size; ++j)
4176  {
4177  CGLTF_CHECK_KEY(tokens[i]);
4178 
4179  if (cgltf_json_strcmp(tokens+i, json_chunk, "name") == 0)
4180  {
4181  i = cgltf_parse_json_string(options, tokens, i + 1, json_chunk, &out_texture->name);
4182  }
4183  else if (cgltf_json_strcmp(tokens + i, json_chunk, "sampler") == 0)
4184  {
4185  ++i;
4186  out_texture->sampler = CGLTF_PTRINDEX(cgltf_sampler, cgltf_json_to_int(tokens + i, json_chunk));
4187  ++i;
4188  }
4189  else if (cgltf_json_strcmp(tokens + i, json_chunk, "source") == 0)
4190  {
4191  ++i;
4192  out_texture->image = CGLTF_PTRINDEX(cgltf_image, cgltf_json_to_int(tokens + i, json_chunk));
4193  ++i;
4194  }
4195  else if (cgltf_json_strcmp(tokens + i, json_chunk, "extras") == 0)
4196  {
4197  i = cgltf_parse_json_extras(tokens, i + 1, json_chunk, &out_texture->extras);
4198  }
4199  else if (cgltf_json_strcmp(tokens + i, json_chunk, "extensions") == 0)
4200  {
4201  ++i;
4202 
4203  CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
4204  if (out_texture->extensions)
4205  {
4206  return CGLTF_ERROR_JSON;
4207  }
4208 
4209  int extensions_size = tokens[i].size;
4210  ++i;
4211  out_texture->extensions = (cgltf_extension*)cgltf_calloc(options, sizeof(cgltf_extension), extensions_size);
4212  out_texture->extensions_count = 0;
4213 
4214  if (!out_texture->extensions)
4215  {
4216  return CGLTF_ERROR_NOMEM;
4217  }
4218 
4219  for (int k = 0; k < extensions_size; ++k)
4220  {
4221  CGLTF_CHECK_KEY(tokens[i]);
4222 
4223  if (cgltf_json_strcmp(tokens + i, json_chunk, "KHR_texture_basisu") == 0)
4224  {
4225  out_texture->has_basisu = 1;
4226  ++i;
4227  CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
4228  int num_properties = tokens[i].size;
4229  ++i;
4230 
4231  for (int t = 0; t < num_properties; ++t)
4232  {
4233  CGLTF_CHECK_KEY(tokens[i]);
4234 
4235  if (cgltf_json_strcmp(tokens + i, json_chunk, "source") == 0)
4236  {
4237  ++i;
4238  out_texture->basisu_image = CGLTF_PTRINDEX(cgltf_image, cgltf_json_to_int(tokens + i, json_chunk));
4239  ++i;
4240  }
4241  else
4242  {
4243  i = cgltf_skip_json(tokens, i + 1);
4244  }
4245  if (i < 0)
4246  {
4247  return i;
4248  }
4249  }
4250  }
4251  else
4252  {
4253  i = cgltf_parse_json_unprocessed_extension(options, tokens, i, json_chunk, &(out_texture->extensions[out_texture->extensions_count++]));
4254  }
4255 
4256  if (i < 0)
4257  {
4258  return i;
4259  }
4260  }
4261  }
4262  else
4263  {
4264  i = cgltf_skip_json(tokens, i + 1);
4265  }
4266 
4267  if (i < 0)
4268  {
4269  return i;
4270  }
4271  }
4272 
4273  return i;
4274 }
4275 
4276 static int cgltf_parse_json_material(cgltf_options* options, jsmntok_t const* tokens, int i, const uint8_t* json_chunk, cgltf_material* out_material)
4277 {
4278  CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
4279 
4280  cgltf_fill_float_array(out_material->pbr_metallic_roughness.base_color_factor, 4, 1.0f);
4281  out_material->pbr_metallic_roughness.metallic_factor = 1.0f;
4282  out_material->pbr_metallic_roughness.roughness_factor = 1.0f;
4283 
4284  cgltf_fill_float_array(out_material->pbr_specular_glossiness.diffuse_factor, 4, 1.0f);
4285  cgltf_fill_float_array(out_material->pbr_specular_glossiness.specular_factor, 3, 1.0f);
4286  out_material->pbr_specular_glossiness.glossiness_factor = 1.0f;
4287 
4288  cgltf_fill_float_array(out_material->volume.attenuation_color, 3, 1.0f);
4289  out_material->volume.attenuation_distance = FLT_MAX;
4290 
4291  out_material->alpha_cutoff = 0.5f;
4292 
4293  int size = tokens[i].size;
4294  ++i;
4295 
4296  for (int j = 0; j < size; ++j)
4297  {
4298  CGLTF_CHECK_KEY(tokens[i]);
4299 
4300  if (cgltf_json_strcmp(tokens+i, json_chunk, "name") == 0)
4301  {
4302  i = cgltf_parse_json_string(options, tokens, i + 1, json_chunk, &out_material->name);
4303  }
4304  else if (cgltf_json_strcmp(tokens+i, json_chunk, "pbrMetallicRoughness") == 0)
4305  {
4306  out_material->has_pbr_metallic_roughness = 1;
4307  i = cgltf_parse_json_pbr_metallic_roughness(options, tokens, i + 1, json_chunk, &out_material->pbr_metallic_roughness);
4308  }
4309  else if (cgltf_json_strcmp(tokens+i, json_chunk, "emissiveFactor") == 0)
4310  {
4311  i = cgltf_parse_json_float_array(tokens, i + 1, json_chunk, out_material->emissive_factor, 3);
4312  }
4313  else if (cgltf_json_strcmp(tokens + i, json_chunk, "normalTexture") == 0)
4314  {
4315  i = cgltf_parse_json_texture_view(options, tokens, i + 1, json_chunk,
4316  &out_material->normal_texture);
4317  }
4318  else if (cgltf_json_strcmp(tokens + i, json_chunk, "occlusionTexture") == 0)
4319  {
4320  i = cgltf_parse_json_texture_view(options, tokens, i + 1, json_chunk,
4321  &out_material->occlusion_texture);
4322  }
4323  else if (cgltf_json_strcmp(tokens + i, json_chunk, "emissiveTexture") == 0)
4324  {
4325  i = cgltf_parse_json_texture_view(options, tokens, i + 1, json_chunk,
4326  &out_material->emissive_texture);
4327  }
4328  else if (cgltf_json_strcmp(tokens + i, json_chunk, "alphaMode") == 0)
4329  {
4330  ++i;
4331  if (cgltf_json_strcmp(tokens + i, json_chunk, "OPAQUE") == 0)
4332  {
4333  out_material->alpha_mode = cgltf_alpha_mode_opaque;
4334  }
4335  else if (cgltf_json_strcmp(tokens + i, json_chunk, "MASK") == 0)
4336  {
4337  out_material->alpha_mode = cgltf_alpha_mode_mask;
4338  }
4339  else if (cgltf_json_strcmp(tokens + i, json_chunk, "BLEND") == 0)
4340  {
4341  out_material->alpha_mode = cgltf_alpha_mode_blend;
4342  }
4343  ++i;
4344  }
4345  else if (cgltf_json_strcmp(tokens + i, json_chunk, "alphaCutoff") == 0)
4346  {
4347  ++i;
4348  out_material->alpha_cutoff = cgltf_json_to_float(tokens + i, json_chunk);
4349  ++i;
4350  }
4351  else if (cgltf_json_strcmp(tokens + i, json_chunk, "doubleSided") == 0)
4352  {
4353  ++i;
4354  out_material->double_sided =
4355  cgltf_json_to_bool(tokens + i, json_chunk);
4356  ++i;
4357  }
4358  else if (cgltf_json_strcmp(tokens + i, json_chunk, "extras") == 0)
4359  {
4360  i = cgltf_parse_json_extras(tokens, i + 1, json_chunk, &out_material->extras);
4361  }
4362  else if (cgltf_json_strcmp(tokens + i, json_chunk, "extensions") == 0)
4363  {
4364  ++i;
4365 
4366  CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
4367  if(out_material->extensions)
4368  {
4369  return CGLTF_ERROR_JSON;
4370  }
4371 
4372  int extensions_size = tokens[i].size;
4373  ++i;
4374  out_material->extensions = (cgltf_extension*)cgltf_calloc(options, sizeof(cgltf_extension), extensions_size);
4375  out_material->extensions_count= 0;
4376 
4377  if (!out_material->extensions)
4378  {
4379  return CGLTF_ERROR_NOMEM;
4380  }
4381 
4382  for (int k = 0; k < extensions_size; ++k)
4383  {
4384  CGLTF_CHECK_KEY(tokens[i]);
4385 
4386  if (cgltf_json_strcmp(tokens+i, json_chunk, "KHR_materials_pbrSpecularGlossiness") == 0)
4387  {
4388  out_material->has_pbr_specular_glossiness = 1;
4389  i = cgltf_parse_json_pbr_specular_glossiness(options, tokens, i + 1, json_chunk, &out_material->pbr_specular_glossiness);
4390  }
4391  else if (cgltf_json_strcmp(tokens+i, json_chunk, "KHR_materials_unlit") == 0)
4392  {
4393  out_material->unlit = 1;
4394  i = cgltf_skip_json(tokens, i+1);
4395  }
4396  else if (cgltf_json_strcmp(tokens+i, json_chunk, "KHR_materials_clearcoat") == 0)
4397  {
4398  out_material->has_clearcoat = 1;
4399  i = cgltf_parse_json_clearcoat(options, tokens, i + 1, json_chunk, &out_material->clearcoat);
4400  }
4401  else if (cgltf_json_strcmp(tokens+i, json_chunk, "KHR_materials_ior") == 0)
4402  {
4403  out_material->has_ior = 1;
4404  i = cgltf_parse_json_ior(tokens, i + 1, json_chunk, &out_material->ior);
4405  }
4406  else if (cgltf_json_strcmp(tokens+i, json_chunk, "KHR_materials_specular") == 0)
4407  {
4408  out_material->has_specular = 1;
4409  i = cgltf_parse_json_specular(options, tokens, i + 1, json_chunk, &out_material->specular);
4410  }
4411  else if (cgltf_json_strcmp(tokens+i, json_chunk, "KHR_materials_transmission") == 0)
4412  {
4413  out_material->has_transmission = 1;
4414  i = cgltf_parse_json_transmission(options, tokens, i + 1, json_chunk, &out_material->transmission);
4415  }
4416  else if (cgltf_json_strcmp(tokens + i, json_chunk, "KHR_materials_volume") == 0)
4417  {
4418  out_material->has_volume = 1;
4419  i = cgltf_parse_json_volume(options, tokens, i + 1, json_chunk, &out_material->volume);
4420  }
4421  else if (cgltf_json_strcmp(tokens+i, json_chunk, "KHR_materials_sheen") == 0)
4422  {
4423  out_material->has_sheen = 1;
4424  i = cgltf_parse_json_sheen(options, tokens, i + 1, json_chunk, &out_material->sheen);
4425  }
4426  else if (cgltf_json_strcmp(tokens + i, json_chunk, "KHR_materials_emissive_strength") == 0)
4427  {
4428  out_material->has_emissive_strength = 1;
4429  i = cgltf_parse_json_emissive_strength(tokens, i + 1, json_chunk, &out_material->emissive_strength);
4430  }
4431  else if (cgltf_json_strcmp(tokens + i, json_chunk, "KHR_materials_iridescence") == 0)
4432  {
4433  out_material->has_iridescence = 1;
4434  i = cgltf_parse_json_iridescence(options, tokens, i + 1, json_chunk, &out_material->iridescence);
4435  }
4436  else
4437  {
4438  i = cgltf_parse_json_unprocessed_extension(options, tokens, i, json_chunk, &(out_material->extensions[out_material->extensions_count++]));
4439  }
4440 
4441  if (i < 0)
4442  {
4443  return i;
4444  }
4445  }
4446  }
4447  else
4448  {
4449  i = cgltf_skip_json(tokens, i+1);
4450  }
4451 
4452  if (i < 0)
4453  {
4454  return i;
4455  }
4456  }
4457 
4458  return i;
4459 }
4460 
4461 static int cgltf_parse_json_accessors(cgltf_options* options, jsmntok_t const* tokens, int i, const uint8_t* json_chunk, cgltf_data* out_data)
4462 {
4463  i = cgltf_parse_json_array(options, tokens, i, json_chunk, sizeof(cgltf_accessor), (void**)&out_data->accessors, &out_data->accessors_count);
4464  if (i < 0)
4465  {
4466  return i;
4467  }
4468 
4469  for (cgltf_size j = 0; j < out_data->accessors_count; ++j)
4470  {
4471  i = cgltf_parse_json_accessor(options, tokens, i, json_chunk, &out_data->accessors[j]);
4472  if (i < 0)
4473  {
4474  return i;
4475  }
4476  }
4477  return i;
4478 }
4479 
4480 static int cgltf_parse_json_materials(cgltf_options* options, jsmntok_t const* tokens, int i, const uint8_t* json_chunk, cgltf_data* out_data)
4481 {
4482  i = cgltf_parse_json_array(options, tokens, i, json_chunk, sizeof(cgltf_material), (void**)&out_data->materials, &out_data->materials_count);
4483  if (i < 0)
4484  {
4485  return i;
4486  }
4487 
4488  for (cgltf_size j = 0; j < out_data->materials_count; ++j)
4489  {
4490  i = cgltf_parse_json_material(options, tokens, i, json_chunk, &out_data->materials[j]);
4491  if (i < 0)
4492  {
4493  return i;
4494  }
4495  }
4496  return i;
4497 }
4498 
4499 static int cgltf_parse_json_images(cgltf_options* options, jsmntok_t const* tokens, int i, const uint8_t* json_chunk, cgltf_data* out_data)
4500 {
4501  i = cgltf_parse_json_array(options, tokens, i, json_chunk, sizeof(cgltf_image), (void**)&out_data->images, &out_data->images_count);
4502  if (i < 0)
4503  {
4504  return i;
4505  }
4506 
4507  for (cgltf_size j = 0; j < out_data->images_count; ++j)
4508  {
4509  i = cgltf_parse_json_image(options, tokens, i, json_chunk, &out_data->images[j]);
4510  if (i < 0)
4511  {
4512  return i;
4513  }
4514  }
4515  return i;
4516 }
4517 
4518 static int cgltf_parse_json_textures(cgltf_options* options, jsmntok_t const* tokens, int i, const uint8_t* json_chunk, cgltf_data* out_data)
4519 {
4520  i = cgltf_parse_json_array(options, tokens, i, json_chunk, sizeof(cgltf_texture), (void**)&out_data->textures, &out_data->textures_count);
4521  if (i < 0)
4522  {
4523  return i;
4524  }
4525 
4526  for (cgltf_size j = 0; j < out_data->textures_count; ++j)
4527  {
4528  i = cgltf_parse_json_texture(options, tokens, i, json_chunk, &out_data->textures[j]);
4529  if (i < 0)
4530  {
4531  return i;
4532  }
4533  }
4534  return i;
4535 }
4536 
4537 static int cgltf_parse_json_samplers(cgltf_options* options, jsmntok_t const* tokens, int i, const uint8_t* json_chunk, cgltf_data* out_data)
4538 {
4539  i = cgltf_parse_json_array(options, tokens, i, json_chunk, sizeof(cgltf_sampler), (void**)&out_data->samplers, &out_data->samplers_count);
4540  if (i < 0)
4541  {
4542  return i;
4543  }
4544 
4545  for (cgltf_size j = 0; j < out_data->samplers_count; ++j)
4546  {
4547  i = cgltf_parse_json_sampler(options, tokens, i, json_chunk, &out_data->samplers[j]);
4548  if (i < 0)
4549  {
4550  return i;
4551  }
4552  }
4553  return i;
4554 }
4555 
4556 static int cgltf_parse_json_meshopt_compression(cgltf_options* options, jsmntok_t const* tokens, int i, const uint8_t* json_chunk, cgltf_meshopt_compression* out_meshopt_compression)
4557 {
4558  (void)options;
4559  CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
4560 
4561  int size = tokens[i].size;
4562  ++i;
4563 
4564  for (int j = 0; j < size; ++j)
4565  {
4566  CGLTF_CHECK_KEY(tokens[i]);
4567 
4568  if (cgltf_json_strcmp(tokens+i, json_chunk, "buffer") == 0)
4569  {
4570  ++i;
4571  out_meshopt_compression->buffer = CGLTF_PTRINDEX(cgltf_buffer, cgltf_json_to_int(tokens + i, json_chunk));
4572  ++i;
4573  }
4574  else if (cgltf_json_strcmp(tokens+i, json_chunk, "byteOffset") == 0)
4575  {
4576  ++i;
4577  out_meshopt_compression->offset = cgltf_json_to_size(tokens+i, json_chunk);
4578  ++i;
4579  }
4580  else if (cgltf_json_strcmp(tokens+i, json_chunk, "byteLength") == 0)
4581  {
4582  ++i;
4583  out_meshopt_compression->size = cgltf_json_to_size(tokens+i, json_chunk);
4584  ++i;
4585  }
4586  else if (cgltf_json_strcmp(tokens+i, json_chunk, "byteStride") == 0)
4587  {
4588  ++i;
4589  out_meshopt_compression->stride = cgltf_json_to_size(tokens+i, json_chunk);
4590  ++i;
4591  }
4592  else if (cgltf_json_strcmp(tokens+i, json_chunk, "count") == 0)
4593  {
4594  ++i;
4595  out_meshopt_compression->count = cgltf_json_to_int(tokens+i, json_chunk);
4596  ++i;
4597  }
4598  else if (cgltf_json_strcmp(tokens+i, json_chunk, "mode") == 0)
4599  {
4600  ++i;
4601  if (cgltf_json_strcmp(tokens+i, json_chunk, "ATTRIBUTES") == 0)
4602  {
4603  out_meshopt_compression->mode = cgltf_meshopt_compression_mode_attributes;
4604  }
4605  else if (cgltf_json_strcmp(tokens+i, json_chunk, "TRIANGLES") == 0)
4606  {
4607  out_meshopt_compression->mode = cgltf_meshopt_compression_mode_triangles;
4608  }
4609  else if (cgltf_json_strcmp(tokens+i, json_chunk, "INDICES") == 0)
4610  {
4611  out_meshopt_compression->mode = cgltf_meshopt_compression_mode_indices;
4612  }
4613  ++i;
4614  }
4615  else if (cgltf_json_strcmp(tokens+i, json_chunk, "filter") == 0)
4616  {
4617  ++i;
4618  if (cgltf_json_strcmp(tokens+i, json_chunk, "NONE") == 0)
4619  {
4620  out_meshopt_compression->filter = cgltf_meshopt_compression_filter_none;
4621  }
4622  else if (cgltf_json_strcmp(tokens+i, json_chunk, "OCTAHEDRAL") == 0)
4623  {
4624  out_meshopt_compression->filter = cgltf_meshopt_compression_filter_octahedral;
4625  }
4626  else if (cgltf_json_strcmp(tokens+i, json_chunk, "QUATERNION") == 0)
4627  {
4628  out_meshopt_compression->filter = cgltf_meshopt_compression_filter_quaternion;
4629  }
4630  else if (cgltf_json_strcmp(tokens+i, json_chunk, "EXPONENTIAL") == 0)
4631  {
4632  out_meshopt_compression->filter = cgltf_meshopt_compression_filter_exponential;
4633  }
4634  ++i;
4635  }
4636  else
4637  {
4638  i = cgltf_skip_json(tokens, i+1);
4639  }
4640 
4641  if (i < 0)
4642  {
4643  return i;
4644  }
4645  }
4646 
4647  return i;
4648 }
4649 
4650 static int cgltf_parse_json_buffer_view(cgltf_options* options, jsmntok_t const* tokens, int i, const uint8_t* json_chunk, cgltf_buffer_view* out_buffer_view)
4651 {
4652  CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
4653 
4654  int size = tokens[i].size;
4655  ++i;
4656 
4657  for (int j = 0; j < size; ++j)
4658  {
4659  CGLTF_CHECK_KEY(tokens[i]);
4660 
4661  if (cgltf_json_strcmp(tokens + i, json_chunk, "name") == 0)
4662  {
4663  i = cgltf_parse_json_string(options, tokens, i + 1, json_chunk, &out_buffer_view->name);
4664  }
4665  else if (cgltf_json_strcmp(tokens+i, json_chunk, "buffer") == 0)
4666  {
4667  ++i;
4668  out_buffer_view->buffer = CGLTF_PTRINDEX(cgltf_buffer, cgltf_json_to_int(tokens + i, json_chunk));
4669  ++i;
4670  }
4671  else if (cgltf_json_strcmp(tokens+i, json_chunk, "byteOffset") == 0)
4672  {
4673  ++i;
4674  out_buffer_view->offset =
4675  cgltf_json_to_size(tokens+i, json_chunk);
4676  ++i;
4677  }
4678  else if (cgltf_json_strcmp(tokens+i, json_chunk, "byteLength") == 0)
4679  {
4680  ++i;
4681  out_buffer_view->size =
4682  cgltf_json_to_size(tokens+i, json_chunk);
4683  ++i;
4684  }
4685  else if (cgltf_json_strcmp(tokens+i, json_chunk, "byteStride") == 0)
4686  {
4687  ++i;
4688  out_buffer_view->stride =
4689  cgltf_json_to_size(tokens+i, json_chunk);
4690  ++i;
4691  }
4692  else if (cgltf_json_strcmp(tokens+i, json_chunk, "target") == 0)
4693  {
4694  ++i;
4695  int type = cgltf_json_to_int(tokens+i, json_chunk);
4696  switch (type)
4697  {
4698  case 34962:
4700  break;
4701  case 34963:
4703  break;
4704  default:
4706  break;
4707  }
4708  out_buffer_view->type = (cgltf_buffer_view_type)type;
4709  ++i;
4710  }
4711  else if (cgltf_json_strcmp(tokens + i, json_chunk, "extras") == 0)
4712  {
4713  i = cgltf_parse_json_extras(tokens, i + 1, json_chunk, &out_buffer_view->extras);
4714  }
4715  else if (cgltf_json_strcmp(tokens + i, json_chunk, "extensions") == 0)
4716  {
4717  ++i;
4718 
4719  CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
4720  if(out_buffer_view->extensions)
4721  {
4722  return CGLTF_ERROR_JSON;
4723  }
4724 
4725  int extensions_size = tokens[i].size;
4726  out_buffer_view->extensions_count = 0;
4727  out_buffer_view->extensions = (cgltf_extension*)cgltf_calloc(options, sizeof(cgltf_extension), extensions_size);
4728 
4729  if (!out_buffer_view->extensions)
4730  {
4731  return CGLTF_ERROR_NOMEM;
4732  }
4733 
4734  ++i;
4735  for (int k = 0; k < extensions_size; ++k)
4736  {
4737  CGLTF_CHECK_KEY(tokens[i]);
4738 
4739  if (cgltf_json_strcmp(tokens+i, json_chunk, "EXT_meshopt_compression") == 0)
4740  {
4741  out_buffer_view->has_meshopt_compression = 1;
4742  i = cgltf_parse_json_meshopt_compression(options, tokens, i + 1, json_chunk, &out_buffer_view->meshopt_compression);
4743  }
4744  else
4745  {
4746  i = cgltf_parse_json_unprocessed_extension(options, tokens, i, json_chunk, &(out_buffer_view->extensions[out_buffer_view->extensions_count++]));
4747  }
4748 
4749  if (i < 0)
4750  {
4751  return i;
4752  }
4753  }
4754  }
4755  else
4756  {
4757  i = cgltf_skip_json(tokens, i+1);
4758  }
4759 
4760  if (i < 0)
4761  {
4762  return i;
4763  }
4764  }
4765 
4766  return i;
4767 }
4768 
4769 static int cgltf_parse_json_buffer_views(cgltf_options* options, jsmntok_t const* tokens, int i, const uint8_t* json_chunk, cgltf_data* out_data)
4770 {
4771  i = cgltf_parse_json_array(options, tokens, i, json_chunk, sizeof(cgltf_buffer_view), (void**)&out_data->buffer_views, &out_data->buffer_views_count);
4772  if (i < 0)
4773  {
4774  return i;
4775  }
4776 
4777  for (cgltf_size j = 0; j < out_data->buffer_views_count; ++j)
4778  {
4779  i = cgltf_parse_json_buffer_view(options, tokens, i, json_chunk, &out_data->buffer_views[j]);
4780  if (i < 0)
4781  {
4782  return i;
4783  }
4784  }
4785  return i;
4786 }
4787 
4788 static int cgltf_parse_json_buffer(cgltf_options* options, jsmntok_t const* tokens, int i, const uint8_t* json_chunk, cgltf_buffer* out_buffer)
4789 {
4790  CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
4791 
4792  int size = tokens[i].size;
4793  ++i;
4794 
4795  for (int j = 0; j < size; ++j)
4796  {
4797  CGLTF_CHECK_KEY(tokens[i]);
4798 
4799  if (cgltf_json_strcmp(tokens + i, json_chunk, "name") == 0)
4800  {
4801  i = cgltf_parse_json_string(options, tokens, i + 1, json_chunk, &out_buffer->name);
4802  }
4803  else if (cgltf_json_strcmp(tokens+i, json_chunk, "byteLength") == 0)
4804  {
4805  ++i;
4806  out_buffer->size =
4807  cgltf_json_to_size(tokens+i, json_chunk);
4808  ++i;
4809  }
4810  else if (cgltf_json_strcmp(tokens+i, json_chunk, "uri") == 0)
4811  {
4812  i = cgltf_parse_json_string(options, tokens, i + 1, json_chunk, &out_buffer->uri);
4813  }
4814  else if (cgltf_json_strcmp(tokens + i, json_chunk, "extras") == 0)
4815  {
4816  i = cgltf_parse_json_extras(tokens, i + 1, json_chunk, &out_buffer->extras);
4817  }
4818  else if (cgltf_json_strcmp(tokens + i, json_chunk, "extensions") == 0)
4819  {
4820  i = cgltf_parse_json_unprocessed_extensions(options, tokens, i, json_chunk, &out_buffer->extensions_count, &out_buffer->extensions);
4821  }
4822  else
4823  {
4824  i = cgltf_skip_json(tokens, i+1);
4825  }
4826 
4827  if (i < 0)
4828  {
4829  return i;
4830  }
4831  }
4832 
4833  return i;
4834 }
4835 
4836 static int cgltf_parse_json_buffers(cgltf_options* options, jsmntok_t const* tokens, int i, const uint8_t* json_chunk, cgltf_data* out_data)
4837 {
4838  i = cgltf_parse_json_array(options, tokens, i, json_chunk, sizeof(cgltf_buffer), (void**)&out_data->buffers, &out_data->buffers_count);
4839  if (i < 0)
4840  {
4841  return i;
4842  }
4843 
4844  for (cgltf_size j = 0; j < out_data->buffers_count; ++j)
4845  {
4846  i = cgltf_parse_json_buffer(options, tokens, i, json_chunk, &out_data->buffers[j]);
4847  if (i < 0)
4848  {
4849  return i;
4850  }
4851  }
4852  return i;
4853 }
4854 
4855 static int cgltf_parse_json_skin(cgltf_options* options, jsmntok_t const* tokens, int i, const uint8_t* json_chunk, cgltf_skin* out_skin)
4856 {
4857  CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
4858 
4859  int size = tokens[i].size;
4860  ++i;
4861 
4862  for (int j = 0; j < size; ++j)
4863  {
4864  CGLTF_CHECK_KEY(tokens[i]);
4865 
4866  if (cgltf_json_strcmp(tokens+i, json_chunk, "name") == 0)
4867  {
4868  i = cgltf_parse_json_string(options, tokens, i + 1, json_chunk, &out_skin->name);
4869  }
4870  else if (cgltf_json_strcmp(tokens+i, json_chunk, "joints") == 0)
4871  {
4872  i = cgltf_parse_json_array(options, tokens, i + 1, json_chunk, sizeof(cgltf_node*), (void**)&out_skin->joints, &out_skin->joints_count);
4873  if (i < 0)
4874  {
4875  return i;
4876  }
4877 
4878  for (cgltf_size k = 0; k < out_skin->joints_count; ++k)
4879  {
4880  out_skin->joints[k] = CGLTF_PTRINDEX(cgltf_node, cgltf_json_to_int(tokens + i, json_chunk));
4881  ++i;
4882  }
4883  }
4884  else if (cgltf_json_strcmp(tokens+i, json_chunk, "skeleton") == 0)
4885  {
4886  ++i;
4887  CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_PRIMITIVE);
4888  out_skin->skeleton = CGLTF_PTRINDEX(cgltf_node, cgltf_json_to_int(tokens + i, json_chunk));
4889  ++i;
4890  }
4891  else if (cgltf_json_strcmp(tokens+i, json_chunk, "inverseBindMatrices") == 0)
4892  {
4893  ++i;
4894  CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_PRIMITIVE);
4895  out_skin->inverse_bind_matrices = CGLTF_PTRINDEX(cgltf_accessor, cgltf_json_to_int(tokens + i, json_chunk));
4896  ++i;
4897  }
4898  else if (cgltf_json_strcmp(tokens + i, json_chunk, "extras") == 0)
4899  {
4900  i = cgltf_parse_json_extras(tokens, i + 1, json_chunk, &out_skin->extras);
4901  }
4902  else if (cgltf_json_strcmp(tokens + i, json_chunk, "extensions") == 0)
4903  {
4904  i = cgltf_parse_json_unprocessed_extensions(options, tokens, i, json_chunk, &out_skin->extensions_count, &out_skin->extensions);
4905  }
4906  else
4907  {
4908  i = cgltf_skip_json(tokens, i+1);
4909  }
4910 
4911  if (i < 0)
4912  {
4913  return i;
4914  }
4915  }
4916 
4917  return i;
4918 }
4919 
4920 static int cgltf_parse_json_skins(cgltf_options* options, jsmntok_t const* tokens, int i, const uint8_t* json_chunk, cgltf_data* out_data)
4921 {
4922  i = cgltf_parse_json_array(options, tokens, i, json_chunk, sizeof(cgltf_skin), (void**)&out_data->skins, &out_data->skins_count);
4923  if (i < 0)
4924  {
4925  return i;
4926  }
4927 
4928  for (cgltf_size j = 0; j < out_data->skins_count; ++j)
4929  {
4930  i = cgltf_parse_json_skin(options, tokens, i, json_chunk, &out_data->skins[j]);
4931  if (i < 0)
4932  {
4933  return i;
4934  }
4935  }
4936  return i;
4937 }
4938 
4939 static int cgltf_parse_json_camera(cgltf_options* options, jsmntok_t const* tokens, int i, const uint8_t* json_chunk, cgltf_camera* out_camera)
4940 {
4941  CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
4942 
4943  int size = tokens[i].size;
4944  ++i;
4945 
4946  for (int j = 0; j < size; ++j)
4947  {
4948  CGLTF_CHECK_KEY(tokens[i]);
4949 
4950  if (cgltf_json_strcmp(tokens+i, json_chunk, "name") == 0)
4951  {
4952  i = cgltf_parse_json_string(options, tokens, i + 1, json_chunk, &out_camera->name);
4953  }
4954  else if (cgltf_json_strcmp(tokens+i, json_chunk, "type") == 0)
4955  {
4956  ++i;
4957  if (cgltf_json_strcmp(tokens + i, json_chunk, "perspective") == 0)
4958  {
4959  out_camera->type = cgltf_camera_type_perspective;
4960  }
4961  else if (cgltf_json_strcmp(tokens + i, json_chunk, "orthographic") == 0)
4962  {
4963  out_camera->type = cgltf_camera_type_orthographic;
4964  }
4965  ++i;
4966  }
4967  else if (cgltf_json_strcmp(tokens+i, json_chunk, "perspective") == 0)
4968  {
4969  ++i;
4970 
4971  CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
4972 
4973  int data_size = tokens[i].size;
4974  ++i;
4975 
4976  out_camera->type = cgltf_camera_type_perspective;
4977 
4978  for (int k = 0; k < data_size; ++k)
4979  {
4980  CGLTF_CHECK_KEY(tokens[i]);
4981 
4982  if (cgltf_json_strcmp(tokens+i, json_chunk, "aspectRatio") == 0)
4983  {
4984  ++i;
4985  out_camera->data.perspective.has_aspect_ratio = 1;
4986  out_camera->data.perspective.aspect_ratio = cgltf_json_to_float(tokens + i, json_chunk);
4987  ++i;
4988  }
4989  else if (cgltf_json_strcmp(tokens+i, json_chunk, "yfov") == 0)
4990  {
4991  ++i;
4992  out_camera->data.perspective.yfov = cgltf_json_to_float(tokens + i, json_chunk);
4993  ++i;
4994  }
4995  else if (cgltf_json_strcmp(tokens+i, json_chunk, "zfar") == 0)
4996  {
4997  ++i;
4998  out_camera->data.perspective.has_zfar = 1;
4999  out_camera->data.perspective.zfar = cgltf_json_to_float(tokens + i, json_chunk);
5000  ++i;
5001  }
5002  else if (cgltf_json_strcmp(tokens+i, json_chunk, "znear") == 0)
5003  {
5004  ++i;
5005  out_camera->data.perspective.znear = cgltf_json_to_float(tokens + i, json_chunk);
5006  ++i;
5007  }
5008  else if (cgltf_json_strcmp(tokens + i, json_chunk, "extras") == 0)
5009  {
5010  i = cgltf_parse_json_extras(tokens, i + 1, json_chunk, &out_camera->data.perspective.extras);
5011  }
5012  else
5013  {
5014  i = cgltf_skip_json(tokens, i+1);
5015  }
5016 
5017  if (i < 0)
5018  {
5019  return i;
5020  }
5021  }
5022  }
5023  else if (cgltf_json_strcmp(tokens+i, json_chunk, "orthographic") == 0)
5024  {
5025  ++i;
5026 
5027  CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
5028 
5029  int data_size = tokens[i].size;
5030  ++i;
5031 
5032  out_camera->type = cgltf_camera_type_orthographic;
5033 
5034  for (int k = 0; k < data_size; ++k)
5035  {
5036  CGLTF_CHECK_KEY(tokens[i]);
5037 
5038  if (cgltf_json_strcmp(tokens+i, json_chunk, "xmag") == 0)
5039  {
5040  ++i;
5041  out_camera->data.orthographic.xmag = cgltf_json_to_float(tokens + i, json_chunk);
5042  ++i;
5043  }
5044  else if (cgltf_json_strcmp(tokens+i, json_chunk, "ymag") == 0)
5045  {
5046  ++i;
5047  out_camera->data.orthographic.ymag = cgltf_json_to_float(tokens + i, json_chunk);
5048  ++i;
5049  }
5050  else if (cgltf_json_strcmp(tokens+i, json_chunk, "zfar") == 0)
5051  {
5052  ++i;
5053  out_camera->data.orthographic.zfar = cgltf_json_to_float(tokens + i, json_chunk);
5054  ++i;
5055  }
5056  else if (cgltf_json_strcmp(tokens+i, json_chunk, "znear") == 0)
5057  {
5058  ++i;
5059  out_camera->data.orthographic.znear = cgltf_json_to_float(tokens + i, json_chunk);
5060  ++i;
5061  }
5062  else if (cgltf_json_strcmp(tokens + i, json_chunk, "extras") == 0)
5063  {
5064  i = cgltf_parse_json_extras(tokens, i + 1, json_chunk, &out_camera->data.orthographic.extras);
5065  }
5066  else
5067  {
5068  i = cgltf_skip_json(tokens, i+1);
5069  }
5070 
5071  if (i < 0)
5072  {
5073  return i;
5074  }
5075  }
5076  }
5077  else if (cgltf_json_strcmp(tokens + i, json_chunk, "extras") == 0)
5078  {
5079  i = cgltf_parse_json_extras(tokens, i + 1, json_chunk, &out_camera->extras);
5080  }
5081  else if (cgltf_json_strcmp(tokens + i, json_chunk, "extensions") == 0)
5082  {
5083  i = cgltf_parse_json_unprocessed_extensions(options, tokens, i, json_chunk, &out_camera->extensions_count, &out_camera->extensions);
5084  }
5085  else
5086  {
5087  i = cgltf_skip_json(tokens, i+1);
5088  }
5089 
5090  if (i < 0)
5091  {
5092  return i;
5093  }
5094  }
5095 
5096  return i;
5097 }
5098 
5099 static int cgltf_parse_json_cameras(cgltf_options* options, jsmntok_t const* tokens, int i, const uint8_t* json_chunk, cgltf_data* out_data)
5100 {
5101  i = cgltf_parse_json_array(options, tokens, i, json_chunk, sizeof(cgltf_camera), (void**)&out_data->cameras, &out_data->cameras_count);
5102  if (i < 0)
5103  {
5104  return i;
5105  }
5106 
5107  for (cgltf_size j = 0; j < out_data->cameras_count; ++j)
5108  {
5109  i = cgltf_parse_json_camera(options, tokens, i, json_chunk, &out_data->cameras[j]);
5110  if (i < 0)
5111  {
5112  return i;
5113  }
5114  }
5115  return i;
5116 }
5117 
5118 static int cgltf_parse_json_light(cgltf_options* options, jsmntok_t const* tokens, int i, const uint8_t* json_chunk, cgltf_light* out_light)
5119 {
5120  CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
5121 
5122  out_light->color[0] = 1.f;
5123  out_light->color[1] = 1.f;
5124  out_light->color[2] = 1.f;
5125  out_light->intensity = 1.f;
5126 
5127  out_light->spot_inner_cone_angle = 0.f;
5128  out_light->spot_outer_cone_angle = 3.1415926535f / 4.0f;
5129 
5130  int size = tokens[i].size;
5131  ++i;
5132 
5133  for (int j = 0; j < size; ++j)
5134  {
5135  CGLTF_CHECK_KEY(tokens[i]);
5136 
5137  if (cgltf_json_strcmp(tokens+i, json_chunk, "name") == 0)
5138  {
5139  i = cgltf_parse_json_string(options, tokens, i + 1, json_chunk, &out_light->name);
5140  }
5141  else if (cgltf_json_strcmp(tokens + i, json_chunk, "color") == 0)
5142  {
5143  i = cgltf_parse_json_float_array(tokens, i + 1, json_chunk, out_light->color, 3);
5144  }
5145  else if (cgltf_json_strcmp(tokens + i, json_chunk, "intensity") == 0)
5146  {
5147  ++i;
5148  out_light->intensity = cgltf_json_to_float(tokens + i, json_chunk);
5149  ++i;
5150  }
5151  else if (cgltf_json_strcmp(tokens+i, json_chunk, "type") == 0)
5152  {
5153  ++i;
5154  if (cgltf_json_strcmp(tokens + i, json_chunk, "directional") == 0)
5155  {
5156  out_light->type = cgltf_light_type_directional;
5157  }
5158  else if (cgltf_json_strcmp(tokens + i, json_chunk, "point") == 0)
5159  {
5160  out_light->type = cgltf_light_type_point;
5161  }
5162  else if (cgltf_json_strcmp(tokens + i, json_chunk, "spot") == 0)
5163  {
5164  out_light->type = cgltf_light_type_spot;
5165  }
5166  ++i;
5167  }
5168  else if (cgltf_json_strcmp(tokens + i, json_chunk, "range") == 0)
5169  {
5170  ++i;
5171  out_light->range = cgltf_json_to_float(tokens + i, json_chunk);
5172  ++i;
5173  }
5174  else if (cgltf_json_strcmp(tokens+i, json_chunk, "spot") == 0)
5175  {
5176  ++i;
5177 
5178  CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
5179 
5180  int data_size = tokens[i].size;
5181  ++i;
5182 
5183  for (int k = 0; k < data_size; ++k)
5184  {
5185  CGLTF_CHECK_KEY(tokens[i]);
5186 
5187  if (cgltf_json_strcmp(tokens+i, json_chunk, "innerConeAngle") == 0)
5188  {
5189  ++i;
5190  out_light->spot_inner_cone_angle = cgltf_json_to_float(tokens + i, json_chunk);
5191  ++i;
5192  }
5193  else if (cgltf_json_strcmp(tokens+i, json_chunk, "outerConeAngle") == 0)
5194  {
5195  ++i;
5196  out_light->spot_outer_cone_angle = cgltf_json_to_float(tokens + i, json_chunk);
5197  ++i;
5198  }
5199  else
5200  {
5201  i = cgltf_skip_json(tokens, i+1);
5202  }
5203 
5204  if (i < 0)
5205  {
5206  return i;
5207  }
5208  }
5209  }
5210  else if (cgltf_json_strcmp(tokens + i, json_chunk, "extras") == 0)
5211  {
5212  i = cgltf_parse_json_extras(tokens, i + 1, json_chunk, &out_light->extras);
5213  }
5214  else
5215  {
5216  i = cgltf_skip_json(tokens, i+1);
5217  }
5218 
5219  if (i < 0)
5220  {
5221  return i;
5222  }
5223  }
5224 
5225  return i;
5226 }
5227 
5228 static int cgltf_parse_json_lights(cgltf_options* options, jsmntok_t const* tokens, int i, const uint8_t* json_chunk, cgltf_data* out_data)
5229 {
5230  i = cgltf_parse_json_array(options, tokens, i, json_chunk, sizeof(cgltf_light), (void**)&out_data->lights, &out_data->lights_count);
5231  if (i < 0)
5232  {
5233  return i;
5234  }
5235 
5236  for (cgltf_size j = 0; j < out_data->lights_count; ++j)
5237  {
5238  i = cgltf_parse_json_light(options, tokens, i, json_chunk, &out_data->lights[j]);
5239  if (i < 0)
5240  {
5241  return i;
5242  }
5243  }
5244  return i;
5245 }
5246 
5247 static int cgltf_parse_json_node(cgltf_options* options, jsmntok_t const* tokens, int i, const uint8_t* json_chunk, cgltf_node* out_node)
5248 {
5249  CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
5250 
5251  out_node->rotation[3] = 1.0f;
5252  out_node->scale[0] = 1.0f;
5253  out_node->scale[1] = 1.0f;
5254  out_node->scale[2] = 1.0f;
5255  out_node->matrix[0] = 1.0f;
5256  out_node->matrix[5] = 1.0f;
5257  out_node->matrix[10] = 1.0f;
5258  out_node->matrix[15] = 1.0f;
5259 
5260  int size = tokens[i].size;
5261  ++i;
5262 
5263  for (int j = 0; j < size; ++j)
5264  {
5265  CGLTF_CHECK_KEY(tokens[i]);
5266 
5267  if (cgltf_json_strcmp(tokens+i, json_chunk, "name") == 0)
5268  {
5269  i = cgltf_parse_json_string(options, tokens, i + 1, json_chunk, &out_node->name);
5270  }
5271  else if (cgltf_json_strcmp(tokens+i, json_chunk, "children") == 0)
5272  {
5273  i = cgltf_parse_json_array(options, tokens, i + 1, json_chunk, sizeof(cgltf_node*), (void**)&out_node->children, &out_node->children_count);
5274  if (i < 0)
5275  {
5276  return i;
5277  }
5278 
5279  for (cgltf_size k = 0; k < out_node->children_count; ++k)
5280  {
5281  out_node->children[k] = CGLTF_PTRINDEX(cgltf_node, cgltf_json_to_int(tokens + i, json_chunk));
5282  ++i;
5283  }
5284  }
5285  else if (cgltf_json_strcmp(tokens+i, json_chunk, "mesh") == 0)
5286  {
5287  ++i;
5288  CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_PRIMITIVE);
5289  out_node->mesh = CGLTF_PTRINDEX(cgltf_mesh, cgltf_json_to_int(tokens + i, json_chunk));
5290  ++i;
5291  }
5292  else if (cgltf_json_strcmp(tokens+i, json_chunk, "skin") == 0)
5293  {
5294  ++i;
5295  CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_PRIMITIVE);
5296  out_node->skin = CGLTF_PTRINDEX(cgltf_skin, cgltf_json_to_int(tokens + i, json_chunk));
5297  ++i;
5298  }
5299  else if (cgltf_json_strcmp(tokens+i, json_chunk, "camera") == 0)
5300  {
5301  ++i;
5302  CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_PRIMITIVE);
5303  out_node->camera = CGLTF_PTRINDEX(cgltf_camera, cgltf_json_to_int(tokens + i, json_chunk));
5304  ++i;
5305  }
5306  else if (cgltf_json_strcmp(tokens+i, json_chunk, "translation") == 0)