92#ifndef CGLTF_H_INCLUDED__
93#define CGLTF_H_INCLUDED__
101typedef size_t cgltf_size;
102typedef long long int cgltf_ssize;
103typedef float cgltf_float;
104typedef int cgltf_int;
105typedef unsigned int cgltf_uint;
106typedef int cgltf_bool;
108typedef enum cgltf_file_type
110 cgltf_file_type_invalid,
111 cgltf_file_type_gltf,
113 cgltf_file_type_max_enum
116typedef enum cgltf_result
118 cgltf_result_success,
119 cgltf_result_data_too_short,
120 cgltf_result_unknown_format,
121 cgltf_result_invalid_json,
122 cgltf_result_invalid_gltf,
123 cgltf_result_invalid_options,
124 cgltf_result_file_not_found,
125 cgltf_result_io_error,
126 cgltf_result_out_of_memory,
127 cgltf_result_legacy_gltf,
128 cgltf_result_max_enum
133 void* (*alloc_func)(
void* user, cgltf_size size);
134 void (*free_func) (
void* user,
void* ptr);
147 cgltf_file_type type;
148 cgltf_size json_token_count;
153typedef enum cgltf_buffer_view_type
155 cgltf_buffer_view_type_invalid,
156 cgltf_buffer_view_type_indices,
157 cgltf_buffer_view_type_vertices,
158 cgltf_buffer_view_type_max_enum
159} cgltf_buffer_view_type;
161typedef enum cgltf_attribute_type
163 cgltf_attribute_type_invalid,
164 cgltf_attribute_type_position,
165 cgltf_attribute_type_normal,
166 cgltf_attribute_type_tangent,
167 cgltf_attribute_type_texcoord,
168 cgltf_attribute_type_color,
169 cgltf_attribute_type_joints,
170 cgltf_attribute_type_weights,
171 cgltf_attribute_type_custom,
172 cgltf_attribute_type_max_enum
173} cgltf_attribute_type;
175typedef enum cgltf_component_type
177 cgltf_component_type_invalid,
178 cgltf_component_type_r_8,
179 cgltf_component_type_r_8u,
180 cgltf_component_type_r_16,
181 cgltf_component_type_r_16u,
182 cgltf_component_type_r_32u,
183 cgltf_component_type_r_32f,
184 cgltf_component_type_max_enum
185} cgltf_component_type;
187typedef enum cgltf_type
200typedef enum cgltf_primitive_type
202 cgltf_primitive_type_points,
203 cgltf_primitive_type_lines,
204 cgltf_primitive_type_line_loop,
205 cgltf_primitive_type_line_strip,
206 cgltf_primitive_type_triangles,
207 cgltf_primitive_type_triangle_strip,
208 cgltf_primitive_type_triangle_fan,
209 cgltf_primitive_type_max_enum
210} cgltf_primitive_type;
212typedef enum cgltf_alpha_mode
214 cgltf_alpha_mode_opaque,
215 cgltf_alpha_mode_mask,
216 cgltf_alpha_mode_blend,
217 cgltf_alpha_mode_max_enum
220typedef enum cgltf_animation_path_type {
221 cgltf_animation_path_type_invalid,
222 cgltf_animation_path_type_translation,
223 cgltf_animation_path_type_rotation,
224 cgltf_animation_path_type_scale,
225 cgltf_animation_path_type_weights,
226 cgltf_animation_path_type_max_enum
227} cgltf_animation_path_type;
229typedef enum cgltf_interpolation_type {
230 cgltf_interpolation_type_linear,
231 cgltf_interpolation_type_step,
232 cgltf_interpolation_type_cubic_spline,
233 cgltf_interpolation_type_max_enum
234} cgltf_interpolation_type;
236typedef enum cgltf_camera_type {
237 cgltf_camera_type_invalid,
238 cgltf_camera_type_perspective,
239 cgltf_camera_type_orthographic,
240 cgltf_camera_type_max_enum
243typedef enum cgltf_light_type {
244 cgltf_light_type_invalid,
245 cgltf_light_type_directional,
246 cgltf_light_type_point,
247 cgltf_light_type_spot,
248 cgltf_light_type_max_enum
251typedef enum cgltf_data_free_method {
252 cgltf_data_free_method_none,
253 cgltf_data_free_method_file_release,
254 cgltf_data_free_method_memory_free,
255 cgltf_data_free_method_max_enum
256} cgltf_data_free_method;
259 cgltf_size start_offset;
260 cgltf_size end_offset;
274 cgltf_data_free_method data_free_method;
276 cgltf_size extensions_count;
280typedef enum cgltf_meshopt_compression_mode {
281 cgltf_meshopt_compression_mode_invalid,
282 cgltf_meshopt_compression_mode_attributes,
283 cgltf_meshopt_compression_mode_triangles,
284 cgltf_meshopt_compression_mode_indices,
285 cgltf_meshopt_compression_mode_max_enum
286} cgltf_meshopt_compression_mode;
288typedef enum cgltf_meshopt_compression_filter {
289 cgltf_meshopt_compression_filter_none,
290 cgltf_meshopt_compression_filter_octahedral,
291 cgltf_meshopt_compression_filter_quaternion,
292 cgltf_meshopt_compression_filter_exponential,
293 cgltf_meshopt_compression_filter_max_enum
294} cgltf_meshopt_compression_filter;
303 cgltf_meshopt_compression_mode mode;
304 cgltf_meshopt_compression_filter filter;
314 cgltf_buffer_view_type type;
316 cgltf_bool has_meshopt_compression;
319 cgltf_size extensions_count;
327 cgltf_size indices_byte_offset;
328 cgltf_component_type indices_component_type;
330 cgltf_size values_byte_offset;
334 cgltf_size extensions_count;
336 cgltf_size indices_extensions_count;
338 cgltf_size values_extensions_count;
345 cgltf_component_type component_type;
346 cgltf_bool normalized;
356 cgltf_bool is_sparse;
359 cgltf_size extensions_count;
366 cgltf_attribute_type type;
378 cgltf_size extensions_count;
385 cgltf_int mag_filter;
386 cgltf_int min_filter;
390 cgltf_size extensions_count;
399 cgltf_bool has_basisu;
402 cgltf_size extensions_count;
408 cgltf_float offset[2];
409 cgltf_float rotation;
410 cgltf_float scale[2];
411 cgltf_bool has_texcoord;
420 cgltf_bool has_transform;
423 cgltf_size extensions_count;
432 cgltf_float base_color_factor[4];
433 cgltf_float metallic_factor;
434 cgltf_float roughness_factor;
444 cgltf_float diffuse_factor[4];
445 cgltf_float specular_factor[3];
446 cgltf_float glossiness_factor;
455 cgltf_float clearcoat_factor;
456 cgltf_float clearcoat_roughness_factor;
462 cgltf_float transmission_factor;
474 cgltf_float specular_color_factor[3];
475 cgltf_float specular_factor;
481 cgltf_float thickness_factor;
482 cgltf_float attenuation_color[3];
483 cgltf_float attenuation_distance;
489 cgltf_float sheen_color_factor[3];
491 cgltf_float sheen_roughness_factor;
496 cgltf_float emissive_strength;
501 cgltf_float iridescence_factor;
503 cgltf_float iridescence_ior;
504 cgltf_float iridescence_thickness_min;
505 cgltf_float iridescence_thickness_max;
512 cgltf_bool has_pbr_metallic_roughness;
513 cgltf_bool has_pbr_specular_glossiness;
514 cgltf_bool has_clearcoat;
515 cgltf_bool has_transmission;
516 cgltf_bool has_volume;
518 cgltf_bool has_specular;
519 cgltf_bool has_sheen;
520 cgltf_bool has_emissive_strength;
521 cgltf_bool has_iridescence;
535 cgltf_float emissive_factor[3];
536 cgltf_alpha_mode alpha_mode;
537 cgltf_float alpha_cutoff;
538 cgltf_bool double_sided;
541 cgltf_size extensions_count;
554 cgltf_size attributes_count;
560 cgltf_size attributes_count;
566 cgltf_size attributes_count;
570 cgltf_primitive_type type;
574 cgltf_size attributes_count;
576 cgltf_size targets_count;
578 cgltf_bool has_draco_mesh_compression;
581 cgltf_size mappings_count;
582 cgltf_size extensions_count;
589 cgltf_size primitives_count;
590 cgltf_float* weights;
591 cgltf_size weights_count;
593 cgltf_size target_names_count;
595 cgltf_size extensions_count;
604 cgltf_size joints_count;
608 cgltf_size extensions_count;
613 cgltf_bool has_aspect_ratio;
614 cgltf_float aspect_ratio;
632 cgltf_camera_type type;
638 cgltf_size extensions_count;
644 cgltf_float color[3];
645 cgltf_float intensity;
646 cgltf_light_type type;
648 cgltf_float spot_inner_cone_angle;
649 cgltf_float spot_outer_cone_angle;
657 cgltf_size children_count;
662 cgltf_float* weights;
663 cgltf_size weights_count;
664 cgltf_bool has_translation;
665 cgltf_bool has_rotation;
666 cgltf_bool has_scale;
667 cgltf_bool has_matrix;
668 cgltf_float translation[3];
669 cgltf_float rotation[4];
670 cgltf_float scale[3];
671 cgltf_float matrix[16];
673 cgltf_bool has_mesh_gpu_instancing;
675 cgltf_size extensions_count;
682 cgltf_size nodes_count;
684 cgltf_size extensions_count;
691 cgltf_interpolation_type interpolation;
693 cgltf_size extensions_count;
700 cgltf_animation_path_type target_path;
702 cgltf_size extensions_count;
709 cgltf_size samplers_count;
711 cgltf_size channels_count;
713 cgltf_size extensions_count;
729 cgltf_size extensions_count;
735 cgltf_file_type file_type;
741 cgltf_size meshes_count;
744 cgltf_size materials_count;
747 cgltf_size accessors_count;
750 cgltf_size buffer_views_count;
753 cgltf_size buffers_count;
756 cgltf_size images_count;
759 cgltf_size textures_count;
762 cgltf_size samplers_count;
765 cgltf_size skins_count;
768 cgltf_size cameras_count;
771 cgltf_size lights_count;
774 cgltf_size nodes_count;
777 cgltf_size scenes_count;
782 cgltf_size animations_count;
785 cgltf_size variants_count;
789 cgltf_size data_extensions_count;
792 char** extensions_used;
793 cgltf_size extensions_used_count;
795 char** extensions_required;
796 cgltf_size extensions_required_count;
799 cgltf_size json_size;
808cgltf_result cgltf_parse(
814cgltf_result cgltf_parse_file(
819cgltf_result cgltf_load_buffers(
822 const char* gltf_path);
824cgltf_result cgltf_load_buffer_base64(
const cgltf_options* options, cgltf_size size,
const char* base64,
void** out_data);
826cgltf_size cgltf_decode_string(
char*
string);
827cgltf_size cgltf_decode_uri(
char* uri);
833void cgltf_node_transform_local(
const cgltf_node* node, cgltf_float* out_matrix);
834void cgltf_node_transform_world(
const cgltf_node* node, cgltf_float* out_matrix);
836cgltf_bool cgltf_accessor_read_float(
const cgltf_accessor* accessor, cgltf_size index, cgltf_float* out, cgltf_size element_size);
837cgltf_bool cgltf_accessor_read_uint(
const cgltf_accessor* accessor, cgltf_size index, cgltf_uint* out, cgltf_size element_size);
838cgltf_size cgltf_accessor_read_index(
const cgltf_accessor* accessor, cgltf_size index);
840cgltf_size cgltf_num_components(cgltf_type type);
842cgltf_size cgltf_accessor_unpack_floats(
const cgltf_accessor* accessor, cgltf_float* out, cgltf_size float_count);
844cgltf_result cgltf_copy_extras_json(
const cgltf_data* data,
const cgltf_extras* extras,
char* dest, cgltf_size* dest_size);
859#if defined(__INTELLISENSE__) || defined(__JETBRAINS_IDE__)
861#define CGLTF_IMPLEMENTATION
864#ifdef CGLTF_IMPLEMENTATION
872#if !defined(CGLTF_MALLOC) || !defined(CGLTF_FREE) || !defined(CGLTF_ATOI) || !defined(CGLTF_ATOF) || !defined(CGLTF_ATOLL)
876#if CGLTF_VALIDATE_ENABLE_ASSERTS
881#define JSMN_PARENT_LINKS
900 JSMN_ERROR_NOMEM = -1,
902 JSMN_ERROR_INVAL = -2,
911#ifdef JSMN_PARENT_LINKS
917 unsigned int toknext;
920static void jsmn_init(jsmn_parser *parser);
921static int jsmn_parse(jsmn_parser *parser,
const char *js,
size_t len, jsmntok_t *tokens,
size_t num_tokens);
927static const cgltf_size GlbHeaderSize = 12;
928static const cgltf_size GlbChunkHeaderSize = 8;
929static const uint32_t GlbVersion = 2;
930static const uint32_t GlbMagic = 0x46546C67;
931static const uint32_t GlbMagicJsonChunk = 0x4E4F534A;
932static const uint32_t GlbMagicBinChunk = 0x004E4942;
935#define CGLTF_MALLOC(size) malloc(size)
938#define CGLTF_FREE(ptr) free(ptr)
941#define CGLTF_ATOI(str) atoi(str)
944#define CGLTF_ATOF(str) atof(str)
947#define CGLTF_ATOLL(str) atoll(str)
949#ifndef CGLTF_VALIDATE_ENABLE_ASSERTS
950#define CGLTF_VALIDATE_ENABLE_ASSERTS 0
953static void* cgltf_default_alloc(
void* user, cgltf_size size)
956 return CGLTF_MALLOC(size);
959static void cgltf_default_free(
void* user,
void* ptr)
965static void* cgltf_calloc(
cgltf_options* options,
size_t element_size, cgltf_size count)
967 if (SIZE_MAX / element_size < count)
971 void* result = options->memory.alloc_func(options->memory.user_data, element_size * count);
976 memset(result, 0, element_size * count);
980static 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)
983 void* (*memory_alloc)(
void*, cgltf_size) = memory_options->alloc_func ? memory_options->alloc_func : &cgltf_default_alloc;
984 void (*memory_free)(
void*,
void*) = memory_options->free_func ? memory_options->free_func : &cgltf_default_free;
986 FILE* file = fopen(path,
"rb");
989 return cgltf_result_file_not_found;
992 cgltf_size file_size = size ? *size : 0;
996 fseek(file, 0, SEEK_END);
999 __int64 length = _ftelli64(file);
1001 long length = ftell(file);
1007 return cgltf_result_io_error;
1010 fseek(file, 0, SEEK_SET);
1011 file_size = (cgltf_size)length;
1014 char* file_data = (
char*)memory_alloc(memory_options->user_data, file_size);
1018 return cgltf_result_out_of_memory;
1021 cgltf_size read_size = fread(file_data, 1, file_size, file);
1025 if (read_size != file_size)
1027 memory_free(memory_options->user_data, file_data);
1028 return cgltf_result_io_error;
1040 return cgltf_result_success;
1046 void (*memfree)(
void*,
void*) = memory_options->free_func ? memory_options->free_func : &cgltf_default_free;
1047 memfree(memory_options->user_data, data);
1050static cgltf_result cgltf_parse_json(
cgltf_options* options,
const uint8_t* json_chunk, cgltf_size size,
cgltf_data** out_data);
1052cgltf_result cgltf_parse(
const cgltf_options* options,
const void* data, cgltf_size size,
cgltf_data** out_data)
1054 if (size < GlbHeaderSize)
1056 return cgltf_result_data_too_short;
1059 if (options == NULL)
1061 return cgltf_result_invalid_options;
1065 if (fixed_options.memory.alloc_func == NULL)
1067 fixed_options.memory.alloc_func = &cgltf_default_alloc;
1069 if (fixed_options.memory.free_func == NULL)
1071 fixed_options.memory.free_func = &cgltf_default_free;
1076 memcpy(&tmp, data, 4);
1077 if (tmp != GlbMagic)
1079 if (fixed_options.type == cgltf_file_type_invalid)
1081 fixed_options.type = cgltf_file_type_gltf;
1083 else if (fixed_options.type == cgltf_file_type_glb)
1085 return cgltf_result_unknown_format;
1089 if (fixed_options.type == cgltf_file_type_gltf)
1091 cgltf_result json_result = cgltf_parse_json(&fixed_options, (
const uint8_t*)data, size, out_data);
1092 if (json_result != cgltf_result_success)
1097 (*out_data)->file_type = cgltf_file_type_gltf;
1099 return cgltf_result_success;
1102 const uint8_t* ptr = (
const uint8_t*)data;
1104 memcpy(&tmp, ptr + 4, 4);
1105 uint32_t version = tmp;
1106 if (version != GlbVersion)
1108 return version < GlbVersion ? cgltf_result_legacy_gltf : cgltf_result_unknown_format;
1112 memcpy(&tmp, ptr + 8, 4);
1115 return cgltf_result_data_too_short;
1118 const uint8_t* json_chunk = ptr + GlbHeaderSize;
1120 if (GlbHeaderSize + GlbChunkHeaderSize > size)
1122 return cgltf_result_data_too_short;
1126 uint32_t json_length;
1127 memcpy(&json_length, json_chunk, 4);
1128 if (GlbHeaderSize + GlbChunkHeaderSize + json_length > size)
1130 return cgltf_result_data_too_short;
1134 memcpy(&tmp, json_chunk + 4, 4);
1135 if (tmp != GlbMagicJsonChunk)
1137 return cgltf_result_unknown_format;
1140 json_chunk += GlbChunkHeaderSize;
1142 const void* bin = 0;
1143 cgltf_size bin_size = 0;
1145 if (GlbHeaderSize + GlbChunkHeaderSize + json_length + GlbChunkHeaderSize <= size)
1148 const uint8_t* bin_chunk = json_chunk + json_length;
1151 uint32_t bin_length;
1152 memcpy(&bin_length, bin_chunk, 4);
1153 if (GlbHeaderSize + GlbChunkHeaderSize + json_length + GlbChunkHeaderSize + bin_length > size)
1155 return cgltf_result_data_too_short;
1159 memcpy(&tmp, bin_chunk + 4, 4);
1160 if (tmp != GlbMagicBinChunk)
1162 return cgltf_result_unknown_format;
1165 bin_chunk += GlbChunkHeaderSize;
1168 bin_size = bin_length;
1171 cgltf_result json_result = cgltf_parse_json(&fixed_options, json_chunk, json_length, out_data);
1172 if (json_result != cgltf_result_success)
1177 (*out_data)->file_type = cgltf_file_type_glb;
1178 (*out_data)->bin = bin;
1179 (*out_data)->bin_size = bin_size;
1181 return cgltf_result_success;
1186 if (options == NULL)
1188 return cgltf_result_invalid_options;
1191 cgltf_result (*file_read)(
const struct cgltf_memory_options*,
const struct cgltf_file_options*,
const char*, cgltf_size*,
void**) = options->file.read ? options->file.read : &cgltf_default_file_read;
1194 void* file_data = NULL;
1195 cgltf_size file_size = 0;
1196 cgltf_result result = file_read(&options->memory, &options->file, path, &file_size, &file_data);
1197 if (result != cgltf_result_success)
1202 result = cgltf_parse(options, file_data, file_size, out_data);
1204 if (result != cgltf_result_success)
1206 file_release(&options->memory, &options->file, file_data);
1210 (*out_data)->file_data = file_data;
1212 return cgltf_result_success;
1215static void cgltf_combine_paths(
char* path,
const char* base,
const char* uri)
1217 const char* s0 = strrchr(base,
'/');
1218 const char* s1 = strrchr(base,
'\\');
1219 const char* slash = s0 ? (s1 && s1 > s0 ? s1 : s0) : s1;
1223 size_t prefix = slash - base + 1;
1225 strncpy(path, base, prefix);
1226 strcpy(path + prefix, uri);
1234static cgltf_result cgltf_load_buffer_file(
const cgltf_options* options, cgltf_size size,
const char* uri,
const char* gltf_path,
void** out_data)
1236 void* (*memory_alloc)(
void*, cgltf_size) = options->memory.alloc_func ? options->memory.alloc_func : &cgltf_default_alloc;
1237 void (*memory_free)(
void*,
void*) = options->memory.free_func ? options->memory.free_func : &cgltf_default_free;
1238 cgltf_result (*file_read)(
const struct cgltf_memory_options*,
const struct cgltf_file_options*,
const char*, cgltf_size*,
void**) = options->file.read ? options->file.read : &cgltf_default_file_read;
1240 char* path = (
char*)memory_alloc(options->memory.user_data, strlen(uri) + strlen(gltf_path) + 1);
1243 return cgltf_result_out_of_memory;
1246 cgltf_combine_paths(path, gltf_path, uri);
1249 cgltf_decode_uri(path + strlen(path) - strlen(uri));
1251 void* file_data = NULL;
1252 cgltf_result result = file_read(&options->memory, &options->file, path, &size, &file_data);
1254 memory_free(options->memory.user_data, path);
1256 *out_data = (result == cgltf_result_success) ? file_data : NULL;
1261cgltf_result cgltf_load_buffer_base64(
const cgltf_options* options, cgltf_size size,
const char* base64,
void** out_data)
1263 void* (*memory_alloc)(
void*, cgltf_size) = options->memory.alloc_func ? options->memory.alloc_func : &cgltf_default_alloc;
1264 void (*memory_free)(
void*,
void*) = options->memory.free_func ? options->memory.free_func : &cgltf_default_free;
1266 unsigned char* data = (
unsigned char*)memory_alloc(options->memory.user_data, size);
1269 return cgltf_result_out_of_memory;
1272 unsigned int buffer = 0;
1273 unsigned int buffer_bits = 0;
1275 for (cgltf_size i = 0; i < size; ++i)
1277 while (buffer_bits < 8)
1279 char ch = *base64++;
1282 (unsigned)(ch -
'A') < 26 ? (ch -
'A') :
1283 (unsigned)(ch -
'a') < 26 ? (ch -
'a') + 26 :
1284 (unsigned)(ch -
'0') < 10 ? (ch -
'0') + 52 :
1291 memory_free(options->memory.user_data, data);
1292 return cgltf_result_io_error;
1295 buffer = (buffer << 6) | index;
1299 data[i] = (
unsigned char)(buffer >> (buffer_bits - 8));
1305 return cgltf_result_success;
1308static int cgltf_unhex(
char ch)
1311 (
unsigned)(ch -
'0') < 10 ? (ch -
'0') :
1312 (unsigned)(ch -
'A') < 6 ? (ch -
'A') + 10 :
1313 (unsigned)(ch -
'a') < 6 ? (ch -
'a') + 10 :
1317cgltf_size cgltf_decode_string(
char*
string)
1319 char* read =
string + strcspn(
string,
"\\");
1322 return read - string;
1324 char* write = string;
1325 char* last = string;
1330 cgltf_size written = read - last;
1331 memmove(write, last, written);
1342 case '\"': *write++ =
'\"';
break;
1343 case '/': *write++ =
'/';
break;
1344 case '\\': *write++ =
'\\';
break;
1345 case 'b': *write++ =
'\b';
break;
1346 case 'f': *write++ =
'\f';
break;
1347 case 'r': *write++ =
'\r';
break;
1348 case 'n': *write++ =
'\n';
break;
1349 case 't': *write++ =
'\t';
break;
1354 for (cgltf_size i = 0; i < 4; ++i)
1356 character = (character << 4) + cgltf_unhex(*read++);
1359 if (character <= 0x7F)
1361 *write++ = character & 0xFF;
1363 else if (character <= 0x7FF)
1365 *write++ = 0xC0 | ((character >> 6) & 0xFF);
1366 *write++ = 0x80 | (character & 0x3F);
1370 *write++ = 0xE0 | ((character >> 12) & 0xFF);
1371 *write++ = 0x80 | ((character >> 6) & 0x3F);
1372 *write++ = 0x80 | (character & 0x3F);
1381 read += strcspn(read,
"\\");
1385 return write - string;
1388cgltf_size cgltf_decode_uri(
char* uri)
1397 int ch1 = cgltf_unhex(i[1]);
1401 int ch2 = cgltf_unhex(i[2]);
1405 *write++ = (char)(ch1 * 16 + ch2);
1421 if (options == NULL)
1423 return cgltf_result_invalid_options;
1426 if (data->buffers_count && data->buffers[0].data == NULL && data->buffers[0].uri == NULL && data->bin)
1428 if (data->bin_size < data->buffers[0].size)
1430 return cgltf_result_data_too_short;
1433 data->buffers[0].data = (
void*)data->bin;
1434 data->buffers[0].data_free_method = cgltf_data_free_method_none;
1437 for (cgltf_size i = 0; i < data->buffers_count; ++i)
1439 if (data->buffers[i].data)
1444 const char* uri = data->buffers[i].uri;
1451 if (strncmp(uri,
"data:", 5) == 0)
1453 const char* comma = strchr(uri,
',');
1455 if (comma && comma - uri >= 7 && strncmp(comma - 7,
";base64", 7) == 0)
1457 cgltf_result res = cgltf_load_buffer_base64(options, data->buffers[i].size, comma + 1, &data->buffers[i].data);
1458 data->buffers[i].data_free_method = cgltf_data_free_method_memory_free;
1460 if (res != cgltf_result_success)
1467 return cgltf_result_unknown_format;
1470 else if (strstr(uri,
"://") == NULL && gltf_path)
1472 cgltf_result res = cgltf_load_buffer_file(options, data->buffers[i].size, uri, gltf_path, &data->buffers[i].data);
1473 data->buffers[i].data_free_method = cgltf_data_free_method_file_release;
1475 if (res != cgltf_result_success)
1482 return cgltf_result_unknown_format;
1486 return cgltf_result_success;
1489static cgltf_size cgltf_calc_size(cgltf_type type, cgltf_component_type component_type);
1491static cgltf_size cgltf_calc_index_bound(
cgltf_buffer_view* buffer_view, cgltf_size offset, cgltf_component_type component_type, cgltf_size count)
1493 char* data = (
char*)buffer_view->buffer->data + offset + buffer_view->offset;
1494 cgltf_size bound = 0;
1496 switch (component_type)
1498 case cgltf_component_type_r_8u:
1499 for (
size_t i = 0; i < count; ++i)
1501 cgltf_size v = ((
unsigned char*)data)[i];
1502 bound = bound > v ? bound : v;
1506 case cgltf_component_type_r_16u:
1507 for (
size_t i = 0; i < count; ++i)
1509 cgltf_size v = ((
unsigned short*)data)[i];
1510 bound = bound > v ? bound : v;
1514 case cgltf_component_type_r_32u:
1515 for (
size_t i = 0; i < count; ++i)
1517 cgltf_size v = ((
unsigned int*)data)[i];
1518 bound = bound > v ? bound : v;
1529#if CGLTF_VALIDATE_ENABLE_ASSERTS
1530#define CGLTF_ASSERT_IF(cond, result) assert(!(cond)); if (cond) return result;
1532#define CGLTF_ASSERT_IF(cond, result) if (cond) return result;
1537 for (cgltf_size i = 0; i < data->accessors_count; ++i)
1541 cgltf_size element_size = cgltf_calc_size(accessor->type, accessor->component_type);
1543 if (accessor->buffer_view)
1545 cgltf_size req_size = accessor->offset + accessor->stride * (accessor->count - 1) + element_size;
1547 CGLTF_ASSERT_IF(accessor->buffer_view->size < req_size, cgltf_result_data_too_short);
1550 if (accessor->is_sparse)
1554 cgltf_size indices_component_size = cgltf_calc_size(cgltf_type_scalar, sparse->indices_component_type);
1555 cgltf_size indices_req_size = sparse->indices_byte_offset + indices_component_size * sparse->count;
1556 cgltf_size values_req_size = sparse->values_byte_offset + element_size * sparse->count;
1558 CGLTF_ASSERT_IF(sparse->indices_buffer_view->size < indices_req_size ||
1559 sparse->values_buffer_view->size < values_req_size, cgltf_result_data_too_short);
1561 CGLTF_ASSERT_IF(sparse->indices_component_type != cgltf_component_type_r_8u &&
1562 sparse->indices_component_type != cgltf_component_type_r_16u &&
1563 sparse->indices_component_type != cgltf_component_type_r_32u, cgltf_result_invalid_gltf);
1565 if (sparse->indices_buffer_view->buffer->data)
1567 cgltf_size index_bound = cgltf_calc_index_bound(sparse->indices_buffer_view, sparse->indices_byte_offset, sparse->indices_component_type, sparse->count);
1569 CGLTF_ASSERT_IF(index_bound >= accessor->count, cgltf_result_data_too_short);
1574 for (cgltf_size i = 0; i < data->buffer_views_count; ++i)
1576 cgltf_size req_size = data->buffer_views[i].offset + data->buffer_views[i].size;
1578 CGLTF_ASSERT_IF(data->buffer_views[i].buffer && data->buffer_views[i].buffer->size < req_size, cgltf_result_data_too_short);
1580 if (data->buffer_views[i].has_meshopt_compression)
1584 CGLTF_ASSERT_IF(mc->buffer == NULL || mc->buffer->size < mc->offset + mc->size, cgltf_result_data_too_short);
1586 CGLTF_ASSERT_IF(data->buffer_views[i].stride && mc->stride != data->buffer_views[i].stride, cgltf_result_invalid_gltf);
1588 CGLTF_ASSERT_IF(data->buffer_views[i].size != mc->stride * mc->count, cgltf_result_invalid_gltf);
1590 CGLTF_ASSERT_IF(mc->mode == cgltf_meshopt_compression_mode_invalid, cgltf_result_invalid_gltf);
1592 CGLTF_ASSERT_IF(mc->mode == cgltf_meshopt_compression_mode_attributes && !(mc->stride % 4 == 0 && mc->stride <= 256), cgltf_result_invalid_gltf);
1594 CGLTF_ASSERT_IF(mc->mode == cgltf_meshopt_compression_mode_triangles && mc->count % 3 != 0, cgltf_result_invalid_gltf);
1596 CGLTF_ASSERT_IF((mc->mode == cgltf_meshopt_compression_mode_triangles || mc->mode == cgltf_meshopt_compression_mode_indices) && mc->stride != 2 && mc->stride != 4, cgltf_result_invalid_gltf);
1598 CGLTF_ASSERT_IF((mc->mode == cgltf_meshopt_compression_mode_triangles || mc->mode == cgltf_meshopt_compression_mode_indices) && mc->filter != cgltf_meshopt_compression_filter_none, cgltf_result_invalid_gltf);
1600 CGLTF_ASSERT_IF(mc->filter == cgltf_meshopt_compression_filter_octahedral && mc->stride != 4 && mc->stride != 8, cgltf_result_invalid_gltf);
1602 CGLTF_ASSERT_IF(mc->filter == cgltf_meshopt_compression_filter_quaternion && mc->stride != 8, cgltf_result_invalid_gltf);
1606 for (cgltf_size i = 0; i < data->meshes_count; ++i)
1608 if (data->meshes[i].weights)
1610 CGLTF_ASSERT_IF(data->meshes[i].primitives_count && data->meshes[i].primitives[0].targets_count != data->meshes[i].weights_count, cgltf_result_invalid_gltf);
1613 if (data->meshes[i].target_names)
1615 CGLTF_ASSERT_IF(data->meshes[i].primitives_count && data->meshes[i].primitives[0].targets_count != data->meshes[i].target_names_count, cgltf_result_invalid_gltf);
1618 for (cgltf_size j = 0; j < data->meshes[i].primitives_count; ++j)
1620 CGLTF_ASSERT_IF(data->meshes[i].primitives[j].targets_count != data->meshes[i].primitives[0].targets_count, cgltf_result_invalid_gltf);
1622 if (data->meshes[i].primitives[j].attributes_count)
1624 cgltf_accessor* first = data->meshes[i].primitives[j].attributes[0].data;
1626 for (cgltf_size k = 0; k < data->meshes[i].primitives[j].attributes_count; ++k)
1628 CGLTF_ASSERT_IF(data->meshes[i].primitives[j].attributes[k].data->count != first->count, cgltf_result_invalid_gltf);
1631 for (cgltf_size k = 0; k < data->meshes[i].primitives[j].targets_count; ++k)
1633 for (cgltf_size m = 0; m < data->meshes[i].primitives[j].targets[k].attributes_count; ++m)
1635 CGLTF_ASSERT_IF(data->meshes[i].primitives[j].targets[k].attributes[m].data->count != first->count, cgltf_result_invalid_gltf);
1641 CGLTF_ASSERT_IF(indices &&
1642 indices->component_type != cgltf_component_type_r_8u &&
1643 indices->component_type != cgltf_component_type_r_16u &&
1644 indices->component_type != cgltf_component_type_r_32u, cgltf_result_invalid_gltf);
1646 if (indices && indices->buffer_view && indices->buffer_view->buffer->data)
1648 cgltf_size index_bound = cgltf_calc_index_bound(indices->buffer_view, indices->offset, indices->component_type, indices->count);
1650 CGLTF_ASSERT_IF(index_bound >= first->count, cgltf_result_data_too_short);
1653 for (cgltf_size k = 0; k < data->meshes[i].primitives[j].mappings_count; ++k)
1655 CGLTF_ASSERT_IF(data->meshes[i].primitives[j].mappings[k].variant >= data->variants_count, cgltf_result_invalid_gltf);
1661 for (cgltf_size i = 0; i < data->nodes_count; ++i)
1663 if (data->nodes[i].weights && data->nodes[i].mesh)
1665 CGLTF_ASSERT_IF (data->nodes[i].mesh->primitives_count && data->nodes[i].mesh->primitives[0].targets_count != data->nodes[i].weights_count, cgltf_result_invalid_gltf);
1669 for (cgltf_size i = 0; i < data->nodes_count; ++i)
1676 CGLTF_ASSERT_IF(p1 == p2, cgltf_result_invalid_gltf);
1679 p2 = p2->parent ? p2->parent->parent : NULL;
1683 for (cgltf_size i = 0; i < data->scenes_count; ++i)
1685 for (cgltf_size j = 0; j < data->scenes[i].nodes_count; ++j)
1687 CGLTF_ASSERT_IF(data->scenes[i].nodes[j]->parent, cgltf_result_invalid_gltf);
1691 for (cgltf_size i = 0; i < data->animations_count; ++i)
1693 for (cgltf_size j = 0; j < data->animations[i].channels_count; ++j)
1697 if (!channel->target_node)
1702 cgltf_size components = 1;
1704 if (channel->target_path == cgltf_animation_path_type_weights)
1706 CGLTF_ASSERT_IF(!channel->target_node->mesh || !channel->target_node->mesh->primitives_count, cgltf_result_invalid_gltf);
1708 components = channel->target_node->mesh->primitives[0].targets_count;
1711 cgltf_size values = channel->sampler->interpolation == cgltf_interpolation_type_cubic_spline ? 3 : 1;
1713 CGLTF_ASSERT_IF(channel->sampler->input->count * components * values != channel->sampler->output->count, cgltf_result_data_too_short);
1717 return cgltf_result_success;
1720cgltf_result cgltf_copy_extras_json(
const cgltf_data* data,
const cgltf_extras* extras,
char* dest, cgltf_size* dest_size)
1722 cgltf_size json_size = extras->end_offset - extras->start_offset;
1728 *dest_size = json_size + 1;
1729 return cgltf_result_success;
1731 return cgltf_result_invalid_options;
1734 if (*dest_size + 1 < json_size)
1736 strncpy(dest, data->json + extras->start_offset, *dest_size - 1);
1737 dest[*dest_size - 1] = 0;
1741 strncpy(dest, data->json + extras->start_offset, json_size);
1742 dest[json_size] = 0;
1745 return cgltf_result_success;
1750 for (cgltf_size i = 0; i < extensions_count; ++i)
1752 data->memory.free_func(data->memory.user_data, extensions[i].name);
1753 data->memory.free_func(data->memory.user_data, extensions[i].data);
1755 data->memory.free_func(data->memory.user_data, extensions);
1767 data->memory.free_func(data->memory.user_data, data->asset.copyright);
1768 data->memory.free_func(data->memory.user_data, data->asset.generator);
1769 data->memory.free_func(data->memory.user_data, data->asset.version);
1770 data->memory.free_func(data->memory.user_data, data->asset.min_version);
1772 cgltf_free_extensions(data, data->asset.extensions, data->asset.extensions_count);
1774 for (cgltf_size i = 0; i < data->accessors_count; ++i)
1776 data->memory.free_func(data->memory.user_data, data->accessors[i].name);
1778 if(data->accessors[i].is_sparse)
1780 cgltf_free_extensions(data, data->accessors[i].sparse.extensions, data->accessors[i].sparse.extensions_count);
1781 cgltf_free_extensions(data, data->accessors[i].sparse.indices_extensions, data->accessors[i].sparse.indices_extensions_count);
1782 cgltf_free_extensions(data, data->accessors[i].sparse.values_extensions, data->accessors[i].sparse.values_extensions_count);
1784 cgltf_free_extensions(data, data->accessors[i].extensions, data->accessors[i].extensions_count);
1786 data->memory.free_func(data->memory.user_data, data->accessors);
1788 for (cgltf_size i = 0; i < data->buffer_views_count; ++i)
1790 data->memory.free_func(data->memory.user_data, data->buffer_views[i].name);
1791 data->memory.free_func(data->memory.user_data, data->buffer_views[i].data);
1793 cgltf_free_extensions(data, data->buffer_views[i].extensions, data->buffer_views[i].extensions_count);
1795 data->memory.free_func(data->memory.user_data, data->buffer_views);
1797 for (cgltf_size i = 0; i < data->buffers_count; ++i)
1799 data->memory.free_func(data->memory.user_data, data->buffers[i].name);
1801 if (data->buffers[i].data_free_method == cgltf_data_free_method_file_release)
1803 file_release(&data->memory, &data->file, data->buffers[i].data);
1805 else if (data->buffers[i].data_free_method == cgltf_data_free_method_memory_free)
1807 data->memory.free_func(data->memory.user_data, data->buffers[i].data);
1810 data->memory.free_func(data->memory.user_data, data->buffers[i].uri);
1812 cgltf_free_extensions(data, data->buffers[i].extensions, data->buffers[i].extensions_count);
1815 data->memory.free_func(data->memory.user_data, data->buffers);
1817 for (cgltf_size i = 0; i < data->meshes_count; ++i)
1819 data->memory.free_func(data->memory.user_data, data->meshes[i].name);
1821 for (cgltf_size j = 0; j < data->meshes[i].primitives_count; ++j)
1823 for (cgltf_size k = 0; k < data->meshes[i].primitives[j].attributes_count; ++k)
1825 data->memory.free_func(data->memory.user_data, data->meshes[i].primitives[j].attributes[k].name);
1828 data->memory.free_func(data->memory.user_data, data->meshes[i].primitives[j].attributes);
1830 for (cgltf_size k = 0; k < data->meshes[i].primitives[j].targets_count; ++k)
1832 for (cgltf_size m = 0; m < data->meshes[i].primitives[j].targets[k].attributes_count; ++m)
1834 data->memory.free_func(data->memory.user_data, data->meshes[i].primitives[j].targets[k].attributes[m].name);
1837 data->memory.free_func(data->memory.user_data, data->meshes[i].primitives[j].targets[k].attributes);
1840 data->memory.free_func(data->memory.user_data, data->meshes[i].primitives[j].targets);
1842 if (data->meshes[i].primitives[j].has_draco_mesh_compression)
1844 for (cgltf_size k = 0; k < data->meshes[i].primitives[j].draco_mesh_compression.attributes_count; ++k)
1846 data->memory.free_func(data->memory.user_data, data->meshes[i].primitives[j].draco_mesh_compression.attributes[k].name);
1849 data->memory.free_func(data->memory.user_data, data->meshes[i].primitives[j].draco_mesh_compression.attributes);
1852 data->memory.free_func(data->memory.user_data, data->meshes[i].primitives[j].mappings);
1854 cgltf_free_extensions(data, data->meshes[i].primitives[j].extensions, data->meshes[i].primitives[j].extensions_count);
1857 data->memory.free_func(data->memory.user_data, data->meshes[i].primitives);
1858 data->memory.free_func(data->memory.user_data, data->meshes[i].weights);
1860 for (cgltf_size j = 0; j < data->meshes[i].target_names_count; ++j)
1862 data->memory.free_func(data->memory.user_data, data->meshes[i].target_names[j]);
1865 cgltf_free_extensions(data, data->meshes[i].extensions, data->meshes[i].extensions_count);
1867 data->memory.free_func(data->memory.user_data, data->meshes[i].target_names);
1870 data->memory.free_func(data->memory.user_data, data->meshes);
1872 for (cgltf_size i = 0; i < data->materials_count; ++i)
1874 data->memory.free_func(data->memory.user_data, data->materials[i].name);
1876 if(data->materials[i].has_pbr_metallic_roughness)
1878 cgltf_free_extensions(data, data->materials[i].pbr_metallic_roughness.metallic_roughness_texture.extensions, data->materials[i].pbr_metallic_roughness.metallic_roughness_texture.extensions_count);
1879 cgltf_free_extensions(data, data->materials[i].pbr_metallic_roughness.base_color_texture.extensions, data->materials[i].pbr_metallic_roughness.base_color_texture.extensions_count);
1881 if(data->materials[i].has_pbr_specular_glossiness)
1883 cgltf_free_extensions(data, data->materials[i].pbr_specular_glossiness.diffuse_texture.extensions, data->materials[i].pbr_specular_glossiness.diffuse_texture.extensions_count);
1884 cgltf_free_extensions(data, data->materials[i].pbr_specular_glossiness.specular_glossiness_texture.extensions, data->materials[i].pbr_specular_glossiness.specular_glossiness_texture.extensions_count);
1886 if(data->materials[i].has_clearcoat)
1888 cgltf_free_extensions(data, data->materials[i].clearcoat.clearcoat_texture.extensions, data->materials[i].clearcoat.clearcoat_texture.extensions_count);
1889 cgltf_free_extensions(data, data->materials[i].clearcoat.clearcoat_roughness_texture.extensions, data->materials[i].clearcoat.clearcoat_roughness_texture.extensions_count);
1890 cgltf_free_extensions(data, data->materials[i].clearcoat.clearcoat_normal_texture.extensions, data->materials[i].clearcoat.clearcoat_normal_texture.extensions_count);
1892 if(data->materials[i].has_specular)
1894 cgltf_free_extensions(data, data->materials[i].specular.specular_texture.extensions, data->materials[i].specular.specular_texture.extensions_count);
1895 cgltf_free_extensions(data, data->materials[i].specular.specular_color_texture.extensions, data->materials[i].specular.specular_color_texture.extensions_count);
1897 if(data->materials[i].has_transmission)
1899 cgltf_free_extensions(data, data->materials[i].transmission.transmission_texture.extensions, data->materials[i].transmission.transmission_texture.extensions_count);
1901 if (data->materials[i].has_volume)
1903 cgltf_free_extensions(data, data->materials[i].volume.thickness_texture.extensions, data->materials[i].volume.thickness_texture.extensions_count);
1905 if(data->materials[i].has_sheen)
1907 cgltf_free_extensions(data, data->materials[i].sheen.sheen_color_texture.extensions, data->materials[i].sheen.sheen_color_texture.extensions_count);
1908 cgltf_free_extensions(data, data->materials[i].sheen.sheen_roughness_texture.extensions, data->materials[i].sheen.sheen_roughness_texture.extensions_count);
1910 if(data->materials[i].has_iridescence)
1912 cgltf_free_extensions(data, data->materials[i].iridescence.iridescence_texture.extensions, data->materials[i].iridescence.iridescence_texture.extensions_count);
1913 cgltf_free_extensions(data, data->materials[i].iridescence.iridescence_thickness_texture.extensions, data->materials[i].iridescence.iridescence_thickness_texture.extensions_count);
1916 cgltf_free_extensions(data, data->materials[i].normal_texture.extensions, data->materials[i].normal_texture.extensions_count);
1917 cgltf_free_extensions(data, data->materials[i].occlusion_texture.extensions, data->materials[i].occlusion_texture.extensions_count);
1918 cgltf_free_extensions(data, data->materials[i].emissive_texture.extensions, data->materials[i].emissive_texture.extensions_count);
1920 cgltf_free_extensions(data, data->materials[i].extensions, data->materials[i].extensions_count);
1923 data->memory.free_func(data->memory.user_data, data->materials);
1925 for (cgltf_size i = 0; i < data->images_count; ++i)
1927 data->memory.free_func(data->memory.user_data, data->images[i].name);
1928 data->memory.free_func(data->memory.user_data, data->images[i].uri);
1929 data->memory.free_func(data->memory.user_data, data->images[i].mime_type);
1931 cgltf_free_extensions(data, data->images[i].extensions, data->images[i].extensions_count);
1934 data->memory.free_func(data->memory.user_data, data->images);
1936 for (cgltf_size i = 0; i < data->textures_count; ++i)
1938 data->memory.free_func(data->memory.user_data, data->textures[i].name);
1939 cgltf_free_extensions(data, data->textures[i].extensions, data->textures[i].extensions_count);
1942 data->memory.free_func(data->memory.user_data, data->textures);
1944 for (cgltf_size i = 0; i < data->samplers_count; ++i)
1946 data->memory.free_func(data->memory.user_data, data->samplers[i].name);
1947 cgltf_free_extensions(data, data->samplers[i].extensions, data->samplers[i].extensions_count);
1950 data->memory.free_func(data->memory.user_data, data->samplers);
1952 for (cgltf_size i = 0; i < data->skins_count; ++i)
1954 data->memory.free_func(data->memory.user_data, data->skins[i].name);
1955 data->memory.free_func(data->memory.user_data, data->skins[i].joints);
1957 cgltf_free_extensions(data, data->skins[i].extensions, data->skins[i].extensions_count);
1960 data->memory.free_func(data->memory.user_data, data->skins);
1962 for (cgltf_size i = 0; i < data->cameras_count; ++i)
1964 data->memory.free_func(data->memory.user_data, data->cameras[i].name);
1965 cgltf_free_extensions(data, data->cameras[i].extensions, data->cameras[i].extensions_count);
1968 data->memory.free_func(data->memory.user_data, data->cameras);
1970 for (cgltf_size i = 0; i < data->lights_count; ++i)
1972 data->memory.free_func(data->memory.user_data, data->lights[i].name);
1975 data->memory.free_func(data->memory.user_data, data->lights);
1977 for (cgltf_size i = 0; i < data->nodes_count; ++i)
1979 data->memory.free_func(data->memory.user_data, data->nodes[i].name);
1980 data->memory.free_func(data->memory.user_data, data->nodes[i].children);
1981 data->memory.free_func(data->memory.user_data, data->nodes[i].weights);
1982 cgltf_free_extensions(data, data->nodes[i].extensions, data->nodes[i].extensions_count);
1985 data->memory.free_func(data->memory.user_data, data->nodes);
1987 for (cgltf_size i = 0; i < data->scenes_count; ++i)
1989 data->memory.free_func(data->memory.user_data, data->scenes[i].name);
1990 data->memory.free_func(data->memory.user_data, data->scenes[i].nodes);
1992 cgltf_free_extensions(data, data->scenes[i].extensions, data->scenes[i].extensions_count);
1995 data->memory.free_func(data->memory.user_data, data->scenes);
1997 for (cgltf_size i = 0; i < data->animations_count; ++i)
1999 data->memory.free_func(data->memory.user_data, data->animations[i].name);
2000 for (cgltf_size j = 0; j < data->animations[i].samplers_count; ++j)
2002 cgltf_free_extensions(data, data->animations[i].samplers[j].extensions, data->animations[i].samplers[j].extensions_count);
2004 data->memory.free_func(data->memory.user_data, data->animations[i].samplers);
2006 for (cgltf_size j = 0; j < data->animations[i].channels_count; ++j)
2008 cgltf_free_extensions(data, data->animations[i].channels[j].extensions, data->animations[i].channels[j].extensions_count);
2010 data->memory.free_func(data->memory.user_data, data->animations[i].channels);
2012 cgltf_free_extensions(data, data->animations[i].extensions, data->animations[i].extensions_count);
2015 data->memory.free_func(data->memory.user_data, data->animations);
2017 for (cgltf_size i = 0; i < data->variants_count; ++i)
2019 data->memory.free_func(data->memory.user_data, data->variants[i].name);
2022 data->memory.free_func(data->memory.user_data, data->variants);
2024 cgltf_free_extensions(data, data->data_extensions, data->data_extensions_count);
2026 for (cgltf_size i = 0; i < data->extensions_used_count; ++i)
2028 data->memory.free_func(data->memory.user_data, data->extensions_used[i]);
2031 data->memory.free_func(data->memory.user_data, data->extensions_used);
2033 for (cgltf_size i = 0; i < data->extensions_required_count; ++i)
2035 data->memory.free_func(data->memory.user_data, data->extensions_required[i]);
2038 data->memory.free_func(data->memory.user_data, data->extensions_required);
2040 file_release(&data->memory, &data->file, data->file_data);
2042 data->memory.free_func(data->memory.user_data, data);
2045void cgltf_node_transform_local(
const cgltf_node* node, cgltf_float* out_matrix)
2047 cgltf_float* lm = out_matrix;
2049 if (node->has_matrix)
2051 memcpy(lm, node->matrix,
sizeof(
float) * 16);
2055 float tx = node->translation[0];
2056 float ty = node->translation[1];
2057 float tz = node->translation[2];
2059 float qx = node->rotation[0];
2060 float qy = node->rotation[1];
2061 float qz = node->rotation[2];
2062 float qw = node->rotation[3];
2064 float sx = node->scale[0];
2065 float sy = node->scale[1];
2066 float sz = node->scale[2];
2068 lm[0] = (1 - 2 * qy*qy - 2 * qz*qz) * sx;
2069 lm[1] = (2 * qx*qy + 2 * qz*qw) * sx;
2070 lm[2] = (2 * qx*qz - 2 * qy*qw) * sx;
2073 lm[4] = (2 * qx*qy - 2 * qz*qw) * sy;
2074 lm[5] = (1 - 2 * qx*qx - 2 * qz*qz) * sy;
2075 lm[6] = (2 * qy*qz + 2 * qx*qw) * sy;
2078 lm[8] = (2 * qx*qz + 2 * qy*qw) * sz;
2079 lm[9] = (2 * qy*qz - 2 * qx*qw) * sz;
2080 lm[10] = (1 - 2 * qx*qx - 2 * qy*qy) * sz;
2090void cgltf_node_transform_world(
const cgltf_node* node, cgltf_float* out_matrix)
2092 cgltf_float* lm = out_matrix;
2093 cgltf_node_transform_local(node, lm);
2100 cgltf_node_transform_local(parent, pm);
2102 for (
int i = 0; i < 4; ++i)
2104 float l0 = lm[i * 4 + 0];
2105 float l1 = lm[i * 4 + 1];
2106 float l2 = lm[i * 4 + 2];
2108 float r0 = l0 * pm[0] + l1 * pm[4] + l2 * pm[8];
2109 float r1 = l0 * pm[1] + l1 * pm[5] + l2 * pm[9];
2110 float r2 = l0 * pm[2] + l1 * pm[6] + l2 * pm[10];
2121 parent = parent->parent;
2125static cgltf_ssize cgltf_component_read_integer(
const void* in, cgltf_component_type component_type)
2127 switch (component_type)
2129 case cgltf_component_type_r_16:
2130 return *((
const int16_t*) in);
2131 case cgltf_component_type_r_16u:
2132 return *((
const uint16_t*) in);
2133 case cgltf_component_type_r_32u:
2134 return *((
const uint32_t*) in);
2135 case cgltf_component_type_r_32f:
2136 return (cgltf_ssize)*((
const float*) in);
2137 case cgltf_component_type_r_8:
2138 return *((
const int8_t*) in);
2139 case cgltf_component_type_r_8u:
2140 return *((
const uint8_t*) in);
2146static cgltf_size cgltf_component_read_index(
const void* in, cgltf_component_type component_type)
2148 switch (component_type)
2150 case cgltf_component_type_r_16u:
2151 return *((
const uint16_t*) in);
2152 case cgltf_component_type_r_32u:
2153 return *((
const uint32_t*) in);
2154 case cgltf_component_type_r_32f:
2155 return (cgltf_size)*((
const float*) in);
2156 case cgltf_component_type_r_8u:
2157 return *((
const uint8_t*) in);
2163static cgltf_float cgltf_component_read_float(
const void* in, cgltf_component_type component_type, cgltf_bool normalized)
2165 if (component_type == cgltf_component_type_r_32f)
2167 return *((
const float*) in);
2172 switch (component_type)
2175 case cgltf_component_type_r_16:
2176 return *((
const int16_t*) in) / (cgltf_float)32767;
2177 case cgltf_component_type_r_16u:
2178 return *((
const uint16_t*) in) / (cgltf_float)65535;
2179 case cgltf_component_type_r_8:
2180 return *((
const int8_t*) in) / (cgltf_float)127;
2181 case cgltf_component_type_r_8u:
2182 return *((
const uint8_t*) in) / (cgltf_float)255;
2188 return (cgltf_float)cgltf_component_read_integer(in, component_type);
2191static cgltf_size cgltf_component_size(cgltf_component_type component_type);
2193static 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)
2195 cgltf_size num_components = cgltf_num_components(type);
2197 if (element_size < num_components) {
2203 cgltf_size component_size = cgltf_component_size(component_type);
2205 if (type == cgltf_type_mat2 && component_size == 1)
2207 out[0] = cgltf_component_read_float(element, component_type, normalized);
2208 out[1] = cgltf_component_read_float(element + 1, component_type, normalized);
2209 out[2] = cgltf_component_read_float(element + 4, component_type, normalized);
2210 out[3] = cgltf_component_read_float(element + 5, component_type, normalized);
2214 if (type == cgltf_type_mat3 && component_size == 1)
2216 out[0] = cgltf_component_read_float(element, component_type, normalized);
2217 out[1] = cgltf_component_read_float(element + 1, component_type, normalized);
2218 out[2] = cgltf_component_read_float(element + 2, component_type, normalized);
2219 out[3] = cgltf_component_read_float(element + 4, component_type, normalized);
2220 out[4] = cgltf_component_read_float(element + 5, component_type, normalized);
2221 out[5] = cgltf_component_read_float(element + 6, component_type, normalized);
2222 out[6] = cgltf_component_read_float(element + 8, component_type, normalized);
2223 out[7] = cgltf_component_read_float(element + 9, component_type, normalized);
2224 out[8] = cgltf_component_read_float(element + 10, component_type, normalized);
2228 if (type == cgltf_type_mat3 && component_size == 2)
2230 out[0] = cgltf_component_read_float(element, component_type, normalized);
2231 out[1] = cgltf_component_read_float(element + 2, component_type, normalized);
2232 out[2] = cgltf_component_read_float(element + 4, component_type, normalized);
2233 out[3] = cgltf_component_read_float(element + 8, component_type, normalized);
2234 out[4] = cgltf_component_read_float(element + 10, component_type, normalized);
2235 out[5] = cgltf_component_read_float(element + 12, component_type, normalized);
2236 out[6] = cgltf_component_read_float(element + 16, component_type, normalized);
2237 out[7] = cgltf_component_read_float(element + 18, component_type, normalized);
2238 out[8] = cgltf_component_read_float(element + 20, component_type, normalized);
2242 for (cgltf_size i = 0; i < num_components; ++i)
2244 out[i] = cgltf_component_read_float(element + component_size * i, component_type, normalized);
2252 return (
const uint8_t*)view->data;
2254 if (!view->buffer->data)
2257 const uint8_t* result = (
const uint8_t*)view->buffer->data;
2258 result += view->offset;
2262cgltf_bool cgltf_accessor_read_float(
const cgltf_accessor* accessor, cgltf_size index, cgltf_float* out, cgltf_size element_size)
2264 if (accessor->is_sparse)
2268 if (accessor->buffer_view == NULL)
2270 memset(out, 0, element_size *
sizeof(cgltf_float));
2273 const uint8_t* element = cgltf_buffer_view_data(accessor->buffer_view);
2274 if (element == NULL)
2278 element += accessor->offset + accessor->stride * index;
2279 return cgltf_element_read_float(element, accessor->type, accessor->component_type, accessor->normalized, out, element_size);
2282cgltf_size cgltf_accessor_unpack_floats(
const cgltf_accessor* accessor, cgltf_float* out, cgltf_size float_count)
2284 cgltf_size floats_per_element = cgltf_num_components(accessor->type);
2285 cgltf_size available_floats = accessor->count * floats_per_element;
2288 return available_floats;
2291 float_count = available_floats < float_count ? available_floats : float_count;
2292 cgltf_size element_count = float_count / floats_per_element;
2295 cgltf_float* dest = out;
2297 dense.is_sparse = 0;
2298 for (cgltf_size index = 0; index < element_count; index++, dest += floats_per_element)
2300 if (!cgltf_accessor_read_float(&dense, index, dest, floats_per_element))
2307 if (accessor->is_sparse)
2311 const uint8_t* index_data = cgltf_buffer_view_data(sparse->indices_buffer_view);
2312 const uint8_t* reader_head = cgltf_buffer_view_data(sparse->values_buffer_view);
2314 if (index_data == NULL || reader_head == NULL)
2319 index_data += sparse->indices_byte_offset;
2320 reader_head += sparse->values_byte_offset;
2322 cgltf_size index_stride = cgltf_component_size(sparse->indices_component_type);
2323 for (cgltf_size reader_index = 0; reader_index < sparse->count; reader_index++, index_data += index_stride)
2325 size_t writer_index = cgltf_component_read_index(index_data, sparse->indices_component_type);
2326 float* writer_head = out + writer_index * floats_per_element;
2328 if (!cgltf_element_read_float(reader_head, dense.type, dense.component_type, dense.normalized, writer_head, floats_per_element))
2333 reader_head += dense.stride;
2337 return element_count * floats_per_element;
2340static cgltf_uint cgltf_component_read_uint(
const void* in, cgltf_component_type component_type)
2342 switch (component_type)
2344 case cgltf_component_type_r_8:
2345 return *((
const int8_t*) in);
2347 case cgltf_component_type_r_8u:
2348 return *((
const uint8_t*) in);
2350 case cgltf_component_type_r_16:
2351 return *((
const int16_t*) in);
2353 case cgltf_component_type_r_16u:
2354 return *((
const uint16_t*) in);
2356 case cgltf_component_type_r_32u:
2357 return *((
const uint32_t*) in);
2364static 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)
2366 cgltf_size num_components = cgltf_num_components(type);
2368 if (element_size < num_components)
2374 if (type == cgltf_type_mat2 || type == cgltf_type_mat3 || type == cgltf_type_mat4)
2379 cgltf_size component_size = cgltf_component_size(component_type);
2381 for (cgltf_size i = 0; i < num_components; ++i)
2383 out[i] = cgltf_component_read_uint(element + component_size * i, component_type);
2388cgltf_bool cgltf_accessor_read_uint(
const cgltf_accessor* accessor, cgltf_size index, cgltf_uint* out, cgltf_size element_size)
2390 if (accessor->is_sparse)
2394 if (accessor->buffer_view == NULL)
2396 memset(out, 0, element_size *
sizeof( cgltf_uint ));
2399 const uint8_t* element = cgltf_buffer_view_data(accessor->buffer_view);
2400 if (element == NULL)
2404 element += accessor->offset + accessor->stride * index;
2405 return cgltf_element_read_uint(element, accessor->type, accessor->component_type, out, element_size);
2408cgltf_size cgltf_accessor_read_index(
const cgltf_accessor* accessor, cgltf_size index)
2410 if (accessor->is_sparse)
2414 if (accessor->buffer_view == NULL)
2418 const uint8_t* element = cgltf_buffer_view_data(accessor->buffer_view);
2419 if (element == NULL)
2423 element += accessor->offset + accessor->stride * index;
2424 return cgltf_component_read_index(element, accessor->component_type);
2427#define CGLTF_ERROR_JSON -1
2428#define CGLTF_ERROR_NOMEM -2
2429#define CGLTF_ERROR_LEGACY -3
2431#define CGLTF_CHECK_TOKTYPE(tok_, type_) if ((tok_).type != (type_)) { return CGLTF_ERROR_JSON; }
2432#define CGLTF_CHECK_TOKTYPE_RETTYPE(tok_, type_, ret_) if ((tok_).type != (type_)) { return (ret_)CGLTF_ERROR_JSON; }
2433#define CGLTF_CHECK_KEY(tok_) if ((tok_).type != JSMN_STRING || (tok_).size == 0) { return CGLTF_ERROR_JSON; }
2435#define CGLTF_PTRINDEX(type, idx) (type*)((cgltf_size)idx + 1)
2436#define CGLTF_PTRFIXUP(var, data, size) if (var) { if ((cgltf_size)var > size) { return CGLTF_ERROR_JSON; } var = &data[(cgltf_size)var-1]; }
2437#define CGLTF_PTRFIXUP_REQ(var, data, size) if (!var || (cgltf_size)var > size) { return CGLTF_ERROR_JSON; } var = &data[(cgltf_size)var-1];
2439static int cgltf_json_strcmp(jsmntok_t
const* tok,
const uint8_t* json_chunk,
const char* str)
2441 CGLTF_CHECK_TOKTYPE(*tok, JSMN_STRING);
2442 size_t const str_len = strlen(str);
2443 size_t const name_length = tok->end - tok->start;
2444 return (str_len == name_length) ? strncmp((
const char*)json_chunk + tok->start, str, str_len) : 128;
2447static int cgltf_json_to_int(jsmntok_t
const* tok,
const uint8_t* json_chunk)
2449 CGLTF_CHECK_TOKTYPE(*tok, JSMN_PRIMITIVE);
2451 int size = (cgltf_size)(tok->end - tok->start) <
sizeof(tmp) ? tok->end - tok->start : (int)(sizeof(tmp) - 1);
2452 strncpy(tmp, (
const char*)json_chunk + tok->start, size);
2454 return CGLTF_ATOI(tmp);
2457static cgltf_size cgltf_json_to_size(jsmntok_t
const* tok,
const uint8_t* json_chunk)
2459 CGLTF_CHECK_TOKTYPE_RETTYPE(*tok, JSMN_PRIMITIVE, cgltf_size);
2461 int size = (cgltf_size)(tok->end - tok->start) <
sizeof(tmp) ? tok->end - tok->start : (int)(sizeof(tmp) - 1);
2462 strncpy(tmp, (
const char*)json_chunk + tok->start, size);
2464 return (cgltf_size)CGLTF_ATOLL(tmp);
2467static cgltf_float cgltf_json_to_float(jsmntok_t
const* tok,
const uint8_t* json_chunk)
2469 CGLTF_CHECK_TOKTYPE(*tok, JSMN_PRIMITIVE);
2471 int size = (cgltf_size)(tok->end - tok->start) <
sizeof(tmp) ? tok->end - tok->start : (int)(sizeof(tmp) - 1);
2472 strncpy(tmp, (
const char*)json_chunk + tok->start, size);
2474 return (cgltf_float)CGLTF_ATOF(tmp);
2477static cgltf_bool cgltf_json_to_bool(jsmntok_t
const* tok,
const uint8_t* json_chunk)
2479 int size = tok->end - tok->start;
2480 return size == 4 && memcmp(json_chunk + tok->start,
"true", 4) == 0;
2483static int cgltf_skip_json(jsmntok_t
const* tokens,
int i)
2489 switch (tokens[i].type)
2492 end += tokens[i].size * 2;
2496 end += tokens[i].size;
2499 case JSMN_PRIMITIVE:
2513static void cgltf_fill_float_array(
float* out_array,
int size,
float value)
2515 for (
int j = 0; j < size; ++j)
2517 out_array[j] = value;
2521static int cgltf_parse_json_float_array(jsmntok_t
const* tokens,
int i,
const uint8_t* json_chunk,
float* out_array,
int size)
2523 CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_ARRAY);
2524 if (tokens[i].size != size)
2526 return CGLTF_ERROR_JSON;
2529 for (
int j = 0; j < size; ++j)
2531 CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_PRIMITIVE);
2532 out_array[j] = cgltf_json_to_float(tokens + i, json_chunk);
2538static int cgltf_parse_json_string(
cgltf_options* options, jsmntok_t
const* tokens,
int i,
const uint8_t* json_chunk,
char** out_string)
2540 CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_STRING);
2543 return CGLTF_ERROR_JSON;
2545 int size = tokens[i].end - tokens[i].start;
2546 char* result = (
char*)options->memory.alloc_func(options->memory.user_data, size + 1);
2549 return CGLTF_ERROR_NOMEM;
2551 strncpy(result, (
const char*)json_chunk + tokens[i].start, size);
2553 *out_string = result;
2557static 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)
2560 if (tokens[i].type != JSMN_ARRAY)
2562 return tokens[i].type == JSMN_OBJECT ? CGLTF_ERROR_LEGACY : CGLTF_ERROR_JSON;
2566 return CGLTF_ERROR_JSON;
2568 int size = tokens[i].size;
2569 void* result = cgltf_calloc(options, element_size, size);
2572 return CGLTF_ERROR_NOMEM;
2574 *out_array = result;
2579static 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)
2581 CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_ARRAY);
2582 i = cgltf_parse_json_array(options, tokens, i, json_chunk,
sizeof(
char*), (
void**)out_array, out_size);
2588 for (cgltf_size j = 0; j < *out_size; ++j)
2590 i = cgltf_parse_json_string(options, tokens, i, json_chunk, j + (*out_array));
2599static void cgltf_parse_attribute_type(
const char* name, cgltf_attribute_type* out_type,
int* out_index)
2603 *out_type = cgltf_attribute_type_custom;
2607 const char* us = strchr(name,
'_');
2608 size_t len = us ? (size_t)(us - name) : strlen(name);
2610 if (len == 8 && strncmp(name,
"POSITION", 8) == 0)
2612 *out_type = cgltf_attribute_type_position;
2614 else if (len == 6 && strncmp(name,
"NORMAL", 6) == 0)
2616 *out_type = cgltf_attribute_type_normal;
2618 else if (len == 7 && strncmp(name,
"TANGENT", 7) == 0)
2620 *out_type = cgltf_attribute_type_tangent;
2622 else if (len == 8 && strncmp(name,
"TEXCOORD", 8) == 0)
2624 *out_type = cgltf_attribute_type_texcoord;
2626 else if (len == 5 && strncmp(name,
"COLOR", 5) == 0)
2628 *out_type = cgltf_attribute_type_color;
2630 else if (len == 6 && strncmp(name,
"JOINTS", 6) == 0)
2632 *out_type = cgltf_attribute_type_joints;
2634 else if (len == 7 && strncmp(name,
"WEIGHTS", 7) == 0)
2636 *out_type = cgltf_attribute_type_weights;
2640 *out_type = cgltf_attribute_type_invalid;
2643 if (us && *out_type != cgltf_attribute_type_invalid)
2645 *out_index = CGLTF_ATOI(us + 1);
2649static 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)
2651 CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
2653 if (*out_attributes)
2655 return CGLTF_ERROR_JSON;
2658 *out_attributes_count = tokens[i].size;
2662 if (!*out_attributes)
2664 return CGLTF_ERROR_NOMEM;
2667 for (cgltf_size j = 0; j < *out_attributes_count; ++j)
2669 CGLTF_CHECK_KEY(tokens[i]);
2671 i = cgltf_parse_json_string(options, tokens, i, json_chunk, &(*out_attributes)[j].name);
2674 return CGLTF_ERROR_JSON;
2677 cgltf_parse_attribute_type((*out_attributes)[j].name, &(*out_attributes)[j].type, &(*out_attributes)[j].index);
2679 (*out_attributes)[j].data = CGLTF_PTRINDEX(
cgltf_accessor, cgltf_json_to_int(tokens + i, json_chunk));
2686static int cgltf_parse_json_extras(jsmntok_t
const* tokens,
int i,
const uint8_t* json_chunk,
cgltf_extras* out_extras)
2689 out_extras->start_offset = tokens[i].start;
2690 out_extras->end_offset = tokens[i].end;
2691 i = cgltf_skip_json(tokens, i);
2695static int cgltf_parse_json_unprocessed_extension(
cgltf_options* options, jsmntok_t
const* tokens,
int i,
const uint8_t* json_chunk,
cgltf_extension* out_extension)
2697 CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_STRING);
2698 CGLTF_CHECK_TOKTYPE(tokens[i+1], JSMN_OBJECT);
2699 if (out_extension->name)
2701 return CGLTF_ERROR_JSON;
2704 cgltf_size name_length = tokens[i].end - tokens[i].start;
2705 out_extension->name = (
char*)options->memory.alloc_func(options->memory.user_data, name_length + 1);
2706 if (!out_extension->name)
2708 return CGLTF_ERROR_NOMEM;
2710 strncpy(out_extension->name, (
const char*)json_chunk + tokens[i].start, name_length);
2711 out_extension->name[name_length] = 0;
2714 size_t start = tokens[i].start;
2715 size_t size = tokens[i].end - start;
2716 out_extension->data = (
char*)options->memory.alloc_func(options->memory.user_data, size + 1);
2717 if (!out_extension->data)
2719 return CGLTF_ERROR_NOMEM;
2721 strncpy(out_extension->data, (
const char*)json_chunk + start, size);
2722 out_extension->data[size] =
'\0';
2724 i = cgltf_skip_json(tokens, i);
2729static 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)
2733 CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
2736 return CGLTF_ERROR_JSON;
2739 int extensions_size = tokens[i].size;
2740 *out_extensions_count = 0;
2743 if (!*out_extensions)
2745 return CGLTF_ERROR_NOMEM;
2750 for (
int j = 0; j < extensions_size; ++j)
2752 CGLTF_CHECK_KEY(tokens[i]);
2754 cgltf_size extension_index = (*out_extensions_count)++;
2756 i = cgltf_parse_json_unprocessed_extension(options, tokens, i, json_chunk, extension);
2768 CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
2770 int size = tokens[i].size;
2773 for (
int j = 0; j < size; ++j)
2775 CGLTF_CHECK_KEY(tokens[i]);
2777 if (cgltf_json_strcmp(tokens + i, json_chunk,
"attributes") == 0)
2779 i = cgltf_parse_json_attribute_list(options, tokens, i + 1, json_chunk, &out_draco_mesh_compression->attributes, &out_draco_mesh_compression->attributes_count);
2781 else if (cgltf_json_strcmp(tokens + i, json_chunk,
"bufferView") == 0)
2784 out_draco_mesh_compression->buffer_view = CGLTF_PTRINDEX(
cgltf_buffer_view, cgltf_json_to_int(tokens + i, json_chunk));
2799 CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
2801 int size = tokens[i].size;
2804 for (
int j = 0; j < size; ++j)
2806 CGLTF_CHECK_KEY(tokens[i]);
2808 if (cgltf_json_strcmp(tokens + i, json_chunk,
"attributes") == 0)
2810 i = cgltf_parse_json_attribute_list(options, tokens, i + 1, json_chunk, &out_mesh_gpu_instancing->attributes, &out_mesh_gpu_instancing->attributes_count);
2812 else if (cgltf_json_strcmp(tokens + i, json_chunk,
"bufferView") == 0)
2815 out_mesh_gpu_instancing->buffer_view = CGLTF_PTRINDEX(
cgltf_buffer_view, cgltf_json_to_int(tokens + i, json_chunk));
2828static 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)
2831 CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_ARRAY);
2833 int size = tokens[i].size;
2836 for (
int j = 0; j < size; ++j)
2838 CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
2840 int obj_size = tokens[i].size;
2844 int variants_tok = -1;
2847 for (
int k = 0; k < obj_size; ++k)
2849 CGLTF_CHECK_KEY(tokens[i]);
2851 if (cgltf_json_strcmp(tokens + i, json_chunk,
"material") == 0)
2854 material = cgltf_json_to_int(tokens + i, json_chunk);
2857 else if (cgltf_json_strcmp(tokens + i, json_chunk,
"variants") == 0)
2860 CGLTF_CHECK_TOKTYPE(tokens[variants_tok], JSMN_ARRAY);
2862 i = cgltf_skip_json(tokens, i+1);
2864 else if (cgltf_json_strcmp(tokens + i, json_chunk,
"extras") == 0)
2866 i = cgltf_parse_json_extras(tokens, i + 1, json_chunk, &extras);
2870 i = cgltf_skip_json(tokens, i+1);
2879 if (material < 0 || variants_tok < 0)
2881 return CGLTF_ERROR_JSON;
2886 for (
int k = 0; k < tokens[variants_tok].size; ++k)
2888 int variant = cgltf_json_to_int(&tokens[variants_tok + 1 + k], json_chunk);
2892 out_mappings[*offset].material = CGLTF_PTRINDEX(
cgltf_material, material);
2893 out_mappings[*offset].variant = variant;
2894 out_mappings[*offset].extras = extras;
2901 (*offset) += tokens[variants_tok].size;
2908static int cgltf_parse_json_material_mappings(
cgltf_options* options, jsmntok_t
const* tokens,
int i,
const uint8_t* json_chunk,
cgltf_primitive* out_prim)
2910 CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
2912 int size = tokens[i].size;
2915 for (
int j = 0; j < size; ++j)
2917 CGLTF_CHECK_KEY(tokens[i]);
2919 if (cgltf_json_strcmp(tokens + i, json_chunk,
"mappings") == 0)
2921 if (out_prim->mappings)
2923 return CGLTF_ERROR_JSON;
2926 cgltf_size mappings_offset = 0;
2927 int k = cgltf_parse_json_material_mapping_data(options, tokens, i + 1, json_chunk, NULL, &mappings_offset);
2933 out_prim->mappings_count = mappings_offset;
2936 mappings_offset = 0;
2937 i = cgltf_parse_json_material_mapping_data(options, tokens, i + 1, json_chunk, out_prim->mappings, &mappings_offset);
2941 i = cgltf_skip_json(tokens, i+1);
2953static int cgltf_parse_json_primitive(
cgltf_options* options, jsmntok_t
const* tokens,
int i,
const uint8_t* json_chunk,
cgltf_primitive* out_prim)
2955 CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
2957 out_prim->type = cgltf_primitive_type_triangles;
2959 int size = tokens[i].size;
2962 for (
int j = 0; j < size; ++j)
2964 CGLTF_CHECK_KEY(tokens[i]);
2966 if (cgltf_json_strcmp(tokens+i, json_chunk,
"mode") == 0)
2970 = (cgltf_primitive_type)
2971 cgltf_json_to_int(tokens+i, json_chunk);
2974 else if (cgltf_json_strcmp(tokens+i, json_chunk,
"indices") == 0)
2977 out_prim->indices = CGLTF_PTRINDEX(
cgltf_accessor, cgltf_json_to_int(tokens + i, json_chunk));
2980 else if (cgltf_json_strcmp(tokens+i, json_chunk,
"material") == 0)
2983 out_prim->material = CGLTF_PTRINDEX(
cgltf_material, cgltf_json_to_int(tokens + i, json_chunk));
2986 else if (cgltf_json_strcmp(tokens+i, json_chunk,
"attributes") == 0)
2988 i = cgltf_parse_json_attribute_list(options, tokens, i + 1, json_chunk, &out_prim->attributes, &out_prim->attributes_count);
2990 else if (cgltf_json_strcmp(tokens+i, json_chunk,
"targets") == 0)
2992 i = cgltf_parse_json_array(options, tokens, i + 1, json_chunk,
sizeof(
cgltf_morph_target), (
void**)&out_prim->targets, &out_prim->targets_count);
2998 for (cgltf_size k = 0; k < out_prim->targets_count; ++k)
3000 i = cgltf_parse_json_attribute_list(options, tokens, i, json_chunk, &out_prim->targets[k].attributes, &out_prim->targets[k].attributes_count);
3007 else if (cgltf_json_strcmp(tokens + i, json_chunk,
"extras") == 0)
3009 i = cgltf_parse_json_extras(tokens, i + 1, json_chunk, &out_prim->extras);
3011 else if (cgltf_json_strcmp(tokens + i, json_chunk,
"extensions") == 0)
3015 CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
3016 if(out_prim->extensions)
3018 return CGLTF_ERROR_JSON;
3021 int extensions_size = tokens[i].size;
3022 out_prim->extensions_count = 0;
3025 if (!out_prim->extensions)
3027 return CGLTF_ERROR_NOMEM;
3031 for (
int k = 0; k < extensions_size; ++k)
3033 CGLTF_CHECK_KEY(tokens[i]);
3035 if (cgltf_json_strcmp(tokens+i, json_chunk,
"KHR_draco_mesh_compression") == 0)
3037 out_prim->has_draco_mesh_compression = 1;
3038 i = cgltf_parse_json_draco_mesh_compression(options, tokens, i + 1, json_chunk, &out_prim->draco_mesh_compression);
3040 else if (cgltf_json_strcmp(tokens+i, json_chunk,
"KHR_materials_variants") == 0)
3042 i = cgltf_parse_json_material_mappings(options, tokens, i + 1, json_chunk, out_prim);
3046 i = cgltf_parse_json_unprocessed_extension(options, tokens, i, json_chunk, &(out_prim->extensions[out_prim->extensions_count++]));
3057 i = cgltf_skip_json(tokens, i+1);
3069static int cgltf_parse_json_mesh(
cgltf_options* options, jsmntok_t
const* tokens,
int i,
const uint8_t* json_chunk,
cgltf_mesh* out_mesh)
3071 CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
3073 int size = tokens[i].size;
3076 for (
int j = 0; j < size; ++j)
3078 CGLTF_CHECK_KEY(tokens[i]);
3080 if (cgltf_json_strcmp(tokens+i, json_chunk,
"name") == 0)
3082 i = cgltf_parse_json_string(options, tokens, i + 1, json_chunk, &out_mesh->name);
3084 else if (cgltf_json_strcmp(tokens+i, json_chunk,
"primitives") == 0)
3086 i = cgltf_parse_json_array(options, tokens, i + 1, json_chunk,
sizeof(
cgltf_primitive), (
void**)&out_mesh->primitives, &out_mesh->primitives_count);
3092 for (cgltf_size prim_index = 0; prim_index < out_mesh->primitives_count; ++prim_index)
3094 i = cgltf_parse_json_primitive(options, tokens, i, json_chunk, &out_mesh->primitives[prim_index]);
3101 else if (cgltf_json_strcmp(tokens + i, json_chunk,
"weights") == 0)
3103 i = cgltf_parse_json_array(options, tokens, i + 1, json_chunk,
sizeof(cgltf_float), (
void**)&out_mesh->weights, &out_mesh->weights_count);
3109 i = cgltf_parse_json_float_array(tokens, i - 1, json_chunk, out_mesh->weights, (
int)out_mesh->weights_count);
3111 else if (cgltf_json_strcmp(tokens + i, json_chunk,
"extras") == 0)
3115 out_mesh->extras.start_offset = tokens[i].start;
3116 out_mesh->extras.end_offset = tokens[i].end;
3118 if (tokens[i].type == JSMN_OBJECT)
3120 int extras_size = tokens[i].size;
3123 for (
int k = 0; k < extras_size; ++k)
3125 CGLTF_CHECK_KEY(tokens[i]);
3127 if (cgltf_json_strcmp(tokens+i, json_chunk,
"targetNames") == 0 && tokens[i+1].type == JSMN_ARRAY)
3129 i = cgltf_parse_json_string_array(options, tokens, i + 1, json_chunk, &out_mesh->target_names, &out_mesh->target_names_count);
3133 i = cgltf_skip_json(tokens, i+1);
3144 i = cgltf_skip_json(tokens, i);
3147 else if (cgltf_json_strcmp(tokens + i, json_chunk,
"extensions") == 0)
3149 i = cgltf_parse_json_unprocessed_extensions(options, tokens, i, json_chunk, &out_mesh->extensions_count, &out_mesh->extensions);
3153 i = cgltf_skip_json(tokens, i+1);
3165static int cgltf_parse_json_meshes(
cgltf_options* options, jsmntok_t
const* tokens,
int i,
const uint8_t* json_chunk,
cgltf_data* out_data)
3167 i = cgltf_parse_json_array(options, tokens, i, json_chunk,
sizeof(
cgltf_mesh), (
void**)&out_data->meshes, &out_data->meshes_count);
3173 for (cgltf_size j = 0; j < out_data->meshes_count; ++j)
3175 i = cgltf_parse_json_mesh(options, tokens, i, json_chunk, &out_data->meshes[j]);
3184static cgltf_component_type cgltf_json_to_component_type(jsmntok_t
const* tok,
const uint8_t* json_chunk)
3186 int type = cgltf_json_to_int(tok, json_chunk);
3191 return cgltf_component_type_r_8;
3193 return cgltf_component_type_r_8u;
3195 return cgltf_component_type_r_16;
3197 return cgltf_component_type_r_16u;
3199 return cgltf_component_type_r_32u;
3201 return cgltf_component_type_r_32f;
3203 return cgltf_component_type_invalid;
3209 CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
3211 int size = tokens[i].size;
3214 for (
int j = 0; j < size; ++j)
3216 CGLTF_CHECK_KEY(tokens[i]);
3218 if (cgltf_json_strcmp(tokens+i, json_chunk,
"count") == 0)
3221 out_sparse->count = cgltf_json_to_int(tokens + i, json_chunk);
3224 else if (cgltf_json_strcmp(tokens+i, json_chunk,
"indices") == 0)
3227 CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
3229 int indices_size = tokens[i].size;
3232 for (
int k = 0; k < indices_size; ++k)
3234 CGLTF_CHECK_KEY(tokens[i]);
3236 if (cgltf_json_strcmp(tokens+i, json_chunk,
"bufferView") == 0)
3239 out_sparse->indices_buffer_view = CGLTF_PTRINDEX(
cgltf_buffer_view, cgltf_json_to_int(tokens + i, json_chunk));
3242 else if (cgltf_json_strcmp(tokens+i, json_chunk,
"byteOffset") == 0)
3245 out_sparse->indices_byte_offset = cgltf_json_to_size(tokens + i, json_chunk);
3248 else if (cgltf_json_strcmp(tokens+i, json_chunk,
"componentType") == 0)
3251 out_sparse->indices_component_type = cgltf_json_to_component_type(tokens + i, json_chunk);
3254 else if (cgltf_json_strcmp(tokens + i, json_chunk,
"extras") == 0)
3256 i = cgltf_parse_json_extras(tokens, i + 1, json_chunk, &out_sparse->indices_extras);
3258 else if (cgltf_json_strcmp(tokens + i, json_chunk,
"extensions") == 0)
3260 i = cgltf_parse_json_unprocessed_extensions(options, tokens, i, json_chunk, &out_sparse->indices_extensions_count, &out_sparse->indices_extensions);
3264 i = cgltf_skip_json(tokens, i+1);
3273 else if (cgltf_json_strcmp(tokens+i, json_chunk,
"values") == 0)
3276 CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
3278 int values_size = tokens[i].size;
3281 for (
int k = 0; k < values_size; ++k)
3283 CGLTF_CHECK_KEY(tokens[i]);
3285 if (cgltf_json_strcmp(tokens+i, json_chunk,
"bufferView") == 0)
3288 out_sparse->values_buffer_view = CGLTF_PTRINDEX(
cgltf_buffer_view, cgltf_json_to_int(tokens + i, json_chunk));
3291 else if (cgltf_json_strcmp(tokens+i, json_chunk,
"byteOffset") == 0)
3294 out_sparse->values_byte_offset = cgltf_json_to_size(tokens + i, json_chunk);
3297 else if (cgltf_json_strcmp(tokens + i, json_chunk,
"extras") == 0)
3299 i = cgltf_parse_json_extras(tokens, i + 1, json_chunk, &out_sparse->values_extras);
3301 else if (cgltf_json_strcmp(tokens + i, json_chunk,
"extensions") == 0)
3303 i = cgltf_parse_json_unprocessed_extensions(options, tokens, i, json_chunk, &out_sparse->values_extensions_count, &out_sparse->values_extensions);
3307 i = cgltf_skip_json(tokens, i+1);
3316 else if (cgltf_json_strcmp(tokens + i, json_chunk,
"extras") == 0)
3318 i = cgltf_parse_json_extras(tokens, i + 1, json_chunk, &out_sparse->extras);
3320 else if (cgltf_json_strcmp(tokens + i, json_chunk,
"extensions") == 0)
3322 i = cgltf_parse_json_unprocessed_extensions(options, tokens, i, json_chunk, &out_sparse->extensions_count, &out_sparse->extensions);
3326 i = cgltf_skip_json(tokens, i+1);
3338static int cgltf_parse_json_accessor(
cgltf_options* options, jsmntok_t
const* tokens,
int i,
const uint8_t* json_chunk,
cgltf_accessor* out_accessor)
3340 CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
3342 int size = tokens[i].size;
3345 for (
int j = 0; j < size; ++j)
3347 CGLTF_CHECK_KEY(tokens[i]);
3349 if (cgltf_json_strcmp(tokens + i, json_chunk,
"name") == 0)
3351 i = cgltf_parse_json_string(options, tokens, i + 1, json_chunk, &out_accessor->name);
3353 else if (cgltf_json_strcmp(tokens+i, json_chunk,
"bufferView") == 0)
3356 out_accessor->buffer_view = CGLTF_PTRINDEX(
cgltf_buffer_view, cgltf_json_to_int(tokens + i, json_chunk));
3359 else if (cgltf_json_strcmp(tokens+i, json_chunk,
"byteOffset") == 0)
3362 out_accessor->offset =
3363 cgltf_json_to_size(tokens+i, json_chunk);
3366 else if (cgltf_json_strcmp(tokens+i, json_chunk,
"componentType") == 0)
3369 out_accessor->component_type = cgltf_json_to_component_type(tokens + i, json_chunk);
3372 else if (cgltf_json_strcmp(tokens+i, json_chunk,
"normalized") == 0)
3375 out_accessor->normalized = cgltf_json_to_bool(tokens+i, json_chunk);
3378 else if (cgltf_json_strcmp(tokens+i, json_chunk,
"count") == 0)
3381 out_accessor->count =
3382 cgltf_json_to_int(tokens+i, json_chunk);
3385 else if (cgltf_json_strcmp(tokens+i, json_chunk,
"type") == 0)
3388 if (cgltf_json_strcmp(tokens+i, json_chunk,
"SCALAR") == 0)
3390 out_accessor->type = cgltf_type_scalar;
3392 else if (cgltf_json_strcmp(tokens+i, json_chunk,
"VEC2") == 0)
3394 out_accessor->type = cgltf_type_vec2;
3396 else if (cgltf_json_strcmp(tokens+i, json_chunk,
"VEC3") == 0)
3398 out_accessor->type = cgltf_type_vec3;
3400 else if (cgltf_json_strcmp(tokens+i, json_chunk,
"VEC4") == 0)
3402 out_accessor->type = cgltf_type_vec4;
3404 else if (cgltf_json_strcmp(tokens+i, json_chunk,
"MAT2") == 0)
3406 out_accessor->type = cgltf_type_mat2;
3408 else if (cgltf_json_strcmp(tokens+i, json_chunk,
"MAT3") == 0)
3410 out_accessor->type = cgltf_type_mat3;
3412 else if (cgltf_json_strcmp(tokens+i, json_chunk,
"MAT4") == 0)
3414 out_accessor->type = cgltf_type_mat4;
3418 else if (cgltf_json_strcmp(tokens + i, json_chunk,
"min") == 0)
3421 out_accessor->has_min = 1;
3423 int min_size = tokens[i].size > 16 ? 16 : tokens[i].size;
3424 i = cgltf_parse_json_float_array(tokens, i, json_chunk, out_accessor->min, min_size);
3426 else if (cgltf_json_strcmp(tokens + i, json_chunk,
"max") == 0)
3429 out_accessor->has_max = 1;
3431 int max_size = tokens[i].size > 16 ? 16 : tokens[i].size;
3432 i = cgltf_parse_json_float_array(tokens, i, json_chunk, out_accessor->max, max_size);
3434 else if (cgltf_json_strcmp(tokens + i, json_chunk,
"sparse") == 0)
3436 out_accessor->is_sparse = 1;
3437 i = cgltf_parse_json_accessor_sparse(options, tokens, i + 1, json_chunk, &out_accessor->sparse);
3439 else if (cgltf_json_strcmp(tokens + i, json_chunk,
"extras") == 0)
3441 i = cgltf_parse_json_extras(tokens, i + 1, json_chunk, &out_accessor->extras);
3443 else if (cgltf_json_strcmp(tokens + i, json_chunk,
"extensions") == 0)
3445 i = cgltf_parse_json_unprocessed_extensions(options, tokens, i, json_chunk, &out_accessor->extensions_count, &out_accessor->extensions);
3449 i = cgltf_skip_json(tokens, i+1);
3461static int cgltf_parse_json_texture_transform(jsmntok_t
const* tokens,
int i,
const uint8_t* json_chunk,
cgltf_texture_transform* out_texture_transform)
3463 CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
3465 int size = tokens[i].size;
3468 for (
int j = 0; j < size; ++j)
3470 CGLTF_CHECK_KEY(tokens[i]);
3472 if (cgltf_json_strcmp(tokens + i, json_chunk,
"offset") == 0)
3474 i = cgltf_parse_json_float_array(tokens, i + 1, json_chunk, out_texture_transform->offset, 2);
3476 else if (cgltf_json_strcmp(tokens + i, json_chunk,
"rotation") == 0)
3479 out_texture_transform->rotation = cgltf_json_to_float(tokens + i, json_chunk);
3482 else if (cgltf_json_strcmp(tokens + i, json_chunk,
"scale") == 0)
3484 i = cgltf_parse_json_float_array(tokens, i + 1, json_chunk, out_texture_transform->scale, 2);
3486 else if (cgltf_json_strcmp(tokens + i, json_chunk,
"texCoord") == 0)
3489 out_texture_transform->has_texcoord = 1;
3490 out_texture_transform->texcoord = cgltf_json_to_int(tokens + i, json_chunk);
3495 i = cgltf_skip_json(tokens, i + 1);
3507static 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)
3509 CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
3511 out_texture_view->scale = 1.0f;
3512 cgltf_fill_float_array(out_texture_view->transform.scale, 2, 1.0f);
3514 int size = tokens[i].size;
3517 for (
int j = 0; j < size; ++j)
3519 CGLTF_CHECK_KEY(tokens[i]);
3521 if (cgltf_json_strcmp(tokens + i, json_chunk,
"index") == 0)
3524 out_texture_view->texture = CGLTF_PTRINDEX(
cgltf_texture, cgltf_json_to_int(tokens + i, json_chunk));
3527 else if (cgltf_json_strcmp(tokens + i, json_chunk,
"texCoord") == 0)
3530 out_texture_view->texcoord = cgltf_json_to_int(tokens + i, json_chunk);
3533 else if (cgltf_json_strcmp(tokens + i, json_chunk,
"scale") == 0)
3536 out_texture_view->scale = cgltf_json_to_float(tokens + i, json_chunk);
3539 else if (cgltf_json_strcmp(tokens + i, json_chunk,
"strength") == 0)
3542 out_texture_view->scale = cgltf_json_to_float(tokens + i, json_chunk);
3545 else if (cgltf_json_strcmp(tokens + i, json_chunk,
"extras") == 0)
3547 i = cgltf_parse_json_extras(tokens, i + 1, json_chunk, &out_texture_view->extras);
3549 else if (cgltf_json_strcmp(tokens + i, json_chunk,
"extensions") == 0)
3553 CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
3554 if(out_texture_view->extensions)
3556 return CGLTF_ERROR_JSON;
3559 int extensions_size = tokens[i].size;
3560 out_texture_view->extensions_count = 0;
3563 if (!out_texture_view->extensions)
3565 return CGLTF_ERROR_NOMEM;
3570 for (
int k = 0; k < extensions_size; ++k)
3572 CGLTF_CHECK_KEY(tokens[i]);
3574 if (cgltf_json_strcmp(tokens+i, json_chunk,
"KHR_texture_transform") == 0)
3576 out_texture_view->has_transform = 1;
3577 i = cgltf_parse_json_texture_transform(tokens, i + 1, json_chunk, &out_texture_view->transform);
3581 i = cgltf_parse_json_unprocessed_extension(options, tokens, i, json_chunk, &(out_texture_view->extensions[out_texture_view->extensions_count++]));
3592 i = cgltf_skip_json(tokens, i + 1);
3606 CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
3608 int size = tokens[i].size;
3611 for (
int j = 0; j < size; ++j)
3613 CGLTF_CHECK_KEY(tokens[i]);
3615 if (cgltf_json_strcmp(tokens+i, json_chunk,
"metallicFactor") == 0)
3618 out_pbr->metallic_factor =
3619 cgltf_json_to_float(tokens + i, json_chunk);
3622 else if (cgltf_json_strcmp(tokens+i, json_chunk,
"roughnessFactor") == 0)
3625 out_pbr->roughness_factor =
3626 cgltf_json_to_float(tokens+i, json_chunk);
3629 else if (cgltf_json_strcmp(tokens+i, json_chunk,
"baseColorFactor") == 0)
3631 i = cgltf_parse_json_float_array(tokens, i + 1, json_chunk, out_pbr->base_color_factor, 4);
3633 else if (cgltf_json_strcmp(tokens+i, json_chunk,
"baseColorTexture") == 0)
3635 i = cgltf_parse_json_texture_view(options, tokens, i + 1, json_chunk,
3636 &out_pbr->base_color_texture);
3638 else if (cgltf_json_strcmp(tokens + i, json_chunk,
"metallicRoughnessTexture") == 0)
3640 i = cgltf_parse_json_texture_view(options, tokens, i + 1, json_chunk,
3641 &out_pbr->metallic_roughness_texture);
3643 else if (cgltf_json_strcmp(tokens + i, json_chunk,
"extras") == 0)
3645 i = cgltf_parse_json_extras(tokens, i + 1, json_chunk, &out_pbr->extras);
3649 i = cgltf_skip_json(tokens, i+1);
3663 CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
3664 int size = tokens[i].size;
3667 for (
int j = 0; j < size; ++j)
3669 CGLTF_CHECK_KEY(tokens[i]);
3671 if (cgltf_json_strcmp(tokens+i, json_chunk,
"diffuseFactor") == 0)
3673 i = cgltf_parse_json_float_array(tokens, i + 1, json_chunk, out_pbr->diffuse_factor, 4);
3675 else if (cgltf_json_strcmp(tokens+i, json_chunk,
"specularFactor") == 0)
3677 i = cgltf_parse_json_float_array(tokens, i + 1, json_chunk, out_pbr->specular_factor, 3);
3679 else if (cgltf_json_strcmp(tokens+i, json_chunk,
"glossinessFactor") == 0)
3682 out_pbr->glossiness_factor = cgltf_json_to_float(tokens + i, json_chunk);
3685 else if (cgltf_json_strcmp(tokens+i, json_chunk,
"diffuseTexture") == 0)
3687 i = cgltf_parse_json_texture_view(options, tokens, i + 1, json_chunk, &out_pbr->diffuse_texture);
3689 else if (cgltf_json_strcmp(tokens+i, json_chunk,
"specularGlossinessTexture") == 0)
3691 i = cgltf_parse_json_texture_view(options, tokens, i + 1, json_chunk, &out_pbr->specular_glossiness_texture);
3695 i = cgltf_skip_json(tokens, i+1);
3707static int cgltf_parse_json_clearcoat(
cgltf_options* options, jsmntok_t
const* tokens,
int i,
const uint8_t* json_chunk,
cgltf_clearcoat* out_clearcoat)
3709 CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
3710 int size = tokens[i].size;
3713 for (
int j = 0; j < size; ++j)
3715 CGLTF_CHECK_KEY(tokens[i]);
3717 if (cgltf_json_strcmp(tokens+i, json_chunk,
"clearcoatFactor") == 0)
3720 out_clearcoat->clearcoat_factor = cgltf_json_to_float(tokens + i, json_chunk);
3723 else if (cgltf_json_strcmp(tokens+i, json_chunk,
"clearcoatRoughnessFactor") == 0)
3726 out_clearcoat->clearcoat_roughness_factor = cgltf_json_to_float(tokens + i, json_chunk);
3729 else if (cgltf_json_strcmp(tokens+i, json_chunk,
"clearcoatTexture") == 0)
3731 i = cgltf_parse_json_texture_view(options, tokens, i + 1, json_chunk, &out_clearcoat->clearcoat_texture);
3733 else if (cgltf_json_strcmp(tokens+i, json_chunk,
"clearcoatRoughnessTexture") == 0)
3735 i = cgltf_parse_json_texture_view(options, tokens, i + 1, json_chunk, &out_clearcoat->clearcoat_roughness_texture);
3737 else if (cgltf_json_strcmp(tokens+i, json_chunk,
"clearcoatNormalTexture") == 0)
3739 i = cgltf_parse_json_texture_view(options, tokens, i + 1, json_chunk, &out_clearcoat->clearcoat_normal_texture);
3743 i = cgltf_skip_json(tokens, i+1);
3755static int cgltf_parse_json_ior(jsmntok_t
const* tokens,
int i,
const uint8_t* json_chunk,
cgltf_ior* out_ior)
3757 CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
3758 int size = tokens[i].size;
3762 out_ior->ior = 1.5f;
3764 for (
int j = 0; j < size; ++j)
3766 CGLTF_CHECK_KEY(tokens[i]);
3768 if (cgltf_json_strcmp(tokens+i, json_chunk,
"ior") == 0)
3771 out_ior->ior = cgltf_json_to_float(tokens + i, json_chunk);
3776 i = cgltf_skip_json(tokens, i+1);
3788static int cgltf_parse_json_specular(
cgltf_options* options, jsmntok_t
const* tokens,
int i,
const uint8_t* json_chunk,
cgltf_specular* out_specular)
3790 CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
3791 int size = tokens[i].size;
3795 out_specular->specular_factor = 1.0f;
3796 cgltf_fill_float_array(out_specular->specular_color_factor, 3, 1.0f);
3798 for (
int j = 0; j < size; ++j)
3800 CGLTF_CHECK_KEY(tokens[i]);
3802 if (cgltf_json_strcmp(tokens+i, json_chunk,
"specularFactor") == 0)
3805 out_specular->specular_factor = cgltf_json_to_float(tokens + i, json_chunk);
3808 else if (cgltf_json_strcmp(tokens+i, json_chunk,
"specularColorFactor") == 0)
3810 i = cgltf_parse_json_float_array(tokens, i + 1, json_chunk, out_specular->specular_color_factor, 3);
3812 else if (cgltf_json_strcmp(tokens+i, json_chunk,
"specularTexture") == 0)
3814 i = cgltf_parse_json_texture_view(options, tokens, i + 1, json_chunk, &out_specular->specular_texture);
3816 else if (cgltf_json_strcmp(tokens + i, json_chunk,
"specularColorTexture") == 0)
3818 i = cgltf_parse_json_texture_view(options, tokens, i + 1, json_chunk, &out_specular->specular_color_texture);
3822 i = cgltf_skip_json(tokens, i+1);
3834static int cgltf_parse_json_transmission(
cgltf_options* options, jsmntok_t
const* tokens,
int i,
const uint8_t* json_chunk,
cgltf_transmission* out_transmission)
3836 CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
3837 int size = tokens[i].size;
3840 for (
int j = 0; j < size; ++j)
3842 CGLTF_CHECK_KEY(tokens[i]);
3844 if (cgltf_json_strcmp(tokens+i, json_chunk,
"transmissionFactor") == 0)
3847 out_transmission->transmission_factor = cgltf_json_to_float(tokens + i, json_chunk);
3850 else if (cgltf_json_strcmp(tokens+i, json_chunk,
"transmissionTexture") == 0)
3852 i = cgltf_parse_json_texture_view(options, tokens, i + 1, json_chunk, &out_transmission->transmission_texture);
3856 i = cgltf_skip_json(tokens, i+1);
3868static int cgltf_parse_json_volume(
cgltf_options* options, jsmntok_t
const* tokens,
int i,
const uint8_t* json_chunk,
cgltf_volume* out_volume)
3870 CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
3871 int size = tokens[i].size;
3874 for (
int j = 0; j < size; ++j)
3876 CGLTF_CHECK_KEY(tokens[i]);
3878 if (cgltf_json_strcmp(tokens + i, json_chunk,
"thicknessFactor") == 0)
3881 out_volume->thickness_factor = cgltf_json_to_float(tokens + i, json_chunk);
3884 else if (cgltf_json_strcmp(tokens + i, json_chunk,
"thicknessTexture") == 0)
3886 i = cgltf_parse_json_texture_view(options, tokens, i + 1, json_chunk, &out_volume->thickness_texture);
3888 else if (cgltf_json_strcmp(tokens + i, json_chunk,
"attenuationColor") == 0)
3890 i = cgltf_parse_json_float_array(tokens, i + 1, json_chunk, out_volume->attenuation_color, 3);
3892 else if (cgltf_json_strcmp(tokens + i, json_chunk,
"attenuationDistance") == 0)
3895 out_volume->attenuation_distance = cgltf_json_to_float(tokens + i, json_chunk);
3900 i = cgltf_skip_json(tokens, i + 1);
3912static int cgltf_parse_json_sheen(
cgltf_options* options, jsmntok_t
const* tokens,
int i,
const uint8_t* json_chunk,
cgltf_sheen* out_sheen)
3914 CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
3915 int size = tokens[i].size;
3918 for (
int j = 0; j < size; ++j)
3920 CGLTF_CHECK_KEY(tokens[i]);
3922 if (cgltf_json_strcmp(tokens+i, json_chunk,
"sheenColorFactor") == 0)
3924 i = cgltf_parse_json_float_array(tokens, i + 1, json_chunk, out_sheen->sheen_color_factor, 3);
3926 else if (cgltf_json_strcmp(tokens+i, json_chunk,
"sheenColorTexture") == 0)
3928 i = cgltf_parse_json_texture_view(options, tokens, i + 1, json_chunk, &out_sheen->sheen_color_texture);
3930 else if (cgltf_json_strcmp(tokens+i, json_chunk,
"sheenRoughnessFactor") == 0)
3933 out_sheen->sheen_roughness_factor = cgltf_json_to_float(tokens + i, json_chunk);
3936 else if (cgltf_json_strcmp(tokens+i, json_chunk,
"sheenRoughnessTexture") == 0)
3938 i = cgltf_parse_json_texture_view(options, tokens, i + 1, json_chunk, &out_sheen->sheen_roughness_texture);
3942 i = cgltf_skip_json(tokens, i+1);
3954static int cgltf_parse_json_emissive_strength(jsmntok_t
const* tokens,
int i,
const uint8_t* json_chunk,
cgltf_emissive_strength* out_emissive_strength)
3956 CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
3957 int size = tokens[i].size;
3961 out_emissive_strength->emissive_strength = 1.f;
3963 for (
int j = 0; j < size; ++j)
3965 CGLTF_CHECK_KEY(tokens[i]);
3967 if (cgltf_json_strcmp(tokens + i, json_chunk,
"emissiveStrength") == 0)
3970 out_emissive_strength->emissive_strength = cgltf_json_to_float(tokens + i, json_chunk);
3975 i = cgltf_skip_json(tokens, i + 1);
3987static int cgltf_parse_json_iridescence(
cgltf_options* options, jsmntok_t
const* tokens,
int i,
const uint8_t* json_chunk,
cgltf_iridescence* out_iridescence)
3989 CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
3990 int size = tokens[i].size;
3994 out_iridescence->iridescence_ior = 1.3f;
3995 out_iridescence->iridescence_thickness_min = 100.f;
3996 out_iridescence->iridescence_thickness_max = 400.f;
3998 for (
int j = 0; j < size; ++j)
4000 CGLTF_CHECK_KEY(tokens[i]);
4002 if (cgltf_json_strcmp(tokens + i, json_chunk,
"iridescenceFactor") == 0)
4005 out_iridescence->iridescence_factor = cgltf_json_to_float(tokens + i, json_chunk);
4008 else if (cgltf_json_strcmp(tokens + i, json_chunk,
"iridescenceTexture") == 0)
4010 i = cgltf_parse_json_texture_view(options, tokens, i + 1, json_chunk, &out_iridescence->iridescence_texture);
4012 else if (cgltf_json_strcmp(tokens + i, json_chunk,
"iridescenceIor") == 0)
4015 out_iridescence->iridescence_ior = cgltf_json_to_float(tokens + i, json_chunk);
4018 else if (cgltf_json_strcmp(tokens + i, json_chunk,
"iridescenceThicknessMinimum") == 0)
4021 out_iridescence->iridescence_thickness_min = cgltf_json_to_float(tokens + i, json_chunk);
4024 else if (cgltf_json_strcmp(tokens + i, json_chunk,
"iridescenceThicknessMaximum") == 0)
4027 out_iridescence->iridescence_thickness_max = cgltf_json_to_float(tokens + i, json_chunk);
4030 else if (cgltf_json_strcmp(tokens + i, json_chunk,
"iridescenceThicknessTexture") == 0)
4032 i = cgltf_parse_json_texture_view(options, tokens, i + 1, json_chunk, &out_iridescence->iridescence_thickness_texture);
4036 i = cgltf_skip_json(tokens, i + 1);
4048static int cgltf_parse_json_image(
cgltf_options* options, jsmntok_t
const* tokens,
int i,
const uint8_t* json_chunk,
cgltf_image* out_image)
4050 CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
4052 int size = tokens[i].size;
4055 for (
int j = 0; j < size; ++j)
4057 CGLTF_CHECK_KEY(tokens[i]);
4059 if (cgltf_json_strcmp(tokens + i, json_chunk,
"uri") == 0)
4061 i = cgltf_parse_json_string(options, tokens, i + 1, json_chunk, &out_image->uri);
4063 else if (cgltf_json_strcmp(tokens+i, json_chunk,
"bufferView") == 0)
4066 out_image->buffer_view = CGLTF_PTRINDEX(
cgltf_buffer_view, cgltf_json_to_int(tokens + i, json_chunk));
4069 else if (cgltf_json_strcmp(tokens + i, json_chunk,
"mimeType") == 0)
4071 i = cgltf_parse_json_string(options, tokens, i + 1, json_chunk, &out_image->mime_type);
4073 else if (cgltf_json_strcmp(tokens + i, json_chunk,
"name") == 0)
4075 i = cgltf_parse_json_string(options, tokens, i + 1, json_chunk, &out_image->name);
4077 else if (cgltf_json_strcmp(tokens + i, json_chunk,
"extras") == 0)
4079 i = cgltf_parse_json_extras(tokens, i + 1, json_chunk, &out_image->extras);
4081 else if (cgltf_json_strcmp(tokens + i, json_chunk,
"extensions") == 0)
4083 i = cgltf_parse_json_unprocessed_extensions(options, tokens, i, json_chunk, &out_image->extensions_count, &out_image->extensions);
4087 i = cgltf_skip_json(tokens, i + 1);
4099static int cgltf_parse_json_sampler(
cgltf_options* options, jsmntok_t
const* tokens,
int i,
const uint8_t* json_chunk,
cgltf_sampler* out_sampler)
4102 CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
4104 out_sampler->wrap_s = 10497;
4105 out_sampler->wrap_t = 10497;
4107 int size = tokens[i].size;
4110 for (
int j = 0; j < size; ++j)
4112 CGLTF_CHECK_KEY(tokens[i]);
4114 if (cgltf_json_strcmp(tokens + i, json_chunk,
"name") == 0)
4116 i = cgltf_parse_json_string(options, tokens, i + 1, json_chunk, &out_sampler->name);
4118 else if (cgltf_json_strcmp(tokens + i, json_chunk,
"magFilter") == 0)
4121 out_sampler->mag_filter
4122 = cgltf_json_to_int(tokens + i, json_chunk);
4125 else if (cgltf_json_strcmp(tokens + i, json_chunk,
"minFilter") == 0)
4128 out_sampler->min_filter
4129 = cgltf_json_to_int(tokens + i, json_chunk);
4132 else if (cgltf_json_strcmp(tokens + i, json_chunk,
"wrapS") == 0)
4136 = cgltf_json_to_int(tokens + i, json_chunk);
4139 else if (cgltf_json_strcmp(tokens + i, json_chunk,
"wrapT") == 0)
4143 = cgltf_json_to_int(tokens + i, json_chunk);
4146 else if (cgltf_json_strcmp(tokens + i, json_chunk,
"extras") == 0)
4148 i = cgltf_parse_json_extras(tokens, i + 1, json_chunk, &out_sampler->extras);
4150 else if (cgltf_json_strcmp(tokens + i, json_chunk,
"extensions") == 0)
4152 i = cgltf_parse_json_unprocessed_extensions(options, tokens, i, json_chunk, &out_sampler->extensions_count, &out_sampler->extensions);
4156 i = cgltf_skip_json(tokens, i + 1);
4168static int cgltf_parse_json_texture(
cgltf_options* options, jsmntok_t
const* tokens,
int i,
const uint8_t* json_chunk,
cgltf_texture* out_texture)
4170 CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
4172 int size = tokens[i].size;
4175 for (
int j = 0; j < size; ++j)
4177 CGLTF_CHECK_KEY(tokens[i]);
4179 if (cgltf_json_strcmp(tokens+i, json_chunk,
"name") == 0)
4181 i = cgltf_parse_json_string(options, tokens, i + 1, json_chunk, &out_texture->name);
4183 else if (cgltf_json_strcmp(tokens + i, json_chunk,
"sampler") == 0)
4186 out_texture->sampler = CGLTF_PTRINDEX(
cgltf_sampler, cgltf_json_to_int(tokens + i, json_chunk));
4189 else if (cgltf_json_strcmp(tokens + i, json_chunk,
"source") == 0)
4192 out_texture->image = CGLTF_PTRINDEX(
cgltf_image, cgltf_json_to_int(tokens + i, json_chunk));
4195 else if (cgltf_json_strcmp(tokens + i, json_chunk,
"extras") == 0)
4197 i = cgltf_parse_json_extras(tokens, i + 1, json_chunk, &out_texture->extras);
4199 else if (cgltf_json_strcmp(tokens + i, json_chunk,
"extensions") == 0)
4203 CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
4204 if (out_texture->extensions)
4206 return CGLTF_ERROR_JSON;
4209 int extensions_size = tokens[i].size;
4212 out_texture->extensions_count = 0;
4214 if (!out_texture->extensions)
4216 return CGLTF_ERROR_NOMEM;
4219 for (
int k = 0; k < extensions_size; ++k)
4221 CGLTF_CHECK_KEY(tokens[i]);
4223 if (cgltf_json_strcmp(tokens + i, json_chunk,
"KHR_texture_basisu") == 0)
4225 out_texture->has_basisu = 1;
4227 CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
4228 int num_properties = tokens[i].size;
4231 for (
int t = 0; t < num_properties; ++t)
4233 CGLTF_CHECK_KEY(tokens[i]);
4235 if (cgltf_json_strcmp(tokens + i, json_chunk,
"source") == 0)
4238 out_texture->basisu_image = CGLTF_PTRINDEX(
cgltf_image, cgltf_json_to_int(tokens + i, json_chunk));
4243 i = cgltf_skip_json(tokens, i + 1);
4253 i = cgltf_parse_json_unprocessed_extension(options, tokens, i, json_chunk, &(out_texture->extensions[out_texture->extensions_count++]));
4264 i = cgltf_skip_json(tokens, i + 1);
4276static int cgltf_parse_json_material(
cgltf_options* options, jsmntok_t
const* tokens,
int i,
const uint8_t* json_chunk,
cgltf_material* out_material)
4278 CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
4280 cgltf_fill_float_array(out_material->pbr_metallic_roughness.base_color_factor, 4, 1.0f);
4281 out_material->pbr_metallic_roughness.metallic_factor = 1.0f;
4282 out_material->pbr_metallic_roughness.roughness_factor = 1.0f;
4284 cgltf_fill_float_array(out_material->pbr_specular_glossiness.diffuse_factor, 4, 1.0f);
4285 cgltf_fill_float_array(out_material->pbr_specular_glossiness.specular_factor, 3, 1.0f);
4286 out_material->pbr_specular_glossiness.glossiness_factor = 1.0f;
4288 cgltf_fill_float_array(out_material->volume.attenuation_color, 3, 1.0f);
4289 out_material->volume.attenuation_distance = FLT_MAX;
4291 out_material->alpha_cutoff = 0.5f;
4293 int size = tokens[i].size;
4296 for (
int j = 0; j < size; ++j)
4298 CGLTF_CHECK_KEY(tokens[i]);
4300 if (cgltf_json_strcmp(tokens+i, json_chunk,
"name") == 0)
4302 i = cgltf_parse_json_string(options, tokens, i + 1, json_chunk, &out_material->name);
4304 else if (cgltf_json_strcmp(tokens+i, json_chunk,
"pbrMetallicRoughness") == 0)
4306 out_material->has_pbr_metallic_roughness = 1;
4307 i = cgltf_parse_json_pbr_metallic_roughness(options, tokens, i + 1, json_chunk, &out_material->pbr_metallic_roughness);
4309 else if (cgltf_json_strcmp(tokens+i, json_chunk,
"emissiveFactor") == 0)
4311 i = cgltf_parse_json_float_array(tokens, i + 1, json_chunk, out_material->emissive_factor, 3);
4313 else if (cgltf_json_strcmp(tokens + i, json_chunk,
"normalTexture") == 0)
4315 i = cgltf_parse_json_texture_view(options, tokens, i + 1, json_chunk,
4316 &out_material->normal_texture);
4318 else if (cgltf_json_strcmp(tokens + i, json_chunk,
"occlusionTexture") == 0)
4320 i = cgltf_parse_json_texture_view(options, tokens, i + 1, json_chunk,
4321 &out_material->occlusion_texture);
4323 else if (cgltf_json_strcmp(tokens + i, json_chunk,
"emissiveTexture") == 0)
4325 i = cgltf_parse_json_texture_view(options, tokens, i + 1, json_chunk,
4326 &out_material->emissive_texture);
4328 else if (cgltf_json_strcmp(tokens + i, json_chunk,
"alphaMode") == 0)
4331 if (cgltf_json_strcmp(tokens + i, json_chunk,
"OPAQUE") == 0)
4333 out_material->alpha_mode = cgltf_alpha_mode_opaque;
4335 else if (cgltf_json_strcmp(tokens + i, json_chunk,
"MASK") == 0)
4337 out_material->alpha_mode = cgltf_alpha_mode_mask;
4339 else if (cgltf_json_strcmp(tokens + i, json_chunk,
"BLEND") == 0)
4341 out_material->alpha_mode = cgltf_alpha_mode_blend;
4345 else if (cgltf_json_strcmp(tokens + i, json_chunk,
"alphaCutoff") == 0)
4348 out_material->alpha_cutoff = cgltf_json_to_float(tokens + i, json_chunk);
4351 else if (cgltf_json_strcmp(tokens + i, json_chunk,
"doubleSided") == 0)
4354 out_material->double_sided =
4355 cgltf_json_to_bool(tokens + i, json_chunk);
4358 else if (cgltf_json_strcmp(tokens + i, json_chunk,
"extras") == 0)
4360 i = cgltf_parse_json_extras(tokens, i + 1, json_chunk, &out_material->extras);
4362 else if (cgltf_json_strcmp(tokens + i, json_chunk,
"extensions") == 0)
4366 CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
4367 if(out_material->extensions)
4369 return CGLTF_ERROR_JSON;
4372 int extensions_size = tokens[i].size;
4375 out_material->extensions_count= 0;
4377 if (!out_material->extensions)
4379 return CGLTF_ERROR_NOMEM;
4382 for (
int k = 0; k < extensions_size; ++k)
4384 CGLTF_CHECK_KEY(tokens[i]);
4386 if (cgltf_json_strcmp(tokens+i, json_chunk,
"KHR_materials_pbrSpecularGlossiness") == 0)
4388 out_material->has_pbr_specular_glossiness = 1;
4389 i = cgltf_parse_json_pbr_specular_glossiness(options, tokens, i + 1, json_chunk, &out_material->pbr_specular_glossiness);
4391 else if (cgltf_json_strcmp(tokens+i, json_chunk,
"KHR_materials_unlit") == 0)
4393 out_material->unlit = 1;
4394 i = cgltf_skip_json(tokens, i+1);
4396 else if (cgltf_json_strcmp(tokens+i, json_chunk,
"KHR_materials_clearcoat") == 0)
4398 out_material->has_clearcoat = 1;
4399 i = cgltf_parse_json_clearcoat(options, tokens, i + 1, json_chunk, &out_material->clearcoat);
4401 else if (cgltf_json_strcmp(tokens+i, json_chunk,
"KHR_materials_ior") == 0)
4403 out_material->has_ior = 1;
4404 i = cgltf_parse_json_ior(tokens, i + 1, json_chunk, &out_material->ior);
4406 else if (cgltf_json_strcmp(tokens+i, json_chunk,
"KHR_materials_specular") == 0)
4408 out_material->has_specular = 1;
4409 i = cgltf_parse_json_specular(options, tokens, i + 1, json_chunk, &out_material->specular);
4411 else if (cgltf_json_strcmp(tokens+i, json_chunk,
"KHR_materials_transmission") == 0)
4413 out_material->has_transmission = 1;
4414 i = cgltf_parse_json_transmission(options, tokens, i + 1, json_chunk, &out_material->transmission);
4416 else if (cgltf_json_strcmp(tokens + i, json_chunk,
"KHR_materials_volume") == 0)
4418 out_material->has_volume = 1;
4419 i = cgltf_parse_json_volume(options, tokens, i + 1, json_chunk, &out_material->volume);
4421 else if (cgltf_json_strcmp(tokens+i, json_chunk,
"KHR_materials_sheen") == 0)
4423 out_material->has_sheen = 1;
4424 i = cgltf_parse_json_sheen(options, tokens, i + 1, json_chunk, &out_material->sheen);
4426 else if (cgltf_json_strcmp(tokens + i, json_chunk,
"KHR_materials_emissive_strength") == 0)
4428 out_material->has_emissive_strength = 1;
4429 i = cgltf_parse_json_emissive_strength(tokens, i + 1, json_chunk, &out_material->emissive_strength);
4431 else if (cgltf_json_strcmp(tokens + i, json_chunk,
"KHR_materials_iridescence") == 0)
4433 out_material->has_iridescence = 1;
4434 i = cgltf_parse_json_iridescence(options, tokens, i + 1, json_chunk, &out_material->iridescence);
4438 i = cgltf_parse_json_unprocessed_extension(options, tokens, i, json_chunk, &(out_material->extensions[out_material->extensions_count++]));
4449 i = cgltf_skip_json(tokens, i+1);
4461static int cgltf_parse_json_accessors(
cgltf_options* options, jsmntok_t
const* tokens,
int i,
const uint8_t* json_chunk,
cgltf_data* out_data)
4463 i = cgltf_parse_json_array(options, tokens, i, json_chunk,
sizeof(
cgltf_accessor), (
void**)&out_data->accessors, &out_data->accessors_count);
4469 for (cgltf_size j = 0; j < out_data->accessors_count; ++j)
4471 i = cgltf_parse_json_accessor(options, tokens, i, json_chunk, &out_data->accessors[j]);
4480static int cgltf_parse_json_materials(
cgltf_options* options, jsmntok_t
const* tokens,
int i,
const uint8_t* json_chunk,
cgltf_data* out_data)
4482 i = cgltf_parse_json_array(options, tokens, i, json_chunk,
sizeof(
cgltf_material), (
void**)&out_data->materials, &out_data->materials_count);
4488 for (cgltf_size j = 0; j < out_data->materials_count; ++j)
4490 i = cgltf_parse_json_material(options, tokens, i, json_chunk, &out_data->materials[j]);
4499static int cgltf_parse_json_images(
cgltf_options* options, jsmntok_t
const* tokens,
int i,
const uint8_t* json_chunk,
cgltf_data* out_data)
4501 i = cgltf_parse_json_array(options, tokens, i, json_chunk,
sizeof(
cgltf_image), (
void**)&out_data->images, &out_data->images_count);
4507 for (cgltf_size j = 0; j < out_data->images_count; ++j)
4509 i = cgltf_parse_json_image(options, tokens, i, json_chunk, &out_data->images[j]);
4518static int cgltf_parse_json_textures(
cgltf_options* options, jsmntok_t
const* tokens,
int i,
const uint8_t* json_chunk,
cgltf_data* out_data)
4520 i = cgltf_parse_json_array(options, tokens, i, json_chunk,
sizeof(
cgltf_texture), (
void**)&out_data->textures, &out_data->textures_count);
4526 for (cgltf_size j = 0; j < out_data->textures_count; ++j)
4528 i = cgltf_parse_json_texture(options, tokens, i, json_chunk, &out_data->textures[j]);
4537static int cgltf_parse_json_samplers(
cgltf_options* options, jsmntok_t
const* tokens,
int i,
const uint8_t* json_chunk,
cgltf_data* out_data)
4539 i = cgltf_parse_json_array(options, tokens, i, json_chunk,
sizeof(
cgltf_sampler), (
void**)&out_data->samplers, &out_data->samplers_count);
4545 for (cgltf_size j = 0; j < out_data->samplers_count; ++j)
4547 i = cgltf_parse_json_sampler(options, tokens, i, json_chunk, &out_data->samplers[j]);
4559 CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
4561 int size = tokens[i].size;
4564 for (
int j = 0; j < size; ++j)
4566 CGLTF_CHECK_KEY(tokens[i]);
4568 if (cgltf_json_strcmp(tokens+i, json_chunk,
"buffer") == 0)
4571 out_meshopt_compression->buffer = CGLTF_PTRINDEX(
cgltf_buffer, cgltf_json_to_int(tokens + i, json_chunk));
4574 else if (cgltf_json_strcmp(tokens+i, json_chunk,
"byteOffset") == 0)
4577 out_meshopt_compression->offset = cgltf_json_to_size(tokens+i, json_chunk);
4580 else if (cgltf_json_strcmp(tokens+i, json_chunk,
"byteLength") == 0)
4583 out_meshopt_compression->size = cgltf_json_to_size(tokens+i, json_chunk);
4586 else if (cgltf_json_strcmp(tokens+i, json_chunk,
"byteStride") == 0)
4589 out_meshopt_compression->stride = cgltf_json_to_size(tokens+i, json_chunk);
4592 else if (cgltf_json_strcmp(tokens+i, json_chunk,
"count") == 0)
4595 out_meshopt_compression->count = cgltf_json_to_int(tokens+i, json_chunk);
4598 else if (cgltf_json_strcmp(tokens+i, json_chunk,
"mode") == 0)
4601 if (cgltf_json_strcmp(tokens+i, json_chunk,
"ATTRIBUTES") == 0)
4603 out_meshopt_compression->mode = cgltf_meshopt_compression_mode_attributes;
4605 else if (cgltf_json_strcmp(tokens+i, json_chunk,
"TRIANGLES") == 0)
4607 out_meshopt_compression->mode = cgltf_meshopt_compression_mode_triangles;
4609 else if (cgltf_json_strcmp(tokens+i, json_chunk,
"INDICES") == 0)
4611 out_meshopt_compression->mode = cgltf_meshopt_compression_mode_indices;
4615 else if (cgltf_json_strcmp(tokens+i, json_chunk,
"filter") == 0)
4618 if (cgltf_json_strcmp(tokens+i, json_chunk,
"NONE") == 0)
4620 out_meshopt_compression->filter = cgltf_meshopt_compression_filter_none;
4622 else if (cgltf_json_strcmp(tokens+i, json_chunk,
"OCTAHEDRAL") == 0)
4624 out_meshopt_compression->filter = cgltf_meshopt_compression_filter_octahedral;
4626 else if (cgltf_json_strcmp(tokens+i, json_chunk,
"QUATERNION") == 0)
4628 out_meshopt_compression->filter = cgltf_meshopt_compression_filter_quaternion;
4630 else if (cgltf_json_strcmp(tokens+i, json_chunk,
"EXPONENTIAL") == 0)
4632 out_meshopt_compression->filter = cgltf_meshopt_compression_filter_exponential;
4638 i = cgltf_skip_json(tokens, i+1);
4650static 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)
4652 CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
4654 int size = tokens[i].size;
4657 for (
int j = 0; j < size; ++j)
4659 CGLTF_CHECK_KEY(tokens[i]);
4661 if (cgltf_json_strcmp(tokens + i, json_chunk,
"name") == 0)
4663 i = cgltf_parse_json_string(options, tokens, i + 1, json_chunk, &out_buffer_view->name);
4665 else if (cgltf_json_strcmp(tokens+i, json_chunk,
"buffer") == 0)
4668 out_buffer_view->buffer = CGLTF_PTRINDEX(
cgltf_buffer, cgltf_json_to_int(tokens + i, json_chunk));
4671 else if (cgltf_json_strcmp(tokens+i, json_chunk,
"byteOffset") == 0)
4674 out_buffer_view->offset =
4675 cgltf_json_to_size(tokens+i, json_chunk);
4678 else if (cgltf_json_strcmp(tokens+i, json_chunk,
"byteLength") == 0)
4681 out_buffer_view->size =
4682 cgltf_json_to_size(tokens+i, json_chunk);
4685 else if (cgltf_json_strcmp(tokens+i, json_chunk,
"byteStride") == 0)
4688 out_buffer_view->stride =
4689 cgltf_json_to_size(tokens+i, json_chunk);
4692 else if (cgltf_json_strcmp(tokens+i, json_chunk,
"target") == 0)
4695 int type = cgltf_json_to_int(tokens+i, json_chunk);
4699 type = cgltf_buffer_view_type_vertices;
4702 type = cgltf_buffer_view_type_indices;
4705 type = cgltf_buffer_view_type_invalid;
4708 out_buffer_view->type = (cgltf_buffer_view_type)type;
4711 else if (cgltf_json_strcmp(tokens + i, json_chunk,
"extras") == 0)
4713 i = cgltf_parse_json_extras(tokens, i + 1, json_chunk, &out_buffer_view->extras);
4715 else if (cgltf_json_strcmp(tokens + i, json_chunk,
"extensions") == 0)
4719 CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
4720 if(out_buffer_view->extensions)
4722 return CGLTF_ERROR_JSON;
4725 int extensions_size = tokens[i].size;
4726 out_buffer_view->extensions_count = 0;
4729 if (!out_buffer_view->extensions)
4731 return CGLTF_ERROR_NOMEM;
4735 for (
int k = 0; k < extensions_size; ++k)
4737 CGLTF_CHECK_KEY(tokens[i]);
4739 if (cgltf_json_strcmp(tokens+i, json_chunk,
"EXT_meshopt_compression") == 0)
4741 out_buffer_view->has_meshopt_compression = 1;
4742 i = cgltf_parse_json_meshopt_compression(options, tokens, i + 1, json_chunk, &out_buffer_view->meshopt_compression);
4746 i = cgltf_parse_json_unprocessed_extension(options, tokens, i, json_chunk, &(out_buffer_view->extensions[out_buffer_view->extensions_count++]));
4757 i = cgltf_skip_json(tokens, i+1);
4769static int cgltf_parse_json_buffer_views(
cgltf_options* options, jsmntok_t
const* tokens,
int i,
const uint8_t* json_chunk,
cgltf_data* out_data)
4771 i = cgltf_parse_json_array(options, tokens, i, json_chunk,
sizeof(
cgltf_buffer_view), (
void**)&out_data->buffer_views, &out_data->buffer_views_count);
4777 for (cgltf_size j = 0; j < out_data->buffer_views_count; ++j)
4779 i = cgltf_parse_json_buffer_view(options, tokens, i, json_chunk, &out_data->buffer_views[j]);
4788static int cgltf_parse_json_buffer(
cgltf_options* options, jsmntok_t
const* tokens,
int i,
const uint8_t* json_chunk,
cgltf_buffer* out_buffer)
4790 CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
4792 int size = tokens[i].size;
4795 for (
int j = 0; j < size; ++j)
4797 CGLTF_CHECK_KEY(tokens[i]);
4799 if (cgltf_json_strcmp(tokens + i, json_chunk,
"name") == 0)
4801 i = cgltf_parse_json_string(options, tokens, i + 1, json_chunk, &out_buffer->name);
4803 else if (cgltf_json_strcmp(tokens+i, json_chunk,
"byteLength") == 0)
4807 cgltf_json_to_size(tokens+i, json_chunk);
4810 else if (cgltf_json_strcmp(tokens+i, json_chunk,
"uri") == 0)
4812 i = cgltf_parse_json_string(options, tokens, i + 1, json_chunk, &out_buffer->uri);
4814 else if (cgltf_json_strcmp(tokens + i, json_chunk,
"extras") == 0)
4816 i = cgltf_parse_json_extras(tokens, i + 1, json_chunk, &out_buffer->extras);
4818 else if (cgltf_json_strcmp(tokens + i, json_chunk,
"extensions") == 0)
4820 i = cgltf_parse_json_unprocessed_extensions(options, tokens, i, json_chunk, &out_buffer->extensions_count, &out_buffer->extensions);
4824 i = cgltf_skip_json(tokens, i+1);
4836static int cgltf_parse_json_buffers(
cgltf_options* options, jsmntok_t
const* tokens,
int i,
const uint8_t* json_chunk,
cgltf_data* out_data)
4838 i = cgltf_parse_json_array(options, tokens, i, json_chunk,
sizeof(
cgltf_buffer), (
void**)&out_data->buffers, &out_data->buffers_count);
4844 for (cgltf_size j = 0; j < out_data->buffers_count; ++j)
4846 i = cgltf_parse_json_buffer(options, tokens, i, json_chunk, &out_data->buffers[j]);
4855static int cgltf_parse_json_skin(
cgltf_options* options, jsmntok_t
const* tokens,
int i,
const uint8_t* json_chunk,
cgltf_skin* out_skin)
4857 CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
4859 int size = tokens[i].size;
4862 for (
int j = 0; j < size; ++j)
4864 CGLTF_CHECK_KEY(tokens[i]);
4866 if (cgltf_json_strcmp(tokens+i, json_chunk,
"name") == 0)
4868 i = cgltf_parse_json_string(options, tokens, i + 1, json_chunk, &out_skin->name);
4870 else if (cgltf_json_strcmp(tokens+i, json_chunk,
"joints") == 0)
4872 i = cgltf_parse_json_array(options, tokens, i + 1, json_chunk,
sizeof(
cgltf_node*), (
void**)&out_skin->joints, &out_skin->joints_count);
4878 for (cgltf_size k = 0; k < out_skin->joints_count; ++k)
4880 out_skin->joints[k] = CGLTF_PTRINDEX(
cgltf_node, cgltf_json_to_int(tokens + i, json_chunk));
4884 else if (cgltf_json_strcmp(tokens+i, json_chunk,
"skeleton") == 0)
4887 CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_PRIMITIVE);
4888 out_skin->skeleton = CGLTF_PTRINDEX(
cgltf_node, cgltf_json_to_int(tokens + i, json_chunk));
4891 else if (cgltf_json_strcmp(tokens+i, json_chunk,
"inverseBindMatrices") == 0)
4894 CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_PRIMITIVE);
4895 out_skin->inverse_bind_matrices = CGLTF_PTRINDEX(
cgltf_accessor, cgltf_json_to_int(tokens + i, json_chunk));
4898 else if (cgltf_json_strcmp(tokens + i, json_chunk,
"extras") == 0)
4900 i = cgltf_parse_json_extras(tokens, i + 1, json_chunk, &out_skin->extras);
4902 else if (cgltf_json_strcmp(tokens + i, json_chunk,
"extensions") == 0)
4904 i = cgltf_parse_json_unprocessed_extensions(options, tokens, i, json_chunk, &out_skin->extensions_count, &out_skin->extensions);
4908 i = cgltf_skip_json(tokens, i+1);
4920static int cgltf_parse_json_skins(
cgltf_options* options, jsmntok_t
const* tokens,
int i,
const uint8_t* json_chunk,
cgltf_data* out_data)
4922 i = cgltf_parse_json_array(options, tokens, i, json_chunk,
sizeof(
cgltf_skin), (
void**)&out_data->skins, &out_data->skins_count);
4928 for (cgltf_size j = 0; j < out_data->skins_count; ++j)
4930 i = cgltf_parse_json_skin(options, tokens, i, json_chunk, &out_data->skins[j]);
4939static int cgltf_parse_json_camera(
cgltf_options* options, jsmntok_t
const* tokens,
int i,
const uint8_t* json_chunk,
cgltf_camera* out_camera)
4941 CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
4943 int size = tokens[i].size;
4946 for (
int j = 0; j < size; ++j)
4948 CGLTF_CHECK_KEY(tokens[i]);
4950 if (cgltf_json_strcmp(tokens+i, json_chunk,
"name") == 0)
4952 i = cgltf_parse_json_string(options, tokens, i + 1, json_chunk, &out_camera->name);
4954 else if (cgltf_json_strcmp(tokens+i, json_chunk,
"type") == 0)
4957 if (cgltf_json_strcmp(tokens + i, json_chunk,
"perspective") == 0)
4959 out_camera->type = cgltf_camera_type_perspective;
4961 else if (cgltf_json_strcmp(tokens + i, json_chunk,
"orthographic") == 0)
4963 out_camera->type = cgltf_camera_type_orthographic;
4967 else if (cgltf_json_strcmp(tokens+i, json_chunk,
"perspective") == 0)
4971 CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
4973 int data_size = tokens[i].size;
4976 out_camera->type = cgltf_camera_type_perspective;
4978 for (
int k = 0; k < data_size; ++k)
4980 CGLTF_CHECK_KEY(tokens[i]);
4982 if (cgltf_json_strcmp(tokens+i, json_chunk,
"aspectRatio") == 0)
4985 out_camera->data.perspective.has_aspect_ratio = 1;
4986 out_camera->data.perspective.aspect_ratio = cgltf_json_to_float(tokens + i, json_chunk);
4989 else if (cgltf_json_strcmp(tokens+i, json_chunk,
"yfov") == 0)
4992 out_camera->data.perspective.yfov = cgltf_json_to_float(tokens + i, json_chunk);
4995 else if (cgltf_json_strcmp(tokens+i, json_chunk,
"zfar") == 0)
4998 out_camera->data.perspective.has_zfar = 1;
4999 out_camera->data.perspective.zfar = cgltf_json_to_float(tokens + i, json_chunk);
5002 else if (cgltf_json_strcmp(tokens+i, json_chunk,
"znear") == 0)
5005 out_camera->data.perspective.znear = cgltf_json_to_float(tokens + i, json_chunk);
5008 else if (cgltf_json_strcmp(tokens + i, json_chunk,
"extras") == 0)
5010 i = cgltf_parse_json_extras(tokens, i + 1, json_chunk, &out_camera->data.perspective.extras);
5014 i = cgltf_skip_json(tokens, i+1);
5023 else if (cgltf_json_strcmp(tokens+i, json_chunk,
"orthographic") == 0)
5027 CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
5029 int data_size = tokens[i].size;
5032 out_camera->type = cgltf_camera_type_orthographic;
5034 for (
int k = 0; k < data_size; ++k)
5036 CGLTF_CHECK_KEY(tokens[i]);
5038 if (cgltf_json_strcmp(tokens+i, json_chunk,
"xmag") == 0)
5041 out_camera->data.orthographic.xmag = cgltf_json_to_float(tokens + i, json_chunk);
5044 else if (cgltf_json_strcmp(tokens+i, json_chunk,
"ymag") == 0)
5047 out_camera->data.orthographic.ymag = cgltf_json_to_float(tokens + i, json_chunk);
5050 else if (cgltf_json_strcmp(tokens+i, json_chunk,
"zfar") == 0)
5053 out_camera->data.orthographic.zfar = cgltf_json_to_float(tokens + i, json_chunk);
5056 else if (cgltf_json_strcmp(tokens+i, json_chunk,
"znear") == 0)
5059 out_camera->data.orthographic.znear = cgltf_json_to_float(tokens + i, json_chunk);
5062 else if (cgltf_json_strcmp(tokens + i, json_chunk,
"extras") == 0)
5064 i = cgltf_parse_json_extras(tokens, i + 1, json_chunk, &out_camera->data.orthographic.extras);
5068 i = cgltf_skip_json(tokens, i+1);
5077 else if (cgltf_json_strcmp(tokens + i, json_chunk,
"extras") == 0)
5079 i = cgltf_parse_json_extras(tokens, i + 1, json_chunk, &out_camera->extras);
5081 else if (cgltf_json_strcmp(tokens + i, json_chunk,
"extensions") == 0)
5083 i = cgltf_parse_json_unprocessed_extensions(options, tokens, i, json_chunk, &out_camera->extensions_count, &out_camera->extensions);
5087 i = cgltf_skip_json(tokens, i+1);
5099static int cgltf_parse_json_cameras(
cgltf_options* options, jsmntok_t
const* tokens,
int i,
const uint8_t* json_chunk,
cgltf_data* out_data)
5101 i = cgltf_parse_json_array(options, tokens, i, json_chunk,
sizeof(
cgltf_camera), (
void**)&out_data->cameras, &out_data->cameras_count);
5107 for (cgltf_size j = 0; j < out_data->cameras_count; ++j)
5109 i = cgltf_parse_json_camera(options, tokens, i, json_chunk, &out_data->cameras[j]);
5118static int cgltf_parse_json_light(
cgltf_options* options, jsmntok_t
const* tokens,
int i,
const uint8_t* json_chunk,
cgltf_light* out_light)
5120 CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
5122 out_light->color[0] = 1.f;
5123 out_light->color[1] = 1.f;
5124 out_light->color[2] = 1.f;
5125 out_light->intensity = 1.f;
5127 out_light->spot_inner_cone_angle = 0.f;
5128 out_light->spot_outer_cone_angle = 3.1415926535f / 4.0f;
5130 int size = tokens[i].size;
5133 for (
int j = 0; j < size; ++j)
5135 CGLTF_CHECK_KEY(tokens[i]);
5137 if (cgltf_json_strcmp(tokens+i, json_chunk,
"name") == 0)
5139 i = cgltf_parse_json_string(options, tokens, i + 1, json_chunk, &out_light->name);
5141 else if (cgltf_json_strcmp(tokens + i, json_chunk,
"color") == 0)
5143 i = cgltf_parse_json_float_array(tokens, i + 1, json_chunk, out_light->color, 3);
5145 else if (cgltf_json_strcmp(tokens + i, json_chunk,
"intensity") == 0)
5148 out_light->intensity = cgltf_json_to_float(tokens + i, json_chunk);
5151 else if (cgltf_json_strcmp(tokens+i, json_chunk,
"type") == 0)
5154 if (cgltf_json_strcmp(tokens + i, json_chunk,
"directional") == 0)
5156 out_light->type = cgltf_light_type_directional;
5158 else if (cgltf_json_strcmp(tokens + i, json_chunk,
"point") == 0)
5160 out_light->type = cgltf_light_type_point;
5162 else if (cgltf_json_strcmp(tokens + i, json_chunk,
"spot") == 0)
5164 out_light->type = cgltf_light_type_spot;
5168 else if (cgltf_json_strcmp(tokens + i, json_chunk,
"range") == 0)
5171 out_light->range = cgltf_json_to_float(tokens + i, json_chunk);
5174 else if (cgltf_json_strcmp(tokens+i, json_chunk,
"spot") == 0)
5178 CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
5180 int data_size = tokens[i].size;
5183 for (
int k = 0; k < data_size; ++k)
5185 CGLTF_CHECK_KEY(tokens[i]);
5187 if (cgltf_json_strcmp(tokens+i, json_chunk,
"innerConeAngle") == 0)
5190 out_light->spot_inner_cone_angle = cgltf_json_to_float(tokens + i, json_chunk);
5193 else if (cgltf_json_strcmp(tokens+i, json_chunk,
"outerConeAngle") == 0)
5196 out_light->spot_outer_cone_angle = cgltf_json_to_float(tokens + i, json_chunk);
5201 i = cgltf_skip_json(tokens, i+1);
5210 else if (cgltf_json_strcmp(tokens + i, json_chunk,
"extras") == 0)
5212 i = cgltf_parse_json_extras(tokens, i + 1, json_chunk, &out_light->extras);
5216 i = cgltf_skip_json(tokens, i+1);
5228static int cgltf_parse_json_lights(
cgltf_options* options, jsmntok_t
const* tokens,
int i,
const uint8_t* json_chunk,
cgltf_data* out_data)
5230 i = cgltf_parse_json_array(options, tokens, i, json_chunk,
sizeof(
cgltf_light), (
void**)&out_data->lights, &out_data->lights_count);
5236 for (cgltf_size j = 0; j < out_data->lights_count; ++j)
5238 i = cgltf_parse_json_light(options, tokens, i, json_chunk, &out_data->lights[j]);
5247static int cgltf_parse_json_node(
cgltf_options* options, jsmntok_t
const* tokens,
int i,
const uint8_t* json_chunk,
cgltf_node* out_node)
5249 CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
5251 out_node->rotation[3] = 1.0f;
5252 out_node->scale[0] = 1.0f;
5253 out_node->scale[1] = 1.0f;
5254 out_node->scale[2] = 1.0f;
5255 out_node->matrix[0] = 1.0f;
5256 out_node->matrix[5] = 1.0f;
5257 out_node->matrix[10] = 1.0f;
5258 out_node->matrix[15] = 1.0f;
5260 int size = tokens[i].size;
5263 for (
int j = 0; j < size; ++j)
5265 CGLTF_CHECK_KEY(tokens[i]);
5267 if (cgltf_json_strcmp(tokens+i, json_chunk,
"name") == 0)
5269 i = cgltf_parse_json_string(options, tokens, i + 1, json_chunk, &out_node->name);
5271 else if (cgltf_json_strcmp(tokens+i, json_chunk,
"children") == 0)
5273 i = cgltf_parse_json_array(options, tokens, i + 1, json_chunk,
sizeof(
cgltf_node*), (
void**)&out_node->children, &out_node->children_count);
5279 for (cgltf_size k = 0; k < out_node->children_count; ++k)
5281 out_node->children[k] = CGLTF_PTRINDEX(
cgltf_node, cgltf_json_to_int(tokens + i, json_chunk));
5285 else if (cgltf_json_strcmp(tokens+i, json_chunk,
"mesh") == 0)
5288 CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_PRIMITIVE);
5289 out_node->mesh = CGLTF_PTRINDEX(
cgltf_mesh, cgltf_json_to_int(tokens + i, json_chunk));
5292 else if (cgltf_json_strcmp(tokens+i, json_chunk,
"skin") == 0)
5295 CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_PRIMITIVE);
5296 out_node->skin = CGLTF_PTRINDEX(
cgltf_skin, cgltf_json_to_int(tokens + i, json_chunk));
5299 else if (cgltf_json_strcmp(tokens+i, json_chunk,
"camera") == 0)
5302 CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_PRIMITIVE);
5303 out_node->camera = CGLTF_PTRINDEX(
cgltf_camera, cgltf_json_to_int(tokens + i, json_chunk));
5306 else if (cgltf_json_strcmp(tokens+i, json_chunk,
"translation") == 0)
5308 out_node->has_translation = 1;
5309 i = cgltf_parse_json_float_array(tokens, i + 1, json_chunk, out_node->translation, 3);
5311 else if (cgltf_json_strcmp(tokens+i, json_chunk,
"rotation") == 0)
5313 out_node->has_rotation = 1;
5314 i = cgltf_parse_json_float_array(tokens, i + 1, json_chunk, out_node->rotation, 4);
5316 else if (cgltf_json_strcmp(tokens+i, json_chunk,
"scale") == 0)
5318 out_node->has_scale = 1;
5319 i = cgltf_parse_json_float_array(tokens, i + 1, json_chunk, out_node->scale, 3);
5321 else if (cgltf_json_strcmp(tokens+i, json_chunk,
"matrix") == 0)
5323 out_node->has_matrix = 1;
5324 i = cgltf_parse_json_float_array(tokens, i + 1, json_chunk, out_node->matrix, 16);
5326 else if (cgltf_json_strcmp(tokens + i, json_chunk,
"weights") == 0)
5328 i = cgltf_parse_json_array(options, tokens, i + 1, json_chunk,
sizeof(cgltf_float), (
void**)&out_node->weights, &out_node->weights_count);
5334 i = cgltf_parse_json_float_array(tokens, i - 1, json_chunk, out_node->weights, (
int)out_node->weights_count);
5336 else if (cgltf_json_strcmp(tokens + i, json_chunk,
"extras") == 0)
5338 i = cgltf_parse_json_extras(tokens, i + 1, json_chunk, &out_node->extras);
5340 else if (cgltf_json_strcmp(tokens + i, json_chunk,
"extensions") == 0)
5344 CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
5345 if(out_node->extensions)
5347 return CGLTF_ERROR_JSON;
5350 int extensions_size = tokens[i].size;
5351 out_node->extensions_count= 0;
5354 if (!out_node->extensions)
5356 return CGLTF_ERROR_NOMEM;
5361 for (
int k = 0; k < extensions_size; ++k)
5363 CGLTF_CHECK_KEY(tokens[i]);
5365 if (cgltf_json_strcmp(tokens+i, json_chunk,
"KHR_lights_punctual") == 0)
5369 CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
5371 int data_size = tokens[i].size;
5374 for (
int m = 0; m < data_size; ++m)
5376 CGLTF_CHECK_KEY(tokens[i]);
5378 if (cgltf_json_strcmp(tokens + i, json_chunk,
"light") == 0)
5381 CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_PRIMITIVE);
5382 out_node->light = CGLTF_PTRINDEX(
cgltf_light, cgltf_json_to_int(tokens + i, json_chunk));
5387 i = cgltf_skip_json(tokens, i + 1);
5396 else if (cgltf_json_strcmp(tokens + i, json_chunk,
"EXT_mesh_gpu_instancing") == 0)
5398 out_node->has_mesh_gpu_instancing = 1;
5399 i = cgltf_parse_json_mesh_gpu_instancing(options, tokens, i + 1, json_chunk, &out_node->mesh_gpu_instancing);
5403 i = cgltf_parse_json_unprocessed_extension(options, tokens, i, json_chunk, &(out_node->extensions[out_node->extensions_count++]));
5414 i = cgltf_skip_json(tokens, i+1);
5426static int cgltf_parse_json_nodes(
cgltf_options* options, jsmntok_t
const* tokens,
int i,
const uint8_t* json_chunk,
cgltf_data* out_data)
5428 i = cgltf_parse_json_array(options, tokens, i, json_chunk,
sizeof(
cgltf_node), (
void**)&out_data->nodes, &out_data->nodes_count);
5434 for (cgltf_size j = 0; j < out_data->nodes_count; ++j)
5436 i = cgltf_parse_json_node(options, tokens, i, json_chunk, &out_data->nodes[j]);
5445static int cgltf_parse_json_scene(
cgltf_options* options, jsmntok_t
const* tokens,
int i,
const uint8_t* json_chunk,
cgltf_scene* out_scene)
5447 CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
5449 int size = tokens[i].size;
5452 for (
int j = 0; j < size; ++j)
5454 CGLTF_CHECK_KEY(tokens[i]);
5456 if (cgltf_json_strcmp(tokens+i, json_chunk,
"name") == 0)
5458 i = cgltf_parse_json_string(options, tokens, i + 1, json_chunk, &out_scene->name);
5460 else if (cgltf_json_strcmp(tokens+i, json_chunk,
"nodes") == 0)
5462 i = cgltf_parse_json_array(options, tokens, i + 1, json_chunk,
sizeof(
cgltf_node*), (
void**)&out_scene->nodes, &out_scene->nodes_count);
5468 for (cgltf_size k = 0; k < out_scene->nodes_count; ++k)
5470 out_scene->nodes[k] = CGLTF_PTRINDEX(
cgltf_node, cgltf_json_to_int(tokens + i, json_chunk));
5474 else if (cgltf_json_strcmp(tokens + i, json_chunk,
"extras") == 0)
5476 i = cgltf_parse_json_extras(tokens, i + 1, json_chunk, &out_scene->extras);
5478 else if (cgltf_json_strcmp(tokens + i, json_chunk,
"extensions") == 0)
5480 i = cgltf_parse_json_unprocessed_extensions(options, tokens, i, json_chunk, &out_scene->extensions_count, &out_scene->extensions);
5484 i = cgltf_skip_json(tokens, i+1);
5496static int cgltf_parse_json_scenes(
cgltf_options* options, jsmntok_t
const* tokens,
int i,
const uint8_t* json_chunk,
cgltf_data* out_data)
5498 i = cgltf_parse_json_array(options, tokens, i, json_chunk,
sizeof(
cgltf_scene), (
void**)&out_data->scenes, &out_data->scenes_count);
5504 for (cgltf_size j = 0; j < out_data->scenes_count; ++j)
5506 i = cgltf_parse_json_scene(options, tokens, i, json_chunk, &out_data->scenes[j]);
5518 CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
5520 int size = tokens[i].size;
5523 for (
int j = 0; j < size; ++j)
5525 CGLTF_CHECK_KEY(tokens[i]);
5527 if (cgltf_json_strcmp(tokens+i, json_chunk,
"input") == 0)
5530 out_sampler->input = CGLTF_PTRINDEX(
cgltf_accessor, cgltf_json_to_int(tokens + i, json_chunk));
5533 else if (cgltf_json_strcmp(tokens+i, json_chunk,
"output") == 0)
5536 out_sampler->output = CGLTF_PTRINDEX(
cgltf_accessor, cgltf_json_to_int(tokens + i, json_chunk));
5539 else if (cgltf_json_strcmp(tokens+i, json_chunk,
"interpolation") == 0)
5542 if (cgltf_json_strcmp(tokens + i, json_chunk,
"LINEAR") == 0)
5544 out_sampler->interpolation = cgltf_interpolation_type_linear;
5546 else if (cgltf_json_strcmp(tokens + i, json_chunk,
"STEP") == 0)
5548 out_sampler->interpolation = cgltf_interpolation_type_step;
5550 else if (cgltf_json_strcmp(tokens + i, json_chunk,
"CUBICSPLINE") == 0)
5552 out_sampler->interpolation = cgltf_interpolation_type_cubic_spline;
5556 else if (cgltf_json_strcmp(tokens + i, json_chunk,
"extras") == 0)
5558 i = cgltf_parse_json_extras(tokens, i + 1, json_chunk, &out_sampler->extras);
5560 else if (cgltf_json_strcmp(tokens + i, json_chunk,
"extensions") == 0)
5562 i = cgltf_parse_json_unprocessed_extensions(options, tokens, i, json_chunk, &out_sampler->extensions_count, &out_sampler->extensions);
5566 i = cgltf_skip_json(tokens, i+1);
5581 CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
5583 int size = tokens[i].size;
5586 for (
int j = 0; j < size; ++j)
5588 CGLTF_CHECK_KEY(tokens[i]);
5590 if (cgltf_json_strcmp(tokens+i, json_chunk,
"sampler") == 0)
5596 else if (cgltf_json_strcmp(tokens+i, json_chunk,
"target") == 0)
5600 CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
5602 int target_size = tokens[i].size;
5605 for (
int k = 0; k < target_size; ++k)
5607 CGLTF_CHECK_KEY(tokens[i]);
5609 if (cgltf_json_strcmp(tokens+i, json_chunk,
"node") == 0)
5612 out_channel->target_node = CGLTF_PTRINDEX(
cgltf_node, cgltf_json_to_int(tokens + i, json_chunk));
5615 else if (cgltf_json_strcmp(tokens+i, json_chunk,
"path") == 0)
5618 if (cgltf_json_strcmp(tokens+i, json_chunk,
"translation") == 0)
5620 out_channel->target_path = cgltf_animation_path_type_translation;
5622 else if (cgltf_json_strcmp(tokens+i, json_chunk,
"rotation") == 0)
5624 out_channel->target_path = cgltf_animation_path_type_rotation;
5626 else if (cgltf_json_strcmp(tokens+i, json_chunk,
"scale") == 0)
5628 out_channel->target_path = cgltf_animation_path_type_scale;
5630 else if (cgltf_json_strcmp(tokens+i, json_chunk,
"weights") == 0)
5632 out_channel->target_path = cgltf_animation_path_type_weights;
5636 else if (cgltf_json_strcmp(tokens + i, json_chunk,
"extras") == 0)
5638 i = cgltf_parse_json_extras(tokens, i + 1, json_chunk, &out_channel->extras);
5640 else if (cgltf_json_strcmp(tokens + i, json_chunk,
"extensions") == 0)
5642 i = cgltf_parse_json_unprocessed_extensions(options, tokens, i, json_chunk, &out_channel->extensions_count, &out_channel->extensions);
5646 i = cgltf_skip_json(tokens, i+1);
5657 i = cgltf_skip_json(tokens, i+1);
5669static int cgltf_parse_json_animation(
cgltf_options* options, jsmntok_t
const* tokens,
int i,
const uint8_t* json_chunk,
cgltf_animation* out_animation)
5671 CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
5673 int size = tokens[i].size;
5676 for (
int j = 0; j < size; ++j)
5678 CGLTF_CHECK_KEY(tokens[i]);
5680 if (cgltf_json_strcmp(tokens+i, json_chunk,
"name") == 0)
5682 i = cgltf_parse_json_string(options, tokens, i + 1, json_chunk, &out_animation->name);
5684 else if (cgltf_json_strcmp(tokens+i, json_chunk,
"samplers") == 0)
5686 i = cgltf_parse_json_array(options, tokens, i + 1, json_chunk,
sizeof(
cgltf_animation_sampler), (
void**)&out_animation->samplers, &out_animation->samplers_count);
5692 for (cgltf_size k = 0; k < out_animation->samplers_count; ++k)
5694 i = cgltf_parse_json_animation_sampler(options, tokens, i, json_chunk, &out_animation->samplers[k]);
5701 else if (cgltf_json_strcmp(tokens+i, json_chunk,
"channels") == 0)
5703 i = cgltf_parse_json_array(options, tokens, i + 1, json_chunk,
sizeof(
cgltf_animation_channel), (
void**)&out_animation->channels, &out_animation->channels_count);
5709 for (cgltf_size k = 0; k < out_animation->channels_count; ++k)
5711 i = cgltf_parse_json_animation_channel(options, tokens, i, json_chunk, &out_animation->channels[k]);
5718 else if (cgltf_json_strcmp(tokens + i, json_chunk,
"extras") == 0)
5720 i = cgltf_parse_json_extras(tokens, i + 1, json_chunk, &out_animation->extras);
5722 else if (cgltf_json_strcmp(tokens + i, json_chunk,
"extensions") == 0)
5724 i = cgltf_parse_json_unprocessed_extensions(options, tokens, i, json_chunk, &out_animation->extensions_count, &out_animation->extensions);
5728 i = cgltf_skip_json(tokens, i+1);
5740static int cgltf_parse_json_animations(
cgltf_options* options, jsmntok_t
const* tokens,
int i,
const uint8_t* json_chunk,
cgltf_data* out_data)
5742 i = cgltf_parse_json_array(options, tokens, i, json_chunk,
sizeof(
cgltf_animation), (
void**)&out_data->animations, &out_data->animations_count);
5748 for (cgltf_size j = 0; j < out_data->animations_count; ++j)
5750 i = cgltf_parse_json_animation(options, tokens, i, json_chunk, &out_data->animations[j]);
5761 CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
5763 int size = tokens[i].size;
5766 for (
int j = 0; j < size; ++j)
5768 CGLTF_CHECK_KEY(tokens[i]);
5770 if (cgltf_json_strcmp(tokens+i, json_chunk,
"name") == 0)
5772 i = cgltf_parse_json_string(options, tokens, i + 1, json_chunk, &out_variant->name);
5774 else if (cgltf_json_strcmp(tokens + i, json_chunk,
"extras") == 0)
5776 i = cgltf_parse_json_extras(tokens, i + 1, json_chunk, &out_variant->extras);
5780 i = cgltf_skip_json(tokens, i+1);
5792static int cgltf_parse_json_variants(
cgltf_options* options, jsmntok_t
const* tokens,
int i,
const uint8_t* json_chunk,
cgltf_data* out_data)
5794 i = cgltf_parse_json_array(options, tokens, i, json_chunk,
sizeof(
cgltf_material_variant), (
void**)&out_data->variants, &out_data->variants_count);
5800 for (cgltf_size j = 0; j < out_data->variants_count; ++j)
5802 i = cgltf_parse_json_variant(options, tokens, i, json_chunk, &out_data->variants[j]);
5811static int cgltf_parse_json_asset(
cgltf_options* options, jsmntok_t
const* tokens,
int i,
const uint8_t* json_chunk,
cgltf_asset* out_asset)
5813 CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
5815 int size = tokens[i].size;
5818 for (
int j = 0; j < size; ++j)
5820 CGLTF_CHECK_KEY(tokens[i]);
5822 if (cgltf_json_strcmp(tokens+i, json_chunk,
"copyright") == 0)
5824 i = cgltf_parse_json_string(options, tokens, i + 1, json_chunk, &out_asset->copyright);
5826 else if (cgltf_json_strcmp(tokens+i, json_chunk,
"generator") == 0)
5828 i = cgltf_parse_json_string(options, tokens, i + 1, json_chunk, &out_asset->generator);
5830 else if (cgltf_json_strcmp(tokens+i, json_chunk,
"version") == 0)
5832 i = cgltf_parse_json_string(options, tokens, i + 1, json_chunk, &out_asset->version);
5834 else if (cgltf_json_strcmp(tokens+i, json_chunk,
"minVersion") == 0)
5836 i = cgltf_parse_json_string(options, tokens, i + 1, json_chunk, &out_asset->min_version);
5838 else if (cgltf_json_strcmp(tokens + i, json_chunk,
"extras") == 0)
5840 i = cgltf_parse_json_extras(tokens, i + 1, json_chunk, &out_asset->extras);
5842 else if (cgltf_json_strcmp(tokens + i, json_chunk,
"extensions") == 0)
5844 i = cgltf_parse_json_unprocessed_extensions(options, tokens, i, json_chunk, &out_asset->extensions_count, &out_asset->extensions);
5848 i = cgltf_skip_json(tokens, i+1);
5857 if (out_asset->version && CGLTF_ATOF(out_asset->version) < 2)
5859 return CGLTF_ERROR_LEGACY;
5865cgltf_size cgltf_num_components(cgltf_type type) {
5868 case cgltf_type_vec2:
5870 case cgltf_type_vec3:
5872 case cgltf_type_vec4:
5874 case cgltf_type_mat2:
5876 case cgltf_type_mat3:
5878 case cgltf_type_mat4:
5880 case cgltf_type_invalid:
5881 case cgltf_type_scalar:
5887static cgltf_size cgltf_component_size(cgltf_component_type component_type) {
5888 switch (component_type)
5890 case cgltf_component_type_r_8:
5891 case cgltf_component_type_r_8u:
5893 case cgltf_component_type_r_16:
5894 case cgltf_component_type_r_16u:
5896 case cgltf_component_type_r_32u:
5897 case cgltf_component_type_r_32f:
5899 case cgltf_component_type_invalid:
5905static cgltf_size cgltf_calc_size(cgltf_type type, cgltf_component_type component_type)
5907 cgltf_size component_size = cgltf_component_size(component_type);
5908 if (type == cgltf_type_mat2 && component_size == 1)
5910 return 8 * component_size;
5912 else if (type == cgltf_type_mat3 && (component_size == 1 || component_size == 2))
5914 return 12 * component_size;
5916 return component_size * cgltf_num_components(type);
5919static int cgltf_fixup_pointers(
cgltf_data* out_data);
5921static int cgltf_parse_json_root(
cgltf_options* options, jsmntok_t
const* tokens,
int i,
const uint8_t* json_chunk,
cgltf_data* out_data)
5923 CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
5925 int size = tokens[i].size;
5928 for (
int j = 0; j < size; ++j)
5930 CGLTF_CHECK_KEY(tokens[i]);
5932 if (cgltf_json_strcmp(tokens + i, json_chunk,
"asset") == 0)
5934 i = cgltf_parse_json_asset(options, tokens, i + 1, json_chunk, &out_data->asset);
5936 else if (cgltf_json_strcmp(tokens + i, json_chunk,
"meshes") == 0)
5938 i = cgltf_parse_json_meshes(options, tokens, i + 1, json_chunk, out_data);
5940 else if (cgltf_json_strcmp(tokens + i, json_chunk,
"accessors") == 0)
5942 i = cgltf_parse_json_accessors(options, tokens, i + 1, json_chunk, out_data);
5944 else if (cgltf_json_strcmp(tokens + i, json_chunk,
"bufferViews") == 0)
5946 i = cgltf_parse_json_buffer_views(options, tokens, i + 1, json_chunk, out_data);
5948 else if (cgltf_json_strcmp(tokens + i, json_chunk,
"buffers") == 0)
5950 i = cgltf_parse_json_buffers(options, tokens, i + 1, json_chunk, out_data);
5952 else if (cgltf_json_strcmp(tokens + i, json_chunk,
"materials") == 0)
5954 i = cgltf_parse_json_materials(options, tokens, i + 1, json_chunk, out_data);
5956 else if (cgltf_json_strcmp(tokens + i, json_chunk,
"images") == 0)
5958 i = cgltf_parse_json_images(options, tokens, i + 1, json_chunk, out_data);
5960 else if (cgltf_json_strcmp(tokens + i, json_chunk,
"textures") == 0)
5962 i = cgltf_parse_json_textures(options, tokens, i + 1, json_chunk, out_data);
5964 else if (cgltf_json_strcmp(tokens + i, json_chunk,
"samplers") == 0)
5966 i = cgltf_parse_json_samplers(options, tokens, i + 1, json_chunk, out_data);
5968 else if (cgltf_json_strcmp(tokens + i, json_chunk,
"skins") == 0)
5970 i = cgltf_parse_json_skins(options, tokens, i + 1, json_chunk, out_data);
5972 else if (cgltf_json_strcmp(tokens + i, json_chunk,
"cameras") == 0)
5974 i = cgltf_parse_json_cameras(options, tokens, i + 1, json_chunk, out_data);
5976 else if (cgltf_json_strcmp(tokens + i, json_chunk,
"nodes") == 0)
5978 i = cgltf_parse_json_nodes(options, tokens, i + 1, json_chunk, out_data);
5980 else if (cgltf_json_strcmp(tokens + i, json_chunk,
"scenes") == 0)
5982 i = cgltf_parse_json_scenes(options, tokens, i + 1, json_chunk, out_data);
5984 else if (cgltf_json_strcmp(tokens + i, json_chunk,
"scene") == 0)
5987 out_data->scene = CGLTF_PTRINDEX(
cgltf_scene, cgltf_json_to_int(tokens + i, json_chunk));
5990 else if (cgltf_json_strcmp(tokens + i, json_chunk,
"animations") == 0)
5992 i = cgltf_parse_json_animations(options, tokens, i + 1, json_chunk, out_data);
5994 else if (cgltf_json_strcmp(tokens+i, json_chunk,
"extras") == 0)
5996 i = cgltf_parse_json_extras(tokens, i + 1, json_chunk, &out_data->extras);
5998 else if (cgltf_json_strcmp(tokens + i, json_chunk,
"extensions") == 0)
6002 CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
6003 if(out_data->data_extensions)
6005 return CGLTF_ERROR_JSON;
6008 int extensions_size = tokens[i].size;
6009 out_data->data_extensions_count = 0;
6012 if (!out_data->data_extensions)
6014 return CGLTF_ERROR_NOMEM;
6019 for (
int k = 0; k < extensions_size; ++k)
6021 CGLTF_CHECK_KEY(tokens[i]);
6023 if (cgltf_json_strcmp(tokens+i, json_chunk,
"KHR_lights_punctual") == 0)
6027 CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
6029 int data_size = tokens[i].size;
6032 for (
int m = 0; m < data_size; ++m)
6034 CGLTF_CHECK_KEY(tokens[i]);
6036 if (cgltf_json_strcmp(tokens + i, json_chunk,
"lights") == 0)
6038 i = cgltf_parse_json_lights(options, tokens, i + 1, json_chunk, out_data);
6042 i = cgltf_skip_json(tokens, i + 1);
6051 else if (cgltf_json_strcmp(tokens+i, json_chunk,
"KHR_materials_variants") == 0)
6055 CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
6057 int data_size = tokens[i].size;
6060 for (
int m = 0; m < data_size; ++m)
6062 CGLTF_CHECK_KEY(tokens[i]);
6064 if (cgltf_json_strcmp(tokens + i, json_chunk,
"variants") == 0)
6066 i = cgltf_parse_json_variants(options, tokens, i + 1, json_chunk, out_data);
6070 i = cgltf_skip_json(tokens, i + 1);
6081 i = cgltf_parse_json_unprocessed_extension(options, tokens, i, json_chunk, &(out_data->data_extensions[out_data->data_extensions_count++]));
6090 else if (cgltf_json_strcmp(tokens + i, json_chunk,
"extensionsUsed") == 0)
6092 i = cgltf_parse_json_string_array(options, tokens, i + 1, json_chunk, &out_data->extensions_used, &out_data->extensions_used_count);
6094 else if (cgltf_json_strcmp(tokens + i, json_chunk,
"extensionsRequired") == 0)
6096 i = cgltf_parse_json_string_array(options, tokens, i + 1, json_chunk, &out_data->extensions_required, &out_data->extensions_required_count);
6100 i = cgltf_skip_json(tokens, i + 1);
6112cgltf_result cgltf_parse_json(
cgltf_options* options,
const uint8_t* json_chunk, cgltf_size size,
cgltf_data** out_data)
6114 jsmn_parser parser = { 0, 0, 0 };
6116 if (options->json_token_count == 0)
6118 int token_count = jsmn_parse(&parser, (
const char*)json_chunk, size, NULL, 0);
6120 if (token_count <= 0)
6122 return cgltf_result_invalid_json;
6125 options->json_token_count = token_count;
6128 jsmntok_t* tokens = (jsmntok_t*)options->memory.alloc_func(options->memory.user_data,
sizeof(jsmntok_t) * (options->json_token_count + 1));
6132 return cgltf_result_out_of_memory;
6137 int token_count = jsmn_parse(&parser, (
const char*)json_chunk, size, tokens, options->json_token_count);
6139 if (token_count <= 0)
6141 options->memory.free_func(options->memory.user_data, tokens);
6142 return cgltf_result_invalid_json;
6147 tokens[token_count].type = JSMN_UNDEFINED;
6153 options->memory.free_func(options->memory.user_data, tokens);
6154 return cgltf_result_out_of_memory;
6158 data->memory = options->memory;
6159 data->file = options->file;
6161 int i = cgltf_parse_json_root(options, tokens, 0, json_chunk, data);
6163 options->memory.free_func(options->memory.user_data, tokens);
6171 case CGLTF_ERROR_NOMEM:
return cgltf_result_out_of_memory;
6172 case CGLTF_ERROR_LEGACY:
return cgltf_result_legacy_gltf;
6173 default:
return cgltf_result_invalid_gltf;
6177 if (cgltf_fixup_pointers(data) < 0)
6180 return cgltf_result_invalid_gltf;
6183 data->json = (
const char*)json_chunk;
6184 data->json_size = size;
6188 return cgltf_result_success;
6191static int cgltf_fixup_pointers(
cgltf_data* data)
6193 for (cgltf_size i = 0; i < data->meshes_count; ++i)
6195 for (cgltf_size j = 0; j < data->meshes[i].primitives_count; ++j)
6197 CGLTF_PTRFIXUP(data->meshes[i].primitives[j].indices, data->accessors, data->accessors_count);
6198 CGLTF_PTRFIXUP(data->meshes[i].primitives[j].material, data->materials, data->materials_count);
6200 for (cgltf_size k = 0; k < data->meshes[i].primitives[j].attributes_count; ++k)
6202 CGLTF_PTRFIXUP_REQ(data->meshes[i].primitives[j].attributes[k].data, data->accessors, data->accessors_count);
6205 for (cgltf_size k = 0; k < data->meshes[i].primitives[j].targets_count; ++k)
6207 for (cgltf_size m = 0; m < data->meshes[i].primitives[j].targets[k].attributes_count; ++m)
6209 CGLTF_PTRFIXUP_REQ(data->meshes[i].primitives[j].targets[k].attributes[m].data, data->accessors, data->accessors_count);
6213 if (data->meshes[i].primitives[j].has_draco_mesh_compression)
6215 CGLTF_PTRFIXUP_REQ(data->meshes[i].primitives[j].draco_mesh_compression.buffer_view, data->buffer_views, data->buffer_views_count);
6216 for (cgltf_size m = 0; m < data->meshes[i].primitives[j].draco_mesh_compression.attributes_count; ++m)
6218 CGLTF_PTRFIXUP_REQ(data->meshes[i].primitives[j].draco_mesh_compression.attributes[m].data, data->accessors, data->accessors_count);
6222 for (cgltf_size k = 0; k < data->meshes[i].primitives[j].mappings_count; ++k)
6224 CGLTF_PTRFIXUP_REQ(data->meshes[i].primitives[j].mappings[k].material, data->materials, data->materials_count);
6229 for (cgltf_size i = 0; i < data->accessors_count; ++i)
6231 CGLTF_PTRFIXUP(data->accessors[i].buffer_view, data->buffer_views, data->buffer_views_count);
6233 if (data->accessors[i].is_sparse)
6235 CGLTF_PTRFIXUP_REQ(data->accessors[i].sparse.indices_buffer_view, data->buffer_views, data->buffer_views_count);
6236 CGLTF_PTRFIXUP_REQ(data->accessors[i].sparse.values_buffer_view, data->buffer_views, data->buffer_views_count);
6239 if (data->accessors[i].buffer_view)
6241 data->accessors[i].stride = data->accessors[i].buffer_view->stride;
6244 if (data->accessors[i].stride == 0)
6246 data->accessors[i].stride = cgltf_calc_size(data->accessors[i].type, data->accessors[i].component_type);
6250 for (cgltf_size i = 0; i < data->textures_count; ++i)
6252 CGLTF_PTRFIXUP(data->textures[i].image, data->images, data->images_count);
6253 CGLTF_PTRFIXUP(data->textures[i].basisu_image, data->images, data->images_count);
6254 CGLTF_PTRFIXUP(data->textures[i].sampler, data->samplers, data->samplers_count);
6257 for (cgltf_size i = 0; i < data->images_count; ++i)
6259 CGLTF_PTRFIXUP(data->images[i].buffer_view, data->buffer_views, data->buffer_views_count);
6262 for (cgltf_size i = 0; i < data->materials_count; ++i)
6264 CGLTF_PTRFIXUP(data->materials[i].normal_texture.texture, data->textures, data->textures_count);
6265 CGLTF_PTRFIXUP(data->materials[i].emissive_texture.texture, data->textures, data->textures_count);
6266 CGLTF_PTRFIXUP(data->materials[i].occlusion_texture.texture, data->textures, data->textures_count);
6268 CGLTF_PTRFIXUP(data->materials[i].pbr_metallic_roughness.base_color_texture.texture, data->textures, data->textures_count);
6269 CGLTF_PTRFIXUP(data->materials[i].pbr_metallic_roughness.metallic_roughness_texture.texture, data->textures, data->textures_count);
6271 CGLTF_PTRFIXUP(data->materials[i].pbr_specular_glossiness.diffuse_texture.texture, data->textures, data->textures_count);
6272 CGLTF_PTRFIXUP(data->materials[i].pbr_specular_glossiness.specular_glossiness_texture.texture, data->textures, data->textures_count);
6274 CGLTF_PTRFIXUP(data->materials[i].clearcoat.clearcoat_texture.texture, data->textures, data->textures_count);
6275 CGLTF_PTRFIXUP(data->materials[i].clearcoat.clearcoat_roughness_texture.texture, data->textures, data->textures_count);
6276 CGLTF_PTRFIXUP(data->materials[i].clearcoat.clearcoat_normal_texture.texture, data->textures, data->textures_count);
6278 CGLTF_PTRFIXUP(data->materials[i].specular.specular_texture.texture, data->textures, data->textures_count);
6279 CGLTF_PTRFIXUP(data->materials[i].specular.specular_color_texture.texture, data->textures, data->textures_count);
6281 CGLTF_PTRFIXUP(data->materials[i].transmission.transmission_texture.texture, data->textures, data->textures_count);
6283 CGLTF_PTRFIXUP(data->materials[i].volume.thickness_texture.texture, data->textures, data->textures_count);
6285 CGLTF_PTRFIXUP(data->materials[i].sheen.sheen_color_texture.texture, data->textures, data->textures_count);
6286 CGLTF_PTRFIXUP(data->materials[i].sheen.sheen_roughness_texture.texture, data->textures, data->textures_count);
6288 CGLTF_PTRFIXUP(data->materials[i].iridescence.iridescence_texture.texture, data->textures, data->textures_count);
6289 CGLTF_PTRFIXUP(data->materials[i].iridescence.iridescence_thickness_texture.texture, data->textures, data->textures_count);
6292 for (cgltf_size i = 0; i < data->buffer_views_count; ++i)
6294 CGLTF_PTRFIXUP_REQ(data->buffer_views[i].buffer, data->buffers, data->buffers_count);
6296 if (data->buffer_views[i].has_meshopt_compression)
6298 CGLTF_PTRFIXUP_REQ(data->buffer_views[i].meshopt_compression.buffer, data->buffers, data->buffers_count);
6302 for (cgltf_size i = 0; i < data->skins_count; ++i)
6304 for (cgltf_size j = 0; j < data->skins[i].joints_count; ++j)
6306 CGLTF_PTRFIXUP_REQ(data->skins[i].joints[j], data->nodes, data->nodes_count);
6309 CGLTF_PTRFIXUP(data->skins[i].skeleton, data->nodes, data->nodes_count);
6310 CGLTF_PTRFIXUP(data->skins[i].inverse_bind_matrices, data->accessors, data->accessors_count);
6313 for (cgltf_size i = 0; i < data->nodes_count; ++i)
6315 for (cgltf_size j = 0; j < data->nodes[i].children_count; ++j)
6317 CGLTF_PTRFIXUP_REQ(data->nodes[i].children[j], data->nodes, data->nodes_count);
6319 if (data->nodes[i].children[j]->parent)
6321 return CGLTF_ERROR_JSON;
6324 data->nodes[i].children[j]->parent = &data->nodes[i];
6327 CGLTF_PTRFIXUP(data->nodes[i].mesh, data->meshes, data->meshes_count);
6328 CGLTF_PTRFIXUP(data->nodes[i].skin, data->skins, data->skins_count);
6329 CGLTF_PTRFIXUP(data->nodes[i].camera, data->cameras, data->cameras_count);
6330 CGLTF_PTRFIXUP(data->nodes[i].light, data->lights, data->lights_count);
6332 if (data->nodes[i].has_mesh_gpu_instancing)
6334 CGLTF_PTRFIXUP_REQ(data->nodes[i].mesh_gpu_instancing.buffer_view, data->buffer_views, data->buffer_views_count);
6335 for (cgltf_size m = 0; m < data->nodes[i].mesh_gpu_instancing.attributes_count; ++m)
6337 CGLTF_PTRFIXUP_REQ(data->nodes[i].mesh_gpu_instancing.attributes[m].data, data->accessors, data->accessors_count);
6342 for (cgltf_size i = 0; i < data->scenes_count; ++i)
6344 for (cgltf_size j = 0; j < data->scenes[i].nodes_count; ++j)
6346 CGLTF_PTRFIXUP_REQ(data->scenes[i].nodes[j], data->nodes, data->nodes_count);
6348 if (data->scenes[i].nodes[j]->parent)
6350 return CGLTF_ERROR_JSON;
6355 CGLTF_PTRFIXUP(data->scene, data->scenes, data->scenes_count);
6357 for (cgltf_size i = 0; i < data->animations_count; ++i)
6359 for (cgltf_size j = 0; j < data->animations[i].samplers_count; ++j)
6361 CGLTF_PTRFIXUP_REQ(data->animations[i].samplers[j].input, data->accessors, data->accessors_count);
6362 CGLTF_PTRFIXUP_REQ(data->animations[i].samplers[j].output, data->accessors, data->accessors_count);
6365 for (cgltf_size j = 0; j < data->animations[i].channels_count; ++j)
6367 CGLTF_PTRFIXUP_REQ(data->animations[i].channels[j].sampler, data->animations[i].samplers, data->animations[i].samplers_count);
6368 CGLTF_PTRFIXUP(data->animations[i].channels[j].target_node, data->nodes, data->nodes_count);
6404static jsmntok_t *jsmn_alloc_token(jsmn_parser *parser,
6405 jsmntok_t *tokens,
size_t num_tokens) {
6407 if (parser->toknext >= num_tokens) {
6410 tok = &tokens[parser->toknext++];
6411 tok->start = tok->end = -1;
6413#ifdef JSMN_PARENT_LINKS
6422static void jsmn_fill_token(jsmntok_t *token, jsmntype_t type,
6423 int start,
int end) {
6425 token->start = start;
6433static int jsmn_parse_primitive(jsmn_parser *parser,
const char *js,
6434 size_t len, jsmntok_t *tokens,
size_t num_tokens) {
6438 start = parser->pos;
6440 for (; parser->pos < len && js[parser->pos] !=
'\0'; parser->pos++) {
6441 switch (js[parser->pos]) {
6446 case '\t' :
case '\r' :
case '\n' :
case ' ' :
6447 case ',' :
case ']' :
case '}' :
6450 if (js[parser->pos] < 32 || js[parser->pos] >= 127) {
6451 parser->pos = start;
6452 return JSMN_ERROR_INVAL;
6457 parser->pos = start;
6458 return JSMN_ERROR_PART;
6462 if (tokens == NULL) {
6466 token = jsmn_alloc_token(parser, tokens, num_tokens);
6467 if (token == NULL) {
6468 parser->pos = start;
6469 return JSMN_ERROR_NOMEM;
6471 jsmn_fill_token(token, JSMN_PRIMITIVE, start, parser->pos);
6472#ifdef JSMN_PARENT_LINKS
6473 token->parent = parser->toksuper;
6482static int jsmn_parse_string(jsmn_parser *parser,
const char *js,
6483 size_t len, jsmntok_t *tokens,
size_t num_tokens) {
6486 int start = parser->pos;
6491 for (; parser->pos < len && js[parser->pos] !=
'\0'; parser->pos++) {
6492 char c = js[parser->pos];
6496 if (tokens == NULL) {
6499 token = jsmn_alloc_token(parser, tokens, num_tokens);
6500 if (token == NULL) {
6501 parser->pos = start;
6502 return JSMN_ERROR_NOMEM;
6504 jsmn_fill_token(token, JSMN_STRING, start+1, parser->pos);
6505#ifdef JSMN_PARENT_LINKS
6506 token->parent = parser->toksuper;
6512 if (
c ==
'\\' && parser->pos + 1 < len) {
6515 switch (js[parser->pos]) {
6517 case '\"':
case '/' :
case '\\' :
case 'b' :
6518 case 'f' :
case 'r' :
case 'n' :
case 't' :
6523 for(i = 0; i < 4 && parser->pos < len && js[parser->pos] !=
'\0'; i++) {
6525 if(!((js[parser->pos] >= 48 && js[parser->pos] <= 57) ||
6526 (js[parser->pos] >= 65 && js[parser->pos] <= 70) ||
6527 (js[parser->pos] >= 97 && js[parser->pos] <= 102))) {
6528 parser->pos = start;
6529 return JSMN_ERROR_INVAL;
6537 parser->pos = start;
6538 return JSMN_ERROR_INVAL;
6542 parser->pos = start;
6543 return JSMN_ERROR_PART;
6549static int jsmn_parse(jsmn_parser *parser,
const char *js,
size_t len,
6550 jsmntok_t *tokens,
size_t num_tokens) {
6554 int count = parser->toknext;
6556 for (; parser->pos < len && js[parser->pos] !=
'\0'; parser->pos++) {
6560 c = js[parser->pos];
6564 if (tokens == NULL) {
6567 token = jsmn_alloc_token(parser, tokens, num_tokens);
6569 return JSMN_ERROR_NOMEM;
6570 if (parser->toksuper != -1) {
6571 tokens[parser->toksuper].size++;
6572#ifdef JSMN_PARENT_LINKS
6573 token->parent = parser->toksuper;
6576 token->type = (
c ==
'{' ? JSMN_OBJECT : JSMN_ARRAY);
6577 token->start = parser->pos;
6578 parser->toksuper = parser->toknext - 1;
6583 type = (
c ==
'}' ? JSMN_OBJECT : JSMN_ARRAY);
6584#ifdef JSMN_PARENT_LINKS
6585 if (parser->toknext < 1) {
6586 return JSMN_ERROR_INVAL;
6588 token = &tokens[parser->toknext - 1];
6590 if (token->start != -1 && token->end == -1) {
6591 if (token->type != type) {
6592 return JSMN_ERROR_INVAL;
6594 token->end = parser->pos + 1;
6595 parser->toksuper = token->parent;
6598 if (token->parent == -1) {
6599 if(token->type != type || parser->toksuper == -1) {
6600 return JSMN_ERROR_INVAL;
6604 token = &tokens[token->parent];
6607 for (i = parser->toknext - 1; i >= 0; i--) {
6609 if (token->start != -1 && token->end == -1) {
6610 if (token->type != type) {
6611 return JSMN_ERROR_INVAL;
6613 parser->toksuper = -1;
6614 token->end = parser->pos + 1;
6619 if (i == -1)
return JSMN_ERROR_INVAL;
6620 for (; i >= 0; i--) {
6622 if (token->start != -1 && token->end == -1) {
6623 parser->toksuper = i;
6630 r = jsmn_parse_string(parser, js, len, tokens, num_tokens);
6631 if (r < 0)
return r;
6633 if (parser->toksuper != -1 && tokens != NULL)
6634 tokens[parser->toksuper].size++;
6636 case '\t' :
case '\r' :
case '\n' :
case ' ':
6639 parser->toksuper = parser->toknext - 1;
6642 if (tokens != NULL && parser->toksuper != -1 &&
6643 tokens[parser->toksuper].type != JSMN_ARRAY &&
6644 tokens[parser->toksuper].type != JSMN_OBJECT) {
6645#ifdef JSMN_PARENT_LINKS
6646 parser->toksuper = tokens[parser->toksuper].parent;
6648 for (i = parser->toknext - 1; i >= 0; i--) {
6649 if (tokens[i].type == JSMN_ARRAY || tokens[i].type == JSMN_OBJECT) {
6650 if (tokens[i].start != -1 && tokens[i].end == -1) {
6651 parser->toksuper = i;
6661 case '-':
case '0':
case '1' :
case '2':
case '3' :
case '4':
6662 case '5':
case '6':
case '7' :
case '8':
case '9':
6663 case 't':
case 'f':
case 'n' :
6665 if (tokens != NULL && parser->toksuper != -1) {
6666 jsmntok_t *t = &tokens[parser->toksuper];
6667 if (t->type == JSMN_OBJECT ||
6668 (t->type == JSMN_STRING && t->size != 0)) {
6669 return JSMN_ERROR_INVAL;
6676 r = jsmn_parse_primitive(parser, js, len, tokens, num_tokens);
6677 if (r < 0)
return r;
6679 if (parser->toksuper != -1 && tokens != NULL)
6680 tokens[parser->toksuper].size++;
6686 return JSMN_ERROR_INVAL;
6691 if (tokens != NULL) {
6692 for (i = parser->toknext - 1; i >= 0; i--) {
6694 if (tokens[i].start != -1 && tokens[i].end == -1) {
6695 return JSMN_ERROR_PART;
6707static void jsmn_init(jsmn_parser *parser) {
6709 parser->toknext = 0;
6710 parser->toksuper = -1;