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