Foundation
Loading...
Searching...
No Matches
cgltf.h
Go to the documentation of this file.
1
94#ifndef CGLTF_H_INCLUDED__
95#define CGLTF_H_INCLUDED__
96
97#include <stddef.h>
98#include <stdint.h> /* For uint8_t, uint32_t */
99
100#ifdef __cplusplus
101extern "C" {
102#endif
103
104typedef size_t cgltf_size;
105typedef long long int cgltf_ssize;
106typedef float cgltf_float;
107typedef int cgltf_int;
108typedef unsigned int cgltf_uint;
109typedef int cgltf_bool;
110
118
133
135{
136 void* (*alloc_func)(void* user, cgltf_size size);
137 void (*free_func) (void* user, void* ptr);
140
141typedef struct cgltf_file_options
142{
143 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);
144 void (*release)(const struct cgltf_memory_options* memory_options, const struct cgltf_file_options* file_options, void* data);
147
155
163
177
189
202
215
223
232
239
246
254
261
270
276
283
289
296
302
309
310typedef struct cgltf_extras {
311 cgltf_size start_offset; /* this field is deprecated and will be removed in the future; use data instead */
312 cgltf_size end_offset; /* this field is deprecated and will be removed in the future; use data instead */
313
314 char* data;
316
317typedef struct cgltf_extension {
318 char* name;
319 char* data;
321
333
341
349
360
376
386
407
415
426
436
442
454
468
477
486
496
506
516
522
527
535
543
551
556
566
574
582
589
594
609
610typedef struct cgltf_material
611{
612 char* name;
655
662
667
673
678
695
708
709typedef struct cgltf_node cgltf_node;
710
721
731
739
748
762
775
785
795
804
811
839
850
859
868
879
885
895
896typedef struct cgltf_data
897{
900
902
905
908
911
914
917
920
923
926
929
932
935
938
941
944
947
949
952
955
957
962
965
968
969 const char* json;
971
972 const void* bin;
974
978
980 const cgltf_options* options,
981 const void* data,
982 cgltf_size size,
983 cgltf_data** out_data);
984
986 const cgltf_options* options,
987 const char* path,
988 cgltf_data** out_data);
989
991 const cgltf_options* options,
992 cgltf_data* data,
993 const char* gltf_path);
994
995cgltf_result cgltf_load_buffer_base64(const cgltf_options* options, cgltf_size size, const char* base64, void** out_data);
996
999
1001
1003
1006
1007const uint8_t* cgltf_buffer_view_data(const cgltf_buffer_view* view);
1008
1010
1014
1018
1020cgltf_size cgltf_accessor_unpack_indices(const cgltf_accessor* accessor, void* out, cgltf_size out_component_size, cgltf_size index_count);
1021
1022/* this function is deprecated and will be removed in the future; use cgltf_extras::data instead */
1023cgltf_result cgltf_copy_extras_json(const cgltf_data* data, const cgltf_extras* extras, char* dest, cgltf_size* dest_size);
1024
1043
1044#ifdef __cplusplus
1045}
1046#endif
1047
1048#endif /* #ifndef CGLTF_H_INCLUDED__ */
1049
1050/*
1051 *
1052 * Stop now, if you are only interested in the API.
1053 * Below, you find the implementation.
1054 *
1055 */
1056
1057#if defined(__INTELLISENSE__) || defined(__JETBRAINS_IDE__)
1058/* This makes MSVC/CLion intellisense work. */
1059#define CGLTF_IMPLEMENTATION
1060#endif
1061
1062#ifdef CGLTF_IMPLEMENTATION
1063
1064#include <assert.h> /* For assert */
1065#include <string.h> /* For strncpy */
1066#include <stdio.h> /* For fopen */
1067#include <limits.h> /* For UINT_MAX etc */
1068#include <float.h> /* For FLT_MAX */
1069
1070#if !defined(CGLTF_MALLOC) || !defined(CGLTF_FREE) || !defined(CGLTF_ATOI) || !defined(CGLTF_ATOF) || !defined(CGLTF_ATOLL)
1071#include <stdlib.h> /* For malloc, free, atoi, atof */
1072#endif
1073
1074/* JSMN_PARENT_LINKS is necessary to make parsing large structures linear in input size */
1075#define JSMN_PARENT_LINKS
1076
1077/* JSMN_STRICT is necessary to reject invalid JSON documents */
1078#define JSMN_STRICT
1079
1080/*
1081 * -- jsmn.h start --
1082 * Source: https://github.com/zserge/jsmn
1083 * License: MIT
1084 */
1085typedef enum {
1086 JSMN_UNDEFINED = 0,
1087 JSMN_OBJECT = 1,
1088 JSMN_ARRAY = 2,
1089 JSMN_STRING = 3,
1090 JSMN_PRIMITIVE = 4
1091} jsmntype_t;
1092enum jsmnerr {
1093 /* Not enough tokens were provided */
1094 JSMN_ERROR_NOMEM = -1,
1095 /* Invalid character inside JSON string */
1096 JSMN_ERROR_INVAL = -2,
1097 /* The string is not a full JSON packet, more bytes expected */
1098 JSMN_ERROR_PART = -3
1099};
1100typedef struct {
1101 jsmntype_t type;
1102 ptrdiff_t start;
1103 ptrdiff_t end;
1104 int size;
1105#ifdef JSMN_PARENT_LINKS
1106 int parent;
1107#endif
1108} jsmntok_t;
1109typedef struct {
1110 size_t pos; /* offset in the JSON string */
1111 unsigned int toknext; /* next token to allocate */
1112 int toksuper; /* superior token node, e.g parent object or array */
1113} jsmn_parser;
1114static void jsmn_init(jsmn_parser *parser);
1115static int jsmn_parse(jsmn_parser *parser, const char *js, size_t len, jsmntok_t *tokens, size_t num_tokens);
1116/*
1117 * -- jsmn.h end --
1118 */
1119
1120
1121#ifndef CGLTF_CONSTS
1122#define GlbHeaderSize 12
1123#define GlbChunkHeaderSize 8
1124static const uint32_t GlbVersion = 2;
1125static const uint32_t GlbMagic = 0x46546C67;
1126static const uint32_t GlbMagicJsonChunk = 0x4E4F534A;
1127static const uint32_t GlbMagicBinChunk = 0x004E4942;
1128#define CGLTF_CONSTS
1129#endif
1130
1131#ifndef CGLTF_MALLOC
1132#define CGLTF_MALLOC(size) malloc(size)
1133#endif
1134#ifndef CGLTF_FREE
1135#define CGLTF_FREE(ptr) free(ptr)
1136#endif
1137#ifndef CGLTF_ATOI
1138#define CGLTF_ATOI(str) atoi(str)
1139#endif
1140#ifndef CGLTF_ATOF
1141#define CGLTF_ATOF(str) atof(str)
1142#endif
1143#ifndef CGLTF_ATOLL
1144#define CGLTF_ATOLL(str) atoll(str)
1145#endif
1146#ifndef CGLTF_VALIDATE_ENABLE_ASSERTS
1147#define CGLTF_VALIDATE_ENABLE_ASSERTS 0
1148#endif
1149
1150static void* cgltf_default_alloc(void* user, cgltf_size size)
1151{
1152 (void)user;
1153 return CGLTF_MALLOC(size);
1154}
1155
1156static void cgltf_default_free(void* user, void* ptr)
1157{
1158 (void)user;
1159 CGLTF_FREE(ptr);
1160}
1161
1162static void* cgltf_calloc(cgltf_options* options, size_t element_size, cgltf_size count)
1163{
1164 if (SIZE_MAX / element_size < count)
1165 {
1166 return NULL;
1167 }
1168 void* result = options->memory.alloc_func(options->memory.user_data, element_size * count);
1169 if (!result)
1170 {
1171 return NULL;
1172 }
1173 memset(result, 0, element_size * count);
1174 return result;
1175}
1176
1177static 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)
1178{
1179 (void)file_options;
1180 void* (*memory_alloc)(void*, cgltf_size) = memory_options->alloc_func ? memory_options->alloc_func : &cgltf_default_alloc;
1181 void (*memory_free)(void*, void*) = memory_options->free_func ? memory_options->free_func : &cgltf_default_free;
1182
1183 FILE* file = fopen(path, "rb");
1184 if (!file)
1185 {
1187 }
1188
1189 cgltf_size file_size = size ? *size : 0;
1190
1191 if (file_size == 0)
1192 {
1193 fseek(file, 0, SEEK_END);
1194
1195#ifdef _MSC_VER
1196 __int64 length = _ftelli64(file);
1197#else
1198 long length = ftell(file);
1199#endif
1200
1201 if (length < 0)
1202 {
1203 fclose(file);
1204 return cgltf_result_io_error;
1205 }
1206
1207 fseek(file, 0, SEEK_SET);
1208 file_size = (cgltf_size)length;
1209 }
1210
1211 char* file_data = (char*)memory_alloc(memory_options->user_data, file_size);
1212 if (!file_data)
1213 {
1214 fclose(file);
1216 }
1217
1218 cgltf_size read_size = fread(file_data, 1, file_size, file);
1219
1220 fclose(file);
1221
1222 if (read_size != file_size)
1223 {
1224 memory_free(memory_options->user_data, file_data);
1225 return cgltf_result_io_error;
1226 }
1227
1228 if (size)
1229 {
1230 *size = file_size;
1231 }
1232 if (data)
1233 {
1234 *data = file_data;
1235 }
1236
1237 return cgltf_result_success;
1238}
1239
1240static void cgltf_default_file_release(const struct cgltf_memory_options* memory_options, const struct cgltf_file_options* file_options, void* data)
1241{
1242 (void)file_options;
1243 void (*memfree)(void*, void*) = memory_options->free_func ? memory_options->free_func : &cgltf_default_free;
1244 memfree(memory_options->user_data, data);
1245}
1246
1247static cgltf_result cgltf_parse_json(cgltf_options* options, const uint8_t* json_chunk, cgltf_size size, cgltf_data** out_data);
1248
1249cgltf_result cgltf_parse(const cgltf_options* options, const void* data, cgltf_size size, cgltf_data** out_data)
1250{
1251 if (size < GlbHeaderSize)
1252 {
1254 }
1255
1256 if (options == NULL)
1257 {
1259 }
1260
1261 cgltf_options fixed_options = *options;
1262 if (fixed_options.memory.alloc_func == NULL)
1263 {
1264 fixed_options.memory.alloc_func = &cgltf_default_alloc;
1265 }
1266 if (fixed_options.memory.free_func == NULL)
1267 {
1268 fixed_options.memory.free_func = &cgltf_default_free;
1269 }
1270
1271 uint32_t tmp;
1272 // Magic
1273 memcpy(&tmp, data, 4);
1274 if (tmp != GlbMagic)
1275 {
1276 if (fixed_options.type == cgltf_file_type_invalid)
1277 {
1278 fixed_options.type = cgltf_file_type_gltf;
1279 }
1280 else if (fixed_options.type == cgltf_file_type_glb)
1281 {
1283 }
1284 }
1285
1286 if (fixed_options.type == cgltf_file_type_gltf)
1287 {
1288 cgltf_result json_result = cgltf_parse_json(&fixed_options, (const uint8_t*)data, size, out_data);
1289 if (json_result != cgltf_result_success)
1290 {
1291 return json_result;
1292 }
1293
1294 (*out_data)->file_type = cgltf_file_type_gltf;
1295
1296 return cgltf_result_success;
1297 }
1298
1299 const uint8_t* ptr = (const uint8_t*)data;
1300 // Version
1301 memcpy(&tmp, ptr + 4, 4);
1302 uint32_t version = tmp;
1303 if (version != GlbVersion)
1304 {
1305 return version < GlbVersion ? cgltf_result_legacy_gltf : cgltf_result_unknown_format;
1306 }
1307
1308 // Total length
1309 memcpy(&tmp, ptr + 8, 4);
1310 if (tmp > size)
1311 {
1313 }
1314
1315 const uint8_t* json_chunk = ptr + GlbHeaderSize;
1316
1317 if (GlbHeaderSize + GlbChunkHeaderSize > size)
1318 {
1320 }
1321
1322 // JSON chunk: length
1323 uint32_t json_length;
1324 memcpy(&json_length, json_chunk, 4);
1325 if (json_length > size - GlbHeaderSize - GlbChunkHeaderSize)
1326 {
1328 }
1329
1330 // JSON chunk: magic
1331 memcpy(&tmp, json_chunk + 4, 4);
1332 if (tmp != GlbMagicJsonChunk)
1333 {
1335 }
1336
1337 json_chunk += GlbChunkHeaderSize;
1338
1339 const void* bin = NULL;
1340 cgltf_size bin_size = 0;
1341
1342 if (GlbChunkHeaderSize <= size - GlbHeaderSize - GlbChunkHeaderSize - json_length)
1343 {
1344 // We can read another chunk
1345 const uint8_t* bin_chunk = json_chunk + json_length;
1346
1347 // Bin chunk: length
1348 uint32_t bin_length;
1349 memcpy(&bin_length, bin_chunk, 4);
1350 if (bin_length > size - GlbHeaderSize - GlbChunkHeaderSize - json_length - GlbChunkHeaderSize)
1351 {
1353 }
1354
1355 // Bin chunk: magic
1356 memcpy(&tmp, bin_chunk + 4, 4);
1357 if (tmp != GlbMagicBinChunk)
1358 {
1360 }
1361
1362 bin_chunk += GlbChunkHeaderSize;
1363
1364 bin = bin_chunk;
1365 bin_size = bin_length;
1366 }
1367
1368 cgltf_result json_result = cgltf_parse_json(&fixed_options, json_chunk, json_length, out_data);
1369 if (json_result != cgltf_result_success)
1370 {
1371 return json_result;
1372 }
1373
1374 (*out_data)->file_type = cgltf_file_type_glb;
1375 (*out_data)->bin = bin;
1376 (*out_data)->bin_size = bin_size;
1377
1378 return cgltf_result_success;
1379}
1380
1381cgltf_result cgltf_parse_file(const cgltf_options* options, const char* path, cgltf_data** out_data)
1382{
1383 if (options == NULL)
1384 {
1386 }
1387
1388 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;
1389 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;
1390
1391 void* file_data = NULL;
1392 cgltf_size file_size = 0;
1393 cgltf_result result = file_read(&options->memory, &options->file, path, &file_size, &file_data);
1394 if (result != cgltf_result_success)
1395 {
1396 return result;
1397 }
1398
1399 result = cgltf_parse(options, file_data, file_size, out_data);
1400
1401 if (result != cgltf_result_success)
1402 {
1403 file_release(&options->memory, &options->file, file_data);
1404 return result;
1405 }
1406
1407 (*out_data)->file_data = file_data;
1408
1409 return cgltf_result_success;
1410}
1411
1412static void cgltf_combine_paths(char* path, const char* base, const char* uri)
1413{
1414 const char* s0 = strrchr(base, '/');
1415 const char* s1 = strrchr(base, '\\');
1416 const char* slash = s0 ? (s1 && s1 > s0 ? s1 : s0) : s1;
1417
1418 if (slash)
1419 {
1420 size_t prefix = slash - base + 1;
1421
1422 strncpy(path, base, prefix);
1423 strcpy(path + prefix, uri);
1424 }
1425 else
1426 {
1427 strcpy(path, uri);
1428 }
1429}
1430
1431static cgltf_result cgltf_load_buffer_file(const cgltf_options* options, cgltf_size size, const char* uri, const char* gltf_path, void** out_data)
1432{
1433 void* (*memory_alloc)(void*, cgltf_size) = options->memory.alloc_func ? options->memory.alloc_func : &cgltf_default_alloc;
1434 void (*memory_free)(void*, void*) = options->memory.free_func ? options->memory.free_func : &cgltf_default_free;
1435 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;
1436
1437 char* path = (char*)memory_alloc(options->memory.user_data, strlen(uri) + strlen(gltf_path) + 1);
1438 if (!path)
1439 {
1441 }
1442
1443 cgltf_combine_paths(path, gltf_path, uri);
1444
1445 // after combining, the tail of the resulting path is a uri; decode_uri converts it into path
1446 cgltf_decode_uri(path + strlen(path) - strlen(uri));
1447
1448 void* file_data = NULL;
1449 cgltf_result result = file_read(&options->memory, &options->file, path, &size, &file_data);
1450
1451 memory_free(options->memory.user_data, path);
1452
1453 *out_data = (result == cgltf_result_success) ? file_data : NULL;
1454
1455 return result;
1456}
1457
1458cgltf_result cgltf_load_buffer_base64(const cgltf_options* options, cgltf_size size, const char* base64, void** out_data)
1459{
1460 void* (*memory_alloc)(void*, cgltf_size) = options->memory.alloc_func ? options->memory.alloc_func : &cgltf_default_alloc;
1461 void (*memory_free)(void*, void*) = options->memory.free_func ? options->memory.free_func : &cgltf_default_free;
1462
1463 unsigned char* data = (unsigned char*)memory_alloc(options->memory.user_data, size);
1464 if (!data)
1465 {
1467 }
1468
1469 unsigned int buffer = 0;
1470 unsigned int buffer_bits = 0;
1471
1472 for (cgltf_size i = 0; i < size; ++i)
1473 {
1474 while (buffer_bits < 8)
1475 {
1476 char ch = *base64++;
1477
1478 int index =
1479 (unsigned)(ch - 'A') < 26 ? (ch - 'A') :
1480 (unsigned)(ch - 'a') < 26 ? (ch - 'a') + 26 :
1481 (unsigned)(ch - '0') < 10 ? (ch - '0') + 52 :
1482 ch == '+' ? 62 :
1483 ch == '/' ? 63 :
1484 -1;
1485
1486 if (index < 0)
1487 {
1488 memory_free(options->memory.user_data, data);
1489 return cgltf_result_io_error;
1490 }
1491
1492 buffer = (buffer << 6) | index;
1493 buffer_bits += 6;
1494 }
1495
1496 data[i] = (unsigned char)(buffer >> (buffer_bits - 8));
1497 buffer_bits -= 8;
1498 }
1499
1500 *out_data = data;
1501
1502 return cgltf_result_success;
1503}
1504
1505static int cgltf_unhex(char ch)
1506{
1507 return
1508 (unsigned)(ch - '0') < 10 ? (ch - '0') :
1509 (unsigned)(ch - 'A') < 6 ? (ch - 'A') + 10 :
1510 (unsigned)(ch - 'a') < 6 ? (ch - 'a') + 10 :
1511 -1;
1512}
1513
1514cgltf_size cgltf_decode_string(char* string)
1515{
1516 char* read = string + strcspn(string, "\\");
1517 if (*read == 0)
1518 {
1519 return read - string;
1520 }
1521 char* write = string;
1522 char* last = string;
1523
1524 for (;;)
1525 {
1526 // Copy characters since last escaped sequence
1527 cgltf_size written = read - last;
1528 memmove(write, last, written);
1529 write += written;
1530
1531 if (*read++ == 0)
1532 {
1533 break;
1534 }
1535
1536 // jsmn already checked that all escape sequences are valid
1537 switch (*read++)
1538 {
1539 case '\"': *write++ = '\"'; break;
1540 case '/': *write++ = '/'; break;
1541 case '\\': *write++ = '\\'; break;
1542 case 'b': *write++ = '\b'; break;
1543 case 'f': *write++ = '\f'; break;
1544 case 'r': *write++ = '\r'; break;
1545 case 'n': *write++ = '\n'; break;
1546 case 't': *write++ = '\t'; break;
1547 case 'u':
1548 {
1549 // UCS-2 codepoint \uXXXX to UTF-8
1550 int character = 0;
1551 for (cgltf_size i = 0; i < 4; ++i)
1552 {
1553 character = (character << 4) + cgltf_unhex(*read++);
1554 }
1555
1556 if (character <= 0x7F)
1557 {
1558 *write++ = character & 0xFF;
1559 }
1560 else if (character <= 0x7FF)
1561 {
1562 *write++ = 0xC0 | ((character >> 6) & 0xFF);
1563 *write++ = 0x80 | (character & 0x3F);
1564 }
1565 else
1566 {
1567 *write++ = 0xE0 | ((character >> 12) & 0xFF);
1568 *write++ = 0x80 | ((character >> 6) & 0x3F);
1569 *write++ = 0x80 | (character & 0x3F);
1570 }
1571 break;
1572 }
1573 default:
1574 break;
1575 }
1576
1577 last = read;
1578 read += strcspn(read, "\\");
1579 }
1580
1581 *write = 0;
1582 return write - string;
1583}
1584
1586{
1587 char* write = uri;
1588 char* i = uri;
1589
1590 while (*i)
1591 {
1592 if (*i == '%')
1593 {
1594 int ch1 = cgltf_unhex(i[1]);
1595
1596 if (ch1 >= 0)
1597 {
1598 int ch2 = cgltf_unhex(i[2]);
1599
1600 if (ch2 >= 0)
1601 {
1602 *write++ = (char)(ch1 * 16 + ch2);
1603 i += 3;
1604 continue;
1605 }
1606 }
1607 }
1608
1609 *write++ = *i++;
1610 }
1611
1612 *write = 0;
1613 return write - uri;
1614}
1615
1616cgltf_result cgltf_load_buffers(const cgltf_options* options, cgltf_data* data, const char* gltf_path)
1617{
1618 if (options == NULL)
1619 {
1621 }
1622
1623 if (data->buffers_count && data->buffers[0].data == NULL && data->buffers[0].uri == NULL && data->bin)
1624 {
1625 if (data->bin_size < data->buffers[0].size)
1626 {
1628 }
1629
1630 data->buffers[0].data = (void*)data->bin;
1632 }
1633
1634 for (cgltf_size i = 0; i < data->buffers_count; ++i)
1635 {
1636 if (data->buffers[i].data)
1637 {
1638 continue;
1639 }
1640
1641 const char* uri = data->buffers[i].uri;
1642
1643 if (uri == NULL)
1644 {
1645 continue;
1646 }
1647
1648 if (strncmp(uri, "data:", 5) == 0)
1649 {
1650 const char* comma = strchr(uri, ',');
1651
1652 if (comma && comma - uri >= 7 && strncmp(comma - 7, ";base64", 7) == 0)
1653 {
1654 cgltf_result res = cgltf_load_buffer_base64(options, data->buffers[i].size, comma + 1, &data->buffers[i].data);
1656
1657 if (res != cgltf_result_success)
1658 {
1659 return res;
1660 }
1661 }
1662 else
1663 {
1665 }
1666 }
1667 else if (strstr(uri, "://") == NULL && gltf_path)
1668 {
1669 cgltf_result res = cgltf_load_buffer_file(options, data->buffers[i].size, uri, gltf_path, &data->buffers[i].data);
1671
1672 if (res != cgltf_result_success)
1673 {
1674 return res;
1675 }
1676 }
1677 else
1678 {
1680 }
1681 }
1682
1683 return cgltf_result_success;
1684}
1685
1686static cgltf_size cgltf_calc_index_bound(cgltf_buffer_view* buffer_view, cgltf_size offset, cgltf_component_type component_type, cgltf_size count)
1687{
1688 char* data = (char*)buffer_view->buffer->data + offset + buffer_view->offset;
1689 cgltf_size bound = 0;
1690
1691 switch (component_type)
1692 {
1694 for (size_t i = 0; i < count; ++i)
1695 {
1696 cgltf_size v = ((unsigned char*)data)[i];
1697 bound = bound > v ? bound : v;
1698 }
1699 break;
1700
1702 for (size_t i = 0; i < count; ++i)
1703 {
1704 cgltf_size v = ((unsigned short*)data)[i];
1705 bound = bound > v ? bound : v;
1706 }
1707 break;
1708
1710 for (size_t i = 0; i < count; ++i)
1711 {
1712 cgltf_size v = ((unsigned int*)data)[i];
1713 bound = bound > v ? bound : v;
1714 }
1715 break;
1716
1717 default:
1718 ;
1719 }
1720
1721 return bound;
1722}
1723
1724#if CGLTF_VALIDATE_ENABLE_ASSERTS
1725#define CGLTF_ASSERT_IF(cond, result) assert(!(cond)); if (cond) return result;
1726#else
1727#define CGLTF_ASSERT_IF(cond, result) if (cond) return result;
1728#endif
1729
1731{
1732 for (cgltf_size i = 0; i < data->accessors_count; ++i)
1733 {
1734 cgltf_accessor* accessor = &data->accessors[i];
1735
1737 CGLTF_ASSERT_IF(data->accessors[i].type == cgltf_type_invalid, cgltf_result_invalid_gltf);
1738
1739 cgltf_size element_size = cgltf_calc_size(accessor->type, accessor->component_type);
1740
1741 if (accessor->buffer_view)
1742 {
1743 cgltf_size req_size = accessor->offset + accessor->stride * (accessor->count - 1) + element_size;
1744
1745 CGLTF_ASSERT_IF(accessor->buffer_view->size < req_size, cgltf_result_data_too_short);
1746 }
1747
1748 if (accessor->is_sparse)
1749 {
1750 cgltf_accessor_sparse* sparse = &accessor->sparse;
1751
1752 cgltf_size indices_component_size = cgltf_component_size(sparse->indices_component_type);
1753 cgltf_size indices_req_size = sparse->indices_byte_offset + indices_component_size * sparse->count;
1754 cgltf_size values_req_size = sparse->values_byte_offset + element_size * sparse->count;
1755
1756 CGLTF_ASSERT_IF(sparse->indices_buffer_view->size < indices_req_size ||
1757 sparse->values_buffer_view->size < values_req_size, cgltf_result_data_too_short);
1758
1759 CGLTF_ASSERT_IF(sparse->indices_component_type != cgltf_component_type_r_8u &&
1762
1763 if (sparse->indices_buffer_view->buffer->data)
1764 {
1765 cgltf_size index_bound = cgltf_calc_index_bound(sparse->indices_buffer_view, sparse->indices_byte_offset, sparse->indices_component_type, sparse->count);
1766
1767 CGLTF_ASSERT_IF(index_bound >= accessor->count, cgltf_result_data_too_short);
1768 }
1769 }
1770 }
1771
1772 for (cgltf_size i = 0; i < data->buffer_views_count; ++i)
1773 {
1774 cgltf_size req_size = data->buffer_views[i].offset + data->buffer_views[i].size;
1775
1776 CGLTF_ASSERT_IF(data->buffer_views[i].buffer && data->buffer_views[i].buffer->size < req_size, cgltf_result_data_too_short);
1777
1779 {
1781
1782 CGLTF_ASSERT_IF(mc->buffer == NULL || mc->buffer->size < mc->offset + mc->size, cgltf_result_data_too_short);
1783
1784 CGLTF_ASSERT_IF(data->buffer_views[i].stride && mc->stride != data->buffer_views[i].stride, cgltf_result_invalid_gltf);
1785
1786 CGLTF_ASSERT_IF(data->buffer_views[i].size != mc->stride * mc->count, cgltf_result_invalid_gltf);
1787
1789
1790 CGLTF_ASSERT_IF(mc->mode == cgltf_meshopt_compression_mode_attributes && !(mc->stride % 4 == 0 && mc->stride <= 256), cgltf_result_invalid_gltf);
1791
1792 CGLTF_ASSERT_IF(mc->mode == cgltf_meshopt_compression_mode_triangles && mc->count % 3 != 0, cgltf_result_invalid_gltf);
1793
1795
1797
1798 CGLTF_ASSERT_IF(mc->filter == cgltf_meshopt_compression_filter_octahedral && mc->stride != 4 && mc->stride != 8, cgltf_result_invalid_gltf);
1799
1801 }
1802 }
1803
1804 for (cgltf_size i = 0; i < data->meshes_count; ++i)
1805 {
1806 if (data->meshes[i].weights)
1807 {
1808 CGLTF_ASSERT_IF(data->meshes[i].primitives_count && data->meshes[i].primitives[0].targets_count != data->meshes[i].weights_count, cgltf_result_invalid_gltf);
1809 }
1810
1811 if (data->meshes[i].target_names)
1812 {
1813 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);
1814 }
1815
1816 for (cgltf_size j = 0; j < data->meshes[i].primitives_count; ++j)
1817 {
1819 CGLTF_ASSERT_IF(data->meshes[i].primitives[j].targets_count != data->meshes[i].primitives[0].targets_count, cgltf_result_invalid_gltf);
1820
1821 CGLTF_ASSERT_IF(data->meshes[i].primitives[j].attributes_count == 0, cgltf_result_invalid_gltf);
1822
1823 cgltf_accessor* first = data->meshes[i].primitives[j].attributes[0].data;
1824
1825 CGLTF_ASSERT_IF(first->count == 0, cgltf_result_invalid_gltf);
1826
1827 for (cgltf_size k = 0; k < data->meshes[i].primitives[j].attributes_count; ++k)
1828 {
1829 CGLTF_ASSERT_IF(data->meshes[i].primitives[j].attributes[k].data->count != first->count, cgltf_result_invalid_gltf);
1830 }
1831
1832 for (cgltf_size k = 0; k < data->meshes[i].primitives[j].targets_count; ++k)
1833 {
1834 for (cgltf_size m = 0; m < data->meshes[i].primitives[j].targets[k].attributes_count; ++m)
1835 {
1836 CGLTF_ASSERT_IF(data->meshes[i].primitives[j].targets[k].attributes[m].data->count != first->count, cgltf_result_invalid_gltf);
1837 }
1838 }
1839
1840 cgltf_accessor* indices = data->meshes[i].primitives[j].indices;
1841
1842 CGLTF_ASSERT_IF(indices &&
1846
1847 CGLTF_ASSERT_IF(indices && indices->type != cgltf_type_scalar, cgltf_result_invalid_gltf);
1848 CGLTF_ASSERT_IF(indices && indices->stride != cgltf_component_size(indices->component_type), cgltf_result_invalid_gltf);
1849
1850 if (indices && indices->buffer_view && indices->buffer_view->buffer->data)
1851 {
1852 cgltf_size index_bound = cgltf_calc_index_bound(indices->buffer_view, indices->offset, indices->component_type, indices->count);
1853
1854 CGLTF_ASSERT_IF(index_bound >= first->count, cgltf_result_data_too_short);
1855 }
1856
1857 for (cgltf_size k = 0; k < data->meshes[i].primitives[j].mappings_count; ++k)
1858 {
1859 CGLTF_ASSERT_IF(data->meshes[i].primitives[j].mappings[k].variant >= data->variants_count, cgltf_result_invalid_gltf);
1860 }
1861 }
1862 }
1863
1864 for (cgltf_size i = 0; i < data->nodes_count; ++i)
1865 {
1866 if (data->nodes[i].weights && data->nodes[i].mesh)
1867 {
1868 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);
1869 }
1870
1871 if (data->nodes[i].has_mesh_gpu_instancing)
1872 {
1873 CGLTF_ASSERT_IF(data->nodes[i].mesh == NULL, cgltf_result_invalid_gltf);
1875
1877
1878 for (cgltf_size k = 0; k < data->nodes[i].mesh_gpu_instancing.attributes_count; ++k)
1879 {
1880 CGLTF_ASSERT_IF(data->nodes[i].mesh_gpu_instancing.attributes[k].data->count != first->count, cgltf_result_invalid_gltf);
1881 }
1882 }
1883 }
1884
1885 for (cgltf_size i = 0; i < data->nodes_count; ++i)
1886 {
1887 cgltf_node* p1 = data->nodes[i].parent;
1888 cgltf_node* p2 = p1 ? p1->parent : NULL;
1889
1890 while (p1 && p2)
1891 {
1892 CGLTF_ASSERT_IF(p1 == p2, cgltf_result_invalid_gltf);
1893
1894 p1 = p1->parent;
1895 p2 = p2->parent ? p2->parent->parent : NULL;
1896 }
1897 }
1898
1899 for (cgltf_size i = 0; i < data->scenes_count; ++i)
1900 {
1901 for (cgltf_size j = 0; j < data->scenes[i].nodes_count; ++j)
1902 {
1903 CGLTF_ASSERT_IF(data->scenes[i].nodes[j]->parent, cgltf_result_invalid_gltf);
1904 }
1905 }
1906
1907 for (cgltf_size i = 0; i < data->animations_count; ++i)
1908 {
1909 for (cgltf_size j = 0; j < data->animations[i].channels_count; ++j)
1910 {
1911 cgltf_animation_channel* channel = &data->animations[i].channels[j];
1912
1913 if (!channel->target_node)
1914 {
1915 continue;
1916 }
1917
1918 cgltf_size components = 1;
1919
1921 {
1922 CGLTF_ASSERT_IF(!channel->target_node->mesh || !channel->target_node->mesh->primitives_count, cgltf_result_invalid_gltf);
1923
1924 components = channel->target_node->mesh->primitives[0].targets_count;
1925 }
1926
1928
1929 CGLTF_ASSERT_IF(channel->sampler->input->count * components * values != channel->sampler->output->count, cgltf_result_invalid_gltf);
1930 }
1931 }
1932
1933 for (cgltf_size i = 0; i < data->variants_count; ++i)
1934 {
1935 CGLTF_ASSERT_IF(!data->variants[i].name, cgltf_result_invalid_gltf);
1936 }
1937
1938 return cgltf_result_success;
1939}
1940
1941cgltf_result cgltf_copy_extras_json(const cgltf_data* data, const cgltf_extras* extras, char* dest, cgltf_size* dest_size)
1942{
1943 cgltf_size json_size = extras->end_offset - extras->start_offset;
1944
1945 if (!dest)
1946 {
1947 if (dest_size)
1948 {
1949 *dest_size = json_size + 1;
1950 return cgltf_result_success;
1951 }
1953 }
1954
1955 if (*dest_size + 1 < json_size)
1956 {
1957 strncpy(dest, data->json + extras->start_offset, *dest_size - 1);
1958 dest[*dest_size - 1] = 0;
1959 }
1960 else
1961 {
1962 strncpy(dest, data->json + extras->start_offset, json_size);
1963 dest[json_size] = 0;
1964 }
1965
1966 return cgltf_result_success;
1967}
1968
1969static void cgltf_free_extras(cgltf_data* data, cgltf_extras* extras)
1970{
1971 data->memory.free_func(data->memory.user_data, extras->data);
1972}
1973
1974static void cgltf_free_extensions(cgltf_data* data, cgltf_extension* extensions, cgltf_size extensions_count)
1975{
1976 for (cgltf_size i = 0; i < extensions_count; ++i)
1977 {
1978 data->memory.free_func(data->memory.user_data, extensions[i].name);
1979 data->memory.free_func(data->memory.user_data, extensions[i].data);
1980 }
1981 data->memory.free_func(data->memory.user_data, extensions);
1982}
1983
1984void cgltf_free(cgltf_data* data)
1985{
1986 if (!data)
1987 {
1988 return;
1989 }
1990
1991 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;
1992
1993 data->memory.free_func(data->memory.user_data, data->asset.copyright);
1994 data->memory.free_func(data->memory.user_data, data->asset.generator);
1995 data->memory.free_func(data->memory.user_data, data->asset.version);
1996 data->memory.free_func(data->memory.user_data, data->asset.min_version);
1997
1998 cgltf_free_extensions(data, data->asset.extensions, data->asset.extensions_count);
1999 cgltf_free_extras(data, &data->asset.extras);
2000
2001 for (cgltf_size i = 0; i < data->accessors_count; ++i)
2002 {
2003 data->memory.free_func(data->memory.user_data, data->accessors[i].name);
2004
2005 cgltf_free_extensions(data, data->accessors[i].extensions, data->accessors[i].extensions_count);
2006 cgltf_free_extras(data, &data->accessors[i].extras);
2007 }
2008 data->memory.free_func(data->memory.user_data, data->accessors);
2009
2010 for (cgltf_size i = 0; i < data->buffer_views_count; ++i)
2011 {
2012 data->memory.free_func(data->memory.user_data, data->buffer_views[i].name);
2013 data->memory.free_func(data->memory.user_data, data->buffer_views[i].data);
2014
2015 cgltf_free_extensions(data, data->buffer_views[i].extensions, data->buffer_views[i].extensions_count);
2016 cgltf_free_extras(data, &data->buffer_views[i].extras);
2017 }
2018 data->memory.free_func(data->memory.user_data, data->buffer_views);
2019
2020 for (cgltf_size i = 0; i < data->buffers_count; ++i)
2021 {
2022 data->memory.free_func(data->memory.user_data, data->buffers[i].name);
2023
2025 {
2026 file_release(&data->memory, &data->file, data->buffers[i].data);
2027 }
2029 {
2030 data->memory.free_func(data->memory.user_data, data->buffers[i].data);
2031 }
2032
2033 data->memory.free_func(data->memory.user_data, data->buffers[i].uri);
2034
2035 cgltf_free_extensions(data, data->buffers[i].extensions, data->buffers[i].extensions_count);
2036 cgltf_free_extras(data, &data->buffers[i].extras);
2037 }
2038 data->memory.free_func(data->memory.user_data, data->buffers);
2039
2040 for (cgltf_size i = 0; i < data->meshes_count; ++i)
2041 {
2042 data->memory.free_func(data->memory.user_data, data->meshes[i].name);
2043
2044 for (cgltf_size j = 0; j < data->meshes[i].primitives_count; ++j)
2045 {
2046 for (cgltf_size k = 0; k < data->meshes[i].primitives[j].attributes_count; ++k)
2047 {
2048 data->memory.free_func(data->memory.user_data, data->meshes[i].primitives[j].attributes[k].name);
2049 }
2050
2051 data->memory.free_func(data->memory.user_data, data->meshes[i].primitives[j].attributes);
2052
2053 for (cgltf_size k = 0; k < data->meshes[i].primitives[j].targets_count; ++k)
2054 {
2055 for (cgltf_size m = 0; m < data->meshes[i].primitives[j].targets[k].attributes_count; ++m)
2056 {
2057 data->memory.free_func(data->memory.user_data, data->meshes[i].primitives[j].targets[k].attributes[m].name);
2058 }
2059
2060 data->memory.free_func(data->memory.user_data, data->meshes[i].primitives[j].targets[k].attributes);
2061 }
2062
2063 data->memory.free_func(data->memory.user_data, data->meshes[i].primitives[j].targets);
2064
2066 {
2067 for (cgltf_size k = 0; k < data->meshes[i].primitives[j].draco_mesh_compression.attributes_count; ++k)
2068 {
2070 }
2071
2073 }
2074
2075 for (cgltf_size k = 0; k < data->meshes[i].primitives[j].mappings_count; ++k)
2076 {
2077 cgltf_free_extras(data, &data->meshes[i].primitives[j].mappings[k].extras);
2078 }
2079
2080 data->memory.free_func(data->memory.user_data, data->meshes[i].primitives[j].mappings);
2081
2082 cgltf_free_extensions(data, data->meshes[i].primitives[j].extensions, data->meshes[i].primitives[j].extensions_count);
2083 cgltf_free_extras(data, &data->meshes[i].primitives[j].extras);
2084 }
2085
2086 data->memory.free_func(data->memory.user_data, data->meshes[i].primitives);
2087 data->memory.free_func(data->memory.user_data, data->meshes[i].weights);
2088
2089 for (cgltf_size j = 0; j < data->meshes[i].target_names_count; ++j)
2090 {
2091 data->memory.free_func(data->memory.user_data, data->meshes[i].target_names[j]);
2092 }
2093
2094 cgltf_free_extensions(data, data->meshes[i].extensions, data->meshes[i].extensions_count);
2095 cgltf_free_extras(data, &data->meshes[i].extras);
2096
2097 data->memory.free_func(data->memory.user_data, data->meshes[i].target_names);
2098 }
2099
2100 data->memory.free_func(data->memory.user_data, data->meshes);
2101
2102 for (cgltf_size i = 0; i < data->materials_count; ++i)
2103 {
2104 data->memory.free_func(data->memory.user_data, data->materials[i].name);
2106
2107 cgltf_free_extensions(data, data->materials[i].extensions, data->materials[i].extensions_count);
2108 cgltf_free_extras(data, &data->materials[i].extras);
2109 }
2110
2111 data->memory.free_func(data->memory.user_data, data->materials);
2112
2113 for (cgltf_size i = 0; i < data->images_count; ++i)
2114 {
2115 data->memory.free_func(data->memory.user_data, data->images[i].name);
2116 data->memory.free_func(data->memory.user_data, data->images[i].uri);
2117 data->memory.free_func(data->memory.user_data, data->images[i].mime_type);
2118
2119 cgltf_free_extensions(data, data->images[i].extensions, data->images[i].extensions_count);
2120 cgltf_free_extras(data, &data->images[i].extras);
2121 }
2122
2123 data->memory.free_func(data->memory.user_data, data->images);
2124
2125 for (cgltf_size i = 0; i < data->textures_count; ++i)
2126 {
2127 data->memory.free_func(data->memory.user_data, data->textures[i].name);
2128
2129 cgltf_free_extensions(data, data->textures[i].extensions, data->textures[i].extensions_count);
2130 cgltf_free_extras(data, &data->textures[i].extras);
2131 }
2132
2133 data->memory.free_func(data->memory.user_data, data->textures);
2134
2135 for (cgltf_size i = 0; i < data->samplers_count; ++i)
2136 {
2137 data->memory.free_func(data->memory.user_data, data->samplers[i].name);
2138
2139 cgltf_free_extensions(data, data->samplers[i].extensions, data->samplers[i].extensions_count);
2140 cgltf_free_extras(data, &data->samplers[i].extras);
2141 }
2142
2143 data->memory.free_func(data->memory.user_data, data->samplers);
2144
2145 for (cgltf_size i = 0; i < data->skins_count; ++i)
2146 {
2147 data->memory.free_func(data->memory.user_data, data->skins[i].name);
2148 data->memory.free_func(data->memory.user_data, data->skins[i].joints);
2149
2150 cgltf_free_extensions(data, data->skins[i].extensions, data->skins[i].extensions_count);
2151 cgltf_free_extras(data, &data->skins[i].extras);
2152 }
2153
2154 data->memory.free_func(data->memory.user_data, data->skins);
2155
2156 for (cgltf_size i = 0; i < data->cameras_count; ++i)
2157 {
2158 data->memory.free_func(data->memory.user_data, data->cameras[i].name);
2159
2161 {
2162 cgltf_free_extras(data, &data->cameras[i].data.perspective.extras);
2163 }
2164 else if (data->cameras[i].type == cgltf_camera_type_orthographic)
2165 {
2166 cgltf_free_extras(data, &data->cameras[i].data.orthographic.extras);
2167 }
2168
2169 cgltf_free_extensions(data, data->cameras[i].extensions, data->cameras[i].extensions_count);
2170 cgltf_free_extras(data, &data->cameras[i].extras);
2171 }
2172
2173 data->memory.free_func(data->memory.user_data, data->cameras);
2174
2175 for (cgltf_size i = 0; i < data->lights_count; ++i)
2176 {
2177 data->memory.free_func(data->memory.user_data, data->lights[i].name);
2178
2179 cgltf_free_extras(data, &data->lights[i].extras);
2180 }
2181
2182 data->memory.free_func(data->memory.user_data, data->lights);
2183
2184 for (cgltf_size i = 0; i < data->lights_area_count; ++i)
2185 {
2186 data->memory.free_func(data->memory.user_data, data->lights_area[i].name);
2187
2188 cgltf_free_extras(data, &data->lights_area[i].extras);
2189 }
2190
2191 data->memory.free_func(data->memory.user_data, data->lights_area);
2192
2193 for (cgltf_size i = 0; i < data->curves_count; ++i)
2194 {
2195 data->memory.free_func(data->memory.user_data, data->curves[i].name);
2196
2197 cgltf_free_extras(data, &data->curves[i].extras);
2198 }
2199
2200 data->memory.free_func(data->memory.user_data, data->curves);
2201
2202 for (cgltf_size i = 0; i < data->nodes_count; ++i)
2203 {
2204 data->memory.free_func(data->memory.user_data, data->nodes[i].name);
2205 data->memory.free_func(data->memory.user_data, data->nodes[i].children);
2206 data->memory.free_func(data->memory.user_data, data->nodes[i].weights);
2207
2208 if (data->nodes[i].has_mesh_gpu_instancing)
2209 {
2210 for (cgltf_size j = 0; j < data->nodes[i].mesh_gpu_instancing.attributes_count; ++j)
2211 {
2213 }
2214
2216 }
2217
2218 cgltf_free_extensions(data, data->nodes[i].extensions, data->nodes[i].extensions_count);
2219 cgltf_free_extras(data, &data->nodes[i].extras);
2220 }
2221
2222 data->memory.free_func(data->memory.user_data, data->nodes);
2223
2224 for (cgltf_size i = 0; i < data->scenes_count; ++i)
2225 {
2226 data->memory.free_func(data->memory.user_data, data->scenes[i].name);
2227 data->memory.free_func(data->memory.user_data, data->scenes[i].nodes);
2229
2230 cgltf_free_extensions(data, data->scenes[i].extensions, data->scenes[i].extensions_count);
2231 cgltf_free_extras(data, &data->scenes[i].extras);
2232 }
2233
2234 data->memory.free_func(data->memory.user_data, data->scenes);
2235
2236 for (cgltf_size i = 0; i < data->animations_count; ++i)
2237 {
2238 data->memory.free_func(data->memory.user_data, data->animations[i].name);
2239 for (cgltf_size j = 0; j < data->animations[i].samplers_count; ++j)
2240 {
2241 cgltf_free_extensions(data, data->animations[i].samplers[j].extensions, data->animations[i].samplers[j].extensions_count);
2242 cgltf_free_extras(data, &data->animations[i].samplers[j].extras);
2243 }
2244 data->memory.free_func(data->memory.user_data, data->animations[i].samplers);
2245
2246 for (cgltf_size j = 0; j < data->animations[i].channels_count; ++j)
2247 {
2248 cgltf_free_extensions(data, data->animations[i].channels[j].extensions, data->animations[i].channels[j].extensions_count);
2249 cgltf_free_extras(data, &data->animations[i].channels[j].extras);
2250 }
2251 data->memory.free_func(data->memory.user_data, data->animations[i].channels);
2252
2253 cgltf_free_extensions(data, data->animations[i].extensions, data->animations[i].extensions_count);
2254 cgltf_free_extras(data, &data->animations[i].extras);
2255 }
2256
2257 data->memory.free_func(data->memory.user_data, data->animations);
2258
2259 for (cgltf_size i = 0; i < data->variants_count; ++i)
2260 {
2261 data->memory.free_func(data->memory.user_data, data->variants[i].name);
2262
2263 cgltf_free_extras(data, &data->variants[i].extras);
2264 }
2265
2266 data->memory.free_func(data->memory.user_data, data->variants);
2267
2270 cgltf_free_extensions(data, data->data_extensions, data->data_extensions_count);
2271 cgltf_free_extras(data, &data->extras);
2272
2273 for (cgltf_size i = 0; i < data->extensions_used_count; ++i)
2274 {
2275 data->memory.free_func(data->memory.user_data, data->extensions_used[i]);
2276 }
2277
2278 data->memory.free_func(data->memory.user_data, data->extensions_used);
2279
2280 for (cgltf_size i = 0; i < data->extensions_required_count; ++i)
2281 {
2282 data->memory.free_func(data->memory.user_data, data->extensions_required[i]);
2283 }
2284
2286
2287 file_release(&data->memory, &data->file, data->file_data);
2288
2289 data->memory.free_func(data->memory.user_data, data);
2290}
2291
2292void cgltf_node_transform_local(const cgltf_node* node, cgltf_float* out_matrix)
2293{
2294 cgltf_float* lm = out_matrix;
2295
2296 if (node->has_matrix)
2297 {
2298 memcpy(lm, node->matrix, sizeof(float) * 16);
2299 }
2300 else
2301 {
2302 float tx = node->translation[0];
2303 float ty = node->translation[1];
2304 float tz = node->translation[2];
2305
2306 float qx = node->rotation[0];
2307 float qy = node->rotation[1];
2308 float qz = node->rotation[2];
2309 float qw = node->rotation[3];
2310
2311 float sx = node->scale[0];
2312 float sy = node->scale[1];
2313 float sz = node->scale[2];
2314
2315 lm[0] = (1 - 2 * qy*qy - 2 * qz*qz) * sx;
2316 lm[1] = (2 * qx*qy + 2 * qz*qw) * sx;
2317 lm[2] = (2 * qx*qz - 2 * qy*qw) * sx;
2318 lm[3] = 0.f;
2319
2320 lm[4] = (2 * qx*qy - 2 * qz*qw) * sy;
2321 lm[5] = (1 - 2 * qx*qx - 2 * qz*qz) * sy;
2322 lm[6] = (2 * qy*qz + 2 * qx*qw) * sy;
2323 lm[7] = 0.f;
2324
2325 lm[8] = (2 * qx*qz + 2 * qy*qw) * sz;
2326 lm[9] = (2 * qy*qz - 2 * qx*qw) * sz;
2327 lm[10] = (1 - 2 * qx*qx - 2 * qy*qy) * sz;
2328 lm[11] = 0.f;
2329
2330 lm[12] = tx;
2331 lm[13] = ty;
2332 lm[14] = tz;
2333 lm[15] = 1.f;
2334 }
2335}
2336
2337void cgltf_node_transform_world(const cgltf_node* node, cgltf_float* out_matrix)
2338{
2339 cgltf_float* lm = out_matrix;
2341
2342 const cgltf_node* parent = node->parent;
2343
2344 while (parent)
2345 {
2346 float pm[16];
2347 cgltf_node_transform_local(parent, pm);
2348
2349 for (int i = 0; i < 4; ++i)
2350 {
2351 float l0 = lm[i * 4 + 0];
2352 float l1 = lm[i * 4 + 1];
2353 float l2 = lm[i * 4 + 2];
2354
2355 float r0 = l0 * pm[0] + l1 * pm[4] + l2 * pm[8];
2356 float r1 = l0 * pm[1] + l1 * pm[5] + l2 * pm[9];
2357 float r2 = l0 * pm[2] + l1 * pm[6] + l2 * pm[10];
2358
2359 lm[i * 4 + 0] = r0;
2360 lm[i * 4 + 1] = r1;
2361 lm[i * 4 + 2] = r2;
2362 }
2363
2364 lm[12] += pm[12];
2365 lm[13] += pm[13];
2366 lm[14] += pm[14];
2367
2368 parent = parent->parent;
2369 }
2370}
2371
2372static cgltf_ssize cgltf_component_read_integer(const void* in, cgltf_component_type component_type)
2373{
2374 switch (component_type)
2375 {
2377 return *((const int16_t*) in);
2379 return *((const uint16_t*) in);
2381 return *((const uint32_t*) in);
2383 return *((const int8_t*) in);
2385 return *((const uint8_t*) in);
2386 default:
2387 return 0;
2388 }
2389}
2390
2391static cgltf_size cgltf_component_read_index(const void* in, cgltf_component_type component_type)
2392{
2393 switch (component_type)
2394 {
2396 return *((const uint16_t*) in);
2398 return *((const uint32_t*) in);
2400 return *((const uint8_t*) in);
2401 default:
2402 return 0;
2403 }
2404}
2405
2406static cgltf_float cgltf_component_read_float(const void* in, cgltf_component_type component_type, cgltf_bool normalized)
2407{
2408 if (component_type == cgltf_component_type_r_32f)
2409 {
2410 return *((const float*) in);
2411 }
2412
2413 if (normalized)
2414 {
2415 switch (component_type)
2416 {
2417 // note: glTF spec doesn't currently define normalized conversions for 32-bit integers
2419 return *((const int16_t*) in) / (cgltf_float)32767;
2421 return *((const uint16_t*) in) / (cgltf_float)65535;
2423 return *((const int8_t*) in) / (cgltf_float)127;
2425 return *((const uint8_t*) in) / (cgltf_float)255;
2426 default:
2427 return 0;
2428 }
2429 }
2430
2431 return (cgltf_float)cgltf_component_read_integer(in, component_type);
2432}
2433
2434static 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)
2435{
2436 cgltf_size num_components = cgltf_num_components(type);
2437
2438 if (element_size < num_components) {
2439 return 0;
2440 }
2441
2442 // There are three special cases for component extraction, see #data-alignment in the 2.0 spec.
2443
2444 cgltf_size component_size = cgltf_component_size(component_type);
2445
2446 if (type == cgltf_type_mat2 && component_size == 1)
2447 {
2448 out[0] = cgltf_component_read_float(element, component_type, normalized);
2449 out[1] = cgltf_component_read_float(element + 1, component_type, normalized);
2450 out[2] = cgltf_component_read_float(element + 4, component_type, normalized);
2451 out[3] = cgltf_component_read_float(element + 5, component_type, normalized);
2452 return 1;
2453 }
2454
2455 if (type == cgltf_type_mat3 && component_size == 1)
2456 {
2457 out[0] = cgltf_component_read_float(element, component_type, normalized);
2458 out[1] = cgltf_component_read_float(element + 1, component_type, normalized);
2459 out[2] = cgltf_component_read_float(element + 2, component_type, normalized);
2460 out[3] = cgltf_component_read_float(element + 4, component_type, normalized);
2461 out[4] = cgltf_component_read_float(element + 5, component_type, normalized);
2462 out[5] = cgltf_component_read_float(element + 6, component_type, normalized);
2463 out[6] = cgltf_component_read_float(element + 8, component_type, normalized);
2464 out[7] = cgltf_component_read_float(element + 9, component_type, normalized);
2465 out[8] = cgltf_component_read_float(element + 10, component_type, normalized);
2466 return 1;
2467 }
2468
2469 if (type == cgltf_type_mat3 && component_size == 2)
2470 {
2471 out[0] = cgltf_component_read_float(element, component_type, normalized);
2472 out[1] = cgltf_component_read_float(element + 2, component_type, normalized);
2473 out[2] = cgltf_component_read_float(element + 4, component_type, normalized);
2474 out[3] = cgltf_component_read_float(element + 8, component_type, normalized);
2475 out[4] = cgltf_component_read_float(element + 10, component_type, normalized);
2476 out[5] = cgltf_component_read_float(element + 12, component_type, normalized);
2477 out[6] = cgltf_component_read_float(element + 16, component_type, normalized);
2478 out[7] = cgltf_component_read_float(element + 18, component_type, normalized);
2479 out[8] = cgltf_component_read_float(element + 20, component_type, normalized);
2480 return 1;
2481 }
2482
2483 for (cgltf_size i = 0; i < num_components; ++i)
2484 {
2485 out[i] = cgltf_component_read_float(element + component_size * i, component_type, normalized);
2486 }
2487 return 1;
2488}
2489
2490const uint8_t* cgltf_buffer_view_data(const cgltf_buffer_view* view)
2491{
2492 if (view->data)
2493 return (const uint8_t*)view->data;
2494
2495 if (!view->buffer->data)
2496 return NULL;
2497
2498 const uint8_t* result = (const uint8_t*)view->buffer->data;
2499 result += view->offset;
2500 return result;
2501}
2502
2504{
2505 for (cgltf_size i = 0; i < prim->attributes_count; ++i)
2506 {
2507 const cgltf_attribute* attr = &prim->attributes[i];
2508 if (attr->type == type && attr->index == index)
2509 return attr->data;
2510 }
2511
2512 return NULL;
2513}
2514
2515cgltf_bool cgltf_accessor_read_float(const cgltf_accessor* accessor, cgltf_size index, cgltf_float* out, cgltf_size element_size)
2516{
2517 if (accessor->is_sparse)
2518 {
2519 return 0;
2520 }
2521 if (accessor->buffer_view == NULL)
2522 {
2523 memset(out, 0, element_size * sizeof(cgltf_float));
2524 return 1;
2525 }
2526 const uint8_t* element = cgltf_buffer_view_data(accessor->buffer_view);
2527 if (element == NULL)
2528 {
2529 return 0;
2530 }
2531 element += accessor->offset + accessor->stride * index;
2532 return cgltf_element_read_float(element, accessor->type, accessor->component_type, accessor->normalized, out, element_size);
2533}
2534
2536{
2537 cgltf_size floats_per_element = cgltf_num_components(accessor->type);
2538 cgltf_size available_floats = accessor->count * floats_per_element;
2539 if (out == NULL)
2540 {
2541 return available_floats;
2542 }
2543
2544 float_count = available_floats < float_count ? available_floats : float_count;
2545 cgltf_size element_count = float_count / floats_per_element;
2546
2547 // First pass: convert each element in the base accessor.
2548 if (accessor->buffer_view == NULL)
2549 {
2550 memset(out, 0, element_count * floats_per_element * sizeof(cgltf_float));
2551 }
2552 else
2553 {
2554 const uint8_t* element = cgltf_buffer_view_data(accessor->buffer_view);
2555 if (element == NULL)
2556 {
2557 return 0;
2558 }
2559 element += accessor->offset;
2560
2561 if (accessor->component_type == cgltf_component_type_r_32f && accessor->stride == floats_per_element * sizeof(cgltf_float))
2562 {
2563 memcpy(out, element, element_count * floats_per_element * sizeof(cgltf_float));
2564 }
2565 else
2566 {
2567 cgltf_float* dest = out;
2568
2569 for (cgltf_size index = 0; index < element_count; index++, dest += floats_per_element, element += accessor->stride)
2570 {
2571 if (!cgltf_element_read_float(element, accessor->type, accessor->component_type, accessor->normalized, dest, floats_per_element))
2572 {
2573 return 0;
2574 }
2575 }
2576 }
2577 }
2578
2579 // Second pass: write out each element in the sparse accessor.
2580 if (accessor->is_sparse)
2581 {
2582 const cgltf_accessor_sparse* sparse = &accessor->sparse;
2583
2584 const uint8_t* index_data = cgltf_buffer_view_data(sparse->indices_buffer_view);
2585 const uint8_t* reader_head = cgltf_buffer_view_data(sparse->values_buffer_view);
2586
2587 if (index_data == NULL || reader_head == NULL)
2588 {
2589 return 0;
2590 }
2591
2592 index_data += sparse->indices_byte_offset;
2593 reader_head += sparse->values_byte_offset;
2594
2596 for (cgltf_size reader_index = 0; reader_index < sparse->count; reader_index++, index_data += index_stride, reader_head += accessor->stride)
2597 {
2598 size_t writer_index = cgltf_component_read_index(index_data, sparse->indices_component_type);
2599 float* writer_head = out + writer_index * floats_per_element;
2600
2601 if (!cgltf_element_read_float(reader_head, accessor->type, accessor->component_type, accessor->normalized, writer_head, floats_per_element))
2602 {
2603 return 0;
2604 }
2605 }
2606 }
2607
2608 return element_count * floats_per_element;
2609}
2610
2611static cgltf_uint cgltf_component_read_uint(const void* in, cgltf_component_type component_type)
2612{
2613 switch (component_type)
2614 {
2616 return *((const int8_t*) in);
2617
2619 return *((const uint8_t*) in);
2620
2622 return *((const int16_t*) in);
2623
2625 return *((const uint16_t*) in);
2626
2628 return *((const uint32_t*) in);
2629
2630 default:
2631 return 0;
2632 }
2633}
2634
2635static 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)
2636{
2637 cgltf_size num_components = cgltf_num_components(type);
2638
2639 if (element_size < num_components)
2640 {
2641 return 0;
2642 }
2643
2644 // Reading integer matrices is not a valid use case
2645 if (type == cgltf_type_mat2 || type == cgltf_type_mat3 || type == cgltf_type_mat4)
2646 {
2647 return 0;
2648 }
2649
2650 cgltf_size component_size = cgltf_component_size(component_type);
2651
2652 for (cgltf_size i = 0; i < num_components; ++i)
2653 {
2654 out[i] = cgltf_component_read_uint(element + component_size * i, component_type);
2655 }
2656 return 1;
2657}
2658
2659cgltf_bool cgltf_accessor_read_uint(const cgltf_accessor* accessor, cgltf_size index, cgltf_uint* out, cgltf_size element_size)
2660{
2661 if (accessor->is_sparse)
2662 {
2663 return 0;
2664 }
2665 if (accessor->buffer_view == NULL)
2666 {
2667 memset(out, 0, element_size * sizeof( cgltf_uint ));
2668 return 1;
2669 }
2670 const uint8_t* element = cgltf_buffer_view_data(accessor->buffer_view);
2671 if (element == NULL)
2672 {
2673 return 0;
2674 }
2675 element += accessor->offset + accessor->stride * index;
2676 return cgltf_element_read_uint(element, accessor->type, accessor->component_type, out, element_size);
2677}
2678
2680{
2681 if (accessor->is_sparse)
2682 {
2683 return 0; // This is an error case, but we can't communicate the error with existing interface.
2684 }
2685 if (accessor->buffer_view == NULL)
2686 {
2687 return 0;
2688 }
2689 const uint8_t* element = cgltf_buffer_view_data(accessor->buffer_view);
2690 if (element == NULL)
2691 {
2692 return 0; // This is an error case, but we can't communicate the error with existing interface.
2693 }
2694 element += accessor->offset + accessor->stride * index;
2695 return cgltf_component_read_index(element, accessor->component_type);
2696}
2697
2698cgltf_size cgltf_mesh_index(const cgltf_data* data, const cgltf_mesh* object)
2699{
2700 assert(object && (cgltf_size)(object - data->meshes) < data->meshes_count);
2701 return (cgltf_size)(object - data->meshes);
2702}
2703
2704cgltf_size cgltf_material_index(const cgltf_data* data, const cgltf_material* object)
2705{
2706 assert(object && (cgltf_size)(object - data->materials) < data->materials_count);
2707 return (cgltf_size)(object - data->materials);
2708}
2709
2710cgltf_size cgltf_accessor_index(const cgltf_data* data, const cgltf_accessor* object)
2711{
2712 assert(object && (cgltf_size)(object - data->accessors) < data->accessors_count);
2713 return (cgltf_size)(object - data->accessors);
2714}
2715
2717{
2718 assert(object && (cgltf_size)(object - data->buffer_views) < data->buffer_views_count);
2719 return (cgltf_size)(object - data->buffer_views);
2720}
2721
2722cgltf_size cgltf_buffer_index(const cgltf_data* data, const cgltf_buffer* object)
2723{
2724 assert(object && (cgltf_size)(object - data->buffers) < data->buffers_count);
2725 return (cgltf_size)(object - data->buffers);
2726}
2727
2728cgltf_size cgltf_image_index(const cgltf_data* data, const cgltf_image* object)
2729{
2730 assert(object && (cgltf_size)(object - data->images) < data->images_count);
2731 return (cgltf_size)(object - data->images);
2732}
2733
2734cgltf_size cgltf_texture_index(const cgltf_data* data, const cgltf_texture* object)
2735{
2736 assert(object && (cgltf_size)(object - data->textures) < data->textures_count);
2737 return (cgltf_size)(object - data->textures);
2738}
2739
2740cgltf_size cgltf_sampler_index(const cgltf_data* data, const cgltf_sampler* object)
2741{
2742 assert(object && (cgltf_size)(object - data->samplers) < data->samplers_count);
2743 return (cgltf_size)(object - data->samplers);
2744}
2745
2746cgltf_size cgltf_skin_index(const cgltf_data* data, const cgltf_skin* object)
2747{
2748 assert(object && (cgltf_size)(object - data->skins) < data->skins_count);
2749 return (cgltf_size)(object - data->skins);
2750}
2751
2752cgltf_size cgltf_camera_index(const cgltf_data* data, const cgltf_camera* object)
2753{
2754 assert(object && (cgltf_size)(object - data->cameras) < data->cameras_count);
2755 return (cgltf_size)(object - data->cameras);
2756}
2757
2758cgltf_size cgltf_light_index(const cgltf_data* data, const cgltf_light* object)
2759{
2760 assert(object && (cgltf_size)(object - data->lights) < data->lights_count);
2761 return (cgltf_size)(object - data->lights);
2762}
2763
2765{
2766 assert(object && (cgltf_size)(object - data->lights_area) < data->lights_area_count);
2767 return (cgltf_size)(object - data->lights_area);
2768}
2769
2770cgltf_size cgltf_curve_index(const cgltf_data* data, const cgltf_curve* object)
2771{
2772 assert(object && (cgltf_size)(object - data->curves) < data->curves_count);
2773 return (cgltf_size)(object - data->curves);
2774}
2775
2776cgltf_size cgltf_node_index(const cgltf_data* data, const cgltf_node* object)
2777{
2778 assert(object && (cgltf_size)(object - data->nodes) < data->nodes_count);
2779 return (cgltf_size)(object - data->nodes);
2780}
2781
2782cgltf_size cgltf_scene_index(const cgltf_data* data, const cgltf_scene* object)
2783{
2784 assert(object && (cgltf_size)(object - data->scenes) < data->scenes_count);
2785 return (cgltf_size)(object - data->scenes);
2786}
2787
2789{
2790 assert(object && (cgltf_size)(object - data->animations) < data->animations_count);
2791 return (cgltf_size)(object - data->animations);
2792}
2793
2795{
2796 assert(object && (cgltf_size)(object - animation->samplers) < animation->samplers_count);
2797 return (cgltf_size)(object - animation->samplers);
2798}
2799
2801{
2802 assert(object && (cgltf_size)(object - animation->channels) < animation->channels_count);
2803 return (cgltf_size)(object - animation->channels);
2804}
2805
2806cgltf_size cgltf_accessor_unpack_indices(const cgltf_accessor* accessor, void* out, cgltf_size out_component_size, cgltf_size index_count)
2807{
2808 if (out == NULL)
2809 {
2810 return accessor->count;
2811 }
2812
2813 index_count = accessor->count < index_count ? accessor->count : index_count;
2814 cgltf_size index_component_size = cgltf_component_size(accessor->component_type);
2815
2816 if (accessor->is_sparse)
2817 {
2818 return 0;
2819 }
2820 if (accessor->buffer_view == NULL)
2821 {
2822 return 0;
2823 }
2824 if (index_component_size > out_component_size)
2825 {
2826 return 0;
2827 }
2828 const uint8_t* element = cgltf_buffer_view_data(accessor->buffer_view);
2829 if (element == NULL)
2830 {
2831 return 0;
2832 }
2833 element += accessor->offset;
2834
2835 if (index_component_size == out_component_size && accessor->stride == out_component_size)
2836 {
2837 memcpy(out, element, index_count * index_component_size);
2838 return index_count;
2839 }
2840
2841 // The component size of the output array is larger than the component size of the index data, so index data will be padded.
2842 switch (out_component_size)
2843 {
2844 case 2:
2845 for (cgltf_size index = 0; index < index_count; index++, element += accessor->stride)
2846 {
2847 ((uint16_t*)out)[index] = (uint16_t)cgltf_component_read_index(element, accessor->component_type);
2848 }
2849 break;
2850 case 4:
2851 for (cgltf_size index = 0; index < index_count; index++, element += accessor->stride)
2852 {
2853 ((uint32_t*)out)[index] = (uint32_t)cgltf_component_read_index(element, accessor->component_type);
2854 }
2855 break;
2856 default:
2857 break;
2858 }
2859
2860 return index_count;
2861}
2862
2863#define CGLTF_ERROR_JSON -1
2864#define CGLTF_ERROR_NOMEM -2
2865#define CGLTF_ERROR_LEGACY -3
2866
2867#define CGLTF_CHECK_TOKTYPE(tok_, type_) if ((tok_).type != (type_)) { return CGLTF_ERROR_JSON; }
2868#define CGLTF_CHECK_TOKTYPE_RET(tok_, type_, ret_) if ((tok_).type != (type_)) { return ret_; }
2869#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 */
2870
2871#define CGLTF_PTRINDEX(type, idx) (type*)((cgltf_size)idx + 1)
2872#define CGLTF_PTRFIXUP(var, data, size) if (var) { if ((cgltf_size)var > size) { return CGLTF_ERROR_JSON; } var = &data[(cgltf_size)var-1]; }
2873#define CGLTF_PTRFIXUP_REQ(var, data, size) if (!var || (cgltf_size)var > size) { return CGLTF_ERROR_JSON; } var = &data[(cgltf_size)var-1];
2874
2875static int cgltf_json_strcmp(jsmntok_t const* tok, const uint8_t* json_chunk, const char* str)
2876{
2877 CGLTF_CHECK_TOKTYPE(*tok, JSMN_STRING);
2878 size_t const str_len = strlen(str);
2879 size_t const name_length = (size_t)(tok->end - tok->start);
2880 return (str_len == name_length) ? strncmp((const char*)json_chunk + tok->start, str, str_len) : 128;
2881}
2882
2883static int cgltf_json_to_int(jsmntok_t const* tok, const uint8_t* json_chunk)
2884{
2885 CGLTF_CHECK_TOKTYPE(*tok, JSMN_PRIMITIVE);
2886 char tmp[128];
2887 int size = (size_t)(tok->end - tok->start) < sizeof(tmp) ? (int)(tok->end - tok->start) : (int)(sizeof(tmp) - 1);
2888 strncpy(tmp, (const char*)json_chunk + tok->start, size);
2889 tmp[size] = 0;
2890 return CGLTF_ATOI(tmp);
2891}
2892
2893static cgltf_size cgltf_json_to_size(jsmntok_t const* tok, const uint8_t* json_chunk)
2894{
2895 CGLTF_CHECK_TOKTYPE_RET(*tok, JSMN_PRIMITIVE, 0);
2896 char tmp[128];
2897 int size = (size_t)(tok->end - tok->start) < sizeof(tmp) ? (int)(tok->end - tok->start) : (int)(sizeof(tmp) - 1);
2898 strncpy(tmp, (const char*)json_chunk + tok->start, size);
2899 tmp[size] = 0;
2900 long long res = CGLTF_ATOLL(tmp);
2901 return res < 0 ? 0 : (cgltf_size)res;
2902}
2903
2904static cgltf_float cgltf_json_to_float(jsmntok_t const* tok, const uint8_t* json_chunk)
2905{
2906 CGLTF_CHECK_TOKTYPE(*tok, JSMN_PRIMITIVE);
2907 char tmp[128];
2908 int size = (size_t)(tok->end - tok->start) < sizeof(tmp) ? (int)(tok->end - tok->start) : (int)(sizeof(tmp) - 1);
2909 strncpy(tmp, (const char*)json_chunk + tok->start, size);
2910 tmp[size] = 0;
2911 return (cgltf_float)CGLTF_ATOF(tmp);
2912}
2913
2914static cgltf_bool cgltf_json_to_bool(jsmntok_t const* tok, const uint8_t* json_chunk)
2915{
2916 int size = (int)(tok->end - tok->start);
2917 return size == 4 && memcmp(json_chunk + tok->start, "true", 4) == 0;
2918}
2919
2920static int cgltf_skip_json(jsmntok_t const* tokens, int i)
2921{
2922 int end = i + 1;
2923
2924 while (i < end)
2925 {
2926 switch (tokens[i].type)
2927 {
2928 case JSMN_OBJECT:
2929 end += tokens[i].size * 2;
2930 break;
2931
2932 case JSMN_ARRAY:
2933 end += tokens[i].size;
2934 break;
2935
2936 case JSMN_PRIMITIVE:
2937 case JSMN_STRING:
2938 break;
2939
2940 default:
2941 return -1;
2942 }
2943
2944 i++;
2945 }
2946
2947 return i;
2948}
2949
2950static void cgltf_fill_float_array(float* out_array, int size, float value)
2951{
2952 for (int j = 0; j < size; ++j)
2953 {
2954 out_array[j] = value;
2955 }
2956}
2957
2958static int cgltf_parse_json_float_array(jsmntok_t const* tokens, int i, const uint8_t* json_chunk, float* out_array, int size)
2959{
2960 CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_ARRAY);
2961 if (tokens[i].size != size)
2962 {
2963 return CGLTF_ERROR_JSON;
2964 }
2965 ++i;
2966 for (int j = 0; j < size; ++j)
2967 {
2968 CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_PRIMITIVE);
2969 out_array[j] = cgltf_json_to_float(tokens + i, json_chunk);
2970 ++i;
2971 }
2972 return i;
2973}
2974
2975static int cgltf_parse_json_string(cgltf_options* options, jsmntok_t const* tokens, int i, const uint8_t* json_chunk, char** out_string)
2976{
2977 CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_STRING);
2978 if (*out_string)
2979 {
2980 return CGLTF_ERROR_JSON;
2981 }
2982 int size = (int)(tokens[i].end - tokens[i].start);
2983 char* result = (char*)options->memory.alloc_func(options->memory.user_data, size + 1);
2984 if (!result)
2985 {
2986 return CGLTF_ERROR_NOMEM;
2987 }
2988 strncpy(result, (const char*)json_chunk + tokens[i].start, size);
2989 result[size] = 0;
2990 *out_string = result;
2991 return i + 1;
2992}
2993
2994static 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)
2995{
2996 (void)json_chunk;
2997 if (tokens[i].type != JSMN_ARRAY)
2998 {
2999 return tokens[i].type == JSMN_OBJECT ? CGLTF_ERROR_LEGACY : CGLTF_ERROR_JSON;
3000 }
3001 if (*out_array)
3002 {
3003 return CGLTF_ERROR_JSON;
3004 }
3005 int size = tokens[i].size;
3006 void* result = cgltf_calloc(options, element_size, size);
3007 if (!result)
3008 {
3009 return CGLTF_ERROR_NOMEM;
3010 }
3011 *out_array = result;
3012 *out_size = size;
3013 return i + 1;
3014}
3015
3016static 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)
3017{
3018 CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_ARRAY);
3019 i = cgltf_parse_json_array(options, tokens, i, json_chunk, sizeof(char*), (void**)out_array, out_size);
3020 if (i < 0)
3021 {
3022 return i;
3023 }
3024
3025 for (cgltf_size j = 0; j < *out_size; ++j)
3026 {
3027 i = cgltf_parse_json_string(options, tokens, i, json_chunk, j + (*out_array));
3028 if (i < 0)
3029 {
3030 return i;
3031 }
3032 }
3033 return i;
3034}
3035
3036static void cgltf_parse_attribute_type(const char* name, cgltf_attribute_type* out_type, int* out_index)
3037{
3038 if (*name == '_')
3039 {
3040 *out_type = cgltf_attribute_type_custom;
3041 return;
3042 }
3043
3044 const char* us = strchr(name, '_');
3045 size_t len = us ? (size_t)(us - name) : strlen(name);
3046
3047 if (len == 8 && strncmp(name, "POSITION", 8) == 0)
3048 {
3050 }
3051 else if (len == 6 && strncmp(name, "NORMAL", 6) == 0)
3052 {
3053 *out_type = cgltf_attribute_type_normal;
3054 }
3055 else if (len == 7 && strncmp(name, "TANGENT", 7) == 0)
3056 {
3057 *out_type = cgltf_attribute_type_tangent;
3058 }
3059 else if (len == 8 && strncmp(name, "TEXCOORD", 8) == 0)
3060 {
3062 }
3063 else if (len == 5 && strncmp(name, "COLOR", 5) == 0)
3064 {
3065 *out_type = cgltf_attribute_type_color;
3066 }
3067 else if (len == 6 && strncmp(name, "JOINTS", 6) == 0)
3068 {
3069 *out_type = cgltf_attribute_type_joints;
3070 }
3071 else if (len == 7 && strncmp(name, "WEIGHTS", 7) == 0)
3072 {
3073 *out_type = cgltf_attribute_type_weights;
3074 }
3075 else
3076 {
3077 *out_type = cgltf_attribute_type_invalid;
3078 }
3079
3080 if (us && *out_type != cgltf_attribute_type_invalid)
3081 {
3082 *out_index = CGLTF_ATOI(us + 1);
3083 if (*out_index < 0)
3084 {
3085 *out_type = cgltf_attribute_type_invalid;
3086 *out_index = 0;
3087 }
3088 }
3089}
3090
3091static 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)
3092{
3093 CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
3094
3095 if (*out_attributes)
3096 {
3097 return CGLTF_ERROR_JSON;
3098 }
3099
3100 *out_attributes_count = tokens[i].size;
3101 *out_attributes = (cgltf_attribute*)cgltf_calloc(options, sizeof(cgltf_attribute), *out_attributes_count);
3102 ++i;
3103
3104 if (!*out_attributes)
3105 {
3106 return CGLTF_ERROR_NOMEM;
3107 }
3108
3109 for (cgltf_size j = 0; j < *out_attributes_count; ++j)
3110 {
3111 CGLTF_CHECK_KEY(tokens[i]);
3112
3113 i = cgltf_parse_json_string(options, tokens, i, json_chunk, &(*out_attributes)[j].name);
3114 if (i < 0)
3115 {
3116 return CGLTF_ERROR_JSON;
3117 }
3118
3119 cgltf_parse_attribute_type((*out_attributes)[j].name, &(*out_attributes)[j].type, &(*out_attributes)[j].index);
3120
3121 (*out_attributes)[j].data = CGLTF_PTRINDEX(cgltf_accessor, cgltf_json_to_int(tokens + i, json_chunk));
3122 ++i;
3123 }
3124
3125 return i;
3126}
3127
3128static int cgltf_parse_json_extras(cgltf_options* options, jsmntok_t const* tokens, int i, const uint8_t* json_chunk, cgltf_extras* out_extras)
3129{
3130 if (out_extras->data)
3131 {
3132 return CGLTF_ERROR_JSON;
3133 }
3134
3135 /* fill deprecated fields for now, this will be removed in the future */
3136 out_extras->start_offset = tokens[i].start;
3137 out_extras->end_offset = tokens[i].end;
3138
3139 size_t start = tokens[i].start;
3140 size_t size = tokens[i].end - start;
3141 out_extras->data = (char*)options->memory.alloc_func(options->memory.user_data, size + 1);
3142 if (!out_extras->data)
3143 {
3144 return CGLTF_ERROR_NOMEM;
3145 }
3146 strncpy(out_extras->data, (const char*)json_chunk + start, size);
3147 out_extras->data[size] = '\0';
3148
3149 i = cgltf_skip_json(tokens, i);
3150 return i;
3151}
3152
3153static int cgltf_parse_json_unprocessed_extension(cgltf_options* options, jsmntok_t const* tokens, int i, const uint8_t* json_chunk, cgltf_extension* out_extension)
3154{
3155 CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_STRING);
3156 CGLTF_CHECK_TOKTYPE(tokens[i+1], JSMN_OBJECT);
3157 if (out_extension->name)
3158 {
3159 return CGLTF_ERROR_JSON;
3160 }
3161
3162 cgltf_size name_length = tokens[i].end - tokens[i].start;
3163 out_extension->name = (char*)options->memory.alloc_func(options->memory.user_data, name_length + 1);
3164 if (!out_extension->name)
3165 {
3166 return CGLTF_ERROR_NOMEM;
3167 }
3168 strncpy(out_extension->name, (const char*)json_chunk + tokens[i].start, name_length);
3169 out_extension->name[name_length] = 0;
3170 i++;
3171
3172 size_t start = tokens[i].start;
3173 size_t size = tokens[i].end - start;
3174 out_extension->data = (char*)options->memory.alloc_func(options->memory.user_data, size + 1);
3175 if (!out_extension->data)
3176 {
3177 return CGLTF_ERROR_NOMEM;
3178 }
3179 strncpy(out_extension->data, (const char*)json_chunk + start, size);
3180 out_extension->data[size] = '\0';
3181
3182 i = cgltf_skip_json(tokens, i);
3183
3184 return i;
3185}
3186
3187static 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)
3188{
3189 ++i;
3190
3191 CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
3192 if(*out_extensions)
3193 {
3194 return CGLTF_ERROR_JSON;
3195 }
3196
3197 int extensions_size = tokens[i].size;
3198 *out_extensions_count = 0;
3199 *out_extensions = (cgltf_extension*)cgltf_calloc(options, sizeof(cgltf_extension), extensions_size);
3200
3201 if (!*out_extensions)
3202 {
3203 return CGLTF_ERROR_NOMEM;
3204 }
3205
3206 ++i;
3207
3208 for (int j = 0; j < extensions_size; ++j)
3209 {
3210 CGLTF_CHECK_KEY(tokens[i]);
3211
3212 cgltf_size extension_index = (*out_extensions_count)++;
3213 cgltf_extension* extension = &((*out_extensions)[extension_index]);
3214 i = cgltf_parse_json_unprocessed_extension(options, tokens, i, json_chunk, extension);
3215
3216 if (i < 0)
3217 {
3218 return i;
3219 }
3220 }
3221 return i;
3222}
3223
3224static 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)
3225{
3226 CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
3227
3228 int size = tokens[i].size;
3229 ++i;
3230
3231 for (int j = 0; j < size; ++j)
3232 {
3233 CGLTF_CHECK_KEY(tokens[i]);
3234
3235 if (cgltf_json_strcmp(tokens + i, json_chunk, "attributes") == 0)
3236 {
3237 i = cgltf_parse_json_attribute_list(options, tokens, i + 1, json_chunk, &out_draco_mesh_compression->attributes, &out_draco_mesh_compression->attributes_count);
3238 }
3239 else if (cgltf_json_strcmp(tokens + i, json_chunk, "bufferView") == 0)
3240 {
3241 ++i;
3242 out_draco_mesh_compression->buffer_view = CGLTF_PTRINDEX(cgltf_buffer_view, cgltf_json_to_int(tokens + i, json_chunk));
3243 ++i;
3244 }
3245 else
3246 {
3247 i = cgltf_skip_json(tokens, i+1);
3248 }
3249
3250 if (i < 0)
3251 {
3252 return i;
3253 }
3254 }
3255
3256 return i;
3257}
3258
3259static int cgltf_parse_json_mesh_gpu_instancing(cgltf_options* options, jsmntok_t const* tokens, int i, const uint8_t* json_chunk, cgltf_mesh_gpu_instancing* out_mesh_gpu_instancing)
3260{
3261 CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
3262
3263 int size = tokens[i].size;
3264 ++i;
3265
3266 for (int j = 0; j < size; ++j)
3267 {
3268 CGLTF_CHECK_KEY(tokens[i]);
3269
3270 if (cgltf_json_strcmp(tokens + i, json_chunk, "attributes") == 0)
3271 {
3272 i = cgltf_parse_json_attribute_list(options, tokens, i + 1, json_chunk, &out_mesh_gpu_instancing->attributes, &out_mesh_gpu_instancing->attributes_count);
3273 }
3274 else
3275 {
3276 i = cgltf_skip_json(tokens, i+1);
3277 }
3278
3279 if (i < 0)
3280 {
3281 return i;
3282 }
3283 }
3284
3285 return i;
3286}
3287
3288static 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)
3289{
3290 (void)options;
3291 CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_ARRAY);
3292
3293 int size = tokens[i].size;
3294 ++i;
3295
3296 for (int j = 0; j < size; ++j)
3297 {
3298 CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
3299
3300 int obj_size = tokens[i].size;
3301 ++i;
3302
3303 int material = -1;
3304 int variants_tok = -1;
3305 int extras_tok = -1;
3306
3307 for (int k = 0; k < obj_size; ++k)
3308 {
3309 CGLTF_CHECK_KEY(tokens[i]);
3310
3311 if (cgltf_json_strcmp(tokens + i, json_chunk, "material") == 0)
3312 {
3313 ++i;
3314 material = cgltf_json_to_int(tokens + i, json_chunk);
3315 ++i;
3316 }
3317 else if (cgltf_json_strcmp(tokens + i, json_chunk, "variants") == 0)
3318 {
3319 variants_tok = i+1;
3320 CGLTF_CHECK_TOKTYPE(tokens[variants_tok], JSMN_ARRAY);
3321
3322 i = cgltf_skip_json(tokens, i+1);
3323 }
3324 else if (cgltf_json_strcmp(tokens + i, json_chunk, "extras") == 0)
3325 {
3326 extras_tok = i + 1;
3327 i = cgltf_skip_json(tokens, extras_tok);
3328 }
3329 else
3330 {
3331 i = cgltf_skip_json(tokens, i+1);
3332 }
3333
3334 if (i < 0)
3335 {
3336 return i;
3337 }
3338 }
3339
3340 if (material < 0 || variants_tok < 0)
3341 {
3342 return CGLTF_ERROR_JSON;
3343 }
3344
3345 if (out_mappings)
3346 {
3347 for (int k = 0; k < tokens[variants_tok].size; ++k)
3348 {
3349 int variant = cgltf_json_to_int(&tokens[variants_tok + 1 + k], json_chunk);
3350 if (variant < 0)
3351 return variant;
3352
3353 out_mappings[*offset].material = CGLTF_PTRINDEX(cgltf_material, material);
3354 out_mappings[*offset].variant = variant;
3355
3356 if (extras_tok >= 0)
3357 {
3358 int e = cgltf_parse_json_extras(options, tokens, extras_tok, json_chunk, &out_mappings[*offset].extras);
3359 if (e < 0)
3360 return e;
3361 }
3362
3363 (*offset)++;
3364 }
3365 }
3366 else
3367 {
3368 (*offset) += tokens[variants_tok].size;
3369 }
3370 }
3371
3372 return i;
3373}
3374
3375static int cgltf_parse_json_material_mappings(cgltf_options* options, jsmntok_t const* tokens, int i, const uint8_t* json_chunk, cgltf_primitive* out_prim)
3376{
3377 CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
3378
3379 int size = tokens[i].size;
3380 ++i;
3381
3382 for (int j = 0; j < size; ++j)
3383 {
3384 CGLTF_CHECK_KEY(tokens[i]);
3385
3386 if (cgltf_json_strcmp(tokens + i, json_chunk, "mappings") == 0)
3387 {
3388 if (out_prim->mappings)
3389 {
3390 return CGLTF_ERROR_JSON;
3391 }
3392
3393 cgltf_size mappings_offset = 0;
3394 int k = cgltf_parse_json_material_mapping_data(options, tokens, i + 1, json_chunk, NULL, &mappings_offset);
3395 if (k < 0)
3396 {
3397 return k;
3398 }
3399
3400 out_prim->mappings_count = mappings_offset;
3401 out_prim->mappings = (cgltf_material_mapping*)cgltf_calloc(options, sizeof(cgltf_material_mapping), out_prim->mappings_count);
3402
3403 mappings_offset = 0;
3404 i = cgltf_parse_json_material_mapping_data(options, tokens, i + 1, json_chunk, out_prim->mappings, &mappings_offset);
3405 }
3406 else
3407 {
3408 i = cgltf_skip_json(tokens, i+1);
3409 }
3410
3411 if (i < 0)
3412 {
3413 return i;
3414 }
3415 }
3416
3417 return i;
3418}
3419
3420static cgltf_primitive_type cgltf_json_to_primitive_type(jsmntok_t const* tok, const uint8_t* json_chunk)
3421{
3422 int type = cgltf_json_to_int(tok, json_chunk);
3423
3424 switch (type)
3425 {
3426 case 0:
3428 case 1:
3430 case 2:
3432 case 3:
3434 case 4:
3436 case 5:
3438 case 6:
3440 default:
3442 }
3443}
3444
3445static int cgltf_parse_json_primitive(cgltf_options* options, jsmntok_t const* tokens, int i, const uint8_t* json_chunk, cgltf_primitive* out_prim)
3446{
3447 CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
3448
3450
3451 int size = tokens[i].size;
3452 ++i;
3453
3454 for (int j = 0; j < size; ++j)
3455 {
3456 CGLTF_CHECK_KEY(tokens[i]);
3457
3458 if (cgltf_json_strcmp(tokens+i, json_chunk, "mode") == 0)
3459 {
3460 ++i;
3461 out_prim->type = cgltf_json_to_primitive_type(tokens+i, json_chunk);
3462 ++i;
3463 }
3464 else if (cgltf_json_strcmp(tokens+i, json_chunk, "indices") == 0)
3465 {
3466 ++i;
3467 out_prim->indices = CGLTF_PTRINDEX(cgltf_accessor, cgltf_json_to_int(tokens + i, json_chunk));
3468 ++i;
3469 }
3470 else if (cgltf_json_strcmp(tokens+i, json_chunk, "material") == 0)
3471 {
3472 ++i;
3473 out_prim->material = CGLTF_PTRINDEX(cgltf_material, cgltf_json_to_int(tokens + i, json_chunk));
3474 ++i;
3475 }
3476 else if (cgltf_json_strcmp(tokens+i, json_chunk, "attributes") == 0)
3477 {
3478 i = cgltf_parse_json_attribute_list(options, tokens, i + 1, json_chunk, &out_prim->attributes, &out_prim->attributes_count);
3479 }
3480 else if (cgltf_json_strcmp(tokens+i, json_chunk, "targets") == 0)
3481 {
3482 i = cgltf_parse_json_array(options, tokens, i + 1, json_chunk, sizeof(cgltf_morph_target), (void**)&out_prim->targets, &out_prim->targets_count);
3483 if (i < 0)
3484 {
3485 return i;
3486 }
3487
3488 for (cgltf_size k = 0; k < out_prim->targets_count; ++k)
3489 {
3490 i = cgltf_parse_json_attribute_list(options, tokens, i, json_chunk, &out_prim->targets[k].attributes, &out_prim->targets[k].attributes_count);
3491 if (i < 0)
3492 {
3493 return i;
3494 }
3495 }
3496 }
3497 else if (cgltf_json_strcmp(tokens + i, json_chunk, "extras") == 0)
3498 {
3499 i = cgltf_parse_json_extras(options, tokens, i + 1, json_chunk, &out_prim->extras);
3500 }
3501 else if (cgltf_json_strcmp(tokens + i, json_chunk, "extensions") == 0)
3502 {
3503 ++i;
3504
3505 CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
3506 if(out_prim->extensions)
3507 {
3508 return CGLTF_ERROR_JSON;
3509 }
3510
3511 int extensions_size = tokens[i].size;
3512 out_prim->extensions_count = 0;
3513 out_prim->extensions = (cgltf_extension*)cgltf_calloc(options, sizeof(cgltf_extension), extensions_size);
3514
3515 if (!out_prim->extensions)
3516 {
3517 return CGLTF_ERROR_NOMEM;
3518 }
3519
3520 ++i;
3521 for (int k = 0; k < extensions_size; ++k)
3522 {
3523 CGLTF_CHECK_KEY(tokens[i]);
3524
3525 if (cgltf_json_strcmp(tokens+i, json_chunk, "KHR_draco_mesh_compression") == 0)
3526 {
3527 out_prim->has_draco_mesh_compression = 1;
3528 i = cgltf_parse_json_draco_mesh_compression(options, tokens, i + 1, json_chunk, &out_prim->draco_mesh_compression);
3529 }
3530 else if (cgltf_json_strcmp(tokens+i, json_chunk, "KHR_materials_variants") == 0)
3531 {
3532 i = cgltf_parse_json_material_mappings(options, tokens, i + 1, json_chunk, out_prim);
3533 }
3534 else
3535 {
3536 i = cgltf_parse_json_unprocessed_extension(options, tokens, i, json_chunk, &(out_prim->extensions[out_prim->extensions_count++]));
3537 }
3538
3539 if (i < 0)
3540 {
3541 return i;
3542 }
3543 }
3544 }
3545 else
3546 {
3547 i = cgltf_skip_json(tokens, i+1);
3548 }
3549
3550 if (i < 0)
3551 {
3552 return i;
3553 }
3554 }
3555
3556 return i;
3557}
3558
3559static int cgltf_parse_json_mesh(cgltf_options* options, jsmntok_t const* tokens, int i, const uint8_t* json_chunk, cgltf_mesh* out_mesh)
3560{
3561 CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
3562
3563 int size = tokens[i].size;
3564 ++i;
3565
3566 for (int j = 0; j < size; ++j)
3567 {
3568 CGLTF_CHECK_KEY(tokens[i]);
3569
3570 if (cgltf_json_strcmp(tokens+i, json_chunk, "name") == 0)
3571 {
3572 i = cgltf_parse_json_string(options, tokens, i + 1, json_chunk, &out_mesh->name);
3573 }
3574 else if (cgltf_json_strcmp(tokens+i, json_chunk, "primitives") == 0)
3575 {
3576 i = cgltf_parse_json_array(options, tokens, i + 1, json_chunk, sizeof(cgltf_primitive), (void**)&out_mesh->primitives, &out_mesh->primitives_count);
3577 if (i < 0)
3578 {
3579 return i;
3580 }
3581
3582 for (cgltf_size prim_index = 0; prim_index < out_mesh->primitives_count; ++prim_index)
3583 {
3584 i = cgltf_parse_json_primitive(options, tokens, i, json_chunk, &out_mesh->primitives[prim_index]);
3585 if (i < 0)
3586 {
3587 return i;
3588 }
3589 }
3590 }
3591 else if (cgltf_json_strcmp(tokens + i, json_chunk, "weights") == 0)
3592 {
3593 i = cgltf_parse_json_array(options, tokens, i + 1, json_chunk, sizeof(cgltf_float), (void**)&out_mesh->weights, &out_mesh->weights_count);
3594 if (i < 0)
3595 {
3596 return i;
3597 }
3598
3599 i = cgltf_parse_json_float_array(tokens, i - 1, json_chunk, out_mesh->weights, (int)out_mesh->weights_count);
3600 }
3601 else if (cgltf_json_strcmp(tokens + i, json_chunk, "extras") == 0)
3602 {
3603 ++i;
3604
3605 out_mesh->extras.start_offset = tokens[i].start;
3606 out_mesh->extras.end_offset = tokens[i].end;
3607
3608 if (tokens[i].type == JSMN_OBJECT)
3609 {
3610 int extras_size = tokens[i].size;
3611 ++i;
3612
3613 for (int k = 0; k < extras_size; ++k)
3614 {
3615 CGLTF_CHECK_KEY(tokens[i]);
3616
3617 if (cgltf_json_strcmp(tokens+i, json_chunk, "targetNames") == 0 && tokens[i+1].type == JSMN_ARRAY)
3618 {
3619 i = cgltf_parse_json_string_array(options, tokens, i + 1, json_chunk, &out_mesh->target_names, &out_mesh->target_names_count);
3620 }
3621 else
3622 {
3623 i = cgltf_skip_json(tokens, i+1);
3624 }
3625
3626 if (i < 0)
3627 {
3628 return i;
3629 }
3630 }
3631 }
3632 else
3633 {
3634 i = cgltf_skip_json(tokens, i);
3635 }
3636 }
3637 else if (cgltf_json_strcmp(tokens + i, json_chunk, "extensions") == 0)
3638 {
3639 i = cgltf_parse_json_unprocessed_extensions(options, tokens, i, json_chunk, &out_mesh->extensions_count, &out_mesh->extensions);
3640 }
3641 else
3642 {
3643 i = cgltf_skip_json(tokens, i+1);
3644 }
3645
3646 if (i < 0)
3647 {
3648 return i;
3649 }
3650 }
3651
3652 return i;
3653}
3654
3655static int cgltf_parse_json_meshes(cgltf_options* options, jsmntok_t const* tokens, int i, const uint8_t* json_chunk, cgltf_data* out_data)
3656{
3657 i = cgltf_parse_json_array(options, tokens, i, json_chunk, sizeof(cgltf_mesh), (void**)&out_data->meshes, &out_data->meshes_count);
3658 if (i < 0)
3659 {
3660 return i;
3661 }
3662
3663 for (cgltf_size j = 0; j < out_data->meshes_count; ++j)
3664 {
3665 i = cgltf_parse_json_mesh(options, tokens, i, json_chunk, &out_data->meshes[j]);
3666 if (i < 0)
3667 {
3668 return i;
3669 }
3670 }
3671 return i;
3672}
3673
3674static cgltf_component_type cgltf_json_to_component_type(jsmntok_t const* tok, const uint8_t* json_chunk)
3675{
3676 int type = cgltf_json_to_int(tok, json_chunk);
3677
3678 switch (type)
3679 {
3680 case 5120:
3682 case 5121:
3684 case 5122:
3686 case 5123:
3688 case 5125:
3690 case 5126:
3692 default:
3694 }
3695}
3696
3697static int cgltf_parse_json_accessor_sparse(jsmntok_t const* tokens, int i, const uint8_t* json_chunk, cgltf_accessor_sparse* out_sparse)
3698{
3699 CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
3700
3701 int size = tokens[i].size;
3702 ++i;
3703
3704 for (int j = 0; j < size; ++j)
3705 {
3706 CGLTF_CHECK_KEY(tokens[i]);
3707
3708 if (cgltf_json_strcmp(tokens+i, json_chunk, "count") == 0)
3709 {
3710 ++i;
3711 out_sparse->count = cgltf_json_to_size(tokens + i, json_chunk);
3712 ++i;
3713 }
3714 else if (cgltf_json_strcmp(tokens+i, json_chunk, "indices") == 0)
3715 {
3716 ++i;
3717 CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
3718
3719 int indices_size = tokens[i].size;
3720 ++i;
3721
3722 for (int k = 0; k < indices_size; ++k)
3723 {
3724 CGLTF_CHECK_KEY(tokens[i]);
3725
3726 if (cgltf_json_strcmp(tokens+i, json_chunk, "bufferView") == 0)
3727 {
3728 ++i;
3729 out_sparse->indices_buffer_view = CGLTF_PTRINDEX(cgltf_buffer_view, cgltf_json_to_int(tokens + i, json_chunk));
3730 ++i;
3731 }
3732 else if (cgltf_json_strcmp(tokens+i, json_chunk, "byteOffset") == 0)
3733 {
3734 ++i;
3735 out_sparse->indices_byte_offset = cgltf_json_to_size(tokens + i, json_chunk);
3736 ++i;
3737 }
3738 else if (cgltf_json_strcmp(tokens+i, json_chunk, "componentType") == 0)
3739 {
3740 ++i;
3741 out_sparse->indices_component_type = cgltf_json_to_component_type(tokens + i, json_chunk);
3742 ++i;
3743 }
3744 else
3745 {
3746 i = cgltf_skip_json(tokens, i+1);
3747 }
3748
3749 if (i < 0)
3750 {
3751 return i;
3752 }
3753 }
3754 }
3755 else if (cgltf_json_strcmp(tokens+i, json_chunk, "values") == 0)
3756 {
3757 ++i;
3758 CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
3759
3760 int values_size = tokens[i].size;
3761 ++i;
3762
3763 for (int k = 0; k < values_size; ++k)
3764 {
3765 CGLTF_CHECK_KEY(tokens[i]);
3766
3767 if (cgltf_json_strcmp(tokens+i, json_chunk, "bufferView") == 0)
3768 {
3769 ++i;
3770 out_sparse->values_buffer_view = CGLTF_PTRINDEX(cgltf_buffer_view, cgltf_json_to_int(tokens + i, json_chunk));
3771 ++i;
3772 }
3773 else if (cgltf_json_strcmp(tokens+i, json_chunk, "byteOffset") == 0)
3774 {
3775 ++i;
3776 out_sparse->values_byte_offset = cgltf_json_to_size(tokens + i, json_chunk);
3777 ++i;
3778 }
3779 else
3780 {
3781 i = cgltf_skip_json(tokens, i+1);
3782 }
3783
3784 if (i < 0)
3785 {
3786 return i;
3787 }
3788 }
3789 }
3790 else
3791 {
3792 i = cgltf_skip_json(tokens, i+1);
3793 }
3794
3795 if (i < 0)
3796 {
3797 return i;
3798 }
3799 }
3800
3801 return i;
3802}
3803
3804static int cgltf_parse_json_accessor(cgltf_options* options, jsmntok_t const* tokens, int i, const uint8_t* json_chunk, cgltf_accessor* out_accessor)
3805{
3806 CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
3807
3808 int size = tokens[i].size;
3809 ++i;
3810
3811 for (int j = 0; j < size; ++j)
3812 {
3813 CGLTF_CHECK_KEY(tokens[i]);
3814
3815 if (cgltf_json_strcmp(tokens + i, json_chunk, "name") == 0)
3816 {
3817 i = cgltf_parse_json_string(options, tokens, i + 1, json_chunk, &out_accessor->name);
3818 }
3819 else if (cgltf_json_strcmp(tokens+i, json_chunk, "bufferView") == 0)
3820 {
3821 ++i;
3822 out_accessor->buffer_view = CGLTF_PTRINDEX(cgltf_buffer_view, cgltf_json_to_int(tokens + i, json_chunk));
3823 ++i;
3824 }
3825 else if (cgltf_json_strcmp(tokens+i, json_chunk, "byteOffset") == 0)
3826 {
3827 ++i;
3828 out_accessor->offset =
3829 cgltf_json_to_size(tokens+i, json_chunk);
3830 ++i;
3831 }
3832 else if (cgltf_json_strcmp(tokens+i, json_chunk, "componentType") == 0)
3833 {
3834 ++i;
3835 out_accessor->component_type = cgltf_json_to_component_type(tokens + i, json_chunk);
3836 ++i;
3837 }
3838 else if (cgltf_json_strcmp(tokens+i, json_chunk, "normalized") == 0)
3839 {
3840 ++i;
3841 out_accessor->normalized = cgltf_json_to_bool(tokens+i, json_chunk);
3842 ++i;
3843 }
3844 else if (cgltf_json_strcmp(tokens+i, json_chunk, "count") == 0)
3845 {
3846 ++i;
3847 out_accessor->count = cgltf_json_to_size(tokens+i, json_chunk);
3848 ++i;
3849 }
3850 else if (cgltf_json_strcmp(tokens+i, json_chunk, "type") == 0)
3851 {
3852 ++i;
3853 if (cgltf_json_strcmp(tokens+i, json_chunk, "SCALAR") == 0)
3854 {
3855 out_accessor->type = cgltf_type_scalar;
3856 }
3857 else if (cgltf_json_strcmp(tokens+i, json_chunk, "VEC2") == 0)
3858 {
3859 out_accessor->type = cgltf_type_vec2;
3860 }
3861 else if (cgltf_json_strcmp(tokens+i, json_chunk, "VEC3") == 0)
3862 {
3863 out_accessor->type = cgltf_type_vec3;
3864 }
3865 else if (cgltf_json_strcmp(tokens+i, json_chunk, "VEC4") == 0)
3866 {
3867 out_accessor->type = cgltf_type_vec4;
3868 }
3869 else if (cgltf_json_strcmp(tokens+i, json_chunk, "MAT2") == 0)
3870 {
3871 out_accessor->type = cgltf_type_mat2;
3872 }
3873 else if (cgltf_json_strcmp(tokens+i, json_chunk, "MAT3") == 0)
3874 {
3875 out_accessor->type = cgltf_type_mat3;
3876 }
3877 else if (cgltf_json_strcmp(tokens+i, json_chunk, "MAT4") == 0)
3878 {
3879 out_accessor->type = cgltf_type_mat4;
3880 }
3881 ++i;
3882 }
3883 else if (cgltf_json_strcmp(tokens + i, json_chunk, "min") == 0)
3884 {
3885 ++i;
3886 out_accessor->has_min = 1;
3887 // note: we can't parse the precise number of elements since type may not have been computed yet
3888 int min_size = tokens[i].size > 16 ? 16 : tokens[i].size;
3889 i = cgltf_parse_json_float_array(tokens, i, json_chunk, out_accessor->min, min_size);
3890 }
3891 else if (cgltf_json_strcmp(tokens + i, json_chunk, "max") == 0)
3892 {
3893 ++i;
3894 out_accessor->has_max = 1;
3895 // note: we can't parse the precise number of elements since type may not have been computed yet
3896 int max_size = tokens[i].size > 16 ? 16 : tokens[i].size;
3897 i = cgltf_parse_json_float_array(tokens, i, json_chunk, out_accessor->max, max_size);
3898 }
3899 else if (cgltf_json_strcmp(tokens + i, json_chunk, "sparse") == 0)
3900 {
3901 out_accessor->is_sparse = 1;
3902 i = cgltf_parse_json_accessor_sparse(tokens, i + 1, json_chunk, &out_accessor->sparse);
3903 }
3904 else if (cgltf_json_strcmp(tokens + i, json_chunk, "extras") == 0)
3905 {
3906 i = cgltf_parse_json_extras(options, tokens, i + 1, json_chunk, &out_accessor->extras);
3907 }
3908 else if (cgltf_json_strcmp(tokens + i, json_chunk, "extensions") == 0)
3909 {
3910 i = cgltf_parse_json_unprocessed_extensions(options, tokens, i, json_chunk, &out_accessor->extensions_count, &out_accessor->extensions);
3911 }
3912 else
3913 {
3914 i = cgltf_skip_json(tokens, i+1);
3915 }
3916
3917 if (i < 0)
3918 {
3919 return i;
3920 }
3921 }
3922
3923 return i;
3924}
3925
3926static int cgltf_parse_json_texture_transform(jsmntok_t const* tokens, int i, const uint8_t* json_chunk, cgltf_texture_transform* out_texture_transform)
3927{
3928 CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
3929
3930 int size = tokens[i].size;
3931 ++i;
3932
3933 for (int j = 0; j < size; ++j)
3934 {
3935 CGLTF_CHECK_KEY(tokens[i]);
3936
3937 if (cgltf_json_strcmp(tokens + i, json_chunk, "offset") == 0)
3938 {
3939 i = cgltf_parse_json_float_array(tokens, i + 1, json_chunk, out_texture_transform->offset, 2);
3940 }
3941 else if (cgltf_json_strcmp(tokens + i, json_chunk, "rotation") == 0)
3942 {
3943 ++i;
3944 out_texture_transform->rotation = cgltf_json_to_float(tokens + i, json_chunk);
3945 ++i;
3946 }
3947 else if (cgltf_json_strcmp(tokens + i, json_chunk, "scale") == 0)
3948 {
3949 i = cgltf_parse_json_float_array(tokens, i + 1, json_chunk, out_texture_transform->scale, 2);
3950 }
3951 else if (cgltf_json_strcmp(tokens + i, json_chunk, "texCoord") == 0)
3952 {
3953 ++i;
3954 out_texture_transform->has_texcoord = 1;
3955 out_texture_transform->texcoord = cgltf_json_to_int(tokens + i, json_chunk);
3956 ++i;
3957 }
3958 else
3959 {
3960 i = cgltf_skip_json(tokens, i + 1);
3961 }
3962
3963 if (i < 0)
3964 {
3965 return i;
3966 }
3967 }
3968
3969 return i;
3970}
3971
3972static 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)
3973{
3974 (void)options;
3975
3976 CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
3977
3978 out_texture_view->scale = 1.0f;
3979 cgltf_fill_float_array(out_texture_view->transform.scale, 2, 1.0f);
3980
3981 int size = tokens[i].size;
3982 ++i;
3983
3984 for (int j = 0; j < size; ++j)
3985 {
3986 CGLTF_CHECK_KEY(tokens[i]);
3987
3988 if (cgltf_json_strcmp(tokens + i, json_chunk, "index") == 0)
3989 {
3990 ++i;
3991 out_texture_view->texture = CGLTF_PTRINDEX(cgltf_texture, cgltf_json_to_int(tokens + i, json_chunk));
3992 ++i;
3993 }
3994 else if (cgltf_json_strcmp(tokens + i, json_chunk, "texCoord") == 0)
3995 {
3996 ++i;
3997 out_texture_view->texcoord = cgltf_json_to_int(tokens + i, json_chunk);
3998 ++i;
3999 }
4000 else if (cgltf_json_strcmp(tokens + i, json_chunk, "scale") == 0)
4001 {
4002 ++i;
4003 out_texture_view->scale = cgltf_json_to_float(tokens + i, json_chunk);
4004 ++i;
4005 }
4006 else if (cgltf_json_strcmp(tokens + i, json_chunk, "strength") == 0)
4007 {
4008 ++i;
4009 out_texture_view->scale = cgltf_json_to_float(tokens + i, json_chunk);
4010 ++i;
4011 }
4012 else if (cgltf_json_strcmp(tokens + i, json_chunk, "extensions") == 0)
4013 {
4014 ++i;
4015
4016 CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
4017 int extensions_size = tokens[i].size;
4018
4019 ++i;
4020
4021 for (int k = 0; k < extensions_size; ++k)
4022 {
4023 CGLTF_CHECK_KEY(tokens[i]);
4024
4025 if (cgltf_json_strcmp(tokens+i, json_chunk, "KHR_texture_transform") == 0)
4026 {
4027 out_texture_view->has_transform = 1;
4028 i = cgltf_parse_json_texture_transform(tokens, i + 1, json_chunk, &out_texture_view->transform);
4029 }
4030 else
4031 {
4032 i = cgltf_skip_json(tokens, i + 1);
4033 }
4034
4035 if (i < 0)
4036 {
4037 return i;
4038 }
4039 }
4040 }
4041 else
4042 {
4043 i = cgltf_skip_json(tokens, i + 1);
4044 }
4045
4046 if (i < 0)
4047 {
4048 return i;
4049 }
4050 }
4051
4052 return i;
4053}
4054
4055static 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)
4056{
4057 CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
4058
4059 int size = tokens[i].size;
4060 ++i;
4061
4062 for (int j = 0; j < size; ++j)
4063 {
4064 CGLTF_CHECK_KEY(tokens[i]);
4065
4066 if (cgltf_json_strcmp(tokens+i, json_chunk, "metallicFactor") == 0)
4067 {
4068 ++i;
4069 out_pbr->metallic_factor =
4070 cgltf_json_to_float(tokens + i, json_chunk);
4071 ++i;
4072 }
4073 else if (cgltf_json_strcmp(tokens+i, json_chunk, "roughnessFactor") == 0)
4074 {
4075 ++i;
4076 out_pbr->roughness_factor =
4077 cgltf_json_to_float(tokens+i, json_chunk);
4078 ++i;
4079 }
4080 else if (cgltf_json_strcmp(tokens+i, json_chunk, "baseColorFactor") == 0)
4081 {
4082 i = cgltf_parse_json_float_array(tokens, i + 1, json_chunk, out_pbr->base_color_factor, 4);
4083 }
4084 else if (cgltf_json_strcmp(tokens+i, json_chunk, "baseColorTexture") == 0)
4085 {
4086 i = cgltf_parse_json_texture_view(options, tokens, i + 1, json_chunk, &out_pbr->base_color_texture);
4087 }
4088 else if (cgltf_json_strcmp(tokens + i, json_chunk, "metallicRoughnessTexture") == 0)
4089 {
4090 i = cgltf_parse_json_texture_view(options, tokens, i + 1, json_chunk, &out_pbr->metallic_roughness_texture);
4091 }
4092 else
4093 {
4094 i = cgltf_skip_json(tokens, i+1);
4095 }
4096
4097 if (i < 0)
4098 {
4099 return i;
4100 }
4101 }
4102
4103 return i;
4104}
4105
4106static 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)
4107{
4108 CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
4109 int size = tokens[i].size;
4110 ++i;
4111
4112 for (int j = 0; j < size; ++j)
4113 {
4114 CGLTF_CHECK_KEY(tokens[i]);
4115
4116 if (cgltf_json_strcmp(tokens+i, json_chunk, "diffuseFactor") == 0)
4117 {
4118 i = cgltf_parse_json_float_array(tokens, i + 1, json_chunk, out_pbr->diffuse_factor, 4);
4119 }
4120 else if (cgltf_json_strcmp(tokens+i, json_chunk, "specularFactor") == 0)
4121 {
4122 i = cgltf_parse_json_float_array(tokens, i + 1, json_chunk, out_pbr->specular_factor, 3);
4123 }
4124 else if (cgltf_json_strcmp(tokens+i, json_chunk, "glossinessFactor") == 0)
4125 {
4126 ++i;
4127 out_pbr->glossiness_factor = cgltf_json_to_float(tokens + i, json_chunk);
4128 ++i;
4129 }
4130 else if (cgltf_json_strcmp(tokens+i, json_chunk, "diffuseTexture") == 0)
4131 {
4132 i = cgltf_parse_json_texture_view(options, tokens, i + 1, json_chunk, &out_pbr->diffuse_texture);
4133 }
4134 else if (cgltf_json_strcmp(tokens+i, json_chunk, "specularGlossinessTexture") == 0)
4135 {
4136 i = cgltf_parse_json_texture_view(options, tokens, i + 1, json_chunk, &out_pbr->specular_glossiness_texture);
4137 }
4138 else
4139 {
4140 i = cgltf_skip_json(tokens, i+1);
4141 }
4142
4143 if (i < 0)
4144 {
4145 return i;
4146 }
4147 }
4148
4149 return i;
4150}
4151
4152static int cgltf_parse_json_clearcoat(cgltf_options* options, jsmntok_t const* tokens, int i, const uint8_t* json_chunk, cgltf_clearcoat* out_clearcoat)
4153{
4154 CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
4155 int size = tokens[i].size;
4156 ++i;
4157
4158 for (int j = 0; j < size; ++j)
4159 {
4160 CGLTF_CHECK_KEY(tokens[i]);
4161
4162 if (cgltf_json_strcmp(tokens+i, json_chunk, "clearcoatFactor") == 0)
4163 {
4164 ++i;
4165 out_clearcoat->clearcoat_factor = cgltf_json_to_float(tokens + i, json_chunk);
4166 ++i;
4167 }
4168 else if (cgltf_json_strcmp(tokens+i, json_chunk, "clearcoatRoughnessFactor") == 0)
4169 {
4170 ++i;
4171 out_clearcoat->clearcoat_roughness_factor = cgltf_json_to_float(tokens + i, json_chunk);
4172 ++i;
4173 }
4174 else if (cgltf_json_strcmp(tokens+i, json_chunk, "clearcoatTexture") == 0)
4175 {
4176 i = cgltf_parse_json_texture_view(options, tokens, i + 1, json_chunk, &out_clearcoat->clearcoat_texture);
4177 }
4178 else if (cgltf_json_strcmp(tokens+i, json_chunk, "clearcoatRoughnessTexture") == 0)
4179 {
4180 i = cgltf_parse_json_texture_view(options, tokens, i + 1, json_chunk, &out_clearcoat->clearcoat_roughness_texture);
4181 }
4182 else if (cgltf_json_strcmp(tokens+i, json_chunk, "clearcoatNormalTexture") == 0)
4183 {
4184 i = cgltf_parse_json_texture_view(options, tokens, i + 1, json_chunk, &out_clearcoat->clearcoat_normal_texture);
4185 }
4186 else
4187 {
4188 i = cgltf_skip_json(tokens, i+1);
4189 }
4190
4191 if (i < 0)
4192 {
4193 return i;
4194 }
4195 }
4196
4197 return i;
4198}
4199
4200static int cgltf_parse_json_ior(jsmntok_t const* tokens, int i, const uint8_t* json_chunk, cgltf_ior* out_ior)
4201{
4202 CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
4203 int size = tokens[i].size;
4204 ++i;
4205
4206 // Default values
4207 out_ior->ior = 1.5f;
4208
4209 for (int j = 0; j < size; ++j)
4210 {
4211 CGLTF_CHECK_KEY(tokens[i]);
4212
4213 if (cgltf_json_strcmp(tokens+i, json_chunk, "ior") == 0)
4214 {
4215 ++i;
4216 out_ior->ior = cgltf_json_to_float(tokens + i, json_chunk);
4217 ++i;
4218 }
4219 else
4220 {
4221 i = cgltf_skip_json(tokens, i+1);
4222 }
4223
4224 if (i < 0)
4225 {
4226 return i;
4227 }
4228 }
4229
4230 return i;
4231}
4232
4233static int cgltf_parse_json_specular(cgltf_options* options, jsmntok_t const* tokens, int i, const uint8_t* json_chunk, cgltf_specular* out_specular)
4234{
4235 CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
4236 int size = tokens[i].size;
4237 ++i;
4238
4239 // Default values
4240 out_specular->specular_factor = 1.0f;
4241 cgltf_fill_float_array(out_specular->specular_color_factor, 3, 1.0f);
4242
4243 for (int j = 0; j < size; ++j)
4244 {
4245 CGLTF_CHECK_KEY(tokens[i]);
4246
4247 if (cgltf_json_strcmp(tokens+i, json_chunk, "specularFactor") == 0)
4248 {
4249 ++i;
4250 out_specular->specular_factor = cgltf_json_to_float(tokens + i, json_chunk);
4251 ++i;
4252 }
4253 else if (cgltf_json_strcmp(tokens+i, json_chunk, "specularColorFactor") == 0)
4254 {
4255 i = cgltf_parse_json_float_array(tokens, i + 1, json_chunk, out_specular->specular_color_factor, 3);
4256 }
4257 else if (cgltf_json_strcmp(tokens+i, json_chunk, "specularTexture") == 0)
4258 {
4259 i = cgltf_parse_json_texture_view(options, tokens, i + 1, json_chunk, &out_specular->specular_texture);
4260 }
4261 else if (cgltf_json_strcmp(tokens + i, json_chunk, "specularColorTexture") == 0)
4262 {
4263 i = cgltf_parse_json_texture_view(options, tokens, i + 1, json_chunk, &out_specular->specular_color_texture);
4264 }
4265 else
4266 {
4267 i = cgltf_skip_json(tokens, i+1);
4268 }
4269
4270 if (i < 0)
4271 {
4272 return i;
4273 }
4274 }
4275
4276 return i;
4277}
4278
4279static int cgltf_parse_json_transmission(cgltf_options* options, jsmntok_t const* tokens, int i, const uint8_t* json_chunk, cgltf_transmission* out_transmission)
4280{
4281 CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
4282 int size = tokens[i].size;
4283 ++i;
4284
4285 for (int j = 0; j < size; ++j)
4286 {
4287 CGLTF_CHECK_KEY(tokens[i]);
4288
4289 if (cgltf_json_strcmp(tokens+i, json_chunk, "transmissionFactor") == 0)
4290 {
4291 ++i;
4292 out_transmission->transmission_factor = cgltf_json_to_float(tokens + i, json_chunk);
4293 ++i;
4294 }
4295 else if (cgltf_json_strcmp(tokens+i, json_chunk, "transmissionTexture") == 0)
4296 {
4297 i = cgltf_parse_json_texture_view(options, tokens, i + 1, json_chunk, &out_transmission->transmission_texture);
4298 }
4299 else
4300 {
4301 i = cgltf_skip_json(tokens, i+1);
4302 }
4303
4304 if (i < 0)
4305 {
4306 return i;
4307 }
4308 }
4309
4310 return i;
4311}
4312
4313static int cgltf_parse_json_volume(cgltf_options* options, jsmntok_t const* tokens, int i, const uint8_t* json_chunk, cgltf_volume* out_volume)
4314{
4315 CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
4316 int size = tokens[i].size;
4317 ++i;
4318
4319 for (int j = 0; j < size; ++j)
4320 {
4321 CGLTF_CHECK_KEY(tokens[i]);
4322
4323 if (cgltf_json_strcmp(tokens + i, json_chunk, "thicknessFactor") == 0)
4324 {
4325 ++i;
4326 out_volume->thickness_factor = cgltf_json_to_float(tokens + i, json_chunk);
4327 ++i;
4328 }
4329 else if (cgltf_json_strcmp(tokens + i, json_chunk, "thicknessTexture") == 0)
4330 {
4331 i = cgltf_parse_json_texture_view(options, tokens, i + 1, json_chunk, &out_volume->thickness_texture);
4332 }
4333 else if (cgltf_json_strcmp(tokens + i, json_chunk, "attenuationColor") == 0)
4334 {
4335 i = cgltf_parse_json_float_array(tokens, i + 1, json_chunk, out_volume->attenuation_color, 3);
4336 }
4337 else if (cgltf_json_strcmp(tokens + i, json_chunk, "attenuationDistance") == 0)
4338 {
4339 ++i;
4340 out_volume->attenuation_distance = cgltf_json_to_float(tokens + i, json_chunk);
4341 ++i;
4342 }
4343 else
4344 {
4345 i = cgltf_skip_json(tokens, i + 1);
4346 }
4347
4348 if (i < 0)
4349 {
4350 return i;
4351 }
4352 }
4353
4354 return i;
4355}
4356
4357static int cgltf_parse_json_sheen(cgltf_options* options, jsmntok_t const* tokens, int i, const uint8_t* json_chunk, cgltf_sheen* out_sheen)
4358{
4359 CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
4360 int size = tokens[i].size;
4361 ++i;
4362
4363 for (int j = 0; j < size; ++j)
4364 {
4365 CGLTF_CHECK_KEY(tokens[i]);
4366
4367 if (cgltf_json_strcmp(tokens+i, json_chunk, "sheenColorFactor") == 0)
4368 {
4369 i = cgltf_parse_json_float_array(tokens, i + 1, json_chunk, out_sheen->sheen_color_factor, 3);
4370 }
4371 else if (cgltf_json_strcmp(tokens+i, json_chunk, "sheenColorTexture") == 0)
4372 {
4373 i = cgltf_parse_json_texture_view(options, tokens, i + 1, json_chunk, &out_sheen->sheen_color_texture);
4374 }
4375 else if (cgltf_json_strcmp(tokens+i, json_chunk, "sheenRoughnessFactor") == 0)
4376 {
4377 ++i;
4378 out_sheen->sheen_roughness_factor = cgltf_json_to_float(tokens + i, json_chunk);
4379 ++i;
4380 }
4381 else if (cgltf_json_strcmp(tokens+i, json_chunk, "sheenRoughnessTexture") == 0)
4382 {
4383 i = cgltf_parse_json_texture_view(options, tokens, i + 1, json_chunk, &out_sheen->sheen_roughness_texture);
4384 }
4385 else
4386 {
4387 i = cgltf_skip_json(tokens, i+1);
4388 }
4389
4390 if (i < 0)
4391 {
4392 return i;
4393 }
4394 }
4395
4396 return i;
4397}
4398
4399static int cgltf_parse_json_emissive_strength(jsmntok_t const* tokens, int i, const uint8_t* json_chunk, cgltf_emissive_strength* out_emissive_strength)
4400{
4401 CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
4402 int size = tokens[i].size;
4403 ++i;
4404
4405 // Default
4406 out_emissive_strength->emissive_strength = 1.f;
4407
4408 for (int j = 0; j < size; ++j)
4409 {
4410 CGLTF_CHECK_KEY(tokens[i]);
4411
4412 if (cgltf_json_strcmp(tokens + i, json_chunk, "emissiveStrength") == 0)
4413 {
4414 ++i;
4415 out_emissive_strength->emissive_strength = cgltf_json_to_float(tokens + i, json_chunk);
4416 ++i;
4417 }
4418 else
4419 {
4420 i = cgltf_skip_json(tokens, i + 1);
4421 }
4422
4423 if (i < 0)
4424 {
4425 return i;
4426 }
4427 }
4428
4429 return i;
4430}
4431
4432static int cgltf_parse_json_iridescence(cgltf_options* options, jsmntok_t const* tokens, int i, const uint8_t* json_chunk, cgltf_iridescence* out_iridescence)
4433{
4434 CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
4435 int size = tokens[i].size;
4436 ++i;
4437
4438 // Default
4439 out_iridescence->iridescence_ior = 1.3f;
4440 out_iridescence->iridescence_thickness_min = 100.f;
4441 out_iridescence->iridescence_thickness_max = 400.f;
4442
4443 for (int j = 0; j < size; ++j)
4444 {
4445 CGLTF_CHECK_KEY(tokens[i]);
4446
4447 if (cgltf_json_strcmp(tokens + i, json_chunk, "iridescenceFactor") == 0)
4448 {
4449 ++i;
4450 out_iridescence->iridescence_factor = cgltf_json_to_float(tokens + i, json_chunk);
4451 ++i;
4452 }
4453 else if (cgltf_json_strcmp(tokens + i, json_chunk, "iridescenceTexture") == 0)
4454 {
4455 i = cgltf_parse_json_texture_view(options, tokens, i + 1, json_chunk, &out_iridescence->iridescence_texture);
4456 }
4457 else if (cgltf_json_strcmp(tokens + i, json_chunk, "iridescenceIor") == 0)
4458 {
4459 ++i;
4460 out_iridescence->iridescence_ior = cgltf_json_to_float(tokens + i, json_chunk);
4461 ++i;
4462 }
4463 else if (cgltf_json_strcmp(tokens + i, json_chunk, "iridescenceThicknessMinimum") == 0)
4464 {
4465 ++i;
4466 out_iridescence->iridescence_thickness_min = cgltf_json_to_float(tokens + i, json_chunk);
4467 ++i;
4468 }
4469 else if (cgltf_json_strcmp(tokens + i, json_chunk, "iridescenceThicknessMaximum") == 0)
4470 {
4471 ++i;
4472 out_iridescence->iridescence_thickness_max = cgltf_json_to_float(tokens + i, json_chunk);
4473 ++i;
4474 }
4475 else if (cgltf_json_strcmp(tokens + i, json_chunk, "iridescenceThicknessTexture") == 0)
4476 {
4477 i = cgltf_parse_json_texture_view(options, tokens, i + 1, json_chunk, &out_iridescence->iridescence_thickness_texture);
4478 }
4479 else
4480 {
4481 i = cgltf_skip_json(tokens, i + 1);
4482 }
4483
4484 if (i < 0)
4485 {
4486 return i;
4487 }
4488 }
4489
4490 return i;
4491}
4492
4493static int cgltf_parse_json_diffuse_transmission(cgltf_options* options, jsmntok_t const* tokens, int i, const uint8_t* json_chunk, cgltf_diffuse_transmission* out_diff_transmission)
4494{
4495 CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
4496 int size = tokens[i].size;
4497 ++i;
4498
4499 // Defaults
4500 cgltf_fill_float_array(out_diff_transmission->diffuse_transmission_color_factor, 3, 1.0f);
4501 out_diff_transmission->diffuse_transmission_factor = 0.f;
4502
4503 for (int j = 0; j < size; ++j)
4504 {
4505 CGLTF_CHECK_KEY(tokens[i]);
4506
4507 if (cgltf_json_strcmp(tokens + i, json_chunk, "diffuseTransmissionFactor") == 0)
4508 {
4509 ++i;
4510 out_diff_transmission->diffuse_transmission_factor = cgltf_json_to_float(tokens + i, json_chunk);
4511 ++i;
4512 }
4513 else if (cgltf_json_strcmp(tokens + i, json_chunk, "diffuseTransmissionTexture") == 0)
4514 {
4515 i = cgltf_parse_json_texture_view(options, tokens, i + 1, json_chunk, &out_diff_transmission->diffuse_transmission_texture);
4516 }
4517 else if (cgltf_json_strcmp(tokens + i, json_chunk, "diffuseTransmissionColorFactor") == 0)
4518 {
4519 i = cgltf_parse_json_float_array(tokens, i + 1, json_chunk, out_diff_transmission->diffuse_transmission_color_factor, 3);
4520 }
4521 else if (cgltf_json_strcmp(tokens + i, json_chunk, "diffuseTransmissionColorTexture") == 0)
4522 {
4523 i = cgltf_parse_json_texture_view(options, tokens, i + 1, json_chunk, &out_diff_transmission->diffuse_transmission_color_texture);
4524 }
4525 else
4526 {
4527 i = cgltf_skip_json(tokens, i + 1);
4528 }
4529
4530 if (i < 0)
4531 {
4532 return i;
4533 }
4534 }
4535
4536 return i;
4537}
4538
4539static int cgltf_parse_json_subsurface(cgltf_options* options, jsmntok_t const* tokens, int i, const uint8_t* json_chunk, cgltf_subsurface* out_subsurface)
4540{
4541 CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
4542 int size = tokens[i].size;
4543 ++i;
4544
4545 // Defaults mirror EXT_materials_subsurface.md.
4546 out_subsurface->subsurface_weight = 0.f;
4547 cgltf_fill_float_array(out_subsurface->subsurface_radius, 3, 1.0f);
4548 out_subsurface->subsurface_radius[1] = 0.2f;
4549 out_subsurface->subsurface_radius[2] = 0.1f;
4550 out_subsurface->subsurface_scale = 0.05f;
4551
4552 for (int j = 0; j < size; ++j)
4553 {
4554 CGLTF_CHECK_KEY(tokens[i]);
4555
4556 if (cgltf_json_strcmp(tokens + i, json_chunk, "subsurfaceMethod") == 0)
4557 {
4558 i = cgltf_parse_json_string(options, tokens, i + 1, json_chunk, &out_subsurface->subsurface_method);
4559 }
4560 else if (cgltf_json_strcmp(tokens + i, json_chunk, "subsurfaceWeight") == 0)
4561 {
4562 ++i;
4563 out_subsurface->subsurface_weight = cgltf_json_to_float(tokens + i, json_chunk);
4564 ++i;
4565 }
4566 else if (cgltf_json_strcmp(tokens + i, json_chunk, "subsurfaceRadius") == 0)
4567 {
4568 i = cgltf_parse_json_float_array(tokens, i + 1, json_chunk, out_subsurface->subsurface_radius, 3);
4569 }
4570 else if (cgltf_json_strcmp(tokens + i, json_chunk, "subsurfaceScale") == 0)
4571 {
4572 ++i;
4573 out_subsurface->subsurface_scale = cgltf_json_to_float(tokens + i, json_chunk);
4574 ++i;
4575 }
4576 else
4577 {
4578 i = cgltf_skip_json(tokens, i + 1);
4579 }
4580
4581 if (i < 0)
4582 {
4583 return i;
4584 }
4585 }
4586
4587 return i;
4588}
4589
4590static int cgltf_parse_json_anisotropy(cgltf_options* options, jsmntok_t const* tokens, int i, const uint8_t* json_chunk, cgltf_anisotropy* out_anisotropy)
4591{
4592 CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
4593 int size = tokens[i].size;
4594 ++i;
4595
4596
4597 for (int j = 0; j < size; ++j)
4598 {
4599 CGLTF_CHECK_KEY(tokens[i]);
4600
4601 if (cgltf_json_strcmp(tokens + i, json_chunk, "anisotropyStrength") == 0)
4602 {
4603 ++i;
4604 out_anisotropy->anisotropy_strength = cgltf_json_to_float(tokens + i, json_chunk);
4605 ++i;
4606 }
4607 else if (cgltf_json_strcmp(tokens + i, json_chunk, "anisotropyRotation") == 0)
4608 {
4609 ++i;
4610 out_anisotropy->anisotropy_rotation = cgltf_json_to_float(tokens + i, json_chunk);
4611 ++i;
4612 }
4613 else if (cgltf_json_strcmp(tokens + i, json_chunk, "anisotropyTexture") == 0)
4614 {
4615 i = cgltf_parse_json_texture_view(options, tokens, i + 1, json_chunk, &out_anisotropy->anisotropy_texture);
4616 }
4617 else
4618 {
4619 i = cgltf_skip_json(tokens, i + 1);
4620 }
4621
4622 if (i < 0)
4623 {
4624 return i;
4625 }
4626 }
4627
4628 return i;
4629}
4630
4631static int cgltf_parse_json_dispersion(jsmntok_t const* tokens, int i, const uint8_t* json_chunk, cgltf_dispersion* out_dispersion)
4632{
4633 CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
4634 int size = tokens[i].size;
4635 ++i;
4636
4637
4638 for (int j = 0; j < size; ++j)
4639 {
4640 CGLTF_CHECK_KEY(tokens[i]);
4641
4642 if (cgltf_json_strcmp(tokens + i, json_chunk, "dispersion") == 0)
4643 {
4644 ++i;
4645 out_dispersion->dispersion = cgltf_json_to_float(tokens + i, json_chunk);
4646 ++i;
4647 }
4648 else
4649 {
4650 i = cgltf_skip_json(tokens, i + 1);
4651 }
4652
4653 if (i < 0)
4654 {
4655 return i;
4656 }
4657 }
4658
4659 return i;
4660}
4661
4662static int cgltf_parse_json_foundation_materials(jsmntok_t const* tokens, int i, const uint8_t* json_chunk, cgltf_foundation_materials* out_materials)
4663{
4664 CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
4665
4668
4669 int size = tokens[i].size;
4670 ++i;
4671
4672 for (int j = 0; j < size; ++j)
4673 {
4674 CGLTF_CHECK_KEY(tokens[i]);
4675
4676 if (cgltf_json_strcmp(tokens + i, json_chunk, "shaderBlock") == 0)
4677 {
4678 ++i;
4679 out_materials->has_shader_block = 1;
4680 if (cgltf_json_strcmp(tokens + i, json_chunk, "principled") == 0)
4681 {
4683 }
4684 else if (cgltf_json_strcmp(tokens + i, json_chunk, "hair") == 0)
4685 {
4687 }
4688 ++i;
4689 }
4690 else if (cgltf_json_strcmp(tokens + i, json_chunk, "model") == 0)
4691 {
4692 ++i;
4693 if (cgltf_json_strcmp(tokens + i, json_chunk, "chiang") == 0)
4694 {
4696 }
4697 else
4698 {
4700 }
4701 ++i;
4702 }
4703 else if (cgltf_json_strcmp(tokens + i, json_chunk, "betaM") == 0)
4704 {
4705 ++i;
4706 out_materials->has_hair_beta_m = 1;
4707 out_materials->hair_beta_m = cgltf_json_to_float(tokens + i, json_chunk);
4708 ++i;
4709 }
4710 else if (cgltf_json_strcmp(tokens + i, json_chunk, "betaN") == 0)
4711 {
4712 ++i;
4713 out_materials->has_hair_beta_n = 1;
4714 out_materials->hair_beta_n = cgltf_json_to_float(tokens + i, json_chunk);
4715 ++i;
4716 }
4717 else if (cgltf_json_strcmp(tokens + i, json_chunk, "alpha") == 0)
4718 {
4719 ++i;
4720 out_materials->has_hair_alpha = 1;
4721 out_materials->hair_alpha = cgltf_json_to_float(tokens + i, json_chunk);
4722 ++i;
4723 }
4724 else if (cgltf_json_strcmp(tokens + i, json_chunk, "ior") == 0)
4725 {
4726 ++i;
4727 out_materials->has_ior = 1;
4728 out_materials->ior = cgltf_json_to_float(tokens + i, json_chunk);
4729 ++i;
4730 }
4731 else
4732 {
4733 i = cgltf_skip_json(tokens, i + 1);
4734 }
4735
4736 if (i < 0)
4737 {
4738 return i;
4739 }
4740 }
4741
4742 return i;
4743}
4744
4745static int cgltf_parse_json_image(cgltf_options* options, jsmntok_t const* tokens, int i, const uint8_t* json_chunk, cgltf_image* out_image)
4746{
4747 CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
4748
4749 int size = tokens[i].size;
4750 ++i;
4751
4752 for (int j = 0; j < size; ++j)
4753 {
4754 CGLTF_CHECK_KEY(tokens[i]);
4755
4756 if (cgltf_json_strcmp(tokens + i, json_chunk, "uri") == 0)
4757 {
4758 i = cgltf_parse_json_string(options, tokens, i + 1, json_chunk, &out_image->uri);
4759 }
4760 else if (cgltf_json_strcmp(tokens+i, json_chunk, "bufferView") == 0)
4761 {
4762 ++i;
4763 out_image->buffer_view = CGLTF_PTRINDEX(cgltf_buffer_view, cgltf_json_to_int(tokens + i, json_chunk));
4764 ++i;
4765 }
4766 else if (cgltf_json_strcmp(tokens + i, json_chunk, "mimeType") == 0)
4767 {
4768 i = cgltf_parse_json_string(options, tokens, i + 1, json_chunk, &out_image->mime_type);
4769 }
4770 else if (cgltf_json_strcmp(tokens + i, json_chunk, "name") == 0)
4771 {
4772 i = cgltf_parse_json_string(options, tokens, i + 1, json_chunk, &out_image->name);
4773 }
4774 else if (cgltf_json_strcmp(tokens + i, json_chunk, "extras") == 0)
4775 {
4776 i = cgltf_parse_json_extras(options, tokens, i + 1, json_chunk, &out_image->extras);
4777 }
4778 else if (cgltf_json_strcmp(tokens + i, json_chunk, "extensions") == 0)
4779 {
4780 i = cgltf_parse_json_unprocessed_extensions(options, tokens, i, json_chunk, &out_image->extensions_count, &out_image->extensions);
4781 }
4782 else
4783 {
4784 i = cgltf_skip_json(tokens, i + 1);
4785 }
4786
4787 if (i < 0)
4788 {
4789 return i;
4790 }
4791 }
4792
4793 return i;
4794}
4795
4796static int cgltf_parse_json_sampler(cgltf_options* options, jsmntok_t const* tokens, int i, const uint8_t* json_chunk, cgltf_sampler* out_sampler)
4797{
4798 (void)options;
4799 CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
4800
4801 out_sampler->wrap_s = cgltf_wrap_mode_repeat;
4802 out_sampler->wrap_t = cgltf_wrap_mode_repeat;
4803
4804 int size = tokens[i].size;
4805 ++i;
4806
4807 for (int j = 0; j < size; ++j)
4808 {
4809 CGLTF_CHECK_KEY(tokens[i]);
4810
4811 if (cgltf_json_strcmp(tokens + i, json_chunk, "name") == 0)
4812 {
4813 i = cgltf_parse_json_string(options, tokens, i + 1, json_chunk, &out_sampler->name);
4814 }
4815 else if (cgltf_json_strcmp(tokens + i, json_chunk, "magFilter") == 0)
4816 {
4817 ++i;
4818 out_sampler->mag_filter
4819 = (cgltf_filter_type)cgltf_json_to_int(tokens + i, json_chunk);
4820 ++i;
4821 }
4822 else if (cgltf_json_strcmp(tokens + i, json_chunk, "minFilter") == 0)
4823 {
4824 ++i;
4825 out_sampler->min_filter
4826 = (cgltf_filter_type)cgltf_json_to_int(tokens + i, json_chunk);
4827 ++i;
4828 }
4829 else if (cgltf_json_strcmp(tokens + i, json_chunk, "wrapS") == 0)
4830 {
4831 ++i;
4832 out_sampler->wrap_s
4833 = (cgltf_wrap_mode)cgltf_json_to_int(tokens + i, json_chunk);
4834 ++i;
4835 }
4836 else if (cgltf_json_strcmp(tokens + i, json_chunk, "wrapT") == 0)
4837 {
4838 ++i;
4839 out_sampler->wrap_t
4840 = (cgltf_wrap_mode)cgltf_json_to_int(tokens + i, json_chunk);
4841 ++i;
4842 }
4843 else if (cgltf_json_strcmp(tokens + i, json_chunk, "extras") == 0)
4844 {
4845 i = cgltf_parse_json_extras(options, tokens, i + 1, json_chunk, &out_sampler->extras);
4846 }
4847 else if (cgltf_json_strcmp(tokens + i, json_chunk, "extensions") == 0)
4848 {
4849 i = cgltf_parse_json_unprocessed_extensions(options, tokens, i, json_chunk, &out_sampler->extensions_count, &out_sampler->extensions);
4850 }
4851 else
4852 {
4853 i = cgltf_skip_json(tokens, i + 1);
4854 }
4855
4856 if (i < 0)
4857 {
4858 return i;
4859 }
4860 }
4861
4862 return i;
4863}
4864
4865static int cgltf_parse_json_texture(cgltf_options* options, jsmntok_t const* tokens, int i, const uint8_t* json_chunk, cgltf_texture* out_texture)
4866{
4867 CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
4868
4869 int size = tokens[i].size;
4870 ++i;
4871
4872 for (int j = 0; j < size; ++j)
4873 {
4874 CGLTF_CHECK_KEY(tokens[i]);
4875
4876 if (cgltf_json_strcmp(tokens+i, json_chunk, "name") == 0)
4877 {
4878 i = cgltf_parse_json_string(options, tokens, i + 1, json_chunk, &out_texture->name);
4879 }
4880 else if (cgltf_json_strcmp(tokens + i, json_chunk, "sampler") == 0)
4881 {
4882 ++i;
4883 out_texture->sampler = CGLTF_PTRINDEX(cgltf_sampler, cgltf_json_to_int(tokens + i, json_chunk));
4884 ++i;
4885 }
4886 else if (cgltf_json_strcmp(tokens + i, json_chunk, "source") == 0)
4887 {
4888 ++i;
4889 out_texture->image = CGLTF_PTRINDEX(cgltf_image, cgltf_json_to_int(tokens + i, json_chunk));
4890 ++i;
4891 }
4892 else if (cgltf_json_strcmp(tokens + i, json_chunk, "extras") == 0)
4893 {
4894 i = cgltf_parse_json_extras(options, tokens, i + 1, json_chunk, &out_texture->extras);
4895 }
4896 else if (cgltf_json_strcmp(tokens + i, json_chunk, "extensions") == 0)
4897 {
4898 ++i;
4899
4900 CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
4901 if (out_texture->extensions)
4902 {
4903 return CGLTF_ERROR_JSON;
4904 }
4905
4906 int extensions_size = tokens[i].size;
4907 ++i;
4908 out_texture->extensions = (cgltf_extension*)cgltf_calloc(options, sizeof(cgltf_extension), extensions_size);
4909 out_texture->extensions_count = 0;
4910
4911 if (!out_texture->extensions)
4912 {
4913 return CGLTF_ERROR_NOMEM;
4914 }
4915
4916 for (int k = 0; k < extensions_size; ++k)
4917 {
4918 CGLTF_CHECK_KEY(tokens[i]);
4919
4920 if (cgltf_json_strcmp(tokens + i, json_chunk, "KHR_texture_basisu") == 0)
4921 {
4922 out_texture->has_basisu = 1;
4923 ++i;
4924 CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
4925 int num_properties = tokens[i].size;
4926 ++i;
4927
4928 for (int t = 0; t < num_properties; ++t)
4929 {
4930 CGLTF_CHECK_KEY(tokens[i]);
4931
4932 if (cgltf_json_strcmp(tokens + i, json_chunk, "source") == 0)
4933 {
4934 ++i;
4935 out_texture->basisu_image = CGLTF_PTRINDEX(cgltf_image, cgltf_json_to_int(tokens + i, json_chunk));
4936 ++i;
4937 }
4938 else
4939 {
4940 i = cgltf_skip_json(tokens, i + 1);
4941 }
4942 if (i < 0)
4943 {
4944 return i;
4945 }
4946 }
4947 }
4948 else if (cgltf_json_strcmp(tokens + i, json_chunk, "EXT_texture_webp") == 0)
4949 {
4950 out_texture->has_webp = 1;
4951 ++i;
4952 CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
4953 int num_properties = tokens[i].size;
4954 ++i;
4955
4956 for (int t = 0; t < num_properties; ++t)
4957 {
4958 CGLTF_CHECK_KEY(tokens[i]);
4959
4960 if (cgltf_json_strcmp(tokens + i, json_chunk, "source") == 0)
4961 {
4962 ++i;
4963 out_texture->webp_image = CGLTF_PTRINDEX(cgltf_image, cgltf_json_to_int(tokens + i, json_chunk));
4964 ++i;
4965 }
4966 else
4967 {
4968 i = cgltf_skip_json(tokens, i + 1);
4969 }
4970 if (i < 0)
4971 {
4972 return i;
4973 }
4974 }
4975 }
4976 else
4977 {
4978 i = cgltf_parse_json_unprocessed_extension(options, tokens, i, json_chunk, &(out_texture->extensions[out_texture->extensions_count++]));
4979 }
4980
4981 if (i < 0)
4982 {
4983 return i;
4984 }
4985 }
4986 }
4987 else
4988 {
4989 i = cgltf_skip_json(tokens, i + 1);
4990 }
4991
4992 if (i < 0)
4993 {
4994 return i;
4995 }
4996 }
4997
4998 return i;
4999}
5000
5001static int cgltf_parse_json_material(cgltf_options* options, jsmntok_t const* tokens, int i, const uint8_t* json_chunk, cgltf_material* out_material)
5002{
5003 CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
5004
5005 cgltf_fill_float_array(out_material->pbr_metallic_roughness.base_color_factor, 4, 1.0f);
5006 out_material->pbr_metallic_roughness.metallic_factor = 1.0f;
5007 out_material->pbr_metallic_roughness.roughness_factor = 1.0f;
5008
5009 cgltf_fill_float_array(out_material->pbr_specular_glossiness.diffuse_factor, 4, 1.0f);
5010 cgltf_fill_float_array(out_material->pbr_specular_glossiness.specular_factor, 3, 1.0f);
5011 out_material->pbr_specular_glossiness.glossiness_factor = 1.0f;
5012
5013 cgltf_fill_float_array(out_material->volume.attenuation_color, 3, 1.0f);
5014 out_material->volume.attenuation_distance = FLT_MAX;
5015
5016 out_material->alpha_cutoff = 0.5f;
5017
5018 int size = tokens[i].size;
5019 ++i;
5020
5021 for (int j = 0; j < size; ++j)
5022 {
5023 CGLTF_CHECK_KEY(tokens[i]);
5024
5025 if (cgltf_json_strcmp(tokens+i, json_chunk, "name") == 0)
5026 {
5027 i = cgltf_parse_json_string(options, tokens, i + 1, json_chunk, &out_material->name);
5028 }
5029 else if (cgltf_json_strcmp(tokens+i, json_chunk, "pbrMetallicRoughness") == 0)
5030 {
5031 out_material->has_pbr_metallic_roughness = 1;
5032 i = cgltf_parse_json_pbr_metallic_roughness(options, tokens, i + 1, json_chunk, &out_material->pbr_metallic_roughness);
5033 }
5034 else if (cgltf_json_strcmp(tokens+i, json_chunk, "emissiveFactor") == 0)
5035 {
5036 i = cgltf_parse_json_float_array(tokens, i + 1, json_chunk, out_material->emissive_factor, 3);
5037 }
5038 else if (cgltf_json_strcmp(tokens + i, json_chunk, "normalTexture") == 0)
5039 {
5040 i = cgltf_parse_json_texture_view(options, tokens, i + 1, json_chunk,
5041 &out_material->normal_texture);
5042 }
5043 else if (cgltf_json_strcmp(tokens + i, json_chunk, "occlusionTexture") == 0)
5044 {
5045 i = cgltf_parse_json_texture_view(options, tokens, i + 1, json_chunk,
5046 &out_material->occlusion_texture);
5047 }
5048 else if (cgltf_json_strcmp(tokens + i, json_chunk, "emissiveTexture") == 0)
5049 {
5050 i = cgltf_parse_json_texture_view(options, tokens, i + 1, json_chunk,
5051 &out_material->emissive_texture);
5052 }
5053 else if (cgltf_json_strcmp(tokens + i, json_chunk, "alphaMode") == 0)
5054 {
5055 ++i;
5056 if (cgltf_json_strcmp(tokens + i, json_chunk, "OPAQUE") == 0)
5057 {
5058 out_material->alpha_mode = cgltf_alpha_mode_opaque;
5059 }
5060 else if (cgltf_json_strcmp(tokens + i, json_chunk, "MASK") == 0)
5061 {
5062 out_material->alpha_mode = cgltf_alpha_mode_mask;
5063 }
5064 else if (cgltf_json_strcmp(tokens + i, json_chunk, "BLEND") == 0)
5065 {
5066 out_material->alpha_mode = cgltf_alpha_mode_blend;
5067 }
5068 ++i;
5069 }
5070 else if (cgltf_json_strcmp(tokens + i, json_chunk, "alphaCutoff") == 0)
5071 {
5072 ++i;
5073 out_material->alpha_cutoff = cgltf_json_to_float(tokens + i, json_chunk);
5074 ++i;
5075 }
5076 else if (cgltf_json_strcmp(tokens + i, json_chunk, "doubleSided") == 0)
5077 {
5078 ++i;
5079 out_material->double_sided =
5080 cgltf_json_to_bool(tokens + i, json_chunk);
5081 ++i;
5082 }
5083 else if (cgltf_json_strcmp(tokens + i, json_chunk, "extras") == 0)
5084 {
5085 i = cgltf_parse_json_extras(options, tokens, i + 1, json_chunk, &out_material->extras);
5086 }
5087 else if (cgltf_json_strcmp(tokens + i, json_chunk, "extensions") == 0)
5088 {
5089 ++i;
5090
5091 CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
5092 if(out_material->extensions)
5093 {
5094 return CGLTF_ERROR_JSON;
5095 }
5096
5097 int extensions_size = tokens[i].size;
5098 ++i;
5099 out_material->extensions = (cgltf_extension*)cgltf_calloc(options, sizeof(cgltf_extension), extensions_size);
5100 out_material->extensions_count= 0;
5101
5102 if (!out_material->extensions)
5103 {
5104 return CGLTF_ERROR_NOMEM;
5105 }
5106
5107 for (int k = 0; k < extensions_size; ++k)
5108 {
5109 CGLTF_CHECK_KEY(tokens[i]);
5110
5111 if (cgltf_json_strcmp(tokens+i, json_chunk, "KHR_materials_pbrSpecularGlossiness") == 0)
5112 {
5113 out_material->has_pbr_specular_glossiness = 1;
5114 i = cgltf_parse_json_pbr_specular_glossiness(options, tokens, i + 1, json_chunk, &out_material->pbr_specular_glossiness);
5115 }
5116 else if (cgltf_json_strcmp(tokens+i, json_chunk, "KHR_materials_unlit") == 0)
5117 {
5118 out_material->unlit = 1;
5119 i = cgltf_skip_json(tokens, i+1);
5120 }
5121 else if (cgltf_json_strcmp(tokens+i, json_chunk, "KHR_materials_clearcoat") == 0)
5122 {
5123 out_material->has_clearcoat = 1;
5124 i = cgltf_parse_json_clearcoat(options, tokens, i + 1, json_chunk, &out_material->clearcoat);
5125 }
5126 else if (cgltf_json_strcmp(tokens+i, json_chunk, "KHR_materials_ior") == 0)
5127 {
5128 out_material->has_ior = 1;
5129 i = cgltf_parse_json_ior(tokens, i + 1, json_chunk, &out_material->ior);
5130 }
5131 else if (cgltf_json_strcmp(tokens+i, json_chunk, "KHR_materials_specular") == 0)
5132 {
5133 out_material->has_specular = 1;
5134 i = cgltf_parse_json_specular(options, tokens, i + 1, json_chunk, &out_material->specular);
5135 }
5136 else if (cgltf_json_strcmp(tokens+i, json_chunk, "KHR_materials_transmission") == 0)
5137 {
5138 out_material->has_transmission = 1;
5139 i = cgltf_parse_json_transmission(options, tokens, i + 1, json_chunk, &out_material->transmission);
5140 }
5141 else if (cgltf_json_strcmp(tokens + i, json_chunk, "KHR_materials_volume") == 0)
5142 {
5143 out_material->has_volume = 1;
5144 i = cgltf_parse_json_volume(options, tokens, i + 1, json_chunk, &out_material->volume);
5145 }
5146 else if (cgltf_json_strcmp(tokens+i, json_chunk, "KHR_materials_sheen") == 0)
5147 {
5148 out_material->has_sheen = 1;
5149 i = cgltf_parse_json_sheen(options, tokens, i + 1, json_chunk, &out_material->sheen);
5150 }
5151 else if (cgltf_json_strcmp(tokens + i, json_chunk, "KHR_materials_emissive_strength") == 0)
5152 {
5153 out_material->has_emissive_strength = 1;
5154 i = cgltf_parse_json_emissive_strength(tokens, i + 1, json_chunk, &out_material->emissive_strength);
5155 }
5156 else if (cgltf_json_strcmp(tokens + i, json_chunk, "KHR_materials_iridescence") == 0)
5157 {
5158 out_material->has_iridescence = 1;
5159 i = cgltf_parse_json_iridescence(options, tokens, i + 1, json_chunk, &out_material->iridescence);
5160 }
5161 else if (cgltf_json_strcmp(tokens + i, json_chunk, "KHR_materials_diffuse_transmission") == 0)
5162 {
5163 out_material->has_diffuse_transmission = 1;
5164 i = cgltf_parse_json_diffuse_transmission(options, tokens, i + 1, json_chunk, &out_material->diffuse_transmission);
5165 }
5166 else if (cgltf_json_strcmp(tokens + i, json_chunk, "EXT_materials_subsurface") == 0)
5167 {
5168 out_material->has_subsurface = 1;
5169 i = cgltf_parse_json_subsurface(options, tokens, i + 1, json_chunk, &out_material->subsurface);
5170 }
5171 else if (cgltf_json_strcmp(tokens + i, json_chunk, "KHR_materials_anisotropy") == 0)
5172 {
5173 out_material->has_anisotropy = 1;
5174 i = cgltf_parse_json_anisotropy(options, tokens, i + 1, json_chunk, &out_material->anisotropy);
5175 }
5176 else if (cgltf_json_strcmp(tokens + i, json_chunk, "KHR_materials_dispersion") == 0)
5177 {
5178 out_material->has_dispersion = 1;
5179 i = cgltf_parse_json_dispersion(tokens, i + 1, json_chunk, &out_material->dispersion);
5180 }
5181 else if (cgltf_json_strcmp(tokens + i, json_chunk, "EXT_foundation_materials") == 0)
5182 {
5183 out_material->has_foundation_materials = 1;
5184 i = cgltf_parse_json_foundation_materials(tokens, i + 1, json_chunk, &out_material->foundation_materials);
5185 }
5186 else
5187 {
5188 i = cgltf_parse_json_unprocessed_extension(options, tokens, i, json_chunk, &(out_material->extensions[out_material->extensions_count++]));
5189 }
5190
5191 if (i < 0)
5192 {
5193 return i;
5194 }
5195 }
5196 }
5197 else
5198 {
5199 i = cgltf_skip_json(tokens, i+1);
5200 }
5201
5202 if (i < 0)
5203 {
5204 return i;
5205 }
5206 }
5207
5208 return i;
5209}
5210
5211static int cgltf_parse_json_accessors(cgltf_options* options, jsmntok_t const* tokens, int i, const uint8_t* json_chunk, cgltf_data* out_data)
5212{
5213 i = cgltf_parse_json_array(options, tokens, i, json_chunk, sizeof(cgltf_accessor), (void**)&out_data->accessors, &out_data->accessors_count);
5214 if (i < 0)
5215 {
5216 return i;
5217 }
5218
5219 for (cgltf_size j = 0; j < out_data->accessors_count; ++j)
5220 {
5221 i = cgltf_parse_json_accessor(options, tokens, i, json_chunk, &out_data->accessors[j]);
5222 if (i < 0)
5223 {
5224 return i;
5225 }
5226 }
5227 return i;
5228}
5229
5230static int cgltf_parse_json_materials(cgltf_options* options, jsmntok_t const* tokens, int i, const uint8_t* json_chunk, cgltf_data* out_data)
5231{
5232 i = cgltf_parse_json_array(options, tokens, i, json_chunk, sizeof(cgltf_material), (void**)&out_data->materials, &out_data->materials_count);
5233 if (i < 0)
5234 {
5235 return i;
5236 }
5237
5238 for (cgltf_size j = 0; j < out_data->materials_count; ++j)
5239 {
5240 i = cgltf_parse_json_material(options, tokens, i, json_chunk, &out_data->materials[j]);
5241 if (i < 0)
5242 {
5243 return i;
5244 }
5245 }
5246 return i;
5247}
5248
5249static int cgltf_parse_json_images(cgltf_options* options, jsmntok_t const* tokens, int i, const uint8_t* json_chunk, cgltf_data* out_data)
5250{
5251 i = cgltf_parse_json_array(options, tokens, i, json_chunk, sizeof(cgltf_image), (void**)&out_data->images, &out_data->images_count);
5252 if (i < 0)
5253 {
5254 return i;
5255 }
5256
5257 for (cgltf_size j = 0; j < out_data->images_count; ++j)
5258 {
5259 i = cgltf_parse_json_image(options, tokens, i, json_chunk, &out_data->images[j]);
5260 if (i < 0)
5261 {
5262 return i;
5263 }
5264 }
5265 return i;
5266}
5267
5268static int cgltf_parse_json_textures(cgltf_options* options, jsmntok_t const* tokens, int i, const uint8_t* json_chunk, cgltf_data* out_data)
5269{
5270 i = cgltf_parse_json_array(options, tokens, i, json_chunk, sizeof(cgltf_texture), (void**)&out_data->textures, &out_data->textures_count);
5271 if (i < 0)
5272 {
5273 return i;
5274 }
5275
5276 for (cgltf_size j = 0; j < out_data->textures_count; ++j)
5277 {
5278 i = cgltf_parse_json_texture(options, tokens, i, json_chunk, &out_data->textures[j]);
5279 if (i < 0)
5280 {
5281 return i;
5282 }
5283 }
5284 return i;
5285}
5286
5287static int cgltf_parse_json_samplers(cgltf_options* options, jsmntok_t const* tokens, int i, const uint8_t* json_chunk, cgltf_data* out_data)
5288{
5289 i = cgltf_parse_json_array(options, tokens, i, json_chunk, sizeof(cgltf_sampler), (void**)&out_data->samplers, &out_data->samplers_count);
5290 if (i < 0)
5291 {
5292 return i;
5293 }
5294
5295 for (cgltf_size j = 0; j < out_data->samplers_count; ++j)
5296 {
5297 i = cgltf_parse_json_sampler(options, tokens, i, json_chunk, &out_data->samplers[j]);
5298 if (i < 0)
5299 {
5300 return i;
5301 }
5302 }
5303 return i;
5304}
5305
5306static 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)
5307{
5308 (void)options;
5309 CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
5310
5311 int size = tokens[i].size;
5312 ++i;
5313
5314 for (int j = 0; j < size; ++j)
5315 {
5316 CGLTF_CHECK_KEY(tokens[i]);
5317
5318 if (cgltf_json_strcmp(tokens+i, json_chunk, "buffer") == 0)
5319 {
5320 ++i;
5321 out_meshopt_compression->buffer = CGLTF_PTRINDEX(cgltf_buffer, cgltf_json_to_int(tokens + i, json_chunk));
5322 ++i;
5323 }
5324 else if (cgltf_json_strcmp(tokens+i, json_chunk, "byteOffset") == 0)
5325 {
5326 ++i;
5327 out_meshopt_compression->offset = cgltf_json_to_size(tokens+i, json_chunk);
5328 ++i;
5329 }
5330 else if (cgltf_json_strcmp(tokens+i, json_chunk, "byteLength") == 0)
5331 {
5332 ++i;
5333 out_meshopt_compression->size = cgltf_json_to_size(tokens+i, json_chunk);
5334 ++i;
5335 }
5336 else if (cgltf_json_strcmp(tokens+i, json_chunk, "byteStride") == 0)
5337 {
5338 ++i;
5339 out_meshopt_compression->stride = cgltf_json_to_size(tokens+i, json_chunk);
5340 ++i;
5341 }
5342 else if (cgltf_json_strcmp(tokens+i, json_chunk, "count") == 0)
5343 {
5344 ++i;
5345 out_meshopt_compression->count = cgltf_json_to_size(tokens+i, json_chunk);
5346 ++i;
5347 }
5348 else if (cgltf_json_strcmp(tokens+i, json_chunk, "mode") == 0)
5349 {
5350 ++i;
5351 if (cgltf_json_strcmp(tokens+i, json_chunk, "ATTRIBUTES") == 0)
5352 {
5353 out_meshopt_compression->mode = cgltf_meshopt_compression_mode_attributes;
5354 }
5355 else if (cgltf_json_strcmp(tokens+i, json_chunk, "TRIANGLES") == 0)
5356 {
5357 out_meshopt_compression->mode = cgltf_meshopt_compression_mode_triangles;
5358 }
5359 else if (cgltf_json_strcmp(tokens+i, json_chunk, "INDICES") == 0)
5360 {
5361 out_meshopt_compression->mode = cgltf_meshopt_compression_mode_indices;
5362 }
5363 ++i;
5364 }
5365 else if (cgltf_json_strcmp(tokens+i, json_chunk, "filter") == 0)
5366 {
5367 ++i;
5368 if (cgltf_json_strcmp(tokens+i, json_chunk, "NONE") == 0)
5369 {
5370 out_meshopt_compression->filter = cgltf_meshopt_compression_filter_none;
5371 }
5372 else if (cgltf_json_strcmp(tokens+i, json_chunk, "OCTAHEDRAL") == 0)
5373 {
5374 out_meshopt_compression->filter = cgltf_meshopt_compression_filter_octahedral;
5375 }
5376 else if (cgltf_json_strcmp(tokens+i, json_chunk, "QUATERNION") == 0)
5377 {
5378 out_meshopt_compression->filter = cgltf_meshopt_compression_filter_quaternion;
5379 }
5380 else if (cgltf_json_strcmp(tokens+i, json_chunk, "EXPONENTIAL") == 0)
5381 {
5382 out_meshopt_compression->filter = cgltf_meshopt_compression_filter_exponential;
5383 }
5384 ++i;
5385 }
5386 else
5387 {
5388 i = cgltf_skip_json(tokens, i+1);
5389 }
5390
5391 if (i < 0)
5392 {
5393 return i;
5394 }
5395 }
5396
5397 return i;
5398}
5399
5400static 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)
5401{
5402 CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
5403
5404 int size = tokens[i].size;
5405 ++i;
5406
5407 for (int j = 0; j < size; ++j)
5408 {
5409 CGLTF_CHECK_KEY(tokens[i]);
5410
5411 if (cgltf_json_strcmp(tokens + i, json_chunk, "name") == 0)
5412 {
5413 i = cgltf_parse_json_string(options, tokens, i + 1, json_chunk, &out_buffer_view->name);
5414 }
5415 else if (cgltf_json_strcmp(tokens+i, json_chunk, "buffer") == 0)
5416 {
5417 ++i;
5418 out_buffer_view->buffer = CGLTF_PTRINDEX(cgltf_buffer, cgltf_json_to_int(tokens + i, json_chunk));
5419 ++i;
5420 }
5421 else if (cgltf_json_strcmp(tokens+i, json_chunk, "byteOffset") == 0)
5422 {
5423 ++i;
5424 out_buffer_view->offset =
5425 cgltf_json_to_size(tokens+i, json_chunk);
5426 ++i;
5427 }
5428 else if (cgltf_json_strcmp(tokens+i, json_chunk, "byteLength") == 0)
5429 {
5430 ++i;
5431 out_buffer_view->size =
5432 cgltf_json_to_size(tokens+i, json_chunk);
5433 ++i;
5434 }
5435 else if (cgltf_json_strcmp(tokens+i, json_chunk, "byteStride") == 0)
5436 {
5437 ++i;
5438 out_buffer_view->stride =
5439 cgltf_json_to_size(tokens+i, json_chunk);
5440 ++i;
5441 }
5442 else if (cgltf_json_strcmp(tokens+i, json_chunk, "target") == 0)
5443 {
5444 ++i;
5445 int type = cgltf_json_to_int(tokens+i, json_chunk);
5446 switch (type)
5447 {
5448 case 34962:
5450 break;
5451 case 34963:
5453 break;
5454 default:
5456 break;
5457 }
5458 out_buffer_view->type = (cgltf_buffer_view_type)type;
5459 ++i;
5460 }
5461 else if (cgltf_json_strcmp(tokens + i, json_chunk, "extras") == 0)
5462 {
5463 i = cgltf_parse_json_extras(options, tokens, i + 1, json_chunk, &out_buffer_view->extras);
5464 }
5465 else if (cgltf_json_strcmp(tokens + i, json_chunk, "extensions") == 0)
5466 {
5467 ++i;
5468
5469 CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
5470 if(out_buffer_view->extensions)
5471 {
5472 return CGLTF_ERROR_JSON;
5473 }
5474
5475 int extensions_size = tokens[i].size;
5476 out_buffer_view->extensions_count = 0;
5477 out_buffer_view->extensions = (cgltf_extension*)cgltf_calloc(options, sizeof(cgltf_extension), extensions_size);
5478
5479 if (!out_buffer_view->extensions)
5480 {
5481 return CGLTF_ERROR_NOMEM;
5482 }
5483
5484 ++i;
5485 for (int k = 0; k < extensions_size; ++k)
5486 {
5487 CGLTF_CHECK_KEY(tokens[i]);
5488
5489 if (cgltf_json_strcmp(tokens+i, json_chunk, "EXT_meshopt_compression") == 0)
5490 {
5491 out_buffer_view->has_meshopt_compression = 1;
5492 i = cgltf_parse_json_meshopt_compression(options, tokens, i + 1, json_chunk, &out_buffer_view->meshopt_compression);
5493 }
5494 else
5495 {
5496 i = cgltf_parse_json_unprocessed_extension(options, tokens, i, json_chunk, &(out_buffer_view->extensions[out_buffer_view->extensions_count++]));
5497 }
5498
5499 if (i < 0)
5500 {
5501 return i;
5502 }
5503 }
5504 }
5505 else
5506 {
5507 i = cgltf_skip_json(tokens, i+1);
5508 }
5509
5510 if (i < 0)
5511 {
5512 return i;
5513 }
5514 }
5515
5516 return i;
5517}
5518
5519static int cgltf_parse_json_buffer_views(cgltf_options* options, jsmntok_t const* tokens, int i, const uint8_t* json_chunk, cgltf_data* out_data)
5520{
5521 i = cgltf_parse_json_array(options, tokens, i, json_chunk, sizeof(cgltf_buffer_view), (void**)&out_data->buffer_views, &out_data->buffer_views_count);
5522 if (i < 0)
5523 {
5524 return i;
5525 }
5526
5527 for (cgltf_size j = 0; j < out_data->buffer_views_count; ++j)
5528 {
5529 i = cgltf_parse_json_buffer_view(options, tokens, i, json_chunk, &out_data->buffer_views[j]);
5530 if (i < 0)
5531 {
5532 return i;
5533 }
5534 }
5535 return i;
5536}
5537
5538static int cgltf_parse_json_buffer(cgltf_options* options, jsmntok_t const* tokens, int i, const uint8_t* json_chunk, cgltf_buffer* out_buffer)
5539{
5540 CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
5541
5542 int size = tokens[i].size;
5543 ++i;
5544
5545 for (int j = 0; j < size; ++j)
5546 {
5547 CGLTF_CHECK_KEY(tokens[i]);
5548
5549 if (cgltf_json_strcmp(tokens + i, json_chunk, "name") == 0)
5550 {
5551 i = cgltf_parse_json_string(options, tokens, i + 1, json_chunk, &out_buffer->name);
5552 }
5553 else if (cgltf_json_strcmp(tokens+i, json_chunk, "byteLength") == 0)
5554 {
5555 ++i;
5556 out_buffer->size =
5557 cgltf_json_to_size(tokens+i, json_chunk);
5558 ++i;
5559 }
5560 else if (cgltf_json_strcmp(tokens+i, json_chunk, "uri") == 0)
5561 {
5562 i = cgltf_parse_json_string(options, tokens, i + 1, json_chunk, &out_buffer->uri);
5563 }
5564 else if (cgltf_json_strcmp(tokens + i, json_chunk, "extras") == 0)
5565 {
5566 i = cgltf_parse_json_extras(options, tokens, i + 1, json_chunk, &out_buffer->extras);
5567 }
5568 else if (cgltf_json_strcmp(tokens + i, json_chunk, "extensions") == 0)
5569 {
5570 i = cgltf_parse_json_unprocessed_extensions(options, tokens, i, json_chunk, &out_buffer->extensions_count, &out_buffer->extensions);
5571 }
5572 else
5573 {
5574 i = cgltf_skip_json(tokens, i+1);
5575 }
5576
5577 if (i < 0)
5578 {
5579 return i;
5580 }
5581 }
5582
5583 return i;
5584}
5585
5586static int cgltf_parse_json_buffers(cgltf_options* options, jsmntok_t const* tokens, int i, const uint8_t* json_chunk, cgltf_data* out_data)
5587{
5588 i = cgltf_parse_json_array(options, tokens, i, json_chunk, sizeof(cgltf_buffer), (void**)&out_data->buffers, &out_data->buffers_count);
5589 if (i < 0)
5590 {
5591 return i;
5592 }
5593
5594 for (cgltf_size j = 0; j < out_data->buffers_count; ++j)
5595 {
5596 i = cgltf_parse_json_buffer(options, tokens, i, json_chunk, &out_data->buffers[j]);
5597 if (i < 0)
5598 {
5599 return i;
5600 }
5601 }
5602 return i;
5603}
5604
5605static int cgltf_parse_json_skin(cgltf_options* options, jsmntok_t const* tokens, int i, const uint8_t* json_chunk, cgltf_skin* out_skin)
5606{
5607 CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
5608
5609 int size = tokens[i].size;
5610 ++i;
5611
5612 for (int j = 0; j < size; ++j)
5613 {
5614 CGLTF_CHECK_KEY(tokens[i]);
5615
5616 if (cgltf_json_strcmp(tokens+i, json_chunk, "name") == 0)
5617 {
5618 i = cgltf_parse_json_string(options, tokens, i + 1, json_chunk, &out_skin->name);
5619 }
5620 else if (cgltf_json_strcmp(tokens+i, json_chunk, "joints") == 0)
5621 {
5622 i = cgltf_parse_json_array(options, tokens, i + 1, json_chunk, sizeof(cgltf_node*), (void**)&out_skin->joints, &out_skin->joints_count);
5623 if (i < 0)
5624 {
5625 return i;
5626 }
5627
5628 for (cgltf_size k = 0; k < out_skin->joints_count; ++k)
5629 {
5630 out_skin->joints[k] = CGLTF_PTRINDEX(cgltf_node, cgltf_json_to_int(tokens + i, json_chunk));
5631 ++i;
5632 }
5633 }
5634 else if (cgltf_json_strcmp(tokens+i, json_chunk, "skeleton") == 0)
5635 {
5636 ++i;
5637 CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_PRIMITIVE);
5638 out_skin->skeleton = CGLTF_PTRINDEX(cgltf_node, cgltf_json_to_int(tokens + i, json_chunk));
5639 ++i;
5640 }
5641 else if (cgltf_json_strcmp(tokens+i, json_chunk, "inverseBindMatrices") == 0)
5642 {
5643 ++i;
5644 CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_PRIMITIVE);
5645 out_skin->inverse_bind_matrices = CGLTF_PTRINDEX(cgltf_accessor, cgltf_json_to_int(tokens + i, json_chunk));
5646 ++i;
5647 }
5648 else if (cgltf_json_strcmp(tokens + i, json_chunk, "extras") == 0)
5649 {
5650 i = cgltf_parse_json_extras(options, tokens, i + 1, json_chunk, &out_skin->extras);
5651 }
5652 else if (cgltf_json_strcmp(tokens + i, json_chunk, "extensions") == 0)
5653 {
5654 i = cgltf_parse_json_unprocessed_extensions(options, tokens, i, json_chunk, &out_skin->extensions_count, &out_skin->extensions);
5655 }
5656 else
5657 {
5658 i = cgltf_skip_json(tokens, i+1);
5659 }
5660
5661 if (i < 0)
5662 {
5663 return i;
5664 }
5665 }
5666
5667 return i;
5668}
5669
5670static int cgltf_parse_json_skins(cgltf_options* options, jsmntok_t const* tokens, int i, const uint8_t* json_chunk, cgltf_data* out_data)
5671{
5672 i = cgltf_parse_json_array(options, tokens, i, json_chunk, sizeof(cgltf_skin), (void**)&out_data->skins, &out_data->skins_count);
5673 if (i < 0)
5674 {
5675 return i;
5676 }
5677
5678 for (cgltf_size j = 0; j < out_data->skins_count; ++j)
5679 {
5680 i = cgltf_parse_json_skin(options, tokens, i, json_chunk, &out_data->skins[j]);
5681 if (i < 0)
5682 {
5683 return i;
5684 }
5685 }
5686 return i;
5687}
5688
5689static int cgltf_parse_json_camera_lens(cgltf_options* options, jsmntok_t const* tokens, int i, const uint8_t* json_chunk, cgltf_camera_lens* out_lens)
5690{
5691 (void)options;
5692 CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
5693
5694 out_lens->sensor_size = 36.0f;
5695 out_lens->fstop = 2.8f;
5696 out_lens->focus_distance = 10.0f;
5697 out_lens->aperture_blades = 0;
5698 out_lens->aperture_rotation = 0.0f;
5699 out_lens->aperture_ratio = 1.0f;
5700
5701 int size = tokens[i].size;
5702 ++i;
5703
5704 for (int j = 0; j < size; ++j)
5705 {
5706 CGLTF_CHECK_KEY(tokens[i]);
5707
5708 if (cgltf_json_strcmp(tokens+i, json_chunk, "sensorSize") == 0)
5709 {
5710 ++i;
5711 out_lens->sensor_size = cgltf_json_to_float(tokens + i, json_chunk);
5712 ++i;
5713 }
5714 else if (cgltf_json_strcmp(tokens+i, json_chunk, "fStop") == 0)
5715 {
5716 ++i;
5717 out_lens->fstop = cgltf_json_to_float(tokens + i, json_chunk);
5718 ++i;
5719 }
5720 else if (cgltf_json_strcmp(tokens+i, json_chunk, "focusDistance") == 0)
5721 {
5722 ++i;
5723 out_lens->focus_distance = cgltf_json_to_float(tokens + i, json_chunk);
5724 ++i;
5725 }
5726 else if (cgltf_json_strcmp(tokens+i, json_chunk, "apertureBlades") == 0)
5727 {
5728 ++i;
5729 out_lens->aperture_blades = (cgltf_uint)cgltf_json_to_int(tokens + i, json_chunk);
5730 ++i;
5731 }
5732 else if (cgltf_json_strcmp(tokens+i, json_chunk, "apertureRotation") == 0)
5733 {
5734 ++i;
5735 out_lens->aperture_rotation = cgltf_json_to_float(tokens + i, json_chunk);
5736 ++i;
5737 }
5738 else if (cgltf_json_strcmp(tokens+i, json_chunk, "apertureRatio") == 0)
5739 {
5740 ++i;
5741 out_lens->aperture_ratio = cgltf_json_to_float(tokens + i, json_chunk);
5742 ++i;
5743 }
5744 else
5745 {
5746 i = cgltf_skip_json(tokens, i+1);
5747 }
5748
5749 if (i < 0)
5750 {
5751 return i;
5752 }
5753 }
5754
5755 return i;
5756}
5757
5758static int cgltf_parse_json_camera(cgltf_options* options, jsmntok_t const* tokens, int i, const uint8_t* json_chunk, cgltf_camera* out_camera)
5759{
5760 CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
5761
5762 int size = tokens[i].size;
5763 ++i;
5764
5765 for (int j = 0; j < size; ++j)
5766 {
5767 CGLTF_CHECK_KEY(tokens[i]);
5768
5769 if (cgltf_json_strcmp(tokens+i, json_chunk, "name") == 0)
5770 {
5771 i = cgltf_parse_json_string(options, tokens, i + 1, json_chunk, &out_camera->name);
5772 }
5773 else if (cgltf_json_strcmp(tokens+i, json_chunk, "perspective") == 0)
5774 {
5775 ++i;
5776
5777 CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
5778
5779 int data_size = tokens[i].size;
5780 ++i;
5781
5782 if (out_camera->type != cgltf_camera_type_invalid)
5783 {
5784 return CGLTF_ERROR_JSON;
5785 }
5786
5787 out_camera->type = cgltf_camera_type_perspective;
5788
5789 for (int k = 0; k < data_size; ++k)
5790 {
5791 CGLTF_CHECK_KEY(tokens[i]);
5792
5793 if (cgltf_json_strcmp(tokens+i, json_chunk, "aspectRatio") == 0)
5794 {
5795 ++i;
5796 out_camera->data.perspective.has_aspect_ratio = 1;
5797 out_camera->data.perspective.aspect_ratio = cgltf_json_to_float(tokens + i, json_chunk);
5798 ++i;
5799 }
5800 else if (cgltf_json_strcmp(tokens+i, json_chunk, "yfov") == 0)
5801 {
5802 ++i;
5803 out_camera->data.perspective.yfov = cgltf_json_to_float(tokens + i, json_chunk);
5804 ++i;
5805 }
5806 else if (cgltf_json_strcmp(tokens+i, json_chunk, "zfar") == 0)
5807 {
5808 ++i;
5809 out_camera->data.perspective.has_zfar = 1;
5810 out_camera->data.perspective.zfar = cgltf_json_to_float(tokens + i, json_chunk);
5811 ++i;
5812 }
5813 else if (cgltf_json_strcmp(tokens+i, json_chunk, "znear") == 0)
5814 {
5815 ++i;
5816 out_camera->data.perspective.znear = cgltf_json_to_float(tokens + i, json_chunk);
5817 ++i;
5818 }
5819 else if (cgltf_json_strcmp(tokens + i, json_chunk, "extras") == 0)
5820 {
5821 i = cgltf_parse_json_extras(options, tokens, i + 1, json_chunk, &out_camera->data.perspective.extras);
5822 }
5823 else
5824 {
5825 i = cgltf_skip_json(tokens, i+1);
5826 }
5827
5828 if (i < 0)
5829 {
5830 return i;
5831 }
5832 }
5833 }
5834 else if (cgltf_json_strcmp(tokens+i, json_chunk, "orthographic") == 0)
5835 {
5836 ++i;
5837
5838 CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
5839
5840 int data_size = tokens[i].size;
5841 ++i;
5842
5843 if (out_camera->type != cgltf_camera_type_invalid)
5844 {
5845 return CGLTF_ERROR_JSON;
5846 }
5847
5849
5850 for (int k = 0; k < data_size; ++k)
5851 {
5852 CGLTF_CHECK_KEY(tokens[i]);
5853
5854 if (cgltf_json_strcmp(tokens+i, json_chunk, "xmag") == 0)
5855 {
5856 ++i;
5857 out_camera->data.orthographic.xmag = cgltf_json_to_float(tokens + i, json_chunk);
5858 ++i;
5859 }
5860 else if (cgltf_json_strcmp(tokens+i, json_chunk, "ymag") == 0)
5861 {
5862 ++i;
5863 out_camera->data.orthographic.ymag = cgltf_json_to_float(tokens + i, json_chunk);
5864 ++i;
5865 }
5866 else if (cgltf_json_strcmp(tokens+i, json_chunk, "zfar") == 0)
5867 {
5868 ++i;
5869 out_camera->data.orthographic.zfar = cgltf_json_to_float(tokens + i, json_chunk);
5870 ++i;
5871 }
5872 else if (cgltf_json_strcmp(tokens+i, json_chunk, "znear") == 0)
5873 {
5874 ++i;
5875 out_camera->data.orthographic.znear = cgltf_json_to_float(tokens + i, json_chunk);
5876 ++i;
5877 }
5878 else if (cgltf_json_strcmp(tokens + i, json_chunk, "extras") == 0)
5879 {
5880 i = cgltf_parse_json_extras(options, tokens, i + 1, json_chunk, &out_camera->data.orthographic.extras);
5881 }
5882 else
5883 {
5884 i = cgltf_skip_json(tokens, i+1);
5885 }
5886
5887 if (i < 0)
5888 {
5889 return i;
5890 }
5891 }
5892 }
5893 else if (cgltf_json_strcmp(tokens + i, json_chunk, "extras") == 0)
5894 {
5895 i = cgltf_parse_json_extras(options, tokens, i + 1, json_chunk, &out_camera->extras);
5896 }
5897 else if (cgltf_json_strcmp(tokens + i, json_chunk, "extensions") == 0)
5898 {
5899 ++i;
5900
5901 CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
5902 if (out_camera->extensions)
5903 {
5904 return CGLTF_ERROR_JSON;
5905 }
5906
5907 int extensions_size = tokens[i].size;
5908 out_camera->extensions_count = 0;
5909 if (extensions_size > 0)
5910 {
5911 out_camera->extensions = (cgltf_extension*)cgltf_calloc(options, sizeof(cgltf_extension), extensions_size);
5912 }
5913
5914 if (extensions_size > 0 && !out_camera->extensions)
5915 {
5916 return CGLTF_ERROR_NOMEM;
5917 }
5918
5919 ++i;
5920
5921 for (int k = 0; k < extensions_size; ++k)
5922 {
5923 CGLTF_CHECK_KEY(tokens[i]);
5924
5925 if (cgltf_json_strcmp(tokens+i, json_chunk, "EXT_camera_lens") == 0)
5926 {
5927 out_camera->has_lens = 1;
5928 i = cgltf_parse_json_camera_lens(options, tokens, i + 1, json_chunk, &out_camera->lens);
5929 }
5930 else
5931 {
5932 i = cgltf_parse_json_unprocessed_extension(options, tokens, i, json_chunk, &(out_camera->extensions[out_camera->extensions_count++]));
5933 }
5934
5935 if (i < 0)
5936 {
5937 return i;
5938 }
5939 }
5940 }
5941 else
5942 {
5943 i = cgltf_skip_json(tokens, i+1);
5944 }
5945
5946 if (i < 0)
5947 {
5948 return i;
5949 }
5950 }
5951
5952 return i;
5953}
5954
5955static int cgltf_parse_json_cameras(cgltf_options* options, jsmntok_t const* tokens, int i, const uint8_t* json_chunk, cgltf_data* out_data)
5956{
5957 i = cgltf_parse_json_array(options, tokens, i, json_chunk, sizeof(cgltf_camera), (void**)&out_data->cameras, &out_data->cameras_count);
5958 if (i < 0)
5959 {
5960 return i;
5961 }
5962
5963 for (cgltf_size j = 0; j < out_data->cameras_count; ++j)
5964 {
5965 i = cgltf_parse_json_camera(options, tokens, i, json_chunk, &out_data->cameras[j]);
5966 if (i < 0)
5967 {
5968 return i;
5969 }
5970 }
5971 return i;
5972}
5973
5974static int cgltf_parse_json_light(cgltf_options* options, jsmntok_t const* tokens, int i, const uint8_t* json_chunk, cgltf_light* out_light)
5975{
5976 CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
5977
5978 out_light->color[0] = 1.f;
5979 out_light->color[1] = 1.f;
5980 out_light->color[2] = 1.f;
5981 out_light->intensity = 1.f;
5982
5983 out_light->spot_inner_cone_angle = 0.f;
5984 out_light->spot_outer_cone_angle = 3.1415926535f / 4.0f;
5985
5986 out_light->has_foundation_lights = 0;
5987 out_light->angular_diameter = 0.f;
5988
5989 int size = tokens[i].size;
5990 ++i;
5991
5992 for (int j = 0; j < size; ++j)
5993 {
5994 CGLTF_CHECK_KEY(tokens[i]);
5995
5996 if (cgltf_json_strcmp(tokens+i, json_chunk, "name") == 0)
5997 {
5998 i = cgltf_parse_json_string(options, tokens, i + 1, json_chunk, &out_light->name);
5999 }
6000 else if (cgltf_json_strcmp(tokens + i, json_chunk, "color") == 0)
6001 {
6002 i = cgltf_parse_json_float_array(tokens, i + 1, json_chunk, out_light->color, 3);
6003 }
6004 else if (cgltf_json_strcmp(tokens + i, json_chunk, "intensity") == 0)
6005 {
6006 ++i;
6007 out_light->intensity = cgltf_json_to_float(tokens + i, json_chunk);
6008 ++i;
6009 }
6010 else if (cgltf_json_strcmp(tokens+i, json_chunk, "type") == 0)
6011 {
6012 ++i;
6013 if (cgltf_json_strcmp(tokens + i, json_chunk, "directional") == 0)
6014 {
6016 }
6017 else if (cgltf_json_strcmp(tokens + i, json_chunk, "point") == 0)
6018 {
6019 out_light->type = cgltf_light_type_point;
6020 }
6021 else if (cgltf_json_strcmp(tokens + i, json_chunk, "spot") == 0)
6022 {
6023 out_light->type = cgltf_light_type_spot;
6024 }
6025 ++i;
6026 }
6027 else if (cgltf_json_strcmp(tokens + i, json_chunk, "range") == 0)
6028 {
6029 ++i;
6030 out_light->range = cgltf_json_to_float(tokens + i, json_chunk);
6031 ++i;
6032 }
6033 else if (cgltf_json_strcmp(tokens+i, json_chunk, "spot") == 0)
6034 {
6035 ++i;
6036
6037 CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
6038
6039 int data_size = tokens[i].size;
6040 ++i;
6041
6042 for (int k = 0; k < data_size; ++k)
6043 {
6044 CGLTF_CHECK_KEY(tokens[i]);
6045
6046 if (cgltf_json_strcmp(tokens+i, json_chunk, "innerConeAngle") == 0)
6047 {
6048 ++i;
6049 out_light->spot_inner_cone_angle = cgltf_json_to_float(tokens + i, json_chunk);
6050 ++i;
6051 }
6052 else if (cgltf_json_strcmp(tokens+i, json_chunk, "outerConeAngle") == 0)
6053 {
6054 ++i;
6055 out_light->spot_outer_cone_angle = cgltf_json_to_float(tokens + i, json_chunk);
6056 ++i;
6057 }
6058 else
6059 {
6060 i = cgltf_skip_json(tokens, i+1);
6061 }
6062
6063 if (i < 0)
6064 {
6065 return i;
6066 }
6067 }
6068 }
6069 else if (cgltf_json_strcmp(tokens + i, json_chunk, "extensions") == 0)
6070 {
6071 CGLTF_CHECK_TOKTYPE(tokens[i + 1], JSMN_OBJECT);
6072 int extensions_size = tokens[i + 1].size;
6073 i += 2;
6074 for (int k = 0; k < extensions_size; ++k)
6075 {
6076 CGLTF_CHECK_KEY(tokens[i]);
6077 if (cgltf_json_strcmp(tokens+i, json_chunk, "EXT_foundation_lights") == 0)
6078 {
6079 out_light->has_foundation_lights = 1;
6080 CGLTF_CHECK_TOKTYPE(tokens[i + 1], JSMN_OBJECT);
6081 int ext_size = tokens[i + 1].size;
6082 i += 2;
6083 for (int m = 0; m < ext_size; ++m)
6084 {
6085 CGLTF_CHECK_KEY(tokens[i]);
6086 if (cgltf_json_strcmp(tokens+i, json_chunk, "angularDiameter") == 0)
6087 {
6088 ++i;
6089 out_light->angular_diameter = cgltf_json_to_float(tokens + i, json_chunk);
6090 ++i;
6091 }
6092 else
6093 {
6094 i = cgltf_skip_json(tokens, i+1);
6095 }
6096 if (i < 0) return i;
6097 }
6098 }
6099 else
6100 {
6101 i = cgltf_skip_json(tokens, i+1);
6102 }
6103 if (i < 0) return i;
6104 }
6105 }
6106 else if (cgltf_json_strcmp(tokens + i, json_chunk, "extras") == 0)
6107 {
6108 i = cgltf_parse_json_extras(options, tokens, i + 1, json_chunk, &out_light->extras);
6109 }
6110 else
6111 {
6112 i = cgltf_skip_json(tokens, i+1);
6113 }
6114
6115 if (i < 0)
6116 {
6117 return i;
6118 }
6119 }
6120
6121 return i;
6122}
6123
6124static int cgltf_parse_json_lights(cgltf_options* options, jsmntok_t const* tokens, int i, const uint8_t* json_chunk, cgltf_data* out_data)
6125{
6126 i = cgltf_parse_json_array(options, tokens, i, json_chunk, sizeof(cgltf_light), (void**)&out_data->lights, &out_data->lights_count);
6127 if (i < 0)
6128 {
6129 return i;
6130 }
6131
6132 for (cgltf_size j = 0; j < out_data->lights_count; ++j)
6133 {
6134 i = cgltf_parse_json_light(options, tokens, i, json_chunk, &out_data->lights[j]);
6135 if (i < 0)
6136 {
6137 return i;
6138 }
6139 }
6140 return i;
6141}
6142
6143static int cgltf_parse_json_light_area(cgltf_options* options, jsmntok_t const* tokens, int i, const uint8_t* json_chunk, cgltf_light_area* out_light)
6144{
6145 CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
6146
6147 out_light->color[0] = 1.f;
6148 out_light->color[1] = 1.f;
6149 out_light->color[2] = 1.f;
6150 out_light->intensity = 1000.f;
6151 out_light->type = cgltf_light_area_type_rect;
6152 out_light->size = 1.f;
6153 out_light->rect_aspect = 1.f;
6154
6155 int size = tokens[i].size;
6156 ++i;
6157
6158 for (int j = 0; j < size; ++j)
6159 {
6160 CGLTF_CHECK_KEY(tokens[i]);
6161
6162 if (cgltf_json_strcmp(tokens + i, json_chunk, "name") == 0)
6163 {
6164 i = cgltf_parse_json_string(options, tokens, i + 1, json_chunk, &out_light->name);
6165 }
6166 else if (cgltf_json_strcmp(tokens + i, json_chunk, "color") == 0)
6167 {
6168 i = cgltf_parse_json_float_array(tokens, i + 1, json_chunk, out_light->color, 3);
6169 }
6170 else if (cgltf_json_strcmp(tokens + i, json_chunk, "intensity") == 0)
6171 {
6172 ++i;
6173 out_light->intensity = cgltf_json_to_float(tokens + i, json_chunk);
6174 ++i;
6175 }
6176 else if (cgltf_json_strcmp(tokens + i, json_chunk, "type") == 0)
6177 {
6178 ++i;
6179 if (cgltf_json_strcmp(tokens + i, json_chunk, "rect") == 0)
6180 {
6181 out_light->type = cgltf_light_area_type_rect;
6182 }
6183 else if (cgltf_json_strcmp(tokens + i, json_chunk, "disk") == 0)
6184 {
6185 out_light->type = cgltf_light_area_type_disk;
6186 }
6187 ++i;
6188 }
6189 else if (cgltf_json_strcmp(tokens + i, json_chunk, "size") == 0)
6190 {
6191 ++i;
6192 out_light->size = cgltf_json_to_float(tokens + i, json_chunk);
6193 ++i;
6194 }
6195 else if (cgltf_json_strcmp(tokens + i, json_chunk, "rect") == 0)
6196 {
6197 ++i;
6198
6199 CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
6200
6201 int data_size = tokens[i].size;
6202 ++i;
6203
6204 for (int k = 0; k < data_size; ++k)
6205 {
6206 CGLTF_CHECK_KEY(tokens[i]);
6207
6208 if (cgltf_json_strcmp(tokens + i, json_chunk, "aspect") == 0)
6209 {
6210 ++i;
6211 out_light->rect_aspect = cgltf_json_to_float(tokens + i, json_chunk);
6212 ++i;
6213 }
6214 else
6215 {
6216 i = cgltf_skip_json(tokens, i + 1);
6217 }
6218
6219 if (i < 0)
6220 {
6221 return i;
6222 }
6223 }
6224 }
6225 else if (cgltf_json_strcmp(tokens + i, json_chunk, "extras") == 0)
6226 {
6227 i = cgltf_parse_json_extras(options, tokens, i + 1, json_chunk, &out_light->extras);
6228 }
6229 else
6230 {
6231 i = cgltf_skip_json(tokens, i + 1);
6232 }
6233
6234 if (i < 0)
6235 {
6236 return i;
6237 }
6238 }
6239
6240 return i;
6241}
6242
6243static int cgltf_parse_json_lights_area(cgltf_options* options, jsmntok_t const* tokens, int i, const uint8_t* json_chunk, cgltf_data* out_data)
6244{
6245 i = cgltf_parse_json_array(options, tokens, i, json_chunk, sizeof(cgltf_light_area), (void**)&out_data->lights_area, &out_data->lights_area_count);
6246 if (i < 0)
6247 {
6248 return i;
6249 }
6250
6251 for (cgltf_size j = 0; j < out_data->lights_area_count; ++j)
6252 {
6253 i = cgltf_parse_json_light_area(options, tokens, i, json_chunk, &out_data->lights_area[j]);
6254 if (i < 0)
6255 {
6256 return i;
6257 }
6258 }
6259 return i;
6260}
6261
6262static int cgltf_parse_json_curve(cgltf_options* options, jsmntok_t const* tokens, int i, const uint8_t* json_chunk, cgltf_curve* out_curve)
6263{
6264 CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
6265
6266 out_curve->basis = cgltf_curve_basis_linear;
6268
6269 int size = tokens[i].size;
6270 ++i;
6271
6272 for (int j = 0; j < size; ++j)
6273 {
6274 CGLTF_CHECK_KEY(tokens[i]);
6275
6276 if (cgltf_json_strcmp(tokens + i, json_chunk, "name") == 0)
6277 {
6278 i = cgltf_parse_json_string(options, tokens, i + 1, json_chunk, &out_curve->name);
6279 }
6280 else if (cgltf_json_strcmp(tokens + i, json_chunk, "basis") == 0)
6281 {
6282 ++i;
6283 if (cgltf_json_strcmp(tokens + i, json_chunk, "linear") == 0)
6284 {
6285 out_curve->basis = cgltf_curve_basis_linear;
6286 }
6287 else if (cgltf_json_strcmp(tokens + i, json_chunk, "bezier") == 0)
6288 {
6289 out_curve->basis = cgltf_curve_basis_bezier;
6290 }
6291 else if (cgltf_json_strcmp(tokens + i, json_chunk, "bspline") == 0)
6292 {
6293 out_curve->basis = cgltf_curve_basis_bspline;
6294 }
6295 else if (cgltf_json_strcmp(tokens + i, json_chunk, "catmullRom") == 0)
6296 {
6298 }
6299 ++i;
6300 }
6301 else if (cgltf_json_strcmp(tokens + i, json_chunk, "renderMode") == 0)
6302 {
6303 ++i;
6304 if (cgltf_json_strcmp(tokens + i, json_chunk, "capsule") == 0)
6305 {
6307 }
6308 ++i;
6309 }
6310 else if (cgltf_json_strcmp(tokens + i, json_chunk, "points") == 0)
6311 {
6312 ++i;
6313 CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_PRIMITIVE);
6314 out_curve->points = CGLTF_PTRINDEX(cgltf_accessor, cgltf_json_to_int(tokens + i, json_chunk));
6315 ++i;
6316 }
6317 else if (cgltf_json_strcmp(tokens + i, json_chunk, "curveVertexCounts") == 0)
6318 {
6319 ++i;
6320 CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_PRIMITIVE);
6321 out_curve->curve_vertex_counts = CGLTF_PTRINDEX(cgltf_accessor, cgltf_json_to_int(tokens + i, json_chunk));
6322 ++i;
6323 }
6324 else if (cgltf_json_strcmp(tokens + i, json_chunk, "material") == 0)
6325 {
6326 ++i;
6327 CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_PRIMITIVE);
6328 out_curve->material = CGLTF_PTRINDEX(cgltf_material, cgltf_json_to_int(tokens + i, json_chunk));
6329 ++i;
6330 }
6331 else if (cgltf_json_strcmp(tokens + i, json_chunk, "extras") == 0)
6332 {
6333 i = cgltf_parse_json_extras(options, tokens, i + 1, json_chunk, &out_curve->extras);
6334 }
6335 else
6336 {
6337 i = cgltf_skip_json(tokens, i + 1);
6338 }
6339
6340 if (i < 0)
6341 {
6342 return i;
6343 }
6344 }
6345
6346 return i;
6347}
6348
6349static int cgltf_parse_json_curves(cgltf_options* options, jsmntok_t const* tokens, int i, const uint8_t* json_chunk, cgltf_data* out_data)
6350{
6351 i = cgltf_parse_json_array(options, tokens, i, json_chunk, sizeof(cgltf_curve), (void**)&out_data->curves, &out_data->curves_count);
6352 if (i < 0)
6353 {
6354 return i;
6355 }
6356
6357 for (cgltf_size j = 0; j < out_data->curves_count; ++j)
6358 {
6359 i = cgltf_parse_json_curve(options, tokens, i, json_chunk, &out_data->curves[j]);
6360 if (i < 0)
6361 {
6362 return i;
6363 }
6364 }
6365 return i;
6366}
6367
6368static int cgltf_parse_json_node(cgltf_options* options, jsmntok_t const* tokens, int i, const uint8_t* json_chunk, cgltf_node* out_node)
6369{
6370 CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
6371
6372 out_node->rotation[3] = 1.0f;
6373 out_node->scale[0] = 1.0f;
6374 out_node->scale[1] = 1.0f;
6375 out_node->scale[2] = 1.0f;
6376 out_node->matrix[0] = 1.0f;
6377 out_node->matrix[5] = 1.0f;
6378 out_node->matrix[10] = 1.0f;
6379 out_node->matrix[15] = 1.0f;
6380
6381 int size = tokens[i].size;
6382 ++i;
6383
6384 for (int j = 0; j < size; ++j)
6385 {
6386 CGLTF_CHECK_KEY(tokens[i]);
6387
6388 if (cgltf_json_strcmp(tokens+i, json_chunk, "name") == 0)
6389 {
6390 i = cgltf_parse_json_string(options, tokens, i + 1, json_chunk, &out_node->name);
6391 }
6392 else if (cgltf_json_strcmp(tokens+i, json_chunk, "children") == 0)
6393 {
6394 i = cgltf_parse_json_array(options, tokens, i + 1, json_chunk, sizeof(cgltf_node*), (void**)&out_node->children, &out_node->children_count);
6395 if (i < 0)
6396 {
6397 return i;
6398 }
6399
6400 for (cgltf_size k = 0; k < out_node->children_count; ++k)
6401 {
6402 out_node->children[k] = CGLTF_PTRINDEX(cgltf_node, cgltf_json_to_int(tokens + i, json_chunk));
6403 ++i;
6404 }
6405 }
6406 else if (cgltf_json_strcmp(tokens+i, json_chunk, "mesh") == 0)
6407 {
6408 ++i;
6409 CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_PRIMITIVE);
6410 out_node->mesh = CGLTF_PTRINDEX(cgltf_mesh, cgltf_json_to_int(tokens + i, json_chunk));
6411 ++i;
6412 }
6413 else if (cgltf_json_strcmp(tokens+i, json_chunk, "skin") == 0)
6414 {
6415 ++i;
6416 CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_PRIMITIVE);
6417 out_node->skin = CGLTF_PTRINDEX(cgltf_skin, cgltf_json_to_int(tokens + i, json_chunk));
6418 ++i;
6419 }
6420 else if (cgltf_json_strcmp(tokens+i, json_chunk, "camera") == 0)
6421 {
6422 ++i;
6423 CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_PRIMITIVE);
6424 out_node->camera = CGLTF_PTRINDEX(cgltf_camera, cgltf_json_to_int(tokens + i, json_chunk));
6425 ++i;
6426 }
6427 else if (cgltf_json_strcmp(tokens+i, json_chunk, "translation") == 0)
6428 {
6429 out_node->has_translation = 1;
6430 i = cgltf_parse_json_float_array(tokens, i + 1, json_chunk, out_node->translation, 3);
6431 }
6432 else if (cgltf_json_strcmp(tokens+i, json_chunk, "rotation") == 0)
6433 {
6434 out_node->has_rotation = 1;
6435 i = cgltf_parse_json_float_array(tokens, i + 1, json_chunk, out_node->rotation, 4);
6436 }
6437 else if (cgltf_json_strcmp(tokens+i, json_chunk, "scale") == 0)
6438 {
6439 out_node->has_scale = 1;
6440 i = cgltf_parse_json_float_array(tokens, i + 1, json_chunk, out_node->scale, 3);
6441 }
6442 else if (cgltf_json_strcmp(tokens+i, json_chunk, "matrix") == 0)
6443 {
6444 out_node->has_matrix = 1;
6445 i = cgltf_parse_json_float_array(tokens, i + 1, json_chunk, out_node->matrix, 16);
6446 }
6447 else if (cgltf_json_strcmp(tokens + i, json_chunk, "weights") == 0)
6448 {
6449 i = cgltf_parse_json_array(options, tokens, i + 1, json_chunk, sizeof(cgltf_float), (void**)&out_node->weights, &out_node->weights_count);
6450 if (i < 0)
6451 {
6452 return i;
6453 }
6454
6455 i = cgltf_parse_json_float_array(tokens, i - 1, json_chunk, out_node->weights, (int)out_node->weights_count);
6456 }
6457 else if (cgltf_json_strcmp(tokens + i, json_chunk, "extras") == 0)
6458 {
6459 i = cgltf_parse_json_extras(options, tokens, i + 1, json_chunk, &out_node->extras);
6460 }
6461 else if (cgltf_json_strcmp(tokens + i, json_chunk, "extensions") == 0)
6462 {
6463 ++i;
6464
6465 CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
6466 if(out_node->extensions)
6467 {
6468 return CGLTF_ERROR_JSON;
6469 }
6470
6471 int extensions_size = tokens[i].size;
6472 out_node->extensions_count= 0;
6473 out_node->extensions = (cgltf_extension*)cgltf_calloc(options, sizeof(cgltf_extension), extensions_size);
6474
6475 if (!out_node->extensions)
6476 {
6477 return CGLTF_ERROR_NOMEM;
6478 }
6479
6480 ++i;
6481
6482 for (int k = 0; k < extensions_size; ++k)
6483 {
6484 CGLTF_CHECK_KEY(tokens[i]);
6485
6486 if (cgltf_json_strcmp(tokens+i, json_chunk, "KHR_lights_punctual") == 0)
6487 {
6488 ++i;
6489
6490 CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
6491
6492 int data_size = tokens[i].size;
6493 ++i;
6494
6495 for (int m = 0; m < data_size; ++m)
6496 {
6497 CGLTF_CHECK_KEY(tokens[i]);
6498
6499 if (cgltf_json_strcmp(tokens + i, json_chunk, "light") == 0)
6500 {
6501 ++i;
6502 CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_PRIMITIVE);
6503 out_node->light = CGLTF_PTRINDEX(cgltf_light, cgltf_json_to_int(tokens + i, json_chunk));
6504 ++i;
6505 }
6506 else
6507 {
6508 i = cgltf_skip_json(tokens, i + 1);
6509 }
6510
6511 if (i < 0)
6512 {
6513 return i;
6514 }
6515 }
6516 }
6517 else if (cgltf_json_strcmp(tokens+i, json_chunk, "EXT_lights_area") == 0)
6518 {
6519 ++i;
6520
6521 CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
6522
6523 int data_size = tokens[i].size;
6524 ++i;
6525
6526 for (int m = 0; m < data_size; ++m)
6527 {
6528 CGLTF_CHECK_KEY(tokens[i]);
6529
6530 if (cgltf_json_strcmp(tokens + i, json_chunk, "light") == 0)
6531 {
6532 ++i;
6533 CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_PRIMITIVE);
6534 out_node->light_area = CGLTF_PTRINDEX(cgltf_light_area, cgltf_json_to_int(tokens + i, json_chunk));
6535 ++i;
6536 }
6537 else
6538 {
6539 i = cgltf_skip_json(tokens, i + 1);
6540 }
6541
6542 if (i < 0)
6543 {
6544 return i;
6545 }
6546 }
6547 }
6548 else if (cgltf_json_strcmp(tokens+i, json_chunk, "EXT_foundation_curves") == 0)
6549 {
6550 ++i;
6551
6552 CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
6553
6554 int data_size = tokens[i].size;
6555 ++i;
6556
6557 for (int m = 0; m < data_size; ++m)
6558 {
6559 CGLTF_CHECK_KEY(tokens[i]);
6560
6561 if (cgltf_json_strcmp(tokens + i, json_chunk, "curve") == 0)
6562 {
6563 ++i;
6564 CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_PRIMITIVE);
6565 out_node->curve = CGLTF_PTRINDEX(cgltf_curve, cgltf_json_to_int(tokens + i, json_chunk));
6566 ++i;
6567 }
6568 else
6569 {
6570 i = cgltf_skip_json(tokens, i + 1);
6571 }
6572
6573 if (i < 0)
6574 {
6575 return i;
6576 }
6577 }
6578 }
6579 else if (cgltf_json_strcmp(tokens + i, json_chunk, "EXT_mesh_gpu_instancing") == 0)
6580 {
6581 out_node->has_mesh_gpu_instancing = 1;
6582 i = cgltf_parse_json_mesh_gpu_instancing(options, tokens, i + 1, json_chunk, &out_node->mesh_gpu_instancing);
6583 }
6584 else
6585 {
6586 i = cgltf_parse_json_unprocessed_extension(options, tokens, i, json_chunk, &(out_node->extensions[out_node->extensions_count++]));
6587 }
6588
6589 if (i < 0)
6590 {
6591 return i;
6592 }
6593 }
6594 }
6595 else
6596 {
6597 i = cgltf_skip_json(tokens, i+1);
6598 }
6599
6600 if (i < 0)
6601 {
6602 return i;
6603 }
6604 }
6605
6606 return i;
6607}
6608
6609static int cgltf_parse_json_nodes(cgltf_options* options, jsmntok_t const* tokens, int i, const uint8_t* json_chunk, cgltf_data* out_data)
6610{
6611 i = cgltf_parse_json_array(options, tokens, i, json_chunk, sizeof(cgltf_node), (void**)&out_data->nodes, &out_data->nodes_count);
6612 if (i < 0)
6613 {
6614 return i;
6615 }
6616
6617 for (cgltf_size j = 0; j < out_data->nodes_count; ++j)
6618 {
6619 i = cgltf_parse_json_node(options, tokens, i, json_chunk, &out_data->nodes[j]);
6620 if (i < 0)
6621 {
6622 return i;
6623 }
6624 }
6625 return i;
6626}
6627
6628static int cgltf_parse_json_foundation_color_management(cgltf_options* options, jsmntok_t const* tokens, int i, const uint8_t* json_chunk, cgltf_foundation_color_management* out_color_management)
6629{
6630 CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
6631
6632 int size = tokens[i].size;
6633 ++i;
6634
6635 for (int j = 0; j < size; ++j)
6636 {
6637 CGLTF_CHECK_KEY(tokens[i]);
6638
6639 if (cgltf_json_strcmp(tokens + i, json_chunk, "postExposure") == 0)
6640 {
6641 ++i;
6642 out_color_management->has_post_exposure = 1;
6643 out_color_management->post_exposure = cgltf_json_to_float(tokens + i, json_chunk);
6644 ++i;
6645 }
6646 else if (cgltf_json_strcmp(tokens + i, json_chunk, "sdr") == 0)
6647 {
6648 i = cgltf_parse_json_string(options, tokens, i + 1, json_chunk, &out_color_management->sdr);
6649 }
6650 else if (cgltf_json_strcmp(tokens + i, json_chunk, "hdr") == 0)
6651 {
6652 i = cgltf_parse_json_string(options, tokens, i + 1, json_chunk, &out_color_management->hdr);
6653 }
6654 else
6655 {
6656 i = cgltf_skip_json(tokens, i + 1);
6657 }
6658
6659 if (i < 0)
6660 {
6661 return i;
6662 }
6663 }
6664
6665 return i;
6666}
6667
6668static int cgltf_parse_json_foundation_environment(cgltf_options* options, jsmntok_t const* tokens, int i, const uint8_t* json_chunk, cgltf_foundation_environment* out_environment)
6669{
6670 CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
6671
6673 out_environment->color[0] = 0.25f;
6674 out_environment->color[1] = 0.25f;
6675 out_environment->color[2] = 0.25f;
6676 out_environment->strength = 1.0f;
6678 out_environment->azimuth_offset = 0.0f;
6679
6680 int size = tokens[i].size;
6681 ++i;
6682
6683 for (int j = 0; j < size; ++j)
6684 {
6685 CGLTF_CHECK_KEY(tokens[i]);
6686
6687 if (cgltf_json_strcmp(tokens + i, json_chunk, "type") == 0)
6688 {
6689 ++i;
6690 if (cgltf_json_strcmp(tokens + i, json_chunk, "color") == 0)
6691 {
6693 }
6694 else if (cgltf_json_strcmp(tokens + i, json_chunk, "hdri") == 0 || cgltf_json_strcmp(tokens + i, json_chunk, "envMap") == 0)
6695 {
6697 }
6698 ++i;
6699 }
6700 else if (cgltf_json_strcmp(tokens + i, json_chunk, "color") == 0)
6701 {
6702 i = cgltf_parse_json_float_array(tokens, i + 1, json_chunk, out_environment->color, 3);
6703 }
6704 else if (cgltf_json_strcmp(tokens + i, json_chunk, "strength") == 0)
6705 {
6706 ++i;
6707 out_environment->strength = cgltf_json_to_float(tokens + i, json_chunk);
6708 ++i;
6709 }
6710 else if (cgltf_json_strcmp(tokens + i, json_chunk, "uri") == 0)
6711 {
6712 i = cgltf_parse_json_string(options, tokens, i + 1, json_chunk, &out_environment->uri);
6713 }
6714 else if (cgltf_json_strcmp(tokens + i, json_chunk, "projection") == 0)
6715 {
6716 ++i;
6717 if (cgltf_json_strcmp(tokens + i, json_chunk, "longlat") == 0 || cgltf_json_strcmp(tokens + i, json_chunk, "equirectangular") == 0)
6718 {
6720 }
6721 else
6722 {
6724 }
6725 ++i;
6726 }
6727 else if (cgltf_json_strcmp(tokens + i, json_chunk, "azimuthOffset") == 0)
6728 {
6729 ++i;
6730 out_environment->azimuth_offset = cgltf_json_to_float(tokens + i, json_chunk);
6731 ++i;
6732 }
6733 else
6734 {
6735 i = cgltf_skip_json(tokens, i + 1);
6736 }
6737
6738 if (i < 0)
6739 {
6740 return i;
6741 }
6742 }
6743
6744 return i;
6745}
6746
6747static int cgltf_parse_json_scene(cgltf_options* options, jsmntok_t const* tokens, int i, const uint8_t* json_chunk, cgltf_scene* out_scene)
6748{
6749 CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
6750
6751 int size = tokens[i].size;
6752 ++i;
6753
6754 for (int j = 0; j < size; ++j)
6755 {
6756 CGLTF_CHECK_KEY(tokens[i]);
6757
6758 if (cgltf_json_strcmp(tokens+i, json_chunk, "name") == 0)
6759 {
6760 i = cgltf_parse_json_string(options, tokens, i + 1, json_chunk, &out_scene->name);
6761 }
6762 else if (cgltf_json_strcmp(tokens+i, json_chunk, "nodes") == 0)
6763 {
6764 i = cgltf_parse_json_array(options, tokens, i + 1, json_chunk, sizeof(cgltf_node*), (void**)&out_scene->nodes, &out_scene->nodes_count);
6765 if (i < 0)
6766 {
6767 return i;
6768 }
6769
6770 for (cgltf_size k = 0; k < out_scene->nodes_count; ++k)
6771 {
6772 out_scene->nodes[k] = CGLTF_PTRINDEX(cgltf_node, cgltf_json_to_int(tokens + i, json_chunk));
6773 ++i;
6774 }
6775 }
6776 else if (cgltf_json_strcmp(tokens + i, json_chunk, "extras") == 0)
6777 {
6778 i = cgltf_parse_json_extras(options, tokens, i + 1, json_chunk, &out_scene->extras);
6779 }
6780 else if (cgltf_json_strcmp(tokens + i, json_chunk, "extensions") == 0)
6781 {
6782 ++i;
6783
6784 CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
6785 if(out_scene->extensions)
6786 {
6787 return CGLTF_ERROR_JSON;
6788 }
6789
6790 int extensions_size = tokens[i].size;
6791 out_scene->extensions_count = 0;
6792 out_scene->extensions = (cgltf_extension*)cgltf_calloc(options, sizeof(cgltf_extension), extensions_size);
6793
6794 if (!out_scene->extensions)
6795 {
6796 return CGLTF_ERROR_NOMEM;
6797 }
6798
6799 ++i;
6800
6801 for (int k = 0; k < extensions_size; ++k)
6802 {
6803 CGLTF_CHECK_KEY(tokens[i]);
6804
6805 if (cgltf_json_strcmp(tokens+i, json_chunk, "EXT_foundation_environment") == 0)
6806 {
6807 out_scene->has_foundation_environment = 1;
6808 i = cgltf_parse_json_foundation_environment(options, tokens, i + 1, json_chunk, &out_scene->foundation_environment);
6809 }
6810 else
6811 {
6812 i = cgltf_parse_json_unprocessed_extension(options, tokens, i, json_chunk, &(out_scene->extensions[out_scene->extensions_count++]));
6813 }
6814
6815 if (i < 0)
6816 {
6817 return i;
6818 }
6819 }
6820 }
6821 else
6822 {
6823 i = cgltf_skip_json(tokens, i+1);
6824 }
6825
6826 if (i < 0)
6827 {
6828 return i;
6829 }
6830 }
6831
6832 return i;
6833}
6834
6835static int cgltf_parse_json_scenes(cgltf_options* options, jsmntok_t const* tokens, int i, const uint8_t* json_chunk, cgltf_data* out_data)
6836{
6837 i = cgltf_parse_json_array(options, tokens, i, json_chunk, sizeof(cgltf_scene), (void**)&out_data->scenes, &out_data->scenes_count);
6838 if (i < 0)
6839 {
6840 return i;
6841 }
6842
6843 for (cgltf_size j = 0; j < out_data->scenes_count; ++j)
6844 {
6845 i = cgltf_parse_json_scene(options, tokens, i, json_chunk, &out_data->scenes[j]);
6846 if (i < 0)
6847 {
6848 return i;
6849 }
6850 }
6851 return i;
6852}
6853
6854static 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)
6855{
6856 (void)options;
6857 CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
6858
6859 int size = tokens[i].size;
6860 ++i;
6861
6862 for (int j = 0; j < size; ++j)
6863 {
6864 CGLTF_CHECK_KEY(tokens[i]);
6865
6866 if (cgltf_json_strcmp(tokens+i, json_chunk, "input") == 0)
6867 {
6868 ++i;
6869 out_sampler->input = CGLTF_PTRINDEX(cgltf_accessor, cgltf_json_to_int(tokens + i, json_chunk));
6870 ++i;
6871 }
6872 else if (cgltf_json_strcmp(tokens+i, json_chunk, "output") == 0)
6873 {
6874 ++i;
6875 out_sampler->output = CGLTF_PTRINDEX(cgltf_accessor, cgltf_json_to_int(tokens + i, json_chunk));
6876 ++i;
6877 }
6878 else if (cgltf_json_strcmp(tokens+i, json_chunk, "interpolation") == 0)
6879 {
6880 ++i;
6881 if (cgltf_json_strcmp(tokens + i, json_chunk, "LINEAR") == 0)
6882 {
6884 }
6885 else if (cgltf_json_strcmp(tokens + i, json_chunk, "STEP") == 0)
6886 {
6888 }
6889 else if (cgltf_json_strcmp(tokens + i, json_chunk, "CUBICSPLINE") == 0)
6890 {
6892 }
6893 ++i;
6894 }
6895 else if (cgltf_json_strcmp(tokens + i, json_chunk, "extras") == 0)
6896 {
6897 i = cgltf_parse_json_extras(options, tokens, i + 1, json_chunk, &out_sampler->extras);
6898 }
6899 else if (cgltf_json_strcmp(tokens + i, json_chunk, "extensions") == 0)
6900 {
6901 i = cgltf_parse_json_unprocessed_extensions(options, tokens, i, json_chunk, &out_sampler->extensions_count, &out_sampler->extensions);
6902 }
6903 else
6904 {
6905 i = cgltf_skip_json(tokens, i+1);
6906 }
6907
6908 if (i < 0)
6909 {
6910 return i;
6911 }
6912 }
6913
6914 return i;
6915}
6916
6917static 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)
6918{
6919 (void)options;
6920 CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
6921
6922 int size = tokens[i].size;
6923 ++i;
6924
6925 for (int j = 0; j < size; ++j)
6926 {
6927 CGLTF_CHECK_KEY(tokens[i]);
6928
6929 if (cgltf_json_strcmp(tokens+i, json_chunk, "sampler") == 0)
6930 {
6931 ++i;
6932 out_channel->sampler = CGLTF_PTRINDEX(cgltf_animation_sampler, cgltf_json_to_int(tokens + i, json_chunk));
6933 ++i;
6934 }
6935 else if (cgltf_json_strcmp(tokens+i, json_chunk, "target") == 0)
6936 {
6937 ++i;
6938
6939 CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
6940
6941 int target_size = tokens[i].size;
6942 ++i;
6943
6944 for (int k = 0; k < target_size; ++k)
6945 {
6946 CGLTF_CHECK_KEY(tokens[i]);
6947
6948 if (cgltf_json_strcmp(tokens+i, json_chunk, "node") == 0)
6949 {
6950 ++i;
6951 out_channel->target_node = CGLTF_PTRINDEX(cgltf_node, cgltf_json_to_int(tokens + i, json_chunk));
6952 ++i;
6953 }
6954 else if (cgltf_json_strcmp(tokens+i, json_chunk, "path") == 0)
6955 {
6956 ++i;
6957 if (cgltf_json_strcmp(tokens+i, json_chunk, "translation") == 0)
6958 {
6960 }
6961 else if (cgltf_json_strcmp(tokens+i, json_chunk, "rotation") == 0)
6962 {
6964 }
6965 else if (cgltf_json_strcmp(tokens+i, json_chunk, "scale") == 0)
6966 {
6968 }
6969 else if (cgltf_json_strcmp(tokens+i, json_chunk, "weights") == 0)
6970 {
6972 }
6973 ++i;
6974 }
6975 else if (cgltf_json_strcmp(tokens + i, json_chunk, "extras") == 0)
6976 {
6977 i = cgltf_parse_json_extras(options, tokens, i + 1, json_chunk, &out_channel->extras);
6978 }
6979 else if (cgltf_json_strcmp(tokens + i, json_chunk, "extensions") == 0)
6980 {
6981 i = cgltf_parse_json_unprocessed_extensions(options, tokens, i, json_chunk, &out_channel->extensions_count, &out_channel->extensions);
6982 }
6983 else
6984 {
6985 i = cgltf_skip_json(tokens, i+1);
6986 }
6987
6988 if (i < 0)
6989 {
6990 return i;
6991 }
6992 }
6993 }
6994 else
6995 {
6996 i = cgltf_skip_json(tokens, i+1);
6997 }
6998
6999 if (i < 0)
7000 {
7001 return i;
7002 }
7003 }
7004
7005 return i;
7006}
7007
7008static int cgltf_parse_json_animation(cgltf_options* options, jsmntok_t const* tokens, int i, const uint8_t* json_chunk, cgltf_animation* out_animation)
7009{
7010 CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
7011
7012 int size = tokens[i].size;
7013 ++i;
7014
7015 for (int j = 0; j < size; ++j)
7016 {
7017 CGLTF_CHECK_KEY(tokens[i]);
7018
7019 if (cgltf_json_strcmp(tokens+i, json_chunk, "name") == 0)
7020 {
7021 i = cgltf_parse_json_string(options, tokens, i + 1, json_chunk, &out_animation->name);
7022 }
7023 else if (cgltf_json_strcmp(tokens+i, json_chunk, "samplers") == 0)
7024 {
7025 i = cgltf_parse_json_array(options, tokens, i + 1, json_chunk, sizeof(cgltf_animation_sampler), (void**)&out_animation->samplers, &out_animation->samplers_count);
7026 if (i < 0)
7027 {
7028 return i;
7029 }
7030
7031 for (cgltf_size k = 0; k < out_animation->samplers_count; ++k)
7032 {
7033 i = cgltf_parse_json_animation_sampler(options, tokens, i, json_chunk, &out_animation->samplers[k]);
7034 if (i < 0)
7035 {
7036 return i;
7037 }
7038 }
7039 }
7040 else if (cgltf_json_strcmp(tokens+i, json_chunk, "channels") == 0)
7041 {
7042 i = cgltf_parse_json_array(options, tokens, i + 1, json_chunk, sizeof(cgltf_animation_channel), (void**)&out_animation->channels, &out_animation->channels_count);
7043 if (i < 0)
7044 {
7045 return i;
7046 }
7047
7048 for (cgltf_size k = 0; k < out_animation->channels_count; ++k)
7049 {
7050 i = cgltf_parse_json_animation_channel(options, tokens, i, json_chunk, &out_animation->channels[k]);
7051 if (i < 0)
7052 {
7053 return i;
7054 }
7055 }
7056 }
7057 else if (cgltf_json_strcmp(tokens + i, json_chunk, "extras") == 0)
7058 {
7059 i = cgltf_parse_json_extras(options, tokens, i + 1, json_chunk, &out_animation->extras);
7060 }
7061 else if (cgltf_json_strcmp(tokens + i, json_chunk, "extensions") == 0)
7062 {
7063 i = cgltf_parse_json_unprocessed_extensions(options, tokens, i, json_chunk, &out_animation->extensions_count, &out_animation->extensions);
7064 }
7065 else
7066 {
7067 i = cgltf_skip_json(tokens, i+1);
7068 }
7069
7070 if (i < 0)
7071 {
7072 return i;
7073 }
7074 }
7075
7076 return i;
7077}
7078
7079static int cgltf_parse_json_animations(cgltf_options* options, jsmntok_t const* tokens, int i, const uint8_t* json_chunk, cgltf_data* out_data)
7080{
7081 i = cgltf_parse_json_array(options, tokens, i, json_chunk, sizeof(cgltf_animation), (void**)&out_data->animations, &out_data->animations_count);
7082 if (i < 0)
7083 {
7084 return i;
7085 }
7086
7087 for (cgltf_size j = 0; j < out_data->animations_count; ++j)
7088 {
7089 i = cgltf_parse_json_animation(options, tokens, i, json_chunk, &out_data->animations[j]);
7090 if (i < 0)
7091 {
7092 return i;
7093 }
7094 }
7095 return i;
7096}
7097
7098static int cgltf_parse_json_variant(cgltf_options* options, jsmntok_t const* tokens, int i, const uint8_t* json_chunk, cgltf_material_variant* out_variant)
7099{
7100 CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
7101
7102 int size = tokens[i].size;
7103 ++i;
7104
7105 for (int j = 0; j < size; ++j)
7106 {
7107 CGLTF_CHECK_KEY(tokens[i]);
7108
7109 if (cgltf_json_strcmp(tokens+i, json_chunk, "name") == 0)
7110 {
7111 i = cgltf_parse_json_string(options, tokens, i + 1, json_chunk, &out_variant->name);
7112 }
7113 else if (cgltf_json_strcmp(tokens + i, json_chunk, "extras") == 0)
7114 {
7115 i = cgltf_parse_json_extras(options, tokens, i + 1, json_chunk, &out_variant->extras);
7116 }
7117 else
7118 {
7119 i = cgltf_skip_json(tokens, i+1);
7120 }
7121
7122 if (i < 0)
7123 {
7124 return i;
7125 }
7126 }
7127
7128 return i;
7129}
7130
7131static int cgltf_parse_json_variants(cgltf_options* options, jsmntok_t const* tokens, int i, const uint8_t* json_chunk, cgltf_data* out_data)
7132{
7133 i = cgltf_parse_json_array(options, tokens, i, json_chunk, sizeof(cgltf_material_variant), (void**)&out_data->variants, &out_data->variants_count);
7134 if (i < 0)
7135 {
7136 return i;
7137 }
7138
7139 for (cgltf_size j = 0; j < out_data->variants_count; ++j)
7140 {
7141 i = cgltf_parse_json_variant(options, tokens, i, json_chunk, &out_data->variants[j]);
7142 if (i < 0)
7143 {
7144 return i;
7145 }
7146 }
7147 return i;
7148}
7149
7150static int cgltf_parse_json_asset(cgltf_options* options, jsmntok_t const* tokens, int i, const uint8_t* json_chunk, cgltf_asset* out_asset)
7151{
7152 CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
7153
7154 int size = tokens[i].size;
7155 ++i;
7156
7157 for (int j = 0; j < size; ++j)
7158 {
7159 CGLTF_CHECK_KEY(tokens[i]);
7160
7161 if (cgltf_json_strcmp(tokens+i, json_chunk, "copyright") == 0)
7162 {
7163 i = cgltf_parse_json_string(options, tokens, i + 1, json_chunk, &out_asset->copyright);
7164 }
7165 else if (cgltf_json_strcmp(tokens+i, json_chunk, "generator") == 0)
7166 {
7167 i = cgltf_parse_json_string(options, tokens, i + 1, json_chunk, &out_asset->generator);
7168 }
7169 else if (cgltf_json_strcmp(tokens+i, json_chunk, "version") == 0)
7170 {
7171 i = cgltf_parse_json_string(options, tokens, i + 1, json_chunk, &out_asset->version);
7172 }
7173 else if (cgltf_json_strcmp(tokens+i, json_chunk, "minVersion") == 0)
7174 {
7175 i = cgltf_parse_json_string(options, tokens, i + 1, json_chunk, &out_asset->min_version);
7176 }
7177 else if (cgltf_json_strcmp(tokens + i, json_chunk, "extras") == 0)
7178 {
7179 i = cgltf_parse_json_extras(options, tokens, i + 1, json_chunk, &out_asset->extras);
7180 }
7181 else if (cgltf_json_strcmp(tokens + i, json_chunk, "extensions") == 0)
7182 {
7183 i = cgltf_parse_json_unprocessed_extensions(options, tokens, i, json_chunk, &out_asset->extensions_count, &out_asset->extensions);
7184 }
7185 else
7186 {
7187 i = cgltf_skip_json(tokens, i+1);
7188 }
7189
7190 if (i < 0)
7191 {
7192 return i;
7193 }
7194 }
7195
7196 if (out_asset->version && CGLTF_ATOF(out_asset->version) < 2)
7197 {
7198 return CGLTF_ERROR_LEGACY;
7199 }
7200
7201 return i;
7202}
7203
7205 switch (type)
7206 {
7207 case cgltf_type_vec2:
7208 return 2;
7209 case cgltf_type_vec3:
7210 return 3;
7211 case cgltf_type_vec4:
7212 return 4;
7213 case cgltf_type_mat2:
7214 return 4;
7215 case cgltf_type_mat3:
7216 return 9;
7217 case cgltf_type_mat4:
7218 return 16;
7219 case cgltf_type_invalid:
7220 case cgltf_type_scalar:
7221 default:
7222 return 1;
7223 }
7224}
7225
7227 switch (component_type)
7228 {
7231 return 1;
7234 return 2;
7237 return 4;
7239 default:
7240 return 0;
7241 }
7242}
7243
7245{
7246 cgltf_size component_size = cgltf_component_size(component_type);
7247 if (type == cgltf_type_mat2 && component_size == 1)
7248 {
7249 return 8 * component_size;
7250 }
7251 else if (type == cgltf_type_mat3 && (component_size == 1 || component_size == 2))
7252 {
7253 return 12 * component_size;
7254 }
7255 return component_size * cgltf_num_components(type);
7256}
7257
7258static int cgltf_fixup_pointers(cgltf_data* out_data);
7259
7260static int cgltf_parse_json_root(cgltf_options* options, jsmntok_t const* tokens, int i, const uint8_t* json_chunk, cgltf_data* out_data)
7261{
7262 CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
7263
7264 int size = tokens[i].size;
7265 ++i;
7266
7267 for (int j = 0; j < size; ++j)
7268 {
7269 CGLTF_CHECK_KEY(tokens[i]);
7270
7271 if (cgltf_json_strcmp(tokens + i, json_chunk, "asset") == 0)
7272 {
7273 i = cgltf_parse_json_asset(options, tokens, i + 1, json_chunk, &out_data->asset);
7274 }
7275 else if (cgltf_json_strcmp(tokens + i, json_chunk, "meshes") == 0)
7276 {
7277 i = cgltf_parse_json_meshes(options, tokens, i + 1, json_chunk, out_data);
7278 }
7279 else if (cgltf_json_strcmp(tokens + i, json_chunk, "accessors") == 0)
7280 {
7281 i = cgltf_parse_json_accessors(options, tokens, i + 1, json_chunk, out_data);
7282 }
7283 else if (cgltf_json_strcmp(tokens + i, json_chunk, "bufferViews") == 0)
7284 {
7285 i = cgltf_parse_json_buffer_views(options, tokens, i + 1, json_chunk, out_data);
7286 }
7287 else if (cgltf_json_strcmp(tokens + i, json_chunk, "buffers") == 0)
7288 {
7289 i = cgltf_parse_json_buffers(options, tokens, i + 1, json_chunk, out_data);
7290 }
7291 else if (cgltf_json_strcmp(tokens + i, json_chunk, "materials") == 0)
7292 {
7293 i = cgltf_parse_json_materials(options, tokens, i + 1, json_chunk, out_data);
7294 }
7295 else if (cgltf_json_strcmp(tokens + i, json_chunk, "images") == 0)
7296 {
7297 i = cgltf_parse_json_images(options, tokens, i + 1, json_chunk, out_data);
7298 }
7299 else if (cgltf_json_strcmp(tokens + i, json_chunk, "textures") == 0)
7300 {
7301 i = cgltf_parse_json_textures(options, tokens, i + 1, json_chunk, out_data);
7302 }
7303 else if (cgltf_json_strcmp(tokens + i, json_chunk, "samplers") == 0)
7304 {
7305 i = cgltf_parse_json_samplers(options, tokens, i + 1, json_chunk, out_data);
7306 }
7307 else if (cgltf_json_strcmp(tokens + i, json_chunk, "skins") == 0)
7308 {
7309 i = cgltf_parse_json_skins(options, tokens, i + 1, json_chunk, out_data);
7310 }
7311 else if (cgltf_json_strcmp(tokens + i, json_chunk, "cameras") == 0)
7312 {
7313 i = cgltf_parse_json_cameras(options, tokens, i + 1, json_chunk, out_data);
7314 }
7315 else if (cgltf_json_strcmp(tokens + i, json_chunk, "nodes") == 0)
7316 {
7317 i = cgltf_parse_json_nodes(options, tokens, i + 1, json_chunk, out_data);
7318 }
7319 else if (cgltf_json_strcmp(tokens + i, json_chunk, "scenes") == 0)
7320 {
7321 i = cgltf_parse_json_scenes(options, tokens, i + 1, json_chunk, out_data);
7322 }
7323 else if (cgltf_json_strcmp(tokens + i, json_chunk, "scene") == 0)
7324 {
7325 ++i;
7326 out_data->scene = CGLTF_PTRINDEX(cgltf_scene, cgltf_json_to_int(tokens + i, json_chunk));
7327 ++i;
7328 }
7329 else if (cgltf_json_strcmp(tokens + i, json_chunk, "animations") == 0)
7330 {
7331 i = cgltf_parse_json_animations(options, tokens, i + 1, json_chunk, out_data);
7332 }
7333 else if (cgltf_json_strcmp(tokens+i, json_chunk, "extras") == 0)
7334 {
7335 i = cgltf_parse_json_extras(options, tokens, i + 1, json_chunk, &out_data->extras);
7336 }
7337 else if (cgltf_json_strcmp(tokens + i, json_chunk, "extensions") == 0)
7338 {
7339 ++i;
7340
7341 CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
7342 if(out_data->data_extensions)
7343 {
7344 return CGLTF_ERROR_JSON;
7345 }
7346
7347 int extensions_size = tokens[i].size;
7348 out_data->data_extensions_count = 0;
7349 out_data->data_extensions = (cgltf_extension*)cgltf_calloc(options, sizeof(cgltf_extension), extensions_size);
7350
7351 if (!out_data->data_extensions)
7352 {
7353 return CGLTF_ERROR_NOMEM;
7354 }
7355
7356 ++i;
7357
7358 for (int k = 0; k < extensions_size; ++k)
7359 {
7360 CGLTF_CHECK_KEY(tokens[i]);
7361
7362 if (cgltf_json_strcmp(tokens+i, json_chunk, "EXT_foundation_colormanagement") == 0)
7363 {
7364 out_data->has_foundation_color_management = 1;
7365 i = cgltf_parse_json_foundation_color_management(options, tokens, i + 1, json_chunk, &out_data->foundation_color_management);
7366 }
7367 else if (cgltf_json_strcmp(tokens+i, json_chunk, "KHR_lights_punctual") == 0)
7368 {
7369 ++i;
7370
7371 CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
7372
7373 int data_size = tokens[i].size;
7374 ++i;
7375
7376 for (int m = 0; m < data_size; ++m)
7377 {
7378 CGLTF_CHECK_KEY(tokens[i]);
7379
7380 if (cgltf_json_strcmp(tokens + i, json_chunk, "lights") == 0)
7381 {
7382 i = cgltf_parse_json_lights(options, tokens, i + 1, json_chunk, out_data);
7383 }
7384 else
7385 {
7386 i = cgltf_skip_json(tokens, i + 1);
7387 }
7388
7389 if (i < 0)
7390 {
7391 return i;
7392 }
7393 }
7394 }
7395 else if (cgltf_json_strcmp(tokens+i, json_chunk, "EXT_lights_area") == 0)
7396 {
7397 ++i;
7398
7399 CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
7400
7401 int data_size = tokens[i].size;
7402 ++i;
7403
7404 for (int m = 0; m < data_size; ++m)
7405 {
7406 CGLTF_CHECK_KEY(tokens[i]);
7407
7408 if (cgltf_json_strcmp(tokens + i, json_chunk, "lights") == 0)
7409 {
7410 i = cgltf_parse_json_lights_area(options, tokens, i + 1, json_chunk, out_data);
7411 }
7412 else
7413 {
7414 i = cgltf_skip_json(tokens, i + 1);
7415 }
7416
7417 if (i < 0)
7418 {
7419 return i;
7420 }
7421 }
7422 }
7423 else if (cgltf_json_strcmp(tokens+i, json_chunk, "EXT_foundation_curves") == 0)
7424 {
7425 ++i;
7426
7427 CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
7428
7429 int data_size = tokens[i].size;
7430 ++i;
7431
7432 for (int m = 0; m < data_size; ++m)
7433 {
7434 CGLTF_CHECK_KEY(tokens[i]);
7435
7436 if (cgltf_json_strcmp(tokens + i, json_chunk, "curves") == 0)
7437 {
7438 i = cgltf_parse_json_curves(options, tokens, i + 1, json_chunk, out_data);
7439 }
7440 else
7441 {
7442 i = cgltf_skip_json(tokens, i + 1);
7443 }
7444
7445 if (i < 0)
7446 {
7447 return i;
7448 }
7449 }
7450 }
7451 else if (cgltf_json_strcmp(tokens+i, json_chunk, "KHR_materials_variants") == 0)
7452 {
7453 ++i;
7454
7455 CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
7456
7457 int data_size = tokens[i].size;
7458 ++i;
7459
7460 for (int m = 0; m < data_size; ++m)
7461 {
7462 CGLTF_CHECK_KEY(tokens[i]);
7463
7464 if (cgltf_json_strcmp(tokens + i, json_chunk, "variants") == 0)
7465 {
7466 i = cgltf_parse_json_variants(options, tokens, i + 1, json_chunk, out_data);
7467 }
7468 else
7469 {
7470 i = cgltf_skip_json(tokens, i + 1);
7471 }
7472
7473 if (i < 0)
7474 {
7475 return i;
7476 }
7477 }
7478 }
7479 else
7480 {
7481 i = cgltf_parse_json_unprocessed_extension(options, tokens, i, json_chunk, &(out_data->data_extensions[out_data->data_extensions_count++]));
7482 }
7483
7484 if (i < 0)
7485 {
7486 return i;
7487 }
7488 }
7489 }
7490 else if (cgltf_json_strcmp(tokens + i, json_chunk, "extensionsUsed") == 0)
7491 {
7492 i = cgltf_parse_json_string_array(options, tokens, i + 1, json_chunk, &out_data->extensions_used, &out_data->extensions_used_count);
7493 }
7494 else if (cgltf_json_strcmp(tokens + i, json_chunk, "extensionsRequired") == 0)
7495 {
7496 i = cgltf_parse_json_string_array(options, tokens, i + 1, json_chunk, &out_data->extensions_required, &out_data->extensions_required_count);
7497 }
7498 else
7499 {
7500 i = cgltf_skip_json(tokens, i + 1);
7501 }
7502
7503 if (i < 0)
7504 {
7505 return i;
7506 }
7507 }
7508
7509 return i;
7510}
7511
7512cgltf_result cgltf_parse_json(cgltf_options* options, const uint8_t* json_chunk, cgltf_size size, cgltf_data** out_data)
7513{
7514 jsmn_parser parser = { 0, 0, 0 };
7515
7516 if (options->json_token_count == 0)
7517 {
7518 int token_count = jsmn_parse(&parser, (const char*)json_chunk, size, NULL, 0);
7519
7520 if (token_count <= 0)
7521 {
7523 }
7524
7525 options->json_token_count = token_count;
7526 }
7527
7528 jsmntok_t* tokens = (jsmntok_t*)options->memory.alloc_func(options->memory.user_data, sizeof(jsmntok_t) * (options->json_token_count + 1));
7529
7530 if (!tokens)
7531 {
7533 }
7534
7535 jsmn_init(&parser);
7536
7537 int token_count = jsmn_parse(&parser, (const char*)json_chunk, size, tokens, options->json_token_count);
7538
7539 if (token_count <= 0)
7540 {
7541 options->memory.free_func(options->memory.user_data, tokens);
7543 }
7544
7545 // this makes sure that we always have an UNDEFINED token at the end of the stream
7546 // for invalid JSON inputs this makes sure we don't perform out of bound reads of token data
7547 tokens[token_count].type = JSMN_UNDEFINED;
7548
7549 cgltf_data* data = (cgltf_data*)options->memory.alloc_func(options->memory.user_data, sizeof(cgltf_data));
7550
7551 if (!data)
7552 {
7553 options->memory.free_func(options->memory.user_data, tokens);
7555 }
7556
7557 memset(data, 0, sizeof(cgltf_data));
7558 data->memory = options->memory;
7559 data->file = options->file;
7560
7561 int i = cgltf_parse_json_root(options, tokens, 0, json_chunk, data);
7562
7563 options->memory.free_func(options->memory.user_data, tokens);
7564
7565 if (i < 0)
7566 {
7567 cgltf_free(data);
7568
7569 switch (i)
7570 {
7571 case CGLTF_ERROR_NOMEM: return cgltf_result_out_of_memory;
7572 case CGLTF_ERROR_LEGACY: return cgltf_result_legacy_gltf;
7573 default: return cgltf_result_invalid_gltf;
7574 }
7575 }
7576
7577 if (cgltf_fixup_pointers(data) < 0)
7578 {
7579 cgltf_free(data);
7581 }
7582
7583 data->json = (const char*)json_chunk;
7584 data->json_size = size;
7585
7586 *out_data = data;
7587
7588 return cgltf_result_success;
7589}
7590
7591static int cgltf_fixup_pointers(cgltf_data* data)
7592{
7593 for (cgltf_size i = 0; i < data->meshes_count; ++i)
7594 {
7595 for (cgltf_size j = 0; j < data->meshes[i].primitives_count; ++j)
7596 {
7597 CGLTF_PTRFIXUP(data->meshes[i].primitives[j].indices, data->accessors, data->accessors_count);
7598 CGLTF_PTRFIXUP(data->meshes[i].primitives[j].material, data->materials, data->materials_count);
7599
7600 for (cgltf_size k = 0; k < data->meshes[i].primitives[j].attributes_count; ++k)
7601 {
7602 CGLTF_PTRFIXUP_REQ(data->meshes[i].primitives[j].attributes[k].data, data->accessors, data->accessors_count);
7603 }
7604
7605 for (cgltf_size k = 0; k < data->meshes[i].primitives[j].targets_count; ++k)
7606 {
7607 for (cgltf_size m = 0; m < data->meshes[i].primitives[j].targets[k].attributes_count; ++m)
7608 {
7609 CGLTF_PTRFIXUP_REQ(data->meshes[i].primitives[j].targets[k].attributes[m].data, data->accessors, data->accessors_count);
7610 }
7611 }
7612
7614 {
7615 CGLTF_PTRFIXUP_REQ(data->meshes[i].primitives[j].draco_mesh_compression.buffer_view, data->buffer_views, data->buffer_views_count);
7616 for (cgltf_size m = 0; m < data->meshes[i].primitives[j].draco_mesh_compression.attributes_count; ++m)
7617 {
7618 CGLTF_PTRFIXUP_REQ(data->meshes[i].primitives[j].draco_mesh_compression.attributes[m].data, data->accessors, data->accessors_count);
7619 }
7620 }
7621
7622 for (cgltf_size k = 0; k < data->meshes[i].primitives[j].mappings_count; ++k)
7623 {
7624 CGLTF_PTRFIXUP_REQ(data->meshes[i].primitives[j].mappings[k].material, data->materials, data->materials_count);
7625 }
7626 }
7627 }
7628
7629 for (cgltf_size i = 0; i < data->accessors_count; ++i)
7630 {
7631 CGLTF_PTRFIXUP(data->accessors[i].buffer_view, data->buffer_views, data->buffer_views_count);
7632
7633 if (data->accessors[i].is_sparse)
7634 {
7635 CGLTF_PTRFIXUP_REQ(data->accessors[i].sparse.indices_buffer_view, data->buffer_views, data->buffer_views_count);
7636 CGLTF_PTRFIXUP_REQ(data->accessors[i].sparse.values_buffer_view, data->buffer_views, data->buffer_views_count);
7637 }
7638
7639 if (data->accessors[i].buffer_view)
7640 {
7641 data->accessors[i].stride = data->accessors[i].buffer_view->stride;
7642 }
7643
7644 if (data->accessors[i].stride == 0)
7645 {
7646 data->accessors[i].stride = cgltf_calc_size(data->accessors[i].type, data->accessors[i].component_type);
7647 }
7648 }
7649
7650 for (cgltf_size i = 0; i < data->textures_count; ++i)
7651 {
7652 CGLTF_PTRFIXUP(data->textures[i].image, data->images, data->images_count);
7653 CGLTF_PTRFIXUP(data->textures[i].basisu_image, data->images, data->images_count);
7654 CGLTF_PTRFIXUP(data->textures[i].webp_image, data->images, data->images_count);
7655 CGLTF_PTRFIXUP(data->textures[i].sampler, data->samplers, data->samplers_count);
7656 }
7657
7658 for (cgltf_size i = 0; i < data->images_count; ++i)
7659 {
7660 CGLTF_PTRFIXUP(data->images[i].buffer_view, data->buffer_views, data->buffer_views_count);
7661 }
7662
7663 for (cgltf_size i = 0; i < data->materials_count; ++i)
7664 {
7665 CGLTF_PTRFIXUP(data->materials[i].normal_texture.texture, data->textures, data->textures_count);
7666 CGLTF_PTRFIXUP(data->materials[i].emissive_texture.texture, data->textures, data->textures_count);
7667 CGLTF_PTRFIXUP(data->materials[i].occlusion_texture.texture, data->textures, data->textures_count);
7668
7671
7672 CGLTF_PTRFIXUP(data->materials[i].pbr_specular_glossiness.diffuse_texture.texture, data->textures, data->textures_count);
7674
7675 CGLTF_PTRFIXUP(data->materials[i].clearcoat.clearcoat_texture.texture, data->textures, data->textures_count);
7676 CGLTF_PTRFIXUP(data->materials[i].clearcoat.clearcoat_roughness_texture.texture, data->textures, data->textures_count);
7677 CGLTF_PTRFIXUP(data->materials[i].clearcoat.clearcoat_normal_texture.texture, data->textures, data->textures_count);
7678
7679 CGLTF_PTRFIXUP(data->materials[i].specular.specular_texture.texture, data->textures, data->textures_count);
7680 CGLTF_PTRFIXUP(data->materials[i].specular.specular_color_texture.texture, data->textures, data->textures_count);
7681
7682 CGLTF_PTRFIXUP(data->materials[i].transmission.transmission_texture.texture, data->textures, data->textures_count);
7683
7684 CGLTF_PTRFIXUP(data->materials[i].volume.thickness_texture.texture, data->textures, data->textures_count);
7685
7686 CGLTF_PTRFIXUP(data->materials[i].sheen.sheen_color_texture.texture, data->textures, data->textures_count);
7687 CGLTF_PTRFIXUP(data->materials[i].sheen.sheen_roughness_texture.texture, data->textures, data->textures_count);
7688
7689 CGLTF_PTRFIXUP(data->materials[i].iridescence.iridescence_texture.texture, data->textures, data->textures_count);
7691
7694
7695 CGLTF_PTRFIXUP(data->materials[i].anisotropy.anisotropy_texture.texture, data->textures, data->textures_count);
7696 }
7697
7698 for (cgltf_size i = 0; i < data->curves_count; ++i)
7699 {
7700 CGLTF_PTRFIXUP_REQ(data->curves[i].points, data->accessors, data->accessors_count);
7701 CGLTF_PTRFIXUP_REQ(data->curves[i].curve_vertex_counts, data->accessors, data->accessors_count);
7702 CGLTF_PTRFIXUP(data->curves[i].material, data->materials, data->materials_count);
7703 }
7704
7705 for (cgltf_size i = 0; i < data->buffer_views_count; ++i)
7706 {
7707 CGLTF_PTRFIXUP_REQ(data->buffer_views[i].buffer, data->buffers, data->buffers_count);
7708
7710 {
7711 CGLTF_PTRFIXUP_REQ(data->buffer_views[i].meshopt_compression.buffer, data->buffers, data->buffers_count);
7712 }
7713 }
7714
7715 for (cgltf_size i = 0; i < data->skins_count; ++i)
7716 {
7717 for (cgltf_size j = 0; j < data->skins[i].joints_count; ++j)
7718 {
7719 CGLTF_PTRFIXUP_REQ(data->skins[i].joints[j], data->nodes, data->nodes_count);
7720 }
7721
7722 CGLTF_PTRFIXUP(data->skins[i].skeleton, data->nodes, data->nodes_count);
7723 CGLTF_PTRFIXUP(data->skins[i].inverse_bind_matrices, data->accessors, data->accessors_count);
7724 }
7725
7726 for (cgltf_size i = 0; i < data->nodes_count; ++i)
7727 {
7728 for (cgltf_size j = 0; j < data->nodes[i].children_count; ++j)
7729 {
7730 CGLTF_PTRFIXUP_REQ(data->nodes[i].children[j], data->nodes, data->nodes_count);
7731
7732 if (data->nodes[i].children[j]->parent)
7733 {
7734 return CGLTF_ERROR_JSON;
7735 }
7736
7737 data->nodes[i].children[j]->parent = &data->nodes[i];
7738 }
7739
7740 CGLTF_PTRFIXUP(data->nodes[i].mesh, data->meshes, data->meshes_count);
7741 CGLTF_PTRFIXUP(data->nodes[i].skin, data->skins, data->skins_count);
7742 CGLTF_PTRFIXUP(data->nodes[i].camera, data->cameras, data->cameras_count);
7743 CGLTF_PTRFIXUP(data->nodes[i].light, data->lights, data->lights_count);
7744 CGLTF_PTRFIXUP(data->nodes[i].light_area, data->lights_area, data->lights_area_count);
7745 CGLTF_PTRFIXUP(data->nodes[i].curve, data->curves, data->curves_count);
7746
7747 if (data->nodes[i].has_mesh_gpu_instancing)
7748 {
7749 for (cgltf_size m = 0; m < data->nodes[i].mesh_gpu_instancing.attributes_count; ++m)
7750 {
7751 CGLTF_PTRFIXUP_REQ(data->nodes[i].mesh_gpu_instancing.attributes[m].data, data->accessors, data->accessors_count);
7752 }
7753 }
7754 }
7755
7756 for (cgltf_size i = 0; i < data->scenes_count; ++i)
7757 {
7758 for (cgltf_size j = 0; j < data->scenes[i].nodes_count; ++j)
7759 {
7760 CGLTF_PTRFIXUP_REQ(data->scenes[i].nodes[j], data->nodes, data->nodes_count);
7761
7762 if (data->scenes[i].nodes[j]->parent)
7763 {
7764 return CGLTF_ERROR_JSON;
7765 }
7766 }
7767 }
7768
7769 CGLTF_PTRFIXUP(data->scene, data->scenes, data->scenes_count);
7770
7771 for (cgltf_size i = 0; i < data->animations_count; ++i)
7772 {
7773 for (cgltf_size j = 0; j < data->animations[i].samplers_count; ++j)
7774 {
7775 CGLTF_PTRFIXUP_REQ(data->animations[i].samplers[j].input, data->accessors, data->accessors_count);
7776 CGLTF_PTRFIXUP_REQ(data->animations[i].samplers[j].output, data->accessors, data->accessors_count);
7777 }
7778
7779 for (cgltf_size j = 0; j < data->animations[i].channels_count; ++j)
7780 {
7781 CGLTF_PTRFIXUP_REQ(data->animations[i].channels[j].sampler, data->animations[i].samplers, data->animations[i].samplers_count);
7782 CGLTF_PTRFIXUP(data->animations[i].channels[j].target_node, data->nodes, data->nodes_count);
7783 }
7784 }
7785
7786 return 0;
7787}
7788
7789/*
7790 * -- jsmn.c start --
7791 * Source: https://github.com/zserge/jsmn
7792 * License: MIT
7793 *
7794 * Copyright (c) 2010 Serge A. Zaitsev
7795
7796 * Permission is hereby granted, free of charge, to any person obtaining a copy
7797 * of this software and associated documentation files (the "Software"), to deal
7798 * in the Software without restriction, including without limitation the rights
7799 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7800 * copies of the Software, and to permit persons to whom the Software is
7801 * furnished to do so, subject to the following conditions:
7802
7803 * The above copyright notice and this permission notice shall be included in
7804 * all copies or substantial portions of the Software.
7805
7806 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
7807 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
7808 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
7809 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
7810 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
7811 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
7812 * THE SOFTWARE.
7813 */
7814
7818static jsmntok_t *jsmn_alloc_token(jsmn_parser *parser,
7819 jsmntok_t *tokens, size_t num_tokens) {
7820 jsmntok_t *tok;
7821 if (parser->toknext >= num_tokens) {
7822 return NULL;
7823 }
7824 tok = &tokens[parser->toknext++];
7825 tok->start = tok->end = -1;
7826 tok->size = 0;
7827#ifdef JSMN_PARENT_LINKS
7828 tok->parent = -1;
7829#endif
7830 return tok;
7831}
7832
7836static void jsmn_fill_token(jsmntok_t *token, jsmntype_t type,
7837 ptrdiff_t start, ptrdiff_t end) {
7838 token->type = type;
7839 token->start = start;
7840 token->end = end;
7841 token->size = 0;
7842}
7843
7847static int jsmn_parse_primitive(jsmn_parser *parser, const char *js,
7848 size_t len, jsmntok_t *tokens, size_t num_tokens) {
7849 jsmntok_t *token;
7850 ptrdiff_t start;
7851
7852 start = parser->pos;
7853
7854 for (; parser->pos < len && js[parser->pos] != '\0'; parser->pos++) {
7855 switch (js[parser->pos]) {
7856#ifndef JSMN_STRICT
7857 /* In strict mode primitive must be followed by "," or "}" or "]" */
7858 case ':':
7859#endif
7860 case '\t' : case '\r' : case '\n' : case ' ' :
7861 case ',' : case ']' : case '}' :
7862 goto found;
7863 }
7864 if (js[parser->pos] < 32 || js[parser->pos] >= 127) {
7865 parser->pos = start;
7866 return JSMN_ERROR_INVAL;
7867 }
7868 }
7869#ifdef JSMN_STRICT
7870 /* In strict mode primitive must be followed by a comma/object/array */
7871 parser->pos = start;
7872 return JSMN_ERROR_PART;
7873#endif
7874
7875found:
7876 if (tokens == NULL) {
7877 parser->pos--;
7878 return 0;
7879 }
7880 token = jsmn_alloc_token(parser, tokens, num_tokens);
7881 if (token == NULL) {
7882 parser->pos = start;
7883 return JSMN_ERROR_NOMEM;
7884 }
7885 jsmn_fill_token(token, JSMN_PRIMITIVE, start, parser->pos);
7886#ifdef JSMN_PARENT_LINKS
7887 token->parent = parser->toksuper;
7888#endif
7889 parser->pos--;
7890 return 0;
7891}
7892
7896static int jsmn_parse_string(jsmn_parser *parser, const char *js,
7897 size_t len, jsmntok_t *tokens, size_t num_tokens) {
7898 jsmntok_t *token;
7899
7900 ptrdiff_t start = parser->pos;
7901
7902 parser->pos++;
7903
7904 /* Skip starting quote */
7905 for (; parser->pos < len && js[parser->pos] != '\0'; parser->pos++) {
7906 char c = js[parser->pos];
7907
7908 /* Quote: end of string */
7909 if (c == '\"') {
7910 if (tokens == NULL) {
7911 return 0;
7912 }
7913 token = jsmn_alloc_token(parser, tokens, num_tokens);
7914 if (token == NULL) {
7915 parser->pos = start;
7916 return JSMN_ERROR_NOMEM;
7917 }
7918 jsmn_fill_token(token, JSMN_STRING, start+1, parser->pos);
7919#ifdef JSMN_PARENT_LINKS
7920 token->parent = parser->toksuper;
7921#endif
7922 return 0;
7923 }
7924
7925 /* Backslash: Quoted symbol expected */
7926 if (c == '\\' && parser->pos + 1 < len) {
7927 int i;
7928 parser->pos++;
7929 switch (js[parser->pos]) {
7930 /* Allowed escaped symbols */
7931 case '\"': case '/' : case '\\' : case 'b' :
7932 case 'f' : case 'r' : case 'n' : case 't' :
7933 break;
7934 /* Allows escaped symbol \uXXXX */
7935 case 'u':
7936 parser->pos++;
7937 for(i = 0; i < 4 && parser->pos < len && js[parser->pos] != '\0'; i++) {
7938 /* If it isn't a hex character we have an error */
7939 if(!((js[parser->pos] >= 48 && js[parser->pos] <= 57) || /* 0-9 */
7940 (js[parser->pos] >= 65 && js[parser->pos] <= 70) || /* A-F */
7941 (js[parser->pos] >= 97 && js[parser->pos] <= 102))) { /* a-f */
7942 parser->pos = start;
7943 return JSMN_ERROR_INVAL;
7944 }
7945 parser->pos++;
7946 }
7947 parser->pos--;
7948 break;
7949 /* Unexpected symbol */
7950 default:
7951 parser->pos = start;
7952 return JSMN_ERROR_INVAL;
7953 }
7954 }
7955 }
7956 parser->pos = start;
7957 return JSMN_ERROR_PART;
7958}
7959
7963static int jsmn_parse(jsmn_parser *parser, const char *js, size_t len,
7964 jsmntok_t *tokens, size_t num_tokens) {
7965 int r;
7966 int i;
7967 jsmntok_t *token;
7968 int count = parser->toknext;
7969
7970 for (; parser->pos < len && js[parser->pos] != '\0'; parser->pos++) {
7971 char c;
7972 jsmntype_t type;
7973
7974 c = js[parser->pos];
7975 switch (c) {
7976 case '{': case '[':
7977 count++;
7978 if (tokens == NULL) {
7979 break;
7980 }
7981 token = jsmn_alloc_token(parser, tokens, num_tokens);
7982 if (token == NULL)
7983 return JSMN_ERROR_NOMEM;
7984 if (parser->toksuper != -1) {
7985 tokens[parser->toksuper].size++;
7986#ifdef JSMN_PARENT_LINKS
7987 token->parent = parser->toksuper;
7988#endif
7989 }
7990 token->type = (c == '{' ? JSMN_OBJECT : JSMN_ARRAY);
7991 token->start = parser->pos;
7992 parser->toksuper = parser->toknext - 1;
7993 break;
7994 case '}': case ']':
7995 if (tokens == NULL)
7996 break;
7997 type = (c == '}' ? JSMN_OBJECT : JSMN_ARRAY);
7998#ifdef JSMN_PARENT_LINKS
7999 if (parser->toknext < 1) {
8000 return JSMN_ERROR_INVAL;
8001 }
8002 token = &tokens[parser->toknext - 1];
8003 for (;;) {
8004 if (token->start != -1 && token->end == -1) {
8005 if (token->type != type) {
8006 return JSMN_ERROR_INVAL;
8007 }
8008 token->end = parser->pos + 1;
8009 parser->toksuper = token->parent;
8010 break;
8011 }
8012 if (token->parent == -1) {
8013 if(token->type != type || parser->toksuper == -1) {
8014 return JSMN_ERROR_INVAL;
8015 }
8016 break;
8017 }
8018 token = &tokens[token->parent];
8019 }
8020#else
8021 for (i = parser->toknext - 1; i >= 0; i--) {
8022 token = &tokens[i];
8023 if (token->start != -1 && token->end == -1) {
8024 if (token->type != type) {
8025 return JSMN_ERROR_INVAL;
8026 }
8027 parser->toksuper = -1;
8028 token->end = parser->pos + 1;
8029 break;
8030 }
8031 }
8032 /* Error if unmatched closing bracket */
8033 if (i == -1) return JSMN_ERROR_INVAL;
8034 for (; i >= 0; i--) {
8035 token = &tokens[i];
8036 if (token->start != -1 && token->end == -1) {
8037 parser->toksuper = i;
8038 break;
8039 }
8040 }
8041#endif
8042 break;
8043 case '\"':
8044 r = jsmn_parse_string(parser, js, len, tokens, num_tokens);
8045 if (r < 0) return r;
8046 count++;
8047 if (parser->toksuper != -1 && tokens != NULL)
8048 tokens[parser->toksuper].size++;
8049 break;
8050 case '\t' : case '\r' : case '\n' : case ' ':
8051 break;
8052 case ':':
8053 parser->toksuper = parser->toknext - 1;
8054 break;
8055 case ',':
8056 if (tokens != NULL && parser->toksuper != -1 &&
8057 tokens[parser->toksuper].type != JSMN_ARRAY &&
8058 tokens[parser->toksuper].type != JSMN_OBJECT) {
8059#ifdef JSMN_PARENT_LINKS
8060 parser->toksuper = tokens[parser->toksuper].parent;
8061#else
8062 for (i = parser->toknext - 1; i >= 0; i--) {
8063 if (tokens[i].type == JSMN_ARRAY || tokens[i].type == JSMN_OBJECT) {
8064 if (tokens[i].start != -1 && tokens[i].end == -1) {
8065 parser->toksuper = i;
8066 break;
8067 }
8068 }
8069 }
8070#endif
8071 }
8072 break;
8073#ifdef JSMN_STRICT
8074 /* In strict mode primitives are: numbers and booleans */
8075 case '-': case '0': case '1' : case '2': case '3' : case '4':
8076 case '5': case '6': case '7' : case '8': case '9':
8077 case 't': case 'f': case 'n' :
8078 /* And they must not be keys of the object */
8079 if (tokens != NULL && parser->toksuper != -1) {
8080 jsmntok_t *t = &tokens[parser->toksuper];
8081 if (t->type == JSMN_OBJECT ||
8082 (t->type == JSMN_STRING && t->size != 0)) {
8083 return JSMN_ERROR_INVAL;
8084 }
8085 }
8086#else
8087 /* In non-strict mode every unquoted value is a primitive */
8088 default:
8089#endif
8090 r = jsmn_parse_primitive(parser, js, len, tokens, num_tokens);
8091 if (r < 0) return r;
8092 count++;
8093 if (parser->toksuper != -1 && tokens != NULL)
8094 tokens[parser->toksuper].size++;
8095 break;
8096
8097#ifdef JSMN_STRICT
8098 /* Unexpected char in strict mode */
8099 default:
8100 return JSMN_ERROR_INVAL;
8101#endif
8102 }
8103 }
8104
8105 if (tokens != NULL) {
8106 for (i = parser->toknext - 1; i >= 0; i--) {
8107 /* Unmatched opened object or array */
8108 if (tokens[i].start != -1 && tokens[i].end == -1) {
8109 return JSMN_ERROR_PART;
8110 }
8111 }
8112 }
8113
8114 return count;
8115}
8116
8121static void jsmn_init(jsmn_parser *parser) {
8122 parser->pos = 0;
8123 parser->toknext = 0;
8124 parser->toksuper = -1;
8125}
8126/*
8127 * -- jsmn.c end --
8128 */
8129
8130#endif /* #ifdef CGLTF_IMPLEMENTATION */
8131
8132/* cgltf is distributed under MIT license:
8133 *
8134 * Copyright (c) 2018-2021 Johannes Kuhlmann
8135
8136 * Permission is hereby granted, free of charge, to any person obtaining a copy
8137 * of this software and associated documentation files (the "Software"), to deal
8138 * in the Software without restriction, including without limitation the rights
8139 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8140 * copies of the Software, and to permit persons to whom the Software is
8141 * furnished to do so, subject to the following conditions:
8142
8143 * The above copyright notice and this permission notice shall be included in all
8144 * copies or substantial portions of the Software.
8145
8146 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
8147 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
8148 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
8149 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
8150 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
8151 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
8152 * SOFTWARE.
8153 */
cgltf_size cgltf_scene_index(const cgltf_data *data, const cgltf_scene *object)
size_t cgltf_size
Definition cgltf.h:104
cgltf_size cgltf_sampler_index(const cgltf_data *data, const cgltf_sampler *object)
void cgltf_node_transform_local(const cgltf_node *node, cgltf_float *out_matrix)
cgltf_size cgltf_accessor_index(const cgltf_data *data, const cgltf_accessor *object)
long long int cgltf_ssize
Definition cgltf.h:105
unsigned int cgltf_uint
Definition cgltf.h:108
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_foundation_material_shader_block
Definition cgltf.h:290
@ cgltf_foundation_material_shader_block_hair
Definition cgltf.h:293
@ cgltf_foundation_material_shader_block_invalid
Definition cgltf.h:291
@ cgltf_foundation_material_shader_block_max_enum
Definition cgltf.h:294
@ cgltf_foundation_material_shader_block_principled
Definition cgltf.h:292
cgltf_animation_path_type
Definition cgltf.h:224
@ cgltf_animation_path_type_max_enum
Definition cgltf.h:230
@ cgltf_animation_path_type_weights
Definition cgltf.h:229
@ cgltf_animation_path_type_invalid
Definition cgltf.h:225
@ cgltf_animation_path_type_translation
Definition cgltf.h:226
@ cgltf_animation_path_type_scale
Definition cgltf.h:228
@ cgltf_animation_path_type_rotation
Definition cgltf.h:227
cgltf_size cgltf_component_size(cgltf_component_type component_type)
cgltf_result cgltf_validate(cgltf_data *data)
cgltf_filter_type
Definition cgltf.h:427
@ cgltf_filter_type_undefined
Definition cgltf.h:428
@ cgltf_filter_type_nearest_mipmap_linear
Definition cgltf.h:433
@ cgltf_filter_type_linear_mipmap_linear
Definition cgltf.h:434
@ cgltf_filter_type_nearest_mipmap_nearest
Definition cgltf.h:431
@ cgltf_filter_type_linear
Definition cgltf.h:430
@ cgltf_filter_type_linear_mipmap_nearest
Definition cgltf.h:432
@ cgltf_filter_type_nearest
Definition cgltf.h:429
cgltf_size cgltf_accessor_unpack_indices(const cgltf_accessor *accessor, void *out, cgltf_size out_component_size, cgltf_size index_count)
cgltf_meshopt_compression_mode
Definition cgltf.h:334
@ cgltf_meshopt_compression_mode_attributes
Definition cgltf.h:336
@ cgltf_meshopt_compression_mode_invalid
Definition cgltf.h:335
@ cgltf_meshopt_compression_mode_triangles
Definition cgltf.h:337
@ cgltf_meshopt_compression_mode_max_enum
Definition cgltf.h:339
@ cgltf_meshopt_compression_mode_indices
Definition cgltf.h:338
cgltf_size cgltf_animation_channel_index(const cgltf_animation *animation, const cgltf_animation_channel *object)
cgltf_wrap_mode
Definition cgltf.h:437
@ cgltf_wrap_mode_repeat
Definition cgltf.h:440
@ cgltf_wrap_mode_clamp_to_edge
Definition cgltf.h:438
@ cgltf_wrap_mode_mirrored_repeat
Definition cgltf.h:439
cgltf_curve_basis
Definition cgltf.h:262
@ cgltf_curve_basis_catmull_rom
Definition cgltf.h:267
@ cgltf_curve_basis_invalid
Definition cgltf.h:263
@ cgltf_curve_basis_linear
Definition cgltf.h:264
@ cgltf_curve_basis_bezier
Definition cgltf.h:265
@ cgltf_curve_basis_max_enum
Definition cgltf.h:268
@ cgltf_curve_basis_bspline
Definition cgltf.h:266
void cgltf_node_transform_world(const cgltf_node *node, cgltf_float *out_matrix)
cgltf_size cgltf_decode_uri(char *uri)
cgltf_foundation_material_hair_model
Definition cgltf.h:297
@ cgltf_foundation_material_hair_model_invalid
Definition cgltf.h:298
@ cgltf_foundation_material_hair_model_chiang
Definition cgltf.h:299
@ cgltf_foundation_material_hair_model_max_enum
Definition cgltf.h:300
cgltf_size cgltf_image_index(const cgltf_data *data, const cgltf_image *object)
cgltf_primitive_type
Definition cgltf.h:204
@ cgltf_primitive_type_invalid
Definition cgltf.h:205
@ cgltf_primitive_type_line_strip
Definition cgltf.h:209
@ cgltf_primitive_type_lines
Definition cgltf.h:207
@ cgltf_primitive_type_triangles
Definition cgltf.h:210
@ cgltf_primitive_type_line_loop
Definition cgltf.h:208
@ cgltf_primitive_type_triangle_fan
Definition cgltf.h:212
@ cgltf_primitive_type_points
Definition cgltf.h:206
@ cgltf_primitive_type_max_enum
Definition cgltf.h:213
@ cgltf_primitive_type_triangle_strip
Definition cgltf.h:211
cgltf_size cgltf_node_index(const cgltf_data *data, const cgltf_node *object)
cgltf_bool cgltf_accessor_read_uint(const cgltf_accessor *accessor, cgltf_size index, cgltf_uint *out, cgltf_size element_size)
cgltf_size cgltf_light_area_index(const cgltf_data *data, const cgltf_light_area *object)
cgltf_result cgltf_parse(const cgltf_options *options, const void *data, cgltf_size size, cgltf_data **out_data)
cgltf_size cgltf_calc_size(cgltf_type type, cgltf_component_type component_type)
cgltf_size cgltf_decode_string(char *string)
const uint8_t * cgltf_buffer_view_data(const cgltf_buffer_view *view)
const cgltf_accessor * cgltf_find_accessor(const cgltf_primitive *prim, cgltf_attribute_type type, cgltf_int index)
cgltf_light_area_type
Definition cgltf.h:255
@ cgltf_light_area_type_disk
Definition cgltf.h:258
@ cgltf_light_area_type_rect
Definition cgltf.h:257
@ cgltf_light_area_type_invalid
Definition cgltf.h:256
@ cgltf_light_area_type_max_enum
Definition cgltf.h:259
int cgltf_bool
Definition cgltf.h:109
int cgltf_int
Definition cgltf.h:107
cgltf_size cgltf_animation_sampler_index(const cgltf_animation *animation, const cgltf_animation_sampler *object)
cgltf_foundation_environment_projection
Definition cgltf.h:284
@ cgltf_foundation_environment_projection_max_enum
Definition cgltf.h:287
@ cgltf_foundation_environment_projection_longlat
Definition cgltf.h:286
@ cgltf_foundation_environment_projection_invalid
Definition cgltf.h:285
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:233
@ cgltf_interpolation_type_cubic_spline
Definition cgltf.h:236
@ cgltf_interpolation_type_max_enum
Definition cgltf.h:237
@ cgltf_interpolation_type_linear
Definition cgltf.h:234
@ cgltf_interpolation_type_step
Definition cgltf.h:235
cgltf_size cgltf_material_index(const cgltf_data *data, const cgltf_material *object)
cgltf_light_type
Definition cgltf.h:247
@ cgltf_light_type_spot
Definition cgltf.h:251
@ cgltf_light_type_invalid
Definition cgltf.h:248
@ cgltf_light_type_max_enum
Definition cgltf.h:252
@ cgltf_light_type_point
Definition cgltf.h:250
@ cgltf_light_type_directional
Definition cgltf.h:249
cgltf_attribute_type
Definition cgltf.h:165
@ cgltf_attribute_type_color
Definition cgltf.h:171
@ cgltf_attribute_type_joints
Definition cgltf.h:172
@ cgltf_attribute_type_custom
Definition cgltf.h:174
@ cgltf_attribute_type_invalid
Definition cgltf.h:166
@ cgltf_attribute_type_texcoord
Definition cgltf.h:170
@ cgltf_attribute_type_weights
Definition cgltf.h:173
@ cgltf_attribute_type_position
Definition cgltf.h:167
@ cgltf_attribute_type_tangent
Definition cgltf.h:169
@ cgltf_attribute_type_normal
Definition cgltf.h:168
@ cgltf_attribute_type_max_enum
Definition cgltf.h:175
cgltf_result cgltf_load_buffer_base64(const cgltf_options *options, cgltf_size size, const char *base64, void **out_data)
cgltf_curve_render_mode
Definition cgltf.h:271
@ cgltf_curve_render_mode_max_enum
Definition cgltf.h:274
@ cgltf_curve_render_mode_invalid
Definition cgltf.h:272
@ cgltf_curve_render_mode_capsule
Definition cgltf.h:273
cgltf_size cgltf_accessor_read_index(const cgltf_accessor *accessor, cgltf_size index)
cgltf_foundation_environment_type
Definition cgltf.h:277
@ cgltf_foundation_environment_type_max_enum
Definition cgltf.h:281
@ cgltf_foundation_environment_type_invalid
Definition cgltf.h:278
@ cgltf_foundation_environment_type_color
Definition cgltf.h:279
@ cgltf_foundation_environment_type_hdri
Definition cgltf.h:280
float cgltf_float
Definition cgltf.h:106
cgltf_size cgltf_curve_index(const cgltf_data *data, const cgltf_curve *object)
cgltf_size cgltf_num_components(cgltf_type type)
cgltf_result cgltf_load_buffers(const cgltf_options *options, cgltf_data *data, const char *gltf_path)
cgltf_size cgltf_light_index(const cgltf_data *data, const cgltf_light *object)
cgltf_size cgltf_skin_index(const cgltf_data *data, const cgltf_skin *object)
cgltf_type
Definition cgltf.h:191
@ cgltf_type_invalid
Definition cgltf.h:192
@ cgltf_type_vec4
Definition cgltf.h:196
@ cgltf_type_mat2
Definition cgltf.h:197
@ cgltf_type_vec2
Definition cgltf.h:194
@ cgltf_type_vec3
Definition cgltf.h:195
@ cgltf_type_scalar
Definition cgltf.h:193
@ cgltf_type_mat3
Definition cgltf.h:198
@ cgltf_type_mat4
Definition cgltf.h:199
@ cgltf_type_max_enum
Definition cgltf.h:200
cgltf_size cgltf_buffer_view_index(const cgltf_data *data, const cgltf_buffer_view *object)
cgltf_component_type
Definition cgltf.h:179
@ cgltf_component_type_r_32f
Definition cgltf.h:186
@ cgltf_component_type_r_8
Definition cgltf.h:181
@ cgltf_component_type_r_8u
Definition cgltf.h:182
@ cgltf_component_type_r_32u
Definition cgltf.h:185
@ cgltf_component_type_r_16u
Definition cgltf.h:184
@ cgltf_component_type_invalid
Definition cgltf.h:180
@ cgltf_component_type_max_enum
Definition cgltf.h:187
@ cgltf_component_type_r_16
Definition cgltf.h:183
cgltf_size cgltf_mesh_index(const cgltf_data *data, const cgltf_mesh *object)
cgltf_size cgltf_accessor_unpack_floats(const cgltf_accessor *accessor, cgltf_float *out, cgltf_size float_count)
cgltf_data_free_method
Definition cgltf.h:303
@ cgltf_data_free_method_max_enum
Definition cgltf.h:307
@ cgltf_data_free_method_memory_free
Definition cgltf.h:306
@ cgltf_data_free_method_none
Definition cgltf.h:304
@ cgltf_data_free_method_file_release
Definition cgltf.h:305
cgltf_size cgltf_texture_index(const cgltf_data *data, const cgltf_texture *object)
cgltf_meshopt_compression_filter
Definition cgltf.h:342
@ cgltf_meshopt_compression_filter_none
Definition cgltf.h:343
@ cgltf_meshopt_compression_filter_quaternion
Definition cgltf.h:345
@ cgltf_meshopt_compression_filter_octahedral
Definition cgltf.h:344
@ cgltf_meshopt_compression_filter_exponential
Definition cgltf.h:346
@ cgltf_meshopt_compression_filter_max_enum
Definition cgltf.h:347
cgltf_size cgltf_camera_index(const cgltf_data *data, const cgltf_camera *object)
cgltf_result
Definition cgltf.h:120
@ cgltf_result_success
Definition cgltf.h:121
@ cgltf_result_invalid_gltf
Definition cgltf.h:125
@ cgltf_result_legacy_gltf
Definition cgltf.h:130
@ cgltf_result_data_too_short
Definition cgltf.h:122
@ cgltf_result_unknown_format
Definition cgltf.h:123
@ cgltf_result_max_enum
Definition cgltf.h:131
@ cgltf_result_file_not_found
Definition cgltf.h:127
@ cgltf_result_out_of_memory
Definition cgltf.h:129
@ cgltf_result_invalid_options
Definition cgltf.h:126
@ cgltf_result_io_error
Definition cgltf.h:128
@ cgltf_result_invalid_json
Definition cgltf.h:124
cgltf_file_type
Definition cgltf.h:112
@ cgltf_file_type_invalid
Definition cgltf.h:113
@ cgltf_file_type_max_enum
Definition cgltf.h:116
@ cgltf_file_type_glb
Definition cgltf.h:115
@ cgltf_file_type_gltf
Definition cgltf.h:114
cgltf_size cgltf_buffer_index(const cgltf_data *data, const cgltf_buffer *object)
cgltf_camera_type
Definition cgltf.h:240
@ cgltf_camera_type_orthographic
Definition cgltf.h:243
@ cgltf_camera_type_invalid
Definition cgltf.h:241
@ cgltf_camera_type_max_enum
Definition cgltf.h:244
@ cgltf_camera_type_perspective
Definition cgltf.h:242
cgltf_alpha_mode
Definition cgltf.h:217
@ cgltf_alpha_mode_mask
Definition cgltf.h:219
@ cgltf_alpha_mode_opaque
Definition cgltf.h:218
@ cgltf_alpha_mode_max_enum
Definition cgltf.h:221
@ cgltf_alpha_mode_blend
Definition cgltf.h:220
cgltf_buffer_view_type
Definition cgltf.h:157
@ cgltf_buffer_view_type_invalid
Definition cgltf.h:158
@ cgltf_buffer_view_type_vertices
Definition cgltf.h:160
@ cgltf_buffer_view_type_max_enum
Definition cgltf.h:161
@ cgltf_buffer_view_type_indices
Definition cgltf.h:159
cgltf_size cgltf_animation_index(const cgltf_data *data, const cgltf_animation *object)
Definition cgltf.h:378
cgltf_buffer_view * indices_buffer_view
Definition cgltf.h:380
cgltf_component_type indices_component_type
Definition cgltf.h:382
cgltf_size values_byte_offset
Definition cgltf.h:384
cgltf_buffer_view * values_buffer_view
Definition cgltf.h:383
cgltf_size indices_byte_offset
Definition cgltf.h:381
cgltf_size count
Definition cgltf.h:379
Definition cgltf.h:388
char * name
Definition cgltf.h:389
cgltf_bool normalized
Definition cgltf.h:391
cgltf_extras extras
Definition cgltf.h:403
cgltf_bool is_sparse
Definition cgltf.h:401
cgltf_float max[16]
Definition cgltf.h:400
cgltf_size count
Definition cgltf.h:394
cgltf_size extensions_count
Definition cgltf.h:404
cgltf_type type
Definition cgltf.h:392
cgltf_float min[16]
Definition cgltf.h:398
cgltf_size offset
Definition cgltf.h:393
cgltf_bool has_min
Definition cgltf.h:397
cgltf_buffer_view * buffer_view
Definition cgltf.h:396
cgltf_bool has_max
Definition cgltf.h:399
cgltf_component_type component_type
Definition cgltf.h:390
cgltf_size stride
Definition cgltf.h:395
cgltf_accessor_sparse sparse
Definition cgltf.h:402
cgltf_extension * extensions
Definition cgltf.h:405
Definition cgltf.h:860
cgltf_node * target_node
Definition cgltf.h:862
cgltf_extras extras
Definition cgltf.h:864
cgltf_animation_path_type target_path
Definition cgltf.h:863
cgltf_animation_sampler * sampler
Definition cgltf.h:861
cgltf_extension * extensions
Definition cgltf.h:866
cgltf_size extensions_count
Definition cgltf.h:865
Definition cgltf.h:851
cgltf_extras extras
Definition cgltf.h:855
cgltf_extension * extensions
Definition cgltf.h:857
cgltf_accessor * input
Definition cgltf.h:852
cgltf_accessor * output
Definition cgltf.h:853
cgltf_interpolation_type interpolation
Definition cgltf.h:854
cgltf_size extensions_count
Definition cgltf.h:856
Definition cgltf.h:869
cgltf_animation_sampler * samplers
Definition cgltf.h:871
cgltf_animation_channel * channels
Definition cgltf.h:873
cgltf_extension * extensions
Definition cgltf.h:877
cgltf_size extensions_count
Definition cgltf.h:876
cgltf_size channels_count
Definition cgltf.h:874
cgltf_size samplers_count
Definition cgltf.h:872
char * name
Definition cgltf.h:870
cgltf_extras extras
Definition cgltf.h:875
Definition cgltf.h:584
cgltf_texture_view anisotropy_texture
Definition cgltf.h:587
cgltf_float anisotropy_strength
Definition cgltf.h:585
cgltf_float anisotropy_rotation
Definition cgltf.h:586
Definition cgltf.h:886
cgltf_extras extras
Definition cgltf.h:891
char * version
Definition cgltf.h:889
char * min_version
Definition cgltf.h:890
cgltf_extension * extensions
Definition cgltf.h:893
cgltf_size extensions_count
Definition cgltf.h:892
char * copyright
Definition cgltf.h:887
char * generator
Definition cgltf.h:888
Definition cgltf.h:409
char * name
Definition cgltf.h:410
cgltf_int index
Definition cgltf.h:412
cgltf_attribute_type type
Definition cgltf.h:411
cgltf_accessor * data
Definition cgltf.h:413
Definition cgltf.h:362
cgltf_extras extras
Definition cgltf.h:372
cgltf_extension * extensions
Definition cgltf.h:374
cgltf_meshopt_compression meshopt_compression
Definition cgltf.h:371
cgltf_size size
Definition cgltf.h:366
cgltf_buffer * buffer
Definition cgltf.h:364
cgltf_buffer_view_type type
Definition cgltf.h:368
char * name
Definition cgltf.h:363
cgltf_size stride
Definition cgltf.h:367
cgltf_size offset
Definition cgltf.h:365
cgltf_bool has_meshopt_compression
Definition cgltf.h:370
cgltf_size extensions_count
Definition cgltf.h:373
void * data
Definition cgltf.h:369
Definition cgltf.h:323
char * uri
Definition cgltf.h:326
char * name
Definition cgltf.h:324
cgltf_extras extras
Definition cgltf.h:329
cgltf_data_free_method data_free_method
Definition cgltf.h:328
cgltf_size size
Definition cgltf.h:325
cgltf_extension * extensions
Definition cgltf.h:331
cgltf_size extensions_count
Definition cgltf.h:330
void * data
Definition cgltf.h:327
Definition cgltf.h:740
cgltf_float sensor_size
Definition cgltf.h:741
cgltf_uint aperture_blades
Definition cgltf.h:744
cgltf_float aperture_ratio
Definition cgltf.h:746
cgltf_float aperture_rotation
Definition cgltf.h:745
cgltf_float fstop
Definition cgltf.h:742
cgltf_float focus_distance
Definition cgltf.h:743
Definition cgltf.h:732
cgltf_float znear
Definition cgltf.h:736
cgltf_float xmag
Definition cgltf.h:733
cgltf_float ymag
Definition cgltf.h:734
cgltf_float zfar
Definition cgltf.h:735
cgltf_extras extras
Definition cgltf.h:737
Definition cgltf.h:722
cgltf_float yfov
Definition cgltf.h:725
cgltf_bool has_zfar
Definition cgltf.h:726
cgltf_bool has_aspect_ratio
Definition cgltf.h:723
cgltf_float zfar
Definition cgltf.h:727
cgltf_float aspect_ratio
Definition cgltf.h:724
cgltf_float znear
Definition cgltf.h:728
cgltf_extras extras
Definition cgltf.h:729
Definition cgltf.h:749
union cgltf_camera::@0 data
cgltf_extension * extensions
Definition cgltf.h:760
cgltf_extras extras
Definition cgltf.h:758
char * name
Definition cgltf.h:750
cgltf_bool has_lens
Definition cgltf.h:756
cgltf_camera_type type
Definition cgltf.h:751
cgltf_size extensions_count
Definition cgltf.h:759
cgltf_camera_orthographic orthographic
Definition cgltf.h:754
cgltf_camera_perspective perspective
Definition cgltf.h:753
cgltf_camera_lens lens
Definition cgltf.h:757
Definition cgltf.h:508
cgltf_float clearcoat_roughness_factor
Definition cgltf.h:514
cgltf_texture_view clearcoat_roughness_texture
Definition cgltf.h:510
cgltf_texture_view clearcoat_normal_texture
Definition cgltf.h:511
cgltf_float clearcoat_factor
Definition cgltf.h:513
cgltf_texture_view clearcoat_texture
Definition cgltf.h:509
Definition cgltf.h:786
cgltf_material * material
Definition cgltf.h:792
char * name
Definition cgltf.h:787
cgltf_accessor * points
Definition cgltf.h:790
cgltf_accessor * curve_vertex_counts
Definition cgltf.h:791
cgltf_curve_basis basis
Definition cgltf.h:788
cgltf_curve_render_mode render_mode
Definition cgltf.h:789
cgltf_extras extras
Definition cgltf.h:793
Definition cgltf.h:897
cgltf_file_options file
Definition cgltf.h:976
cgltf_size bin_size
Definition cgltf.h:973
cgltf_size variants_count
Definition cgltf.h:954
cgltf_scene * scenes
Definition cgltf.h:945
cgltf_extension * data_extensions
Definition cgltf.h:959
const void * bin
Definition cgltf.h:972
cgltf_size buffer_views_count
Definition cgltf.h:913
cgltf_asset asset
Definition cgltf.h:901
cgltf_memory_options memory
Definition cgltf.h:975
cgltf_size extensions_required_count
Definition cgltf.h:967
cgltf_mesh * meshes
Definition cgltf.h:903
cgltf_size lights_area_count
Definition cgltf.h:937
cgltf_light * lights
Definition cgltf.h:933
cgltf_size json_size
Definition cgltf.h:970
cgltf_size buffers_count
Definition cgltf.h:916
cgltf_buffer_view * buffer_views
Definition cgltf.h:912
cgltf_size cameras_count
Definition cgltf.h:931
cgltf_size extensions_used_count
Definition cgltf.h:964
cgltf_skin * skins
Definition cgltf.h:927
cgltf_bool has_foundation_color_management
Definition cgltf.h:960
cgltf_scene * scene
Definition cgltf.h:948
cgltf_size images_count
Definition cgltf.h:919
cgltf_material * materials
Definition cgltf.h:906
cgltf_sampler * samplers
Definition cgltf.h:924
cgltf_size skins_count
Definition cgltf.h:928
cgltf_size textures_count
Definition cgltf.h:922
cgltf_size curves_count
Definition cgltf.h:940
cgltf_animation * animations
Definition cgltf.h:950
cgltf_file_type file_type
Definition cgltf.h:898
cgltf_curve * curves
Definition cgltf.h:939
cgltf_node * nodes
Definition cgltf.h:942
void * file_data
Definition cgltf.h:899
cgltf_accessor * accessors
Definition cgltf.h:909
char ** extensions_required
Definition cgltf.h:966
cgltf_camera * cameras
Definition cgltf.h:930
cgltf_size samplers_count
Definition cgltf.h:925
cgltf_size animations_count
Definition cgltf.h:951
cgltf_image * images
Definition cgltf.h:918
cgltf_size nodes_count
Definition cgltf.h:943
cgltf_foundation_color_management foundation_color_management
Definition cgltf.h:961
cgltf_texture * textures
Definition cgltf.h:921
cgltf_size accessors_count
Definition cgltf.h:910
cgltf_size data_extensions_count
Definition cgltf.h:958
const char * json
Definition cgltf.h:969
cgltf_size scenes_count
Definition cgltf.h:946
char ** extensions_used
Definition cgltf.h:963
cgltf_light_area * lights_area
Definition cgltf.h:936
cgltf_size meshes_count
Definition cgltf.h:904
cgltf_buffer * buffers
Definition cgltf.h:915
cgltf_extras extras
Definition cgltf.h:956
cgltf_size lights_count
Definition cgltf.h:934
cgltf_material_variant * variants
Definition cgltf.h:953
cgltf_size materials_count
Definition cgltf.h:907
Definition cgltf.h:568
cgltf_float diffuse_transmission_color_factor[3]
Definition cgltf.h:571
cgltf_float diffuse_transmission_factor
Definition cgltf.h:570
cgltf_texture_view diffuse_transmission_texture
Definition cgltf.h:569
cgltf_texture_view diffuse_transmission_color_texture
Definition cgltf.h:572
Definition cgltf.h:591
cgltf_float dispersion
Definition cgltf.h:592
Definition cgltf.h:668
cgltf_attribute * attributes
Definition cgltf.h:670
cgltf_size attributes_count
Definition cgltf.h:671
cgltf_buffer_view * buffer_view
Definition cgltf.h:669
Definition cgltf.h:553
cgltf_float emissive_strength
Definition cgltf.h:554
Definition cgltf.h:317
char * name
Definition cgltf.h:318
char * data
Definition cgltf.h:319
Definition cgltf.h:310
cgltf_size end_offset
Definition cgltf.h:312
cgltf_size start_offset
Definition cgltf.h:311
char * data
Definition cgltf.h:314
Definition cgltf.h:142
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:143
void * user_data
Definition cgltf.h:145
void(* release)(const struct cgltf_memory_options *memory_options, const struct cgltf_file_options *file_options, void *data)
Definition cgltf.h:144
Definition cgltf.h:805
char * sdr
Definition cgltf.h:808
cgltf_float post_exposure
Definition cgltf.h:807
char * hdr
Definition cgltf.h:809
cgltf_bool has_post_exposure
Definition cgltf.h:806
Definition cgltf.h:796
cgltf_float strength
Definition cgltf.h:799
cgltf_foundation_environment_projection projection
Definition cgltf.h:801
cgltf_foundation_environment_type type
Definition cgltf.h:797
cgltf_float color[3]
Definition cgltf.h:798
cgltf_float azimuth_offset
Definition cgltf.h:802
char * uri
Definition cgltf.h:800
Definition cgltf.h:596
cgltf_bool has_hair_beta_n
Definition cgltf.h:602
cgltf_bool has_hair_alpha
Definition cgltf.h:604
cgltf_foundation_material_shader_block shader_block
Definition cgltf.h:598
cgltf_bool has_ior
Definition cgltf.h:606
cgltf_float ior
Definition cgltf.h:607
cgltf_bool has_shader_block
Definition cgltf.h:597
cgltf_float hair_beta_n
Definition cgltf.h:603
cgltf_float hair_beta_m
Definition cgltf.h:601
cgltf_bool has_hair_beta_m
Definition cgltf.h:600
cgltf_float hair_alpha
Definition cgltf.h:605
cgltf_foundation_material_hair_model hair_model
Definition cgltf.h:599
Definition cgltf.h:417
char * uri
Definition cgltf.h:419
char * mime_type
Definition cgltf.h:421
cgltf_extras extras
Definition cgltf.h:422
cgltf_extension * extensions
Definition cgltf.h:424
char * name
Definition cgltf.h:418
cgltf_size extensions_count
Definition cgltf.h:423
cgltf_buffer_view * buffer_view
Definition cgltf.h:420
Definition cgltf.h:524
cgltf_float ior
Definition cgltf.h:525
Definition cgltf.h:558
cgltf_float iridescence_thickness_max
Definition cgltf.h:563
cgltf_float iridescence_ior
Definition cgltf.h:561
cgltf_texture_view iridescence_thickness_texture
Definition cgltf.h:564
cgltf_float iridescence_thickness_min
Definition cgltf.h:562
cgltf_texture_view iridescence_texture
Definition cgltf.h:560
cgltf_float iridescence_factor
Definition cgltf.h:559
Definition cgltf.h:776
cgltf_float color[3]
Definition cgltf.h:778
cgltf_float intensity
Definition cgltf.h:779
cgltf_extras extras
Definition cgltf.h:783
cgltf_light_area_type type
Definition cgltf.h:780
cgltf_float rect_aspect
Definition cgltf.h:782
char * name
Definition cgltf.h:777
cgltf_float size
Definition cgltf.h:781
Definition cgltf.h:763
cgltf_float angular_diameter
Definition cgltf.h:773
cgltf_extras extras
Definition cgltf.h:771
cgltf_float range
Definition cgltf.h:768
cgltf_float color[3]
Definition cgltf.h:765
cgltf_bool has_foundation_lights
Definition cgltf.h:772
cgltf_light_type type
Definition cgltf.h:767
cgltf_float intensity
Definition cgltf.h:766
cgltf_float spot_outer_cone_angle
Definition cgltf.h:770
char * name
Definition cgltf.h:764
cgltf_float spot_inner_cone_angle
Definition cgltf.h:769
Definition cgltf.h:657
cgltf_extras extras
Definition cgltf.h:660
cgltf_size variant
Definition cgltf.h:658
cgltf_material * material
Definition cgltf.h:659
Definition cgltf.h:881
cgltf_extras extras
Definition cgltf.h:883
char * name
Definition cgltf.h:882
Definition cgltf.h:611
cgltf_bool double_sided
Definition cgltf.h:649
cgltf_pbr_specular_glossiness pbr_specular_glossiness
Definition cgltf.h:629
char * name
Definition cgltf.h:612
cgltf_pbr_metallic_roughness pbr_metallic_roughness
Definition cgltf.h:628
cgltf_dispersion dispersion
Definition cgltf.h:641
cgltf_iridescence iridescence
Definition cgltf.h:637
cgltf_bool has_subsurface
Definition cgltf.h:624
cgltf_extras extras
Definition cgltf.h:651
cgltf_size extensions_count
Definition cgltf.h:652
cgltf_bool has_anisotropy
Definition cgltf.h:625
cgltf_sheen sheen
Definition cgltf.h:633
cgltf_bool has_foundation_materials
Definition cgltf.h:627
cgltf_bool has_sheen
Definition cgltf.h:620
cgltf_bool unlit
Definition cgltf.h:650
cgltf_bool has_diffuse_transmission
Definition cgltf.h:623
cgltf_specular specular
Definition cgltf.h:632
cgltf_float emissive_factor[3]
Definition cgltf.h:646
cgltf_emissive_strength emissive_strength
Definition cgltf.h:636
cgltf_bool has_ior
Definition cgltf.h:618
cgltf_anisotropy anisotropy
Definition cgltf.h:640
cgltf_bool has_transmission
Definition cgltf.h:616
cgltf_extension * extensions
Definition cgltf.h:653
cgltf_bool has_pbr_metallic_roughness
Definition cgltf.h:613
cgltf_bool has_iridescence
Definition cgltf.h:622
cgltf_volume volume
Definition cgltf.h:635
cgltf_bool has_volume
Definition cgltf.h:617
cgltf_texture_view emissive_texture
Definition cgltf.h:645
cgltf_bool has_emissive_strength
Definition cgltf.h:621
cgltf_diffuse_transmission diffuse_transmission
Definition cgltf.h:638
cgltf_texture_view occlusion_texture
Definition cgltf.h:644
cgltf_transmission transmission
Definition cgltf.h:634
cgltf_bool has_clearcoat
Definition cgltf.h:615
cgltf_ior ior
Definition cgltf.h:631
cgltf_alpha_mode alpha_mode
Definition cgltf.h:647
cgltf_subsurface subsurface
Definition cgltf.h:639
cgltf_foundation_materials foundation_materials
Definition cgltf.h:642
cgltf_clearcoat clearcoat
Definition cgltf.h:630
cgltf_bool has_pbr_specular_glossiness
Definition cgltf.h:614
cgltf_texture_view normal_texture
Definition cgltf.h:643
cgltf_float alpha_cutoff
Definition cgltf.h:648
cgltf_bool has_specular
Definition cgltf.h:619
cgltf_bool has_dispersion
Definition cgltf.h:626
Definition cgltf.h:135
void(* free_func)(void *user, void *ptr)
Definition cgltf.h:137
void * user_data
Definition cgltf.h:138
void *(* alloc_func)(void *user, cgltf_size size)
Definition cgltf.h:136
Definition cgltf.h:674
cgltf_size attributes_count
Definition cgltf.h:676
cgltf_attribute * attributes
Definition cgltf.h:675
Definition cgltf.h:696
cgltf_primitive * primitives
Definition cgltf.h:698
cgltf_size primitives_count
Definition cgltf.h:699
cgltf_extras extras
Definition cgltf.h:704
cgltf_size weights_count
Definition cgltf.h:701
cgltf_extension * extensions
Definition cgltf.h:706
char * name
Definition cgltf.h:697
cgltf_float * weights
Definition cgltf.h:700
cgltf_size target_names_count
Definition cgltf.h:703
cgltf_size extensions_count
Definition cgltf.h:705
char ** target_names
Definition cgltf.h:702
Definition cgltf.h:351
cgltf_size count
Definition cgltf.h:356
cgltf_buffer * buffer
Definition cgltf.h:352
cgltf_meshopt_compression_filter filter
Definition cgltf.h:358
cgltf_size offset
Definition cgltf.h:353
cgltf_meshopt_compression_mode mode
Definition cgltf.h:357
cgltf_size stride
Definition cgltf.h:355
cgltf_size size
Definition cgltf.h:354
Definition cgltf.h:663
cgltf_size attributes_count
Definition cgltf.h:665
cgltf_attribute * attributes
Definition cgltf.h:664
Definition cgltf.h:812
cgltf_mesh_gpu_instancing mesh_gpu_instancing
Definition cgltf.h:835
cgltf_skin * skin
Definition cgltf.h:817
cgltf_extras extras
Definition cgltf.h:833
cgltf_size children_count
Definition cgltf.h:816
char * name
Definition cgltf.h:813
cgltf_size weights_count
Definition cgltf.h:824
cgltf_light * light
Definition cgltf.h:820
cgltf_float rotation[4]
Definition cgltf.h:830
cgltf_bool has_translation
Definition cgltf.h:825
cgltf_node * parent
Definition cgltf.h:814
cgltf_mesh * mesh
Definition cgltf.h:818
cgltf_node ** children
Definition cgltf.h:815
cgltf_curve * curve
Definition cgltf.h:822
cgltf_size extensions_count
Definition cgltf.h:836
cgltf_bool has_rotation
Definition cgltf.h:826
cgltf_light_area * light_area
Definition cgltf.h:821
cgltf_float matrix[16]
Definition cgltf.h:832
cgltf_bool has_matrix
Definition cgltf.h:828
cgltf_bool has_scale
Definition cgltf.h:827
cgltf_float scale[3]
Definition cgltf.h:831
cgltf_extension * extensions
Definition cgltf.h:837
cgltf_float * weights
Definition cgltf.h:823
cgltf_bool has_mesh_gpu_instancing
Definition cgltf.h:834
cgltf_camera * camera
Definition cgltf.h:819
cgltf_float translation[3]
Definition cgltf.h:829
Definition cgltf.h:149
cgltf_memory_options memory
Definition cgltf.h:152
cgltf_size json_token_count
Definition cgltf.h:151
cgltf_file_type type
Definition cgltf.h:150
cgltf_file_options file
Definition cgltf.h:153
Definition cgltf.h:488
cgltf_float metallic_factor
Definition cgltf.h:493
cgltf_texture_view metallic_roughness_texture
Definition cgltf.h:490
cgltf_texture_view base_color_texture
Definition cgltf.h:489
cgltf_float roughness_factor
Definition cgltf.h:494
cgltf_float base_color_factor[4]
Definition cgltf.h:492
Definition cgltf.h:498
cgltf_texture_view diffuse_texture
Definition cgltf.h:499
cgltf_float specular_factor[3]
Definition cgltf.h:503
cgltf_float diffuse_factor[4]
Definition cgltf.h:502
cgltf_float glossiness_factor
Definition cgltf.h:504
cgltf_texture_view specular_glossiness_texture
Definition cgltf.h:500
Definition cgltf.h:679
cgltf_draco_mesh_compression draco_mesh_compression
Definition cgltf.h:689
cgltf_size extensions_count
Definition cgltf.h:692
cgltf_size attributes_count
Definition cgltf.h:684
cgltf_size targets_count
Definition cgltf.h:686
cgltf_accessor * indices
Definition cgltf.h:681
cgltf_extension * extensions
Definition cgltf.h:693
cgltf_morph_target * targets
Definition cgltf.h:685
cgltf_bool has_draco_mesh_compression
Definition cgltf.h:688
cgltf_size mappings_count
Definition cgltf.h:691
cgltf_extras extras
Definition cgltf.h:687
cgltf_material_mapping * mappings
Definition cgltf.h:690
cgltf_attribute * attributes
Definition cgltf.h:683
cgltf_primitive_type type
Definition cgltf.h:680
cgltf_material * material
Definition cgltf.h:682
Definition cgltf.h:444
cgltf_extras extras
Definition cgltf.h:450
cgltf_extension * extensions
Definition cgltf.h:452
cgltf_wrap_mode wrap_t
Definition cgltf.h:449
cgltf_filter_type mag_filter
Definition cgltf.h:446
cgltf_wrap_mode wrap_s
Definition cgltf.h:448
char * name
Definition cgltf.h:445
cgltf_size extensions_count
Definition cgltf.h:451
cgltf_filter_type min_filter
Definition cgltf.h:447
Definition cgltf.h:840
cgltf_bool has_foundation_environment
Definition cgltf.h:844
cgltf_size extensions_count
Definition cgltf.h:847
char * name
Definition cgltf.h:841
cgltf_node ** nodes
Definition cgltf.h:842
cgltf_foundation_environment foundation_environment
Definition cgltf.h:845
cgltf_extension * extensions
Definition cgltf.h:848
cgltf_extras extras
Definition cgltf.h:846
cgltf_size nodes_count
Definition cgltf.h:843
Definition cgltf.h:545
cgltf_texture_view sheen_color_texture
Definition cgltf.h:546
cgltf_float sheen_color_factor[3]
Definition cgltf.h:547
cgltf_float sheen_roughness_factor
Definition cgltf.h:549
cgltf_texture_view sheen_roughness_texture
Definition cgltf.h:548
Definition cgltf.h:711
cgltf_extension * extensions
Definition cgltf.h:719
cgltf_extras extras
Definition cgltf.h:717
cgltf_node * skeleton
Definition cgltf.h:715
cgltf_node ** joints
Definition cgltf.h:713
cgltf_accessor * inverse_bind_matrices
Definition cgltf.h:716
cgltf_size joints_count
Definition cgltf.h:714
char * name
Definition cgltf.h:712
cgltf_size extensions_count
Definition cgltf.h:718
Definition cgltf.h:529
cgltf_float specular_factor
Definition cgltf.h:533
cgltf_float specular_color_factor[3]
Definition cgltf.h:532
cgltf_texture_view specular_color_texture
Definition cgltf.h:531
cgltf_texture_view specular_texture
Definition cgltf.h:530
Definition cgltf.h:576
cgltf_float subsurface_radius[3]
Definition cgltf.h:579
cgltf_float subsurface_scale
Definition cgltf.h:580
char * subsurface_method
Definition cgltf.h:577
cgltf_float subsurface_weight
Definition cgltf.h:578
Definition cgltf.h:470
cgltf_bool has_texcoord
Definition cgltf.h:474
cgltf_float rotation
Definition cgltf.h:472
cgltf_float scale[2]
Definition cgltf.h:473
cgltf_float offset[2]
Definition cgltf.h:471
cgltf_int texcoord
Definition cgltf.h:475
Definition cgltf.h:479
cgltf_float scale
Definition cgltf.h:482
cgltf_bool has_transform
Definition cgltf.h:483
cgltf_int texcoord
Definition cgltf.h:481
cgltf_texture_transform transform
Definition cgltf.h:484
cgltf_texture * texture
Definition cgltf.h:480
Definition cgltf.h:456
cgltf_bool has_basisu
Definition cgltf.h:460
cgltf_image * basisu_image
Definition cgltf.h:461
cgltf_sampler * sampler
Definition cgltf.h:459
char * name
Definition cgltf.h:457
cgltf_image * image
Definition cgltf.h:458
cgltf_bool has_webp
Definition cgltf.h:462
cgltf_extras extras
Definition cgltf.h:464
cgltf_extension * extensions
Definition cgltf.h:466
cgltf_size extensions_count
Definition cgltf.h:465
cgltf_image * webp_image
Definition cgltf.h:463
Definition cgltf.h:518
cgltf_float transmission_factor
Definition cgltf.h:520
cgltf_texture_view transmission_texture
Definition cgltf.h:519
Definition cgltf.h:537
cgltf_float attenuation_distance
Definition cgltf.h:541
cgltf_float thickness_factor
Definition cgltf.h:539
cgltf_texture_view thickness_texture
Definition cgltf.h:538
cgltf_float attenuation_color[3]
Definition cgltf.h:540