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