95#ifndef CGLTF_H_INCLUDED__
96#define CGLTF_H_INCLUDED__
105typedef size_t cgltf_size;
106typedef long long int cgltf_ssize;
107typedef float cgltf_float;
108typedef int cgltf_int;
109typedef unsigned int cgltf_uint;
110typedef int cgltf_bool;
112typedef enum cgltf_file_type
114 cgltf_file_type_invalid,
115 cgltf_file_type_gltf,
117 cgltf_file_type_max_enum
120typedef enum cgltf_result
122 cgltf_result_success,
123 cgltf_result_data_too_short,
124 cgltf_result_unknown_format,
125 cgltf_result_invalid_json,
126 cgltf_result_invalid_gltf,
127 cgltf_result_invalid_options,
128 cgltf_result_file_not_found,
129 cgltf_result_io_error,
130 cgltf_result_out_of_memory,
131 cgltf_result_legacy_gltf,
132 cgltf_result_max_enum
137 void* (*alloc_func)(
void* user, cgltf_size size);
138 void (*free_func) (
void* user,
void* ptr);
151 cgltf_file_type type;
152 cgltf_size json_token_count;
157typedef enum cgltf_buffer_view_type
159 cgltf_buffer_view_type_invalid,
160 cgltf_buffer_view_type_indices,
161 cgltf_buffer_view_type_vertices,
162 cgltf_buffer_view_type_max_enum
163} cgltf_buffer_view_type;
165typedef enum cgltf_attribute_type
167 cgltf_attribute_type_invalid,
168 cgltf_attribute_type_position,
169 cgltf_attribute_type_normal,
170 cgltf_attribute_type_tangent,
171 cgltf_attribute_type_texcoord,
172 cgltf_attribute_type_color,
173 cgltf_attribute_type_joints,
174 cgltf_attribute_type_weights,
175 cgltf_attribute_type_custom,
176 cgltf_attribute_type_max_enum
177} cgltf_attribute_type;
179typedef enum cgltf_component_type
181 cgltf_component_type_invalid,
182 cgltf_component_type_r_8,
183 cgltf_component_type_r_8u,
184 cgltf_component_type_r_16,
185 cgltf_component_type_r_16u,
186 cgltf_component_type_r_32u,
187 cgltf_component_type_r_32f,
188 cgltf_component_type_max_enum
189} cgltf_component_type;
191typedef enum cgltf_type
204typedef enum cgltf_primitive_type
206 cgltf_primitive_type_invalid,
207 cgltf_primitive_type_points,
208 cgltf_primitive_type_lines,
209 cgltf_primitive_type_line_loop,
210 cgltf_primitive_type_line_strip,
211 cgltf_primitive_type_triangles,
212 cgltf_primitive_type_triangle_strip,
213 cgltf_primitive_type_triangle_fan,
214 cgltf_primitive_type_max_enum
215} cgltf_primitive_type;
217typedef enum cgltf_alpha_mode
219 cgltf_alpha_mode_opaque,
220 cgltf_alpha_mode_mask,
221 cgltf_alpha_mode_blend,
222 cgltf_alpha_mode_max_enum
225typedef enum cgltf_animation_path_type {
226 cgltf_animation_path_type_invalid,
227 cgltf_animation_path_type_translation,
228 cgltf_animation_path_type_rotation,
229 cgltf_animation_path_type_scale,
230 cgltf_animation_path_type_weights,
231 cgltf_animation_path_type_max_enum
232} cgltf_animation_path_type;
234typedef enum cgltf_interpolation_type {
235 cgltf_interpolation_type_linear,
236 cgltf_interpolation_type_step,
237 cgltf_interpolation_type_cubic_spline,
238 cgltf_interpolation_type_max_enum
239} cgltf_interpolation_type;
241typedef enum cgltf_camera_type {
242 cgltf_camera_type_invalid,
243 cgltf_camera_type_perspective,
244 cgltf_camera_type_orthographic,
245 cgltf_camera_type_max_enum
248typedef enum cgltf_light_type {
249 cgltf_light_type_invalid,
250 cgltf_light_type_directional,
251 cgltf_light_type_point,
252 cgltf_light_type_spot,
253 cgltf_light_type_max_enum
256typedef enum cgltf_data_free_method {
257 cgltf_data_free_method_none,
258 cgltf_data_free_method_file_release,
259 cgltf_data_free_method_memory_free,
260 cgltf_data_free_method_max_enum
261} cgltf_data_free_method;
264 cgltf_size start_offset;
265 cgltf_size end_offset;
281 cgltf_data_free_method data_free_method;
283 cgltf_size extensions_count;
287typedef enum cgltf_meshopt_compression_mode {
288 cgltf_meshopt_compression_mode_invalid,
289 cgltf_meshopt_compression_mode_attributes,
290 cgltf_meshopt_compression_mode_triangles,
291 cgltf_meshopt_compression_mode_indices,
292 cgltf_meshopt_compression_mode_max_enum
293} cgltf_meshopt_compression_mode;
295typedef enum cgltf_meshopt_compression_filter {
296 cgltf_meshopt_compression_filter_none,
297 cgltf_meshopt_compression_filter_octahedral,
298 cgltf_meshopt_compression_filter_quaternion,
299 cgltf_meshopt_compression_filter_exponential,
300 cgltf_meshopt_compression_filter_max_enum
301} cgltf_meshopt_compression_filter;
310 cgltf_meshopt_compression_mode mode;
311 cgltf_meshopt_compression_filter filter;
321 cgltf_buffer_view_type type;
323 cgltf_bool has_meshopt_compression;
326 cgltf_size extensions_count;
334 cgltf_size indices_byte_offset;
335 cgltf_component_type indices_component_type;
337 cgltf_size values_byte_offset;
343 cgltf_component_type component_type;
344 cgltf_bool normalized;
354 cgltf_bool is_sparse;
357 cgltf_size extensions_count;
364 cgltf_attribute_type type;
376 cgltf_size extensions_count;
383 cgltf_int mag_filter;
384 cgltf_int min_filter;
388 cgltf_size extensions_count;
397 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;
429 cgltf_float base_color_factor[4];
430 cgltf_float metallic_factor;
431 cgltf_float roughness_factor;
439 cgltf_float diffuse_factor[4];
440 cgltf_float specular_factor[3];
441 cgltf_float glossiness_factor;
450 cgltf_float clearcoat_factor;
451 cgltf_float clearcoat_roughness_factor;
457 cgltf_float transmission_factor;
469 cgltf_float specular_color_factor[3];
470 cgltf_float specular_factor;
476 cgltf_float thickness_factor;
477 cgltf_float attenuation_color[3];
478 cgltf_float attenuation_distance;
484 cgltf_float sheen_color_factor[3];
486 cgltf_float sheen_roughness_factor;
491 cgltf_float emissive_strength;
496 cgltf_float iridescence_factor;
498 cgltf_float iridescence_ior;
499 cgltf_float iridescence_thickness_min;
500 cgltf_float iridescence_thickness_max;
506 cgltf_float anisotropy_strength;
507 cgltf_float anisotropy_rotation;
513 cgltf_float dispersion;
519 cgltf_bool has_pbr_metallic_roughness;
520 cgltf_bool has_pbr_specular_glossiness;
521 cgltf_bool has_clearcoat;
522 cgltf_bool has_transmission;
523 cgltf_bool has_volume;
525 cgltf_bool has_specular;
526 cgltf_bool has_sheen;
527 cgltf_bool has_emissive_strength;
528 cgltf_bool has_iridescence;
529 cgltf_bool has_anisotropy;
530 cgltf_bool has_dispersion;
546 cgltf_float emissive_factor[3];
547 cgltf_alpha_mode alpha_mode;
548 cgltf_float alpha_cutoff;
549 cgltf_bool double_sided;
552 cgltf_size extensions_count;
565 cgltf_size attributes_count;
571 cgltf_size attributes_count;
576 cgltf_size attributes_count;
580 cgltf_primitive_type type;
584 cgltf_size attributes_count;
586 cgltf_size targets_count;
588 cgltf_bool has_draco_mesh_compression;
591 cgltf_size mappings_count;
592 cgltf_size extensions_count;
599 cgltf_size primitives_count;
600 cgltf_float* weights;
601 cgltf_size weights_count;
603 cgltf_size target_names_count;
605 cgltf_size extensions_count;
614 cgltf_size joints_count;
618 cgltf_size extensions_count;
623 cgltf_bool has_aspect_ratio;
624 cgltf_float aspect_ratio;
642 cgltf_camera_type type;
648 cgltf_size extensions_count;
654 cgltf_float color[3];
655 cgltf_float intensity;
656 cgltf_light_type type;
658 cgltf_float spot_inner_cone_angle;
659 cgltf_float spot_outer_cone_angle;
667 cgltf_size children_count;
672 cgltf_float* weights;
673 cgltf_size weights_count;
674 cgltf_bool has_translation;
675 cgltf_bool has_rotation;
676 cgltf_bool has_scale;
677 cgltf_bool has_matrix;
678 cgltf_float translation[3];
679 cgltf_float rotation[4];
680 cgltf_float scale[3];
681 cgltf_float matrix[16];
683 cgltf_bool has_mesh_gpu_instancing;
685 cgltf_size extensions_count;
692 cgltf_size nodes_count;
694 cgltf_size extensions_count;
701 cgltf_interpolation_type interpolation;
703 cgltf_size extensions_count;
710 cgltf_animation_path_type target_path;
712 cgltf_size extensions_count;
719 cgltf_size samplers_count;
721 cgltf_size channels_count;
723 cgltf_size extensions_count;
739 cgltf_size extensions_count;
745 cgltf_file_type file_type;
751 cgltf_size meshes_count;
754 cgltf_size materials_count;
757 cgltf_size accessors_count;
760 cgltf_size buffer_views_count;
763 cgltf_size buffers_count;
766 cgltf_size images_count;
769 cgltf_size textures_count;
772 cgltf_size samplers_count;
775 cgltf_size skins_count;
778 cgltf_size cameras_count;
781 cgltf_size lights_count;
784 cgltf_size nodes_count;
787 cgltf_size scenes_count;
792 cgltf_size animations_count;
795 cgltf_size variants_count;
799 cgltf_size data_extensions_count;
802 char** extensions_used;
803 cgltf_size extensions_used_count;
805 char** extensions_required;
806 cgltf_size extensions_required_count;
809 cgltf_size json_size;
818cgltf_result cgltf_parse(
824cgltf_result cgltf_parse_file(
829cgltf_result cgltf_load_buffers(
832 const char* gltf_path);
834cgltf_result cgltf_load_buffer_base64(
const cgltf_options* options, cgltf_size size,
const char* base64,
void** out_data);
836cgltf_size cgltf_decode_string(
char*
string);
837cgltf_size cgltf_decode_uri(
char* uri);
843void cgltf_node_transform_local(
const cgltf_node* node, cgltf_float* out_matrix);
844void cgltf_node_transform_world(
const cgltf_node* node, cgltf_float* out_matrix);
848cgltf_bool cgltf_accessor_read_float(
const cgltf_accessor* accessor, cgltf_size index, cgltf_float* out, cgltf_size element_size);
849cgltf_bool cgltf_accessor_read_uint(
const cgltf_accessor* accessor, cgltf_size index, cgltf_uint* out, cgltf_size element_size);
850cgltf_size cgltf_accessor_read_index(
const cgltf_accessor* accessor, cgltf_size index);
852cgltf_size cgltf_num_components(cgltf_type type);
853cgltf_size cgltf_component_size(cgltf_component_type component_type);
854cgltf_size cgltf_calc_size(cgltf_type type, cgltf_component_type component_type);
856cgltf_size cgltf_accessor_unpack_floats(
const cgltf_accessor* accessor, cgltf_float* out, cgltf_size float_count);
857cgltf_size cgltf_accessor_unpack_indices(
const cgltf_accessor* accessor,
void* out, cgltf_size out_component_size, cgltf_size index_count);
860cgltf_result cgltf_copy_extras_json(
const cgltf_data* data,
const cgltf_extras* extras,
char* dest, cgltf_size* dest_size);
892#if defined(__INTELLISENSE__) || defined(__JETBRAINS_IDE__)
894#define CGLTF_IMPLEMENTATION
897#ifdef CGLTF_IMPLEMENTATION
905#if !defined(CGLTF_MALLOC) || !defined(CGLTF_FREE) || !defined(CGLTF_ATOI) || !defined(CGLTF_ATOF) || !defined(CGLTF_ATOLL)
910#define JSMN_PARENT_LINKS
929 JSMN_ERROR_NOMEM = -1,
931 JSMN_ERROR_INVAL = -2,
940#ifdef JSMN_PARENT_LINKS
946 unsigned int toknext;
949static void jsmn_init(jsmn_parser *parser);
950static int jsmn_parse(jsmn_parser *parser,
const char *js,
size_t len, jsmntok_t *tokens,
size_t num_tokens);
957#define GlbHeaderSize 12
958#define GlbChunkHeaderSize 8
959static const uint32_t GlbVersion = 2;
960static const uint32_t GlbMagic = 0x46546C67;
961static const uint32_t GlbMagicJsonChunk = 0x4E4F534A;
962static const uint32_t GlbMagicBinChunk = 0x004E4942;
967#define CGLTF_MALLOC(size) malloc(size)
970#define CGLTF_FREE(ptr) free(ptr)
973#define CGLTF_ATOI(str) atoi(str)
976#define CGLTF_ATOF(str) atof(str)
979#define CGLTF_ATOLL(str) atoll(str)
981#ifndef CGLTF_VALIDATE_ENABLE_ASSERTS
982#define CGLTF_VALIDATE_ENABLE_ASSERTS 0
985static void* cgltf_default_alloc(
void* user, cgltf_size size)
988 return CGLTF_MALLOC(size);
991static void cgltf_default_free(
void* user,
void* ptr)
997static void* cgltf_calloc(
cgltf_options* options,
size_t element_size, cgltf_size count)
999 if (SIZE_MAX / element_size < count)
1003 void* result = options->memory.alloc_func(options->memory.user_data, element_size * count);
1008 memset(result, 0, element_size * count);
1012static 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)
1015 void* (*memory_alloc)(
void*, cgltf_size) = memory_options->alloc_func ? memory_options->alloc_func : &cgltf_default_alloc;
1016 void (*memory_free)(
void*,
void*) = memory_options->free_func ? memory_options->free_func : &cgltf_default_free;
1018 FILE* file = fopen(path,
"rb");
1021 return cgltf_result_file_not_found;
1024 cgltf_size file_size = size ? *size : 0;
1028 fseek(file, 0, SEEK_END);
1031 __int64 length = _ftelli64(file);
1033 long length = ftell(file);
1039 return cgltf_result_io_error;
1042 fseek(file, 0, SEEK_SET);
1043 file_size = (cgltf_size)length;
1046 char* file_data = (
char*)memory_alloc(memory_options->user_data, file_size);
1050 return cgltf_result_out_of_memory;
1053 cgltf_size read_size = fread(file_data, 1, file_size, file);
1057 if (read_size != file_size)
1059 memory_free(memory_options->user_data, file_data);
1060 return cgltf_result_io_error;
1072 return cgltf_result_success;
1078 void (*memfree)(
void*,
void*) = memory_options->free_func ? memory_options->free_func : &cgltf_default_free;
1079 memfree(memory_options->user_data, data);
1082static cgltf_result cgltf_parse_json(
cgltf_options* options,
const uint8_t* json_chunk, cgltf_size size,
cgltf_data** out_data);
1084cgltf_result cgltf_parse(
const cgltf_options* options,
const void* data, cgltf_size size,
cgltf_data** out_data)
1086 if (size < GlbHeaderSize)
1088 return cgltf_result_data_too_short;
1091 if (options == NULL)
1093 return cgltf_result_invalid_options;
1097 if (fixed_options.memory.alloc_func == NULL)
1099 fixed_options.memory.alloc_func = &cgltf_default_alloc;
1101 if (fixed_options.memory.free_func == NULL)
1103 fixed_options.memory.free_func = &cgltf_default_free;
1108 memcpy(&tmp, data, 4);
1109 if (tmp != GlbMagic)
1111 if (fixed_options.type == cgltf_file_type_invalid)
1113 fixed_options.type = cgltf_file_type_gltf;
1115 else if (fixed_options.type == cgltf_file_type_glb)
1117 return cgltf_result_unknown_format;
1121 if (fixed_options.type == cgltf_file_type_gltf)
1123 cgltf_result json_result = cgltf_parse_json(&fixed_options, (
const uint8_t*)data, size, out_data);
1124 if (json_result != cgltf_result_success)
1129 (*out_data)->file_type = cgltf_file_type_gltf;
1131 return cgltf_result_success;
1134 const uint8_t* ptr = (
const uint8_t*)data;
1136 memcpy(&tmp, ptr + 4, 4);
1137 uint32_t version = tmp;
1138 if (version != GlbVersion)
1140 return version < GlbVersion ? cgltf_result_legacy_gltf : cgltf_result_unknown_format;
1144 memcpy(&tmp, ptr + 8, 4);
1147 return cgltf_result_data_too_short;
1150 const uint8_t* json_chunk = ptr + GlbHeaderSize;
1152 if (GlbHeaderSize + GlbChunkHeaderSize > size)
1154 return cgltf_result_data_too_short;
1158 uint32_t json_length;
1159 memcpy(&json_length, json_chunk, 4);
1160 if (json_length > size - GlbHeaderSize - GlbChunkHeaderSize)
1162 return cgltf_result_data_too_short;
1166 memcpy(&tmp, json_chunk + 4, 4);
1167 if (tmp != GlbMagicJsonChunk)
1169 return cgltf_result_unknown_format;
1172 json_chunk += GlbChunkHeaderSize;
1174 const void* bin = NULL;
1175 cgltf_size bin_size = 0;
1177 if (GlbChunkHeaderSize <= size - GlbHeaderSize - GlbChunkHeaderSize - json_length)
1180 const uint8_t* bin_chunk = json_chunk + json_length;
1183 uint32_t bin_length;
1184 memcpy(&bin_length, bin_chunk, 4);
1185 if (bin_length > size - GlbHeaderSize - GlbChunkHeaderSize - json_length - GlbChunkHeaderSize)
1187 return cgltf_result_data_too_short;
1191 memcpy(&tmp, bin_chunk + 4, 4);
1192 if (tmp != GlbMagicBinChunk)
1194 return cgltf_result_unknown_format;
1197 bin_chunk += GlbChunkHeaderSize;
1200 bin_size = bin_length;
1203 cgltf_result json_result = cgltf_parse_json(&fixed_options, json_chunk, json_length, out_data);
1204 if (json_result != cgltf_result_success)
1209 (*out_data)->file_type = cgltf_file_type_glb;
1210 (*out_data)->bin = bin;
1211 (*out_data)->bin_size = bin_size;
1213 return cgltf_result_success;
1218 if (options == NULL)
1220 return cgltf_result_invalid_options;
1223 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;
1226 void* file_data = NULL;
1227 cgltf_size file_size = 0;
1228 cgltf_result result = file_read(&options->memory, &options->file, path, &file_size, &file_data);
1229 if (result != cgltf_result_success)
1234 result = cgltf_parse(options, file_data, file_size, out_data);
1236 if (result != cgltf_result_success)
1238 file_release(&options->memory, &options->file, file_data);
1242 (*out_data)->file_data = file_data;
1244 return cgltf_result_success;
1247static void cgltf_combine_paths(
char* path,
const char* base,
const char* uri)
1249 const char* s0 = strrchr(base,
'/');
1250 const char* s1 = strrchr(base,
'\\');
1251 const char* slash = s0 ? (s1 && s1 > s0 ? s1 : s0) : s1;
1255 size_t prefix = slash - base + 1;
1257 strncpy(path, base, prefix);
1258 strcpy(path + prefix, uri);
1266static cgltf_result cgltf_load_buffer_file(
const cgltf_options* options, cgltf_size size,
const char* uri,
const char* gltf_path,
void** out_data)
1268 void* (*memory_alloc)(
void*, cgltf_size) = options->memory.alloc_func ? options->memory.alloc_func : &cgltf_default_alloc;
1269 void (*memory_free)(
void*,
void*) = options->memory.free_func ? options->memory.free_func : &cgltf_default_free;
1270 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;
1272 char* path = (
char*)memory_alloc(options->memory.user_data, strlen(uri) + strlen(gltf_path) + 1);
1275 return cgltf_result_out_of_memory;
1278 cgltf_combine_paths(path, gltf_path, uri);
1281 cgltf_decode_uri(path + strlen(path) - strlen(uri));
1283 void* file_data = NULL;
1284 cgltf_result result = file_read(&options->memory, &options->file, path, &size, &file_data);
1286 memory_free(options->memory.user_data, path);
1288 *out_data = (result == cgltf_result_success) ? file_data : NULL;
1293cgltf_result cgltf_load_buffer_base64(
const cgltf_options* options, cgltf_size size,
const char* base64,
void** out_data)
1295 void* (*memory_alloc)(
void*, cgltf_size) = options->memory.alloc_func ? options->memory.alloc_func : &cgltf_default_alloc;
1296 void (*memory_free)(
void*,
void*) = options->memory.free_func ? options->memory.free_func : &cgltf_default_free;
1298 unsigned char* data = (
unsigned char*)memory_alloc(options->memory.user_data, size);
1301 return cgltf_result_out_of_memory;
1304 unsigned int buffer = 0;
1305 unsigned int buffer_bits = 0;
1307 for (cgltf_size i = 0; i < size; ++i)
1309 while (buffer_bits < 8)
1311 char ch = *base64++;
1314 (unsigned)(ch -
'A') < 26 ? (ch -
'A') :
1315 (unsigned)(ch -
'a') < 26 ? (ch -
'a') + 26 :
1316 (unsigned)(ch -
'0') < 10 ? (ch -
'0') + 52 :
1323 memory_free(options->memory.user_data, data);
1324 return cgltf_result_io_error;
1327 buffer = (buffer << 6) | index;
1331 data[i] = (
unsigned char)(buffer >> (buffer_bits - 8));
1337 return cgltf_result_success;
1340static int cgltf_unhex(
char ch)
1343 (
unsigned)(ch -
'0') < 10 ? (ch -
'0') :
1344 (unsigned)(ch -
'A') < 6 ? (ch -
'A') + 10 :
1345 (unsigned)(ch -
'a') < 6 ? (ch -
'a') + 10 :
1349cgltf_size cgltf_decode_string(
char*
string)
1351 char* read =
string + strcspn(
string,
"\\");
1354 return read - string;
1356 char* write = string;
1357 char* last = string;
1362 cgltf_size written = read - last;
1363 memmove(write, last, written);
1374 case '\"': *write++ =
'\"';
break;
1375 case '/': *write++ =
'/';
break;
1376 case '\\': *write++ =
'\\';
break;
1377 case 'b': *write++ =
'\b';
break;
1378 case 'f': *write++ =
'\f';
break;
1379 case 'r': *write++ =
'\r';
break;
1380 case 'n': *write++ =
'\n';
break;
1381 case 't': *write++ =
'\t';
break;
1386 for (cgltf_size i = 0; i < 4; ++i)
1388 character = (character << 4) + cgltf_unhex(*read++);
1391 if (character <= 0x7F)
1393 *write++ = character & 0xFF;
1395 else if (character <= 0x7FF)
1397 *write++ = 0xC0 | ((character >> 6) & 0xFF);
1398 *write++ = 0x80 | (character & 0x3F);
1402 *write++ = 0xE0 | ((character >> 12) & 0xFF);
1403 *write++ = 0x80 | ((character >> 6) & 0x3F);
1404 *write++ = 0x80 | (character & 0x3F);
1413 read += strcspn(read,
"\\");
1417 return write - string;
1420cgltf_size cgltf_decode_uri(
char* uri)
1429 int ch1 = cgltf_unhex(i[1]);
1433 int ch2 = cgltf_unhex(i[2]);
1437 *write++ = (char)(ch1 * 16 + ch2);
1453 if (options == NULL)
1455 return cgltf_result_invalid_options;
1458 if (data->buffers_count && data->buffers[0].data == NULL && data->buffers[0].uri == NULL && data->bin)
1460 if (data->bin_size < data->buffers[0].size)
1462 return cgltf_result_data_too_short;
1465 data->buffers[0].data = (
void*)data->bin;
1466 data->buffers[0].data_free_method = cgltf_data_free_method_none;
1469 for (cgltf_size i = 0; i < data->buffers_count; ++i)
1471 if (data->buffers[i].data)
1476 const char* uri = data->buffers[i].uri;
1483 if (strncmp(uri,
"data:", 5) == 0)
1485 const char* comma = strchr(uri,
',');
1487 if (comma && comma - uri >= 7 && strncmp(comma - 7,
";base64", 7) == 0)
1489 cgltf_result res = cgltf_load_buffer_base64(options, data->buffers[i].size, comma + 1, &data->buffers[i].data);
1490 data->buffers[i].data_free_method = cgltf_data_free_method_memory_free;
1492 if (res != cgltf_result_success)
1499 return cgltf_result_unknown_format;
1502 else if (strstr(uri,
"://") == NULL && gltf_path)
1504 cgltf_result res = cgltf_load_buffer_file(options, data->buffers[i].size, uri, gltf_path, &data->buffers[i].data);
1505 data->buffers[i].data_free_method = cgltf_data_free_method_file_release;
1507 if (res != cgltf_result_success)
1514 return cgltf_result_unknown_format;
1518 return cgltf_result_success;
1521static cgltf_size cgltf_calc_index_bound(
cgltf_buffer_view* buffer_view, cgltf_size offset, cgltf_component_type component_type, cgltf_size count)
1523 char* data = (
char*)buffer_view->buffer->data + offset + buffer_view->offset;
1524 cgltf_size bound = 0;
1526 switch (component_type)
1528 case cgltf_component_type_r_8u:
1529 for (
size_t i = 0; i < count; ++i)
1531 cgltf_size v = ((
unsigned char*)data)[i];
1532 bound = bound > v ? bound : v;
1536 case cgltf_component_type_r_16u:
1537 for (
size_t i = 0; i < count; ++i)
1539 cgltf_size v = ((
unsigned short*)data)[i];
1540 bound = bound > v ? bound : v;
1544 case cgltf_component_type_r_32u:
1545 for (
size_t i = 0; i < count; ++i)
1547 cgltf_size v = ((
unsigned int*)data)[i];
1548 bound = bound > v ? bound : v;
1559#if CGLTF_VALIDATE_ENABLE_ASSERTS
1560#define CGLTF_ASSERT_IF(cond, result) assert(!(cond)); if (cond) return result;
1562#define CGLTF_ASSERT_IF(cond, result) if (cond) return result;
1567 for (cgltf_size i = 0; i < data->accessors_count; ++i)
1571 CGLTF_ASSERT_IF(data->accessors[i].component_type == cgltf_component_type_invalid, cgltf_result_invalid_gltf);
1572 CGLTF_ASSERT_IF(data->accessors[i].type == cgltf_type_invalid, cgltf_result_invalid_gltf);
1574 cgltf_size element_size = cgltf_calc_size(accessor->type, accessor->component_type);
1576 if (accessor->buffer_view)
1578 cgltf_size req_size = accessor->offset + accessor->stride * (accessor->count - 1) + element_size;
1580 CGLTF_ASSERT_IF(accessor->buffer_view->size < req_size, cgltf_result_data_too_short);
1583 if (accessor->is_sparse)
1587 cgltf_size indices_component_size = cgltf_component_size(sparse->indices_component_type);
1588 cgltf_size indices_req_size = sparse->indices_byte_offset + indices_component_size * sparse->count;
1589 cgltf_size values_req_size = sparse->values_byte_offset + element_size * sparse->count;
1591 CGLTF_ASSERT_IF(sparse->indices_buffer_view->size < indices_req_size ||
1592 sparse->values_buffer_view->size < values_req_size, cgltf_result_data_too_short);
1594 CGLTF_ASSERT_IF(sparse->indices_component_type != cgltf_component_type_r_8u &&
1595 sparse->indices_component_type != cgltf_component_type_r_16u &&
1596 sparse->indices_component_type != cgltf_component_type_r_32u, cgltf_result_invalid_gltf);
1598 if (sparse->indices_buffer_view->buffer->data)
1600 cgltf_size index_bound = cgltf_calc_index_bound(sparse->indices_buffer_view, sparse->indices_byte_offset, sparse->indices_component_type, sparse->count);
1602 CGLTF_ASSERT_IF(index_bound >= accessor->count, cgltf_result_data_too_short);
1607 for (cgltf_size i = 0; i < data->buffer_views_count; ++i)
1609 cgltf_size req_size = data->buffer_views[i].offset + data->buffer_views[i].size;
1611 CGLTF_ASSERT_IF(data->buffer_views[i].buffer && data->buffer_views[i].buffer->size < req_size, cgltf_result_data_too_short);
1613 if (data->buffer_views[i].has_meshopt_compression)
1617 CGLTF_ASSERT_IF(mc->buffer == NULL || mc->buffer->size < mc->offset + mc->size, cgltf_result_data_too_short);
1619 CGLTF_ASSERT_IF(data->buffer_views[i].stride && mc->stride != data->buffer_views[i].stride, cgltf_result_invalid_gltf);
1621 CGLTF_ASSERT_IF(data->buffer_views[i].size != mc->stride * mc->count, cgltf_result_invalid_gltf);
1623 CGLTF_ASSERT_IF(mc->mode == cgltf_meshopt_compression_mode_invalid, cgltf_result_invalid_gltf);
1625 CGLTF_ASSERT_IF(mc->mode == cgltf_meshopt_compression_mode_attributes && !(mc->stride % 4 == 0 && mc->stride <= 256), cgltf_result_invalid_gltf);
1627 CGLTF_ASSERT_IF(mc->mode == cgltf_meshopt_compression_mode_triangles && mc->count % 3 != 0, cgltf_result_invalid_gltf);
1629 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);
1631 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);
1633 CGLTF_ASSERT_IF(mc->filter == cgltf_meshopt_compression_filter_octahedral && mc->stride != 4 && mc->stride != 8, cgltf_result_invalid_gltf);
1635 CGLTF_ASSERT_IF(mc->filter == cgltf_meshopt_compression_filter_quaternion && mc->stride != 8, cgltf_result_invalid_gltf);
1639 for (cgltf_size i = 0; i < data->meshes_count; ++i)
1641 if (data->meshes[i].weights)
1643 CGLTF_ASSERT_IF(data->meshes[i].primitives_count && data->meshes[i].primitives[0].targets_count != data->meshes[i].weights_count, cgltf_result_invalid_gltf);
1646 if (data->meshes[i].target_names)
1648 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);
1651 for (cgltf_size j = 0; j < data->meshes[i].primitives_count; ++j)
1653 CGLTF_ASSERT_IF(data->meshes[i].primitives[j].type == cgltf_primitive_type_invalid, cgltf_result_invalid_gltf);
1654 CGLTF_ASSERT_IF(data->meshes[i].primitives[j].targets_count != data->meshes[i].primitives[0].targets_count, cgltf_result_invalid_gltf);
1656 CGLTF_ASSERT_IF(data->meshes[i].primitives[j].attributes_count == 0, cgltf_result_invalid_gltf);
1658 cgltf_accessor* first = data->meshes[i].primitives[j].attributes[0].data;
1660 CGLTF_ASSERT_IF(first->count == 0, cgltf_result_invalid_gltf);
1662 for (cgltf_size k = 0; k < data->meshes[i].primitives[j].attributes_count; ++k)
1664 CGLTF_ASSERT_IF(data->meshes[i].primitives[j].attributes[k].data->count != first->count, cgltf_result_invalid_gltf);
1667 for (cgltf_size k = 0; k < data->meshes[i].primitives[j].targets_count; ++k)
1669 for (cgltf_size m = 0; m < data->meshes[i].primitives[j].targets[k].attributes_count; ++m)
1671 CGLTF_ASSERT_IF(data->meshes[i].primitives[j].targets[k].attributes[m].data->count != first->count, cgltf_result_invalid_gltf);
1677 CGLTF_ASSERT_IF(indices &&
1678 indices->component_type != cgltf_component_type_r_8u &&
1679 indices->component_type != cgltf_component_type_r_16u &&
1680 indices->component_type != cgltf_component_type_r_32u, cgltf_result_invalid_gltf);
1682 CGLTF_ASSERT_IF(indices && indices->type != cgltf_type_scalar, cgltf_result_invalid_gltf);
1683 CGLTF_ASSERT_IF(indices && indices->stride != cgltf_component_size(indices->component_type), cgltf_result_invalid_gltf);
1685 if (indices && indices->buffer_view && indices->buffer_view->buffer->data)
1687 cgltf_size index_bound = cgltf_calc_index_bound(indices->buffer_view, indices->offset, indices->component_type, indices->count);
1689 CGLTF_ASSERT_IF(index_bound >= first->count, cgltf_result_data_too_short);
1692 for (cgltf_size k = 0; k < data->meshes[i].primitives[j].mappings_count; ++k)
1694 CGLTF_ASSERT_IF(data->meshes[i].primitives[j].mappings[k].variant >= data->variants_count, cgltf_result_invalid_gltf);
1699 for (cgltf_size i = 0; i < data->nodes_count; ++i)
1701 if (data->nodes[i].weights && data->nodes[i].mesh)
1703 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);
1706 if (data->nodes[i].has_mesh_gpu_instancing)
1708 CGLTF_ASSERT_IF(data->nodes[i].mesh == NULL, cgltf_result_invalid_gltf);
1709 CGLTF_ASSERT_IF(data->nodes[i].mesh_gpu_instancing.attributes_count == 0, cgltf_result_invalid_gltf);
1711 cgltf_accessor* first = data->nodes[i].mesh_gpu_instancing.attributes[0].data;
1713 for (cgltf_size k = 0; k < data->nodes[i].mesh_gpu_instancing.attributes_count; ++k)
1715 CGLTF_ASSERT_IF(data->nodes[i].mesh_gpu_instancing.attributes[k].data->count != first->count, cgltf_result_invalid_gltf);
1720 for (cgltf_size i = 0; i < data->nodes_count; ++i)
1727 CGLTF_ASSERT_IF(p1 == p2, cgltf_result_invalid_gltf);
1730 p2 = p2->parent ? p2->parent->parent : NULL;
1734 for (cgltf_size i = 0; i < data->scenes_count; ++i)
1736 for (cgltf_size j = 0; j < data->scenes[i].nodes_count; ++j)
1738 CGLTF_ASSERT_IF(data->scenes[i].nodes[j]->parent, cgltf_result_invalid_gltf);
1742 for (cgltf_size i = 0; i < data->animations_count; ++i)
1744 for (cgltf_size j = 0; j < data->animations[i].channels_count; ++j)
1748 if (!channel->target_node)
1753 cgltf_size components = 1;
1755 if (channel->target_path == cgltf_animation_path_type_weights)
1757 CGLTF_ASSERT_IF(!channel->target_node->mesh || !channel->target_node->mesh->primitives_count, cgltf_result_invalid_gltf);
1759 components = channel->target_node->mesh->primitives[0].targets_count;
1762 cgltf_size values = channel->sampler->interpolation == cgltf_interpolation_type_cubic_spline ? 3 : 1;
1764 CGLTF_ASSERT_IF(channel->sampler->input->count * components * values != channel->sampler->output->count, cgltf_result_invalid_gltf);
1768 for (cgltf_size i = 0; i < data->variants_count; ++i)
1770 CGLTF_ASSERT_IF(!data->variants[i].name, cgltf_result_invalid_gltf);
1773 return cgltf_result_success;
1776cgltf_result cgltf_copy_extras_json(
const cgltf_data* data,
const cgltf_extras* extras,
char* dest, cgltf_size* dest_size)
1778 cgltf_size json_size = extras->end_offset - extras->start_offset;
1784 *dest_size = json_size + 1;
1785 return cgltf_result_success;
1787 return cgltf_result_invalid_options;
1790 if (*dest_size + 1 < json_size)
1792 strncpy(dest, data->json + extras->start_offset, *dest_size - 1);
1793 dest[*dest_size - 1] = 0;
1797 strncpy(dest, data->json + extras->start_offset, json_size);
1798 dest[json_size] = 0;
1801 return cgltf_result_success;
1806 data->memory.free_func(data->memory.user_data, extras->data);
1811 for (cgltf_size i = 0; i < extensions_count; ++i)
1813 data->memory.free_func(data->memory.user_data, extensions[i].name);
1814 data->memory.free_func(data->memory.user_data, extensions[i].data);
1816 data->memory.free_func(data->memory.user_data, extensions);
1828 data->memory.free_func(data->memory.user_data, data->asset.copyright);
1829 data->memory.free_func(data->memory.user_data, data->asset.generator);
1830 data->memory.free_func(data->memory.user_data, data->asset.version);
1831 data->memory.free_func(data->memory.user_data, data->asset.min_version);
1833 cgltf_free_extensions(data, data->asset.extensions, data->asset.extensions_count);
1834 cgltf_free_extras(data, &data->asset.extras);
1836 for (cgltf_size i = 0; i < data->accessors_count; ++i)
1838 data->memory.free_func(data->memory.user_data, data->accessors[i].name);
1840 cgltf_free_extensions(data, data->accessors[i].extensions, data->accessors[i].extensions_count);
1841 cgltf_free_extras(data, &data->accessors[i].extras);
1843 data->memory.free_func(data->memory.user_data, data->accessors);
1845 for (cgltf_size i = 0; i < data->buffer_views_count; ++i)
1847 data->memory.free_func(data->memory.user_data, data->buffer_views[i].name);
1848 data->memory.free_func(data->memory.user_data, data->buffer_views[i].data);
1850 cgltf_free_extensions(data, data->buffer_views[i].extensions, data->buffer_views[i].extensions_count);
1851 cgltf_free_extras(data, &data->buffer_views[i].extras);
1853 data->memory.free_func(data->memory.user_data, data->buffer_views);
1855 for (cgltf_size i = 0; i < data->buffers_count; ++i)
1857 data->memory.free_func(data->memory.user_data, data->buffers[i].name);
1859 if (data->buffers[i].data_free_method == cgltf_data_free_method_file_release)
1861 file_release(&data->memory, &data->file, data->buffers[i].data);
1863 else if (data->buffers[i].data_free_method == cgltf_data_free_method_memory_free)
1865 data->memory.free_func(data->memory.user_data, data->buffers[i].data);
1868 data->memory.free_func(data->memory.user_data, data->buffers[i].uri);
1870 cgltf_free_extensions(data, data->buffers[i].extensions, data->buffers[i].extensions_count);
1871 cgltf_free_extras(data, &data->buffers[i].extras);
1873 data->memory.free_func(data->memory.user_data, data->buffers);
1875 for (cgltf_size i = 0; i < data->meshes_count; ++i)
1877 data->memory.free_func(data->memory.user_data, data->meshes[i].name);
1879 for (cgltf_size j = 0; j < data->meshes[i].primitives_count; ++j)
1881 for (cgltf_size k = 0; k < data->meshes[i].primitives[j].attributes_count; ++k)
1883 data->memory.free_func(data->memory.user_data, data->meshes[i].primitives[j].attributes[k].name);
1886 data->memory.free_func(data->memory.user_data, data->meshes[i].primitives[j].attributes);
1888 for (cgltf_size k = 0; k < data->meshes[i].primitives[j].targets_count; ++k)
1890 for (cgltf_size m = 0; m < data->meshes[i].primitives[j].targets[k].attributes_count; ++m)
1892 data->memory.free_func(data->memory.user_data, data->meshes[i].primitives[j].targets[k].attributes[m].name);
1895 data->memory.free_func(data->memory.user_data, data->meshes[i].primitives[j].targets[k].attributes);
1898 data->memory.free_func(data->memory.user_data, data->meshes[i].primitives[j].targets);
1900 if (data->meshes[i].primitives[j].has_draco_mesh_compression)
1902 for (cgltf_size k = 0; k < data->meshes[i].primitives[j].draco_mesh_compression.attributes_count; ++k)
1904 data->memory.free_func(data->memory.user_data, data->meshes[i].primitives[j].draco_mesh_compression.attributes[k].name);
1907 data->memory.free_func(data->memory.user_data, data->meshes[i].primitives[j].draco_mesh_compression.attributes);
1910 for (cgltf_size k = 0; k < data->meshes[i].primitives[j].mappings_count; ++k)
1912 cgltf_free_extras(data, &data->meshes[i].primitives[j].mappings[k].extras);
1915 data->memory.free_func(data->memory.user_data, data->meshes[i].primitives[j].mappings);
1917 cgltf_free_extensions(data, data->meshes[i].primitives[j].extensions, data->meshes[i].primitives[j].extensions_count);
1918 cgltf_free_extras(data, &data->meshes[i].primitives[j].extras);
1921 data->memory.free_func(data->memory.user_data, data->meshes[i].primitives);
1922 data->memory.free_func(data->memory.user_data, data->meshes[i].weights);
1924 for (cgltf_size j = 0; j < data->meshes[i].target_names_count; ++j)
1926 data->memory.free_func(data->memory.user_data, data->meshes[i].target_names[j]);
1929 cgltf_free_extensions(data, data->meshes[i].extensions, data->meshes[i].extensions_count);
1930 cgltf_free_extras(data, &data->meshes[i].extras);
1932 data->memory.free_func(data->memory.user_data, data->meshes[i].target_names);
1935 data->memory.free_func(data->memory.user_data, data->meshes);
1937 for (cgltf_size i = 0; i < data->materials_count; ++i)
1939 data->memory.free_func(data->memory.user_data, data->materials[i].name);
1941 cgltf_free_extensions(data, data->materials[i].extensions, data->materials[i].extensions_count);
1942 cgltf_free_extras(data, &data->materials[i].extras);
1945 data->memory.free_func(data->memory.user_data, data->materials);
1947 for (cgltf_size i = 0; i < data->images_count; ++i)
1949 data->memory.free_func(data->memory.user_data, data->images[i].name);
1950 data->memory.free_func(data->memory.user_data, data->images[i].uri);
1951 data->memory.free_func(data->memory.user_data, data->images[i].mime_type);
1953 cgltf_free_extensions(data, data->images[i].extensions, data->images[i].extensions_count);
1954 cgltf_free_extras(data, &data->images[i].extras);
1957 data->memory.free_func(data->memory.user_data, data->images);
1959 for (cgltf_size i = 0; i < data->textures_count; ++i)
1961 data->memory.free_func(data->memory.user_data, data->textures[i].name);
1963 cgltf_free_extensions(data, data->textures[i].extensions, data->textures[i].extensions_count);
1964 cgltf_free_extras(data, &data->textures[i].extras);
1967 data->memory.free_func(data->memory.user_data, data->textures);
1969 for (cgltf_size i = 0; i < data->samplers_count; ++i)
1971 data->memory.free_func(data->memory.user_data, data->samplers[i].name);
1973 cgltf_free_extensions(data, data->samplers[i].extensions, data->samplers[i].extensions_count);
1974 cgltf_free_extras(data, &data->samplers[i].extras);
1977 data->memory.free_func(data->memory.user_data, data->samplers);
1979 for (cgltf_size i = 0; i < data->skins_count; ++i)
1981 data->memory.free_func(data->memory.user_data, data->skins[i].name);
1982 data->memory.free_func(data->memory.user_data, data->skins[i].joints);
1984 cgltf_free_extensions(data, data->skins[i].extensions, data->skins[i].extensions_count);
1985 cgltf_free_extras(data, &data->skins[i].extras);
1988 data->memory.free_func(data->memory.user_data, data->skins);
1990 for (cgltf_size i = 0; i < data->cameras_count; ++i)
1992 data->memory.free_func(data->memory.user_data, data->cameras[i].name);
1994 if (data->cameras[i].type == cgltf_camera_type_perspective)
1996 cgltf_free_extras(data, &data->cameras[i].data.perspective.extras);
1998 else if (data->cameras[i].type == cgltf_camera_type_orthographic)
2000 cgltf_free_extras(data, &data->cameras[i].data.orthographic.extras);
2003 cgltf_free_extensions(data, data->cameras[i].extensions, data->cameras[i].extensions_count);
2004 cgltf_free_extras(data, &data->cameras[i].extras);
2007 data->memory.free_func(data->memory.user_data, data->cameras);
2009 for (cgltf_size i = 0; i < data->lights_count; ++i)
2011 data->memory.free_func(data->memory.user_data, data->lights[i].name);
2013 cgltf_free_extras(data, &data->lights[i].extras);
2016 data->memory.free_func(data->memory.user_data, data->lights);
2018 for (cgltf_size i = 0; i < data->nodes_count; ++i)
2020 data->memory.free_func(data->memory.user_data, data->nodes[i].name);
2021 data->memory.free_func(data->memory.user_data, data->nodes[i].children);
2022 data->memory.free_func(data->memory.user_data, data->nodes[i].weights);
2024 if (data->nodes[i].has_mesh_gpu_instancing)
2026 for (cgltf_size j = 0; j < data->nodes[i].mesh_gpu_instancing.attributes_count; ++j)
2028 data->memory.free_func(data->memory.user_data, data->nodes[i].mesh_gpu_instancing.attributes[j].name);
2031 data->memory.free_func(data->memory.user_data, data->nodes[i].mesh_gpu_instancing.attributes);
2034 cgltf_free_extensions(data, data->nodes[i].extensions, data->nodes[i].extensions_count);
2035 cgltf_free_extras(data, &data->nodes[i].extras);
2038 data->memory.free_func(data->memory.user_data, data->nodes);
2040 for (cgltf_size i = 0; i < data->scenes_count; ++i)
2042 data->memory.free_func(data->memory.user_data, data->scenes[i].name);
2043 data->memory.free_func(data->memory.user_data, data->scenes[i].nodes);
2045 cgltf_free_extensions(data, data->scenes[i].extensions, data->scenes[i].extensions_count);
2046 cgltf_free_extras(data, &data->scenes[i].extras);
2049 data->memory.free_func(data->memory.user_data, data->scenes);
2051 for (cgltf_size i = 0; i < data->animations_count; ++i)
2053 data->memory.free_func(data->memory.user_data, data->animations[i].name);
2054 for (cgltf_size j = 0; j < data->animations[i].samplers_count; ++j)
2056 cgltf_free_extensions(data, data->animations[i].samplers[j].extensions, data->animations[i].samplers[j].extensions_count);
2057 cgltf_free_extras(data, &data->animations[i].samplers[j].extras);
2059 data->memory.free_func(data->memory.user_data, data->animations[i].samplers);
2061 for (cgltf_size j = 0; j < data->animations[i].channels_count; ++j)
2063 cgltf_free_extensions(data, data->animations[i].channels[j].extensions, data->animations[i].channels[j].extensions_count);
2064 cgltf_free_extras(data, &data->animations[i].channels[j].extras);
2066 data->memory.free_func(data->memory.user_data, data->animations[i].channels);
2068 cgltf_free_extensions(data, data->animations[i].extensions, data->animations[i].extensions_count);
2069 cgltf_free_extras(data, &data->animations[i].extras);
2072 data->memory.free_func(data->memory.user_data, data->animations);
2074 for (cgltf_size i = 0; i < data->variants_count; ++i)
2076 data->memory.free_func(data->memory.user_data, data->variants[i].name);
2078 cgltf_free_extras(data, &data->variants[i].extras);
2081 data->memory.free_func(data->memory.user_data, data->variants);
2083 cgltf_free_extensions(data, data->data_extensions, data->data_extensions_count);
2084 cgltf_free_extras(data, &data->extras);
2086 for (cgltf_size i = 0; i < data->extensions_used_count; ++i)
2088 data->memory.free_func(data->memory.user_data, data->extensions_used[i]);
2091 data->memory.free_func(data->memory.user_data, data->extensions_used);
2093 for (cgltf_size i = 0; i < data->extensions_required_count; ++i)
2095 data->memory.free_func(data->memory.user_data, data->extensions_required[i]);
2098 data->memory.free_func(data->memory.user_data, data->extensions_required);
2100 file_release(&data->memory, &data->file, data->file_data);
2102 data->memory.free_func(data->memory.user_data, data);
2105void cgltf_node_transform_local(
const cgltf_node* node, cgltf_float* out_matrix)
2107 cgltf_float* lm = out_matrix;
2109 if (node->has_matrix)
2111 memcpy(lm, node->matrix,
sizeof(
float) * 16);
2115 float tx = node->translation[0];
2116 float ty = node->translation[1];
2117 float tz = node->translation[2];
2119 float qx = node->rotation[0];
2120 float qy = node->rotation[1];
2121 float qz = node->rotation[2];
2122 float qw = node->rotation[3];
2124 float sx = node->scale[0];
2125 float sy = node->scale[1];
2126 float sz = node->scale[2];
2128 lm[0] = (1 - 2 * qy*qy - 2 * qz*qz) * sx;
2129 lm[1] = (2 * qx*qy + 2 * qz*qw) * sx;
2130 lm[2] = (2 * qx*qz - 2 * qy*qw) * sx;
2133 lm[4] = (2 * qx*qy - 2 * qz*qw) * sy;
2134 lm[5] = (1 - 2 * qx*qx - 2 * qz*qz) * sy;
2135 lm[6] = (2 * qy*qz + 2 * qx*qw) * sy;
2138 lm[8] = (2 * qx*qz + 2 * qy*qw) * sz;
2139 lm[9] = (2 * qy*qz - 2 * qx*qw) * sz;
2140 lm[10] = (1 - 2 * qx*qx - 2 * qy*qy) * sz;
2150void cgltf_node_transform_world(
const cgltf_node* node, cgltf_float* out_matrix)
2152 cgltf_float* lm = out_matrix;
2153 cgltf_node_transform_local(node, lm);
2160 cgltf_node_transform_local(parent, pm);
2162 for (
int i = 0; i < 4; ++i)
2164 float l0 = lm[i * 4 + 0];
2165 float l1 = lm[i * 4 + 1];
2166 float l2 = lm[i * 4 + 2];
2168 float r0 = l0 * pm[0] + l1 * pm[4] + l2 * pm[8];
2169 float r1 = l0 * pm[1] + l1 * pm[5] + l2 * pm[9];
2170 float r2 = l0 * pm[2] + l1 * pm[6] + l2 * pm[10];
2181 parent = parent->parent;
2185static cgltf_ssize cgltf_component_read_integer(
const void* in, cgltf_component_type component_type)
2187 switch (component_type)
2189 case cgltf_component_type_r_16:
2190 return *((
const int16_t*) in);
2191 case cgltf_component_type_r_16u:
2192 return *((
const uint16_t*) in);
2193 case cgltf_component_type_r_32u:
2194 return *((
const uint32_t*) in);
2195 case cgltf_component_type_r_8:
2196 return *((
const int8_t*) in);
2197 case cgltf_component_type_r_8u:
2198 return *((
const uint8_t*) in);
2204static cgltf_size cgltf_component_read_index(
const void* in, cgltf_component_type component_type)
2206 switch (component_type)
2208 case cgltf_component_type_r_16u:
2209 return *((
const uint16_t*) in);
2210 case cgltf_component_type_r_32u:
2211 return *((
const uint32_t*) in);
2212 case cgltf_component_type_r_8u:
2213 return *((
const uint8_t*) in);
2219static cgltf_float cgltf_component_read_float(
const void* in, cgltf_component_type component_type, cgltf_bool normalized)
2221 if (component_type == cgltf_component_type_r_32f)
2223 return *((
const float*) in);
2228 switch (component_type)
2231 case cgltf_component_type_r_16:
2232 return *((
const int16_t*) in) / (cgltf_float)32767;
2233 case cgltf_component_type_r_16u:
2234 return *((
const uint16_t*) in) / (cgltf_float)65535;
2235 case cgltf_component_type_r_8:
2236 return *((
const int8_t*) in) / (cgltf_float)127;
2237 case cgltf_component_type_r_8u:
2238 return *((
const uint8_t*) in) / (cgltf_float)255;
2244 return (cgltf_float)cgltf_component_read_integer(in, component_type);
2247static 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)
2249 cgltf_size num_components = cgltf_num_components(type);
2251 if (element_size < num_components) {
2257 cgltf_size component_size = cgltf_component_size(component_type);
2259 if (type == cgltf_type_mat2 && component_size == 1)
2261 out[0] = cgltf_component_read_float(element, component_type, normalized);
2262 out[1] = cgltf_component_read_float(element + 1, component_type, normalized);
2263 out[2] = cgltf_component_read_float(element + 4, component_type, normalized);
2264 out[3] = cgltf_component_read_float(element + 5, component_type, normalized);
2268 if (type == cgltf_type_mat3 && component_size == 1)
2270 out[0] = cgltf_component_read_float(element, component_type, normalized);
2271 out[1] = cgltf_component_read_float(element + 1, component_type, normalized);
2272 out[2] = cgltf_component_read_float(element + 2, component_type, normalized);
2273 out[3] = cgltf_component_read_float(element + 4, component_type, normalized);
2274 out[4] = cgltf_component_read_float(element + 5, component_type, normalized);
2275 out[5] = cgltf_component_read_float(element + 6, component_type, normalized);
2276 out[6] = cgltf_component_read_float(element + 8, component_type, normalized);
2277 out[7] = cgltf_component_read_float(element + 9, component_type, normalized);
2278 out[8] = cgltf_component_read_float(element + 10, component_type, normalized);
2282 if (type == cgltf_type_mat3 && component_size == 2)
2284 out[0] = cgltf_component_read_float(element, component_type, normalized);
2285 out[1] = cgltf_component_read_float(element + 2, component_type, normalized);
2286 out[2] = cgltf_component_read_float(element + 4, component_type, normalized);
2287 out[3] = cgltf_component_read_float(element + 8, component_type, normalized);
2288 out[4] = cgltf_component_read_float(element + 10, component_type, normalized);
2289 out[5] = cgltf_component_read_float(element + 12, component_type, normalized);
2290 out[6] = cgltf_component_read_float(element + 16, component_type, normalized);
2291 out[7] = cgltf_component_read_float(element + 18, component_type, normalized);
2292 out[8] = cgltf_component_read_float(element + 20, component_type, normalized);
2296 for (cgltf_size i = 0; i < num_components; ++i)
2298 out[i] = cgltf_component_read_float(element + component_size * i, component_type, normalized);
2306 return (
const uint8_t*)view->data;
2308 if (!view->buffer->data)
2311 const uint8_t* result = (
const uint8_t*)view->buffer->data;
2312 result += view->offset;
2316cgltf_bool cgltf_accessor_read_float(
const cgltf_accessor* accessor, cgltf_size index, cgltf_float* out, cgltf_size element_size)
2318 if (accessor->is_sparse)
2322 if (accessor->buffer_view == NULL)
2324 memset(out, 0, element_size *
sizeof(cgltf_float));
2327 const uint8_t* element = cgltf_buffer_view_data(accessor->buffer_view);
2328 if (element == NULL)
2332 element += accessor->offset + accessor->stride * index;
2333 return cgltf_element_read_float(element, accessor->type, accessor->component_type, accessor->normalized, out, element_size);
2336cgltf_size cgltf_accessor_unpack_floats(
const cgltf_accessor* accessor, cgltf_float* out, cgltf_size float_count)
2338 cgltf_size floats_per_element = cgltf_num_components(accessor->type);
2339 cgltf_size available_floats = accessor->count * floats_per_element;
2342 return available_floats;
2345 float_count = available_floats < float_count ? available_floats : float_count;
2346 cgltf_size element_count = float_count / floats_per_element;
2349 if (accessor->buffer_view == NULL)
2351 memset(out, 0, element_count * floats_per_element *
sizeof(cgltf_float));
2355 const uint8_t* element = cgltf_buffer_view_data(accessor->buffer_view);
2356 if (element == NULL)
2360 element += accessor->offset;
2362 if (accessor->component_type == cgltf_component_type_r_32f && accessor->stride == floats_per_element *
sizeof(cgltf_float))
2364 memcpy(out, element, element_count * floats_per_element *
sizeof(cgltf_float));
2368 cgltf_float* dest = out;
2370 for (cgltf_size index = 0; index < element_count; index++, dest += floats_per_element, element += accessor->stride)
2372 if (!cgltf_element_read_float(element, accessor->type, accessor->component_type, accessor->normalized, dest, floats_per_element))
2381 if (accessor->is_sparse)
2385 const uint8_t* index_data = cgltf_buffer_view_data(sparse->indices_buffer_view);
2386 const uint8_t* reader_head = cgltf_buffer_view_data(sparse->values_buffer_view);
2388 if (index_data == NULL || reader_head == NULL)
2393 index_data += sparse->indices_byte_offset;
2394 reader_head += sparse->values_byte_offset;
2396 cgltf_size index_stride = cgltf_component_size(sparse->indices_component_type);
2397 for (cgltf_size reader_index = 0; reader_index < sparse->count; reader_index++, index_data += index_stride, reader_head += accessor->stride)
2399 size_t writer_index = cgltf_component_read_index(index_data, sparse->indices_component_type);
2400 float* writer_head = out + writer_index * floats_per_element;
2402 if (!cgltf_element_read_float(reader_head, accessor->type, accessor->component_type, accessor->normalized, writer_head, floats_per_element))
2409 return element_count * floats_per_element;
2412static cgltf_uint cgltf_component_read_uint(
const void* in, cgltf_component_type component_type)
2414 switch (component_type)
2416 case cgltf_component_type_r_8:
2417 return *((
const int8_t*) in);
2419 case cgltf_component_type_r_8u:
2420 return *((
const uint8_t*) in);
2422 case cgltf_component_type_r_16:
2423 return *((
const int16_t*) in);
2425 case cgltf_component_type_r_16u:
2426 return *((
const uint16_t*) in);
2428 case cgltf_component_type_r_32u:
2429 return *((
const uint32_t*) in);
2436static 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)
2438 cgltf_size num_components = cgltf_num_components(type);
2440 if (element_size < num_components)
2446 if (type == cgltf_type_mat2 || type == cgltf_type_mat3 || type == cgltf_type_mat4)
2451 cgltf_size component_size = cgltf_component_size(component_type);
2453 for (cgltf_size i = 0; i < num_components; ++i)
2455 out[i] = cgltf_component_read_uint(element + component_size * i, component_type);
2460cgltf_bool cgltf_accessor_read_uint(
const cgltf_accessor* accessor, cgltf_size index, cgltf_uint* out, cgltf_size element_size)
2462 if (accessor->is_sparse)
2466 if (accessor->buffer_view == NULL)
2468 memset(out, 0, element_size *
sizeof( cgltf_uint ));
2471 const uint8_t* element = cgltf_buffer_view_data(accessor->buffer_view);
2472 if (element == NULL)
2476 element += accessor->offset + accessor->stride * index;
2477 return cgltf_element_read_uint(element, accessor->type, accessor->component_type, out, element_size);
2480cgltf_size cgltf_accessor_read_index(
const cgltf_accessor* accessor, cgltf_size index)
2482 if (accessor->is_sparse)
2486 if (accessor->buffer_view == NULL)
2490 const uint8_t* element = cgltf_buffer_view_data(accessor->buffer_view);
2491 if (element == NULL)
2495 element += accessor->offset + accessor->stride * index;
2496 return cgltf_component_read_index(element, accessor->component_type);
2501 assert(
object && (cgltf_size)(
object - data->meshes) < data->meshes_count);
2502 return (cgltf_size)(
object - data->meshes);
2507 assert(
object && (cgltf_size)(
object - data->materials) < data->materials_count);
2508 return (cgltf_size)(
object - data->materials);
2513 assert(
object && (cgltf_size)(
object - data->accessors) < data->accessors_count);
2514 return (cgltf_size)(
object - data->accessors);
2519 assert(
object && (cgltf_size)(
object - data->buffer_views) < data->buffer_views_count);
2520 return (cgltf_size)(
object - data->buffer_views);
2525 assert(
object && (cgltf_size)(
object - data->buffers) < data->buffers_count);
2526 return (cgltf_size)(
object - data->buffers);
2531 assert(
object && (cgltf_size)(
object - data->images) < data->images_count);
2532 return (cgltf_size)(
object - data->images);
2537 assert(
object && (cgltf_size)(
object - data->textures) < data->textures_count);
2538 return (cgltf_size)(
object - data->textures);
2543 assert(
object && (cgltf_size)(
object - data->samplers) < data->samplers_count);
2544 return (cgltf_size)(
object - data->samplers);
2549 assert(
object && (cgltf_size)(
object - data->skins) < data->skins_count);
2550 return (cgltf_size)(
object - data->skins);
2555 assert(
object && (cgltf_size)(
object - data->cameras) < data->cameras_count);
2556 return (cgltf_size)(
object - data->cameras);
2561 assert(
object && (cgltf_size)(
object - data->lights) < data->lights_count);
2562 return (cgltf_size)(
object - data->lights);
2567 assert(
object && (cgltf_size)(
object - data->nodes) < data->nodes_count);
2568 return (cgltf_size)(
object - data->nodes);
2573 assert(
object && (cgltf_size)(
object - data->scenes) < data->scenes_count);
2574 return (cgltf_size)(
object - data->scenes);
2579 assert(
object && (cgltf_size)(
object - data->animations) < data->animations_count);
2580 return (cgltf_size)(
object - data->animations);
2585 assert(
object && (cgltf_size)(
object - animation->samplers) < animation->samplers_count);
2586 return (cgltf_size)(
object - animation->samplers);
2591 assert(
object && (cgltf_size)(
object - animation->channels) < animation->channels_count);
2592 return (cgltf_size)(
object - animation->channels);
2595cgltf_size cgltf_accessor_unpack_indices(
const cgltf_accessor* accessor,
void* out, cgltf_size out_component_size, cgltf_size index_count)
2599 return accessor->count;
2602 index_count = accessor->count < index_count ? accessor->count : index_count;
2603 cgltf_size index_component_size = cgltf_component_size(accessor->component_type);
2605 if (accessor->is_sparse)
2609 if (accessor->buffer_view == NULL)
2613 if (index_component_size > out_component_size)
2617 const uint8_t* element = cgltf_buffer_view_data(accessor->buffer_view);
2618 if (element == NULL)
2622 element += accessor->offset;
2624 if (index_component_size == out_component_size && accessor->stride == out_component_size)
2626 memcpy(out, element, index_count * index_component_size);
2631 switch (out_component_size)
2634 for (cgltf_size index = 0; index < index_count; index++, element += accessor->stride)
2636 ((uint16_t*)out)[index] = (uint16_t)cgltf_component_read_index(element, accessor->component_type);
2640 for (cgltf_size index = 0; index < index_count; index++, element += accessor->stride)
2642 ((uint32_t*)out)[index] = (uint32_t)cgltf_component_read_index(element, accessor->component_type);
2652#define CGLTF_ERROR_JSON -1
2653#define CGLTF_ERROR_NOMEM -2
2654#define CGLTF_ERROR_LEGACY -3
2656#define CGLTF_CHECK_TOKTYPE(tok_, type_) if ((tok_).type != (type_)) { return CGLTF_ERROR_JSON; }
2657#define CGLTF_CHECK_TOKTYPE_RET(tok_, type_, ret_) if ((tok_).type != (type_)) { return ret_; }
2658#define CGLTF_CHECK_KEY(tok_) if ((tok_).type != JSMN_STRING || (tok_).size == 0) { return CGLTF_ERROR_JSON; }
2660#define CGLTF_PTRINDEX(type, idx) (type*)((cgltf_size)idx + 1)
2661#define CGLTF_PTRFIXUP(var, data, size) if (var) { if ((cgltf_size)var > size) { return CGLTF_ERROR_JSON; } var = &data[(cgltf_size)var-1]; }
2662#define CGLTF_PTRFIXUP_REQ(var, data, size) if (!var || (cgltf_size)var > size) { return CGLTF_ERROR_JSON; } var = &data[(cgltf_size)var-1];
2664static int cgltf_json_strcmp(jsmntok_t
const* tok,
const uint8_t* json_chunk,
const char* str)
2666 CGLTF_CHECK_TOKTYPE(*tok, JSMN_STRING);
2667 size_t const str_len = strlen(str);
2668 size_t const name_length = (size_t)(tok->end - tok->start);
2669 return (str_len == name_length) ? strncmp((
const char*)json_chunk + tok->start, str, str_len) : 128;
2672static int cgltf_json_to_int(jsmntok_t
const* tok,
const uint8_t* json_chunk)
2674 CGLTF_CHECK_TOKTYPE(*tok, JSMN_PRIMITIVE);
2676 int size = (size_t)(tok->end - tok->start) <
sizeof(tmp) ? (
int)(tok->end - tok->start) : (int)(sizeof(tmp) - 1);
2677 strncpy(tmp, (
const char*)json_chunk + tok->start, size);
2679 return CGLTF_ATOI(tmp);
2682static cgltf_size cgltf_json_to_size(jsmntok_t
const* tok,
const uint8_t* json_chunk)
2684 CGLTF_CHECK_TOKTYPE_RET(*tok, JSMN_PRIMITIVE, 0);
2686 int size = (size_t)(tok->end - tok->start) <
sizeof(tmp) ? (
int)(tok->end - tok->start) : (int)(sizeof(tmp) - 1);
2687 strncpy(tmp, (
const char*)json_chunk + tok->start, size);
2689 long long res = CGLTF_ATOLL(tmp);
2690 return res < 0 ? 0 : (cgltf_size)res;
2693static cgltf_float cgltf_json_to_float(jsmntok_t
const* tok,
const uint8_t* json_chunk)
2695 CGLTF_CHECK_TOKTYPE(*tok, JSMN_PRIMITIVE);
2697 int size = (size_t)(tok->end - tok->start) <
sizeof(tmp) ? (
int)(tok->end - tok->start) : (int)(sizeof(tmp) - 1);
2698 strncpy(tmp, (
const char*)json_chunk + tok->start, size);
2700 return (cgltf_float)CGLTF_ATOF(tmp);
2703static cgltf_bool cgltf_json_to_bool(jsmntok_t
const* tok,
const uint8_t* json_chunk)
2705 int size = (int)(tok->end - tok->start);
2706 return size == 4 && memcmp(json_chunk + tok->start,
"true", 4) == 0;
2709static int cgltf_skip_json(jsmntok_t
const* tokens,
int i)
2715 switch (tokens[i].type)
2718 end += tokens[i].size * 2;
2722 end += tokens[i].size;
2725 case JSMN_PRIMITIVE:
2739static void cgltf_fill_float_array(
float* out_array,
int size,
float value)
2741 for (
int j = 0; j < size; ++j)
2743 out_array[j] = value;
2747static int cgltf_parse_json_float_array(jsmntok_t
const* tokens,
int i,
const uint8_t* json_chunk,
float* out_array,
int size)
2749 CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_ARRAY);
2750 if (tokens[i].size != size)
2752 return CGLTF_ERROR_JSON;
2755 for (
int j = 0; j < size; ++j)
2757 CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_PRIMITIVE);
2758 out_array[j] = cgltf_json_to_float(tokens + i, json_chunk);
2764static int cgltf_parse_json_string(
cgltf_options* options, jsmntok_t
const* tokens,
int i,
const uint8_t* json_chunk,
char** out_string)
2766 CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_STRING);
2769 return CGLTF_ERROR_JSON;
2771 int size = (int)(tokens[i].end - tokens[i].start);
2772 char* result = (
char*)options->memory.alloc_func(options->memory.user_data, size + 1);
2775 return CGLTF_ERROR_NOMEM;
2777 strncpy(result, (
const char*)json_chunk + tokens[i].start, size);
2779 *out_string = result;
2783static 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)
2786 if (tokens[i].type != JSMN_ARRAY)
2788 return tokens[i].type == JSMN_OBJECT ? CGLTF_ERROR_LEGACY : CGLTF_ERROR_JSON;
2792 return CGLTF_ERROR_JSON;
2794 int size = tokens[i].size;
2795 void* result = cgltf_calloc(options, element_size, size);
2798 return CGLTF_ERROR_NOMEM;
2800 *out_array = result;
2805static 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)
2807 CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_ARRAY);
2808 i = cgltf_parse_json_array(options, tokens, i, json_chunk,
sizeof(
char*), (
void**)out_array, out_size);
2814 for (cgltf_size j = 0; j < *out_size; ++j)
2816 i = cgltf_parse_json_string(options, tokens, i, json_chunk, j + (*out_array));
2825static void cgltf_parse_attribute_type(
const char* name, cgltf_attribute_type* out_type,
int* out_index)
2829 *out_type = cgltf_attribute_type_custom;
2833 const char* us = strchr(name,
'_');
2834 size_t len = us ? (size_t)(us - name) : strlen(name);
2836 if (len == 8 && strncmp(name,
"POSITION", 8) == 0)
2838 *out_type = cgltf_attribute_type_position;
2840 else if (len == 6 && strncmp(name,
"NORMAL", 6) == 0)
2842 *out_type = cgltf_attribute_type_normal;
2844 else if (len == 7 && strncmp(name,
"TANGENT", 7) == 0)
2846 *out_type = cgltf_attribute_type_tangent;
2848 else if (len == 8 && strncmp(name,
"TEXCOORD", 8) == 0)
2850 *out_type = cgltf_attribute_type_texcoord;
2852 else if (len == 5 && strncmp(name,
"COLOR", 5) == 0)
2854 *out_type = cgltf_attribute_type_color;
2856 else if (len == 6 && strncmp(name,
"JOINTS", 6) == 0)
2858 *out_type = cgltf_attribute_type_joints;
2860 else if (len == 7 && strncmp(name,
"WEIGHTS", 7) == 0)
2862 *out_type = cgltf_attribute_type_weights;
2866 *out_type = cgltf_attribute_type_invalid;
2869 if (us && *out_type != cgltf_attribute_type_invalid)
2871 *out_index = CGLTF_ATOI(us + 1);
2874 *out_type = cgltf_attribute_type_invalid;
2880static 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)
2882 CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
2884 if (*out_attributes)
2886 return CGLTF_ERROR_JSON;
2889 *out_attributes_count = tokens[i].size;
2893 if (!*out_attributes)
2895 return CGLTF_ERROR_NOMEM;
2898 for (cgltf_size j = 0; j < *out_attributes_count; ++j)
2900 CGLTF_CHECK_KEY(tokens[i]);
2902 i = cgltf_parse_json_string(options, tokens, i, json_chunk, &(*out_attributes)[j].name);
2905 return CGLTF_ERROR_JSON;
2908 cgltf_parse_attribute_type((*out_attributes)[j].name, &(*out_attributes)[j].type, &(*out_attributes)[j].index);
2910 (*out_attributes)[j].data = CGLTF_PTRINDEX(
cgltf_accessor, cgltf_json_to_int(tokens + i, json_chunk));
2917static int cgltf_parse_json_extras(
cgltf_options* options, jsmntok_t
const* tokens,
int i,
const uint8_t* json_chunk,
cgltf_extras* out_extras)
2919 if (out_extras->data)
2921 return CGLTF_ERROR_JSON;
2925 out_extras->start_offset = tokens[i].start;
2926 out_extras->end_offset = tokens[i].end;
2928 size_t start = tokens[i].start;
2929 size_t size = tokens[i].end - start;
2930 out_extras->data = (
char*)options->memory.alloc_func(options->memory.user_data, size + 1);
2931 if (!out_extras->data)
2933 return CGLTF_ERROR_NOMEM;
2935 strncpy(out_extras->data, (
const char*)json_chunk + start, size);
2936 out_extras->data[size] =
'\0';
2938 i = cgltf_skip_json(tokens, i);
2942static int cgltf_parse_json_unprocessed_extension(
cgltf_options* options, jsmntok_t
const* tokens,
int i,
const uint8_t* json_chunk,
cgltf_extension* out_extension)
2944 CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_STRING);
2945 CGLTF_CHECK_TOKTYPE(tokens[i+1], JSMN_OBJECT);
2946 if (out_extension->name)
2948 return CGLTF_ERROR_JSON;
2951 cgltf_size name_length = tokens[i].end - tokens[i].start;
2952 out_extension->name = (
char*)options->memory.alloc_func(options->memory.user_data, name_length + 1);
2953 if (!out_extension->name)
2955 return CGLTF_ERROR_NOMEM;
2957 strncpy(out_extension->name, (
const char*)json_chunk + tokens[i].start, name_length);
2958 out_extension->name[name_length] = 0;
2961 size_t start = tokens[i].start;
2962 size_t size = tokens[i].end - start;
2963 out_extension->data = (
char*)options->memory.alloc_func(options->memory.user_data, size + 1);
2964 if (!out_extension->data)
2966 return CGLTF_ERROR_NOMEM;
2968 strncpy(out_extension->data, (
const char*)json_chunk + start, size);
2969 out_extension->data[size] =
'\0';
2971 i = cgltf_skip_json(tokens, i);
2976static 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)
2980 CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
2983 return CGLTF_ERROR_JSON;
2986 int extensions_size = tokens[i].size;
2987 *out_extensions_count = 0;
2990 if (!*out_extensions)
2992 return CGLTF_ERROR_NOMEM;
2997 for (
int j = 0; j < extensions_size; ++j)
2999 CGLTF_CHECK_KEY(tokens[i]);
3001 cgltf_size extension_index = (*out_extensions_count)++;
3003 i = cgltf_parse_json_unprocessed_extension(options, tokens, i, json_chunk, extension);
3015 CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
3017 int size = tokens[i].size;
3020 for (
int j = 0; j < size; ++j)
3022 CGLTF_CHECK_KEY(tokens[i]);
3024 if (cgltf_json_strcmp(tokens + i, json_chunk,
"attributes") == 0)
3026 i = cgltf_parse_json_attribute_list(options, tokens, i + 1, json_chunk, &out_draco_mesh_compression->attributes, &out_draco_mesh_compression->attributes_count);
3028 else if (cgltf_json_strcmp(tokens + i, json_chunk,
"bufferView") == 0)
3031 out_draco_mesh_compression->buffer_view = CGLTF_PTRINDEX(
cgltf_buffer_view, cgltf_json_to_int(tokens + i, json_chunk));
3036 i = cgltf_skip_json(tokens, i+1);
3050 CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
3052 int size = tokens[i].size;
3055 for (
int j = 0; j < size; ++j)
3057 CGLTF_CHECK_KEY(tokens[i]);
3059 if (cgltf_json_strcmp(tokens + i, json_chunk,
"attributes") == 0)
3061 i = cgltf_parse_json_attribute_list(options, tokens, i + 1, json_chunk, &out_mesh_gpu_instancing->attributes, &out_mesh_gpu_instancing->attributes_count);
3065 i = cgltf_skip_json(tokens, i+1);
3077static 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)
3080 CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_ARRAY);
3082 int size = tokens[i].size;
3085 for (
int j = 0; j < size; ++j)
3087 CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
3089 int obj_size = tokens[i].size;
3093 int variants_tok = -1;
3094 int extras_tok = -1;
3096 for (
int k = 0; k < obj_size; ++k)
3098 CGLTF_CHECK_KEY(tokens[i]);
3100 if (cgltf_json_strcmp(tokens + i, json_chunk,
"material") == 0)
3103 material = cgltf_json_to_int(tokens + i, json_chunk);
3106 else if (cgltf_json_strcmp(tokens + i, json_chunk,
"variants") == 0)
3109 CGLTF_CHECK_TOKTYPE(tokens[variants_tok], JSMN_ARRAY);
3111 i = cgltf_skip_json(tokens, i+1);
3113 else if (cgltf_json_strcmp(tokens + i, json_chunk,
"extras") == 0)
3116 i = cgltf_skip_json(tokens, extras_tok);
3120 i = cgltf_skip_json(tokens, i+1);
3129 if (material < 0 || variants_tok < 0)
3131 return CGLTF_ERROR_JSON;
3136 for (
int k = 0; k < tokens[variants_tok].size; ++k)
3138 int variant = cgltf_json_to_int(&tokens[variants_tok + 1 + k], json_chunk);
3142 out_mappings[*offset].material = CGLTF_PTRINDEX(
cgltf_material, material);
3143 out_mappings[*offset].variant = variant;
3145 if (extras_tok >= 0)
3147 int e = cgltf_parse_json_extras(options, tokens, extras_tok, json_chunk, &out_mappings[*offset].extras);
3157 (*offset) += tokens[variants_tok].size;
3164static int cgltf_parse_json_material_mappings(
cgltf_options* options, jsmntok_t
const* tokens,
int i,
const uint8_t* json_chunk,
cgltf_primitive* out_prim)
3166 CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
3168 int size = tokens[i].size;
3171 for (
int j = 0; j < size; ++j)
3173 CGLTF_CHECK_KEY(tokens[i]);
3175 if (cgltf_json_strcmp(tokens + i, json_chunk,
"mappings") == 0)
3177 if (out_prim->mappings)
3179 return CGLTF_ERROR_JSON;
3182 cgltf_size mappings_offset = 0;
3183 int k = cgltf_parse_json_material_mapping_data(options, tokens, i + 1, json_chunk, NULL, &mappings_offset);
3189 out_prim->mappings_count = mappings_offset;
3192 mappings_offset = 0;
3193 i = cgltf_parse_json_material_mapping_data(options, tokens, i + 1, json_chunk, out_prim->mappings, &mappings_offset);
3197 i = cgltf_skip_json(tokens, i+1);
3209static cgltf_primitive_type cgltf_json_to_primitive_type(jsmntok_t
const* tok,
const uint8_t* json_chunk)
3211 int type = cgltf_json_to_int(tok, json_chunk);
3216 return cgltf_primitive_type_points;
3218 return cgltf_primitive_type_lines;
3220 return cgltf_primitive_type_line_loop;
3222 return cgltf_primitive_type_line_strip;
3224 return cgltf_primitive_type_triangles;
3226 return cgltf_primitive_type_triangle_strip;
3228 return cgltf_primitive_type_triangle_fan;
3230 return cgltf_primitive_type_invalid;
3234static int cgltf_parse_json_primitive(
cgltf_options* options, jsmntok_t
const* tokens,
int i,
const uint8_t* json_chunk,
cgltf_primitive* out_prim)
3236 CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
3238 out_prim->type = cgltf_primitive_type_triangles;
3240 int size = tokens[i].size;
3243 for (
int j = 0; j < size; ++j)
3245 CGLTF_CHECK_KEY(tokens[i]);
3247 if (cgltf_json_strcmp(tokens+i, json_chunk,
"mode") == 0)
3250 out_prim->type = cgltf_json_to_primitive_type(tokens+i, json_chunk);
3253 else if (cgltf_json_strcmp(tokens+i, json_chunk,
"indices") == 0)
3256 out_prim->indices = CGLTF_PTRINDEX(
cgltf_accessor, cgltf_json_to_int(tokens + i, json_chunk));
3259 else if (cgltf_json_strcmp(tokens+i, json_chunk,
"material") == 0)
3262 out_prim->material = CGLTF_PTRINDEX(
cgltf_material, cgltf_json_to_int(tokens + i, json_chunk));
3265 else if (cgltf_json_strcmp(tokens+i, json_chunk,
"attributes") == 0)
3267 i = cgltf_parse_json_attribute_list(options, tokens, i + 1, json_chunk, &out_prim->attributes, &out_prim->attributes_count);
3269 else if (cgltf_json_strcmp(tokens+i, json_chunk,
"targets") == 0)
3271 i = cgltf_parse_json_array(options, tokens, i + 1, json_chunk,
sizeof(
cgltf_morph_target), (
void**)&out_prim->targets, &out_prim->targets_count);
3277 for (cgltf_size k = 0; k < out_prim->targets_count; ++k)
3279 i = cgltf_parse_json_attribute_list(options, tokens, i, json_chunk, &out_prim->targets[k].attributes, &out_prim->targets[k].attributes_count);
3286 else if (cgltf_json_strcmp(tokens + i, json_chunk,
"extras") == 0)
3288 i = cgltf_parse_json_extras(options, tokens, i + 1, json_chunk, &out_prim->extras);
3290 else if (cgltf_json_strcmp(tokens + i, json_chunk,
"extensions") == 0)
3294 CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
3295 if(out_prim->extensions)
3297 return CGLTF_ERROR_JSON;
3300 int extensions_size = tokens[i].size;
3301 out_prim->extensions_count = 0;
3304 if (!out_prim->extensions)
3306 return CGLTF_ERROR_NOMEM;
3310 for (
int k = 0; k < extensions_size; ++k)
3312 CGLTF_CHECK_KEY(tokens[i]);
3314 if (cgltf_json_strcmp(tokens+i, json_chunk,
"KHR_draco_mesh_compression") == 0)
3316 out_prim->has_draco_mesh_compression = 1;
3317 i = cgltf_parse_json_draco_mesh_compression(options, tokens, i + 1, json_chunk, &out_prim->draco_mesh_compression);
3319 else if (cgltf_json_strcmp(tokens+i, json_chunk,
"KHR_materials_variants") == 0)
3321 i = cgltf_parse_json_material_mappings(options, tokens, i + 1, json_chunk, out_prim);
3325 i = cgltf_parse_json_unprocessed_extension(options, tokens, i, json_chunk, &(out_prim->extensions[out_prim->extensions_count++]));
3336 i = cgltf_skip_json(tokens, i+1);
3348static int cgltf_parse_json_mesh(
cgltf_options* options, jsmntok_t
const* tokens,
int i,
const uint8_t* json_chunk,
cgltf_mesh* out_mesh)
3350 CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
3352 int size = tokens[i].size;
3355 for (
int j = 0; j < size; ++j)
3357 CGLTF_CHECK_KEY(tokens[i]);
3359 if (cgltf_json_strcmp(tokens+i, json_chunk,
"name") == 0)
3361 i = cgltf_parse_json_string(options, tokens, i + 1, json_chunk, &out_mesh->name);
3363 else if (cgltf_json_strcmp(tokens+i, json_chunk,
"primitives") == 0)
3365 i = cgltf_parse_json_array(options, tokens, i + 1, json_chunk,
sizeof(
cgltf_primitive), (
void**)&out_mesh->primitives, &out_mesh->primitives_count);
3371 for (cgltf_size prim_index = 0; prim_index < out_mesh->primitives_count; ++prim_index)
3373 i = cgltf_parse_json_primitive(options, tokens, i, json_chunk, &out_mesh->primitives[prim_index]);
3380 else if (cgltf_json_strcmp(tokens + i, json_chunk,
"weights") == 0)
3382 i = cgltf_parse_json_array(options, tokens, i + 1, json_chunk,
sizeof(cgltf_float), (
void**)&out_mesh->weights, &out_mesh->weights_count);
3388 i = cgltf_parse_json_float_array(tokens, i - 1, json_chunk, out_mesh->weights, (
int)out_mesh->weights_count);
3390 else if (cgltf_json_strcmp(tokens + i, json_chunk,
"extras") == 0)
3394 out_mesh->extras.start_offset = tokens[i].start;
3395 out_mesh->extras.end_offset = tokens[i].end;
3397 if (tokens[i].type == JSMN_OBJECT)
3399 int extras_size = tokens[i].size;
3402 for (
int k = 0; k < extras_size; ++k)
3404 CGLTF_CHECK_KEY(tokens[i]);
3406 if (cgltf_json_strcmp(tokens+i, json_chunk,
"targetNames") == 0 && tokens[i+1].type == JSMN_ARRAY)
3408 i = cgltf_parse_json_string_array(options, tokens, i + 1, json_chunk, &out_mesh->target_names, &out_mesh->target_names_count);
3412 i = cgltf_skip_json(tokens, i+1);
3423 i = cgltf_skip_json(tokens, i);
3426 else if (cgltf_json_strcmp(tokens + i, json_chunk,
"extensions") == 0)
3428 i = cgltf_parse_json_unprocessed_extensions(options, tokens, i, json_chunk, &out_mesh->extensions_count, &out_mesh->extensions);
3432 i = cgltf_skip_json(tokens, i+1);
3444static int cgltf_parse_json_meshes(
cgltf_options* options, jsmntok_t
const* tokens,
int i,
const uint8_t* json_chunk,
cgltf_data* out_data)
3446 i = cgltf_parse_json_array(options, tokens, i, json_chunk,
sizeof(
cgltf_mesh), (
void**)&out_data->meshes, &out_data->meshes_count);
3452 for (cgltf_size j = 0; j < out_data->meshes_count; ++j)
3454 i = cgltf_parse_json_mesh(options, tokens, i, json_chunk, &out_data->meshes[j]);
3463static cgltf_component_type cgltf_json_to_component_type(jsmntok_t
const* tok,
const uint8_t* json_chunk)
3465 int type = cgltf_json_to_int(tok, json_chunk);
3470 return cgltf_component_type_r_8;
3472 return cgltf_component_type_r_8u;
3474 return cgltf_component_type_r_16;
3476 return cgltf_component_type_r_16u;
3478 return cgltf_component_type_r_32u;
3480 return cgltf_component_type_r_32f;
3482 return cgltf_component_type_invalid;
3486static int cgltf_parse_json_accessor_sparse(jsmntok_t
const* tokens,
int i,
const uint8_t* json_chunk,
cgltf_accessor_sparse* out_sparse)
3488 CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
3490 int size = tokens[i].size;
3493 for (
int j = 0; j < size; ++j)
3495 CGLTF_CHECK_KEY(tokens[i]);
3497 if (cgltf_json_strcmp(tokens+i, json_chunk,
"count") == 0)
3500 out_sparse->count = cgltf_json_to_size(tokens + i, json_chunk);
3503 else if (cgltf_json_strcmp(tokens+i, json_chunk,
"indices") == 0)
3506 CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
3508 int indices_size = tokens[i].size;
3511 for (
int k = 0; k < indices_size; ++k)
3513 CGLTF_CHECK_KEY(tokens[i]);
3515 if (cgltf_json_strcmp(tokens+i, json_chunk,
"bufferView") == 0)
3518 out_sparse->indices_buffer_view = CGLTF_PTRINDEX(
cgltf_buffer_view, cgltf_json_to_int(tokens + i, json_chunk));
3521 else if (cgltf_json_strcmp(tokens+i, json_chunk,
"byteOffset") == 0)
3524 out_sparse->indices_byte_offset = cgltf_json_to_size(tokens + i, json_chunk);
3527 else if (cgltf_json_strcmp(tokens+i, json_chunk,
"componentType") == 0)
3530 out_sparse->indices_component_type = cgltf_json_to_component_type(tokens + i, json_chunk);
3535 i = cgltf_skip_json(tokens, i+1);
3544 else if (cgltf_json_strcmp(tokens+i, json_chunk,
"values") == 0)
3547 CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
3549 int values_size = tokens[i].size;
3552 for (
int k = 0; k < values_size; ++k)
3554 CGLTF_CHECK_KEY(tokens[i]);
3556 if (cgltf_json_strcmp(tokens+i, json_chunk,
"bufferView") == 0)
3559 out_sparse->values_buffer_view = CGLTF_PTRINDEX(
cgltf_buffer_view, cgltf_json_to_int(tokens + i, json_chunk));
3562 else if (cgltf_json_strcmp(tokens+i, json_chunk,
"byteOffset") == 0)
3565 out_sparse->values_byte_offset = cgltf_json_to_size(tokens + i, json_chunk);
3570 i = cgltf_skip_json(tokens, i+1);
3581 i = cgltf_skip_json(tokens, i+1);
3593static int cgltf_parse_json_accessor(
cgltf_options* options, jsmntok_t
const* tokens,
int i,
const uint8_t* json_chunk,
cgltf_accessor* out_accessor)
3595 CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
3597 int size = tokens[i].size;
3600 for (
int j = 0; j < size; ++j)
3602 CGLTF_CHECK_KEY(tokens[i]);
3604 if (cgltf_json_strcmp(tokens + i, json_chunk,
"name") == 0)
3606 i = cgltf_parse_json_string(options, tokens, i + 1, json_chunk, &out_accessor->name);
3608 else if (cgltf_json_strcmp(tokens+i, json_chunk,
"bufferView") == 0)
3611 out_accessor->buffer_view = CGLTF_PTRINDEX(
cgltf_buffer_view, cgltf_json_to_int(tokens + i, json_chunk));
3614 else if (cgltf_json_strcmp(tokens+i, json_chunk,
"byteOffset") == 0)
3617 out_accessor->offset =
3618 cgltf_json_to_size(tokens+i, json_chunk);
3621 else if (cgltf_json_strcmp(tokens+i, json_chunk,
"componentType") == 0)
3624 out_accessor->component_type = cgltf_json_to_component_type(tokens + i, json_chunk);
3627 else if (cgltf_json_strcmp(tokens+i, json_chunk,
"normalized") == 0)
3630 out_accessor->normalized = cgltf_json_to_bool(tokens+i, json_chunk);
3633 else if (cgltf_json_strcmp(tokens+i, json_chunk,
"count") == 0)
3636 out_accessor->count = cgltf_json_to_size(tokens+i, json_chunk);
3639 else if (cgltf_json_strcmp(tokens+i, json_chunk,
"type") == 0)
3642 if (cgltf_json_strcmp(tokens+i, json_chunk,
"SCALAR") == 0)
3644 out_accessor->type = cgltf_type_scalar;
3646 else if (cgltf_json_strcmp(tokens+i, json_chunk,
"VEC2") == 0)
3648 out_accessor->type = cgltf_type_vec2;
3650 else if (cgltf_json_strcmp(tokens+i, json_chunk,
"VEC3") == 0)
3652 out_accessor->type = cgltf_type_vec3;
3654 else if (cgltf_json_strcmp(tokens+i, json_chunk,
"VEC4") == 0)
3656 out_accessor->type = cgltf_type_vec4;
3658 else if (cgltf_json_strcmp(tokens+i, json_chunk,
"MAT2") == 0)
3660 out_accessor->type = cgltf_type_mat2;
3662 else if (cgltf_json_strcmp(tokens+i, json_chunk,
"MAT3") == 0)
3664 out_accessor->type = cgltf_type_mat3;
3666 else if (cgltf_json_strcmp(tokens+i, json_chunk,
"MAT4") == 0)
3668 out_accessor->type = cgltf_type_mat4;
3672 else if (cgltf_json_strcmp(tokens + i, json_chunk,
"min") == 0)
3675 out_accessor->has_min = 1;
3677 int min_size = tokens[i].size > 16 ? 16 : tokens[i].size;
3678 i = cgltf_parse_json_float_array(tokens, i, json_chunk, out_accessor->min, min_size);
3680 else if (cgltf_json_strcmp(tokens + i, json_chunk,
"max") == 0)
3683 out_accessor->has_max = 1;
3685 int max_size = tokens[i].size > 16 ? 16 : tokens[i].size;
3686 i = cgltf_parse_json_float_array(tokens, i, json_chunk, out_accessor->max, max_size);
3688 else if (cgltf_json_strcmp(tokens + i, json_chunk,
"sparse") == 0)
3690 out_accessor->is_sparse = 1;
3691 i = cgltf_parse_json_accessor_sparse(tokens, i + 1, json_chunk, &out_accessor->sparse);
3693 else if (cgltf_json_strcmp(tokens + i, json_chunk,
"extras") == 0)
3695 i = cgltf_parse_json_extras(options, tokens, i + 1, json_chunk, &out_accessor->extras);
3697 else if (cgltf_json_strcmp(tokens + i, json_chunk,
"extensions") == 0)
3699 i = cgltf_parse_json_unprocessed_extensions(options, tokens, i, json_chunk, &out_accessor->extensions_count, &out_accessor->extensions);
3703 i = cgltf_skip_json(tokens, i+1);
3715static int cgltf_parse_json_texture_transform(jsmntok_t
const* tokens,
int i,
const uint8_t* json_chunk,
cgltf_texture_transform* out_texture_transform)
3717 CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
3719 int size = tokens[i].size;
3722 for (
int j = 0; j < size; ++j)
3724 CGLTF_CHECK_KEY(tokens[i]);
3726 if (cgltf_json_strcmp(tokens + i, json_chunk,
"offset") == 0)
3728 i = cgltf_parse_json_float_array(tokens, i + 1, json_chunk, out_texture_transform->offset, 2);
3730 else if (cgltf_json_strcmp(tokens + i, json_chunk,
"rotation") == 0)
3733 out_texture_transform->rotation = cgltf_json_to_float(tokens + i, json_chunk);
3736 else if (cgltf_json_strcmp(tokens + i, json_chunk,
"scale") == 0)
3738 i = cgltf_parse_json_float_array(tokens, i + 1, json_chunk, out_texture_transform->scale, 2);
3740 else if (cgltf_json_strcmp(tokens + i, json_chunk,
"texCoord") == 0)
3743 out_texture_transform->has_texcoord = 1;
3744 out_texture_transform->texcoord = cgltf_json_to_int(tokens + i, json_chunk);
3749 i = cgltf_skip_json(tokens, i + 1);
3761static 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)
3765 CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
3767 out_texture_view->scale = 1.0f;
3768 cgltf_fill_float_array(out_texture_view->transform.scale, 2, 1.0f);
3770 int size = tokens[i].size;
3773 for (
int j = 0; j < size; ++j)
3775 CGLTF_CHECK_KEY(tokens[i]);
3777 if (cgltf_json_strcmp(tokens + i, json_chunk,
"index") == 0)
3780 out_texture_view->texture = CGLTF_PTRINDEX(
cgltf_texture, cgltf_json_to_int(tokens + i, json_chunk));
3783 else if (cgltf_json_strcmp(tokens + i, json_chunk,
"texCoord") == 0)
3786 out_texture_view->texcoord = cgltf_json_to_int(tokens + i, json_chunk);
3789 else if (cgltf_json_strcmp(tokens + i, json_chunk,
"scale") == 0)
3792 out_texture_view->scale = cgltf_json_to_float(tokens + i, json_chunk);
3795 else if (cgltf_json_strcmp(tokens + i, json_chunk,
"strength") == 0)
3798 out_texture_view->scale = cgltf_json_to_float(tokens + i, json_chunk);
3801 else if (cgltf_json_strcmp(tokens + i, json_chunk,
"extensions") == 0)
3805 CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
3806 int extensions_size = tokens[i].size;
3810 for (
int k = 0; k < extensions_size; ++k)
3812 CGLTF_CHECK_KEY(tokens[i]);
3814 if (cgltf_json_strcmp(tokens+i, json_chunk,
"KHR_texture_transform") == 0)
3816 out_texture_view->has_transform = 1;
3817 i = cgltf_parse_json_texture_transform(tokens, i + 1, json_chunk, &out_texture_view->transform);
3821 i = cgltf_skip_json(tokens, i + 1);
3832 i = cgltf_skip_json(tokens, i + 1);
3846 CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
3848 int size = tokens[i].size;
3851 for (
int j = 0; j < size; ++j)
3853 CGLTF_CHECK_KEY(tokens[i]);
3855 if (cgltf_json_strcmp(tokens+i, json_chunk,
"metallicFactor") == 0)
3858 out_pbr->metallic_factor =
3859 cgltf_json_to_float(tokens + i, json_chunk);
3862 else if (cgltf_json_strcmp(tokens+i, json_chunk,
"roughnessFactor") == 0)
3865 out_pbr->roughness_factor =
3866 cgltf_json_to_float(tokens+i, json_chunk);
3869 else if (cgltf_json_strcmp(tokens+i, json_chunk,
"baseColorFactor") == 0)
3871 i = cgltf_parse_json_float_array(tokens, i + 1, json_chunk, out_pbr->base_color_factor, 4);
3873 else if (cgltf_json_strcmp(tokens+i, json_chunk,
"baseColorTexture") == 0)
3875 i = cgltf_parse_json_texture_view(options, tokens, i + 1, json_chunk, &out_pbr->base_color_texture);
3877 else if (cgltf_json_strcmp(tokens + i, json_chunk,
"metallicRoughnessTexture") == 0)
3879 i = cgltf_parse_json_texture_view(options, tokens, i + 1, json_chunk, &out_pbr->metallic_roughness_texture);
3883 i = cgltf_skip_json(tokens, i+1);
3897 CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
3898 int size = tokens[i].size;
3901 for (
int j = 0; j < size; ++j)
3903 CGLTF_CHECK_KEY(tokens[i]);
3905 if (cgltf_json_strcmp(tokens+i, json_chunk,
"diffuseFactor") == 0)
3907 i = cgltf_parse_json_float_array(tokens, i + 1, json_chunk, out_pbr->diffuse_factor, 4);
3909 else if (cgltf_json_strcmp(tokens+i, json_chunk,
"specularFactor") == 0)
3911 i = cgltf_parse_json_float_array(tokens, i + 1, json_chunk, out_pbr->specular_factor, 3);
3913 else if (cgltf_json_strcmp(tokens+i, json_chunk,
"glossinessFactor") == 0)
3916 out_pbr->glossiness_factor = cgltf_json_to_float(tokens + i, json_chunk);
3919 else if (cgltf_json_strcmp(tokens+i, json_chunk,
"diffuseTexture") == 0)
3921 i = cgltf_parse_json_texture_view(options, tokens, i + 1, json_chunk, &out_pbr->diffuse_texture);
3923 else if (cgltf_json_strcmp(tokens+i, json_chunk,
"specularGlossinessTexture") == 0)
3925 i = cgltf_parse_json_texture_view(options, tokens, i + 1, json_chunk, &out_pbr->specular_glossiness_texture);
3929 i = cgltf_skip_json(tokens, i+1);
3941static int cgltf_parse_json_clearcoat(
cgltf_options* options, jsmntok_t
const* tokens,
int i,
const uint8_t* json_chunk,
cgltf_clearcoat* out_clearcoat)
3943 CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
3944 int size = tokens[i].size;
3947 for (
int j = 0; j < size; ++j)
3949 CGLTF_CHECK_KEY(tokens[i]);
3951 if (cgltf_json_strcmp(tokens+i, json_chunk,
"clearcoatFactor") == 0)
3954 out_clearcoat->clearcoat_factor = cgltf_json_to_float(tokens + i, json_chunk);
3957 else if (cgltf_json_strcmp(tokens+i, json_chunk,
"clearcoatRoughnessFactor") == 0)
3960 out_clearcoat->clearcoat_roughness_factor = cgltf_json_to_float(tokens + i, json_chunk);
3963 else if (cgltf_json_strcmp(tokens+i, json_chunk,
"clearcoatTexture") == 0)
3965 i = cgltf_parse_json_texture_view(options, tokens, i + 1, json_chunk, &out_clearcoat->clearcoat_texture);
3967 else if (cgltf_json_strcmp(tokens+i, json_chunk,
"clearcoatRoughnessTexture") == 0)
3969 i = cgltf_parse_json_texture_view(options, tokens, i + 1, json_chunk, &out_clearcoat->clearcoat_roughness_texture);
3971 else if (cgltf_json_strcmp(tokens+i, json_chunk,
"clearcoatNormalTexture") == 0)
3973 i = cgltf_parse_json_texture_view(options, tokens, i + 1, json_chunk, &out_clearcoat->clearcoat_normal_texture);
3977 i = cgltf_skip_json(tokens, i+1);
3989static int cgltf_parse_json_ior(jsmntok_t
const* tokens,
int i,
const uint8_t* json_chunk,
cgltf_ior* out_ior)
3991 CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
3992 int size = tokens[i].size;
3996 out_ior->ior = 1.5f;
3998 for (
int j = 0; j < size; ++j)
4000 CGLTF_CHECK_KEY(tokens[i]);
4002 if (cgltf_json_strcmp(tokens+i, json_chunk,
"ior") == 0)
4005 out_ior->ior = cgltf_json_to_float(tokens + i, json_chunk);
4010 i = cgltf_skip_json(tokens, i+1);
4022static int cgltf_parse_json_specular(
cgltf_options* options, jsmntok_t
const* tokens,
int i,
const uint8_t* json_chunk,
cgltf_specular* out_specular)
4024 CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
4025 int size = tokens[i].size;
4029 out_specular->specular_factor = 1.0f;
4030 cgltf_fill_float_array(out_specular->specular_color_factor, 3, 1.0f);
4032 for (
int j = 0; j < size; ++j)
4034 CGLTF_CHECK_KEY(tokens[i]);
4036 if (cgltf_json_strcmp(tokens+i, json_chunk,
"specularFactor") == 0)
4039 out_specular->specular_factor = cgltf_json_to_float(tokens + i, json_chunk);
4042 else if (cgltf_json_strcmp(tokens+i, json_chunk,
"specularColorFactor") == 0)
4044 i = cgltf_parse_json_float_array(tokens, i + 1, json_chunk, out_specular->specular_color_factor, 3);
4046 else if (cgltf_json_strcmp(tokens+i, json_chunk,
"specularTexture") == 0)
4048 i = cgltf_parse_json_texture_view(options, tokens, i + 1, json_chunk, &out_specular->specular_texture);
4050 else if (cgltf_json_strcmp(tokens + i, json_chunk,
"specularColorTexture") == 0)
4052 i = cgltf_parse_json_texture_view(options, tokens, i + 1, json_chunk, &out_specular->specular_color_texture);
4056 i = cgltf_skip_json(tokens, i+1);
4068static int cgltf_parse_json_transmission(
cgltf_options* options, jsmntok_t
const* tokens,
int i,
const uint8_t* json_chunk,
cgltf_transmission* out_transmission)
4070 CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
4071 int size = tokens[i].size;
4074 for (
int j = 0; j < size; ++j)
4076 CGLTF_CHECK_KEY(tokens[i]);
4078 if (cgltf_json_strcmp(tokens+i, json_chunk,
"transmissionFactor") == 0)
4081 out_transmission->transmission_factor = cgltf_json_to_float(tokens + i, json_chunk);
4084 else if (cgltf_json_strcmp(tokens+i, json_chunk,
"transmissionTexture") == 0)
4086 i = cgltf_parse_json_texture_view(options, tokens, i + 1, json_chunk, &out_transmission->transmission_texture);
4090 i = cgltf_skip_json(tokens, i+1);
4102static int cgltf_parse_json_volume(
cgltf_options* options, jsmntok_t
const* tokens,
int i,
const uint8_t* json_chunk,
cgltf_volume* out_volume)
4104 CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
4105 int size = tokens[i].size;
4108 for (
int j = 0; j < size; ++j)
4110 CGLTF_CHECK_KEY(tokens[i]);
4112 if (cgltf_json_strcmp(tokens + i, json_chunk,
"thicknessFactor") == 0)
4115 out_volume->thickness_factor = cgltf_json_to_float(tokens + i, json_chunk);
4118 else if (cgltf_json_strcmp(tokens + i, json_chunk,
"thicknessTexture") == 0)
4120 i = cgltf_parse_json_texture_view(options, tokens, i + 1, json_chunk, &out_volume->thickness_texture);
4122 else if (cgltf_json_strcmp(tokens + i, json_chunk,
"attenuationColor") == 0)
4124 i = cgltf_parse_json_float_array(tokens, i + 1, json_chunk, out_volume->attenuation_color, 3);
4126 else if (cgltf_json_strcmp(tokens + i, json_chunk,
"attenuationDistance") == 0)
4129 out_volume->attenuation_distance = cgltf_json_to_float(tokens + i, json_chunk);
4134 i = cgltf_skip_json(tokens, i + 1);
4146static int cgltf_parse_json_sheen(
cgltf_options* options, jsmntok_t
const* tokens,
int i,
const uint8_t* json_chunk,
cgltf_sheen* out_sheen)
4148 CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
4149 int size = tokens[i].size;
4152 for (
int j = 0; j < size; ++j)
4154 CGLTF_CHECK_KEY(tokens[i]);
4156 if (cgltf_json_strcmp(tokens+i, json_chunk,
"sheenColorFactor") == 0)
4158 i = cgltf_parse_json_float_array(tokens, i + 1, json_chunk, out_sheen->sheen_color_factor, 3);
4160 else if (cgltf_json_strcmp(tokens+i, json_chunk,
"sheenColorTexture") == 0)
4162 i = cgltf_parse_json_texture_view(options, tokens, i + 1, json_chunk, &out_sheen->sheen_color_texture);
4164 else if (cgltf_json_strcmp(tokens+i, json_chunk,
"sheenRoughnessFactor") == 0)
4167 out_sheen->sheen_roughness_factor = cgltf_json_to_float(tokens + i, json_chunk);
4170 else if (cgltf_json_strcmp(tokens+i, json_chunk,
"sheenRoughnessTexture") == 0)
4172 i = cgltf_parse_json_texture_view(options, tokens, i + 1, json_chunk, &out_sheen->sheen_roughness_texture);
4176 i = cgltf_skip_json(tokens, i+1);
4188static int cgltf_parse_json_emissive_strength(jsmntok_t
const* tokens,
int i,
const uint8_t* json_chunk,
cgltf_emissive_strength* out_emissive_strength)
4190 CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
4191 int size = tokens[i].size;
4195 out_emissive_strength->emissive_strength = 1.f;
4197 for (
int j = 0; j < size; ++j)
4199 CGLTF_CHECK_KEY(tokens[i]);
4201 if (cgltf_json_strcmp(tokens + i, json_chunk,
"emissiveStrength") == 0)
4204 out_emissive_strength->emissive_strength = cgltf_json_to_float(tokens + i, json_chunk);
4209 i = cgltf_skip_json(tokens, i + 1);
4221static int cgltf_parse_json_iridescence(
cgltf_options* options, jsmntok_t
const* tokens,
int i,
const uint8_t* json_chunk,
cgltf_iridescence* out_iridescence)
4223 CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
4224 int size = tokens[i].size;
4228 out_iridescence->iridescence_ior = 1.3f;
4229 out_iridescence->iridescence_thickness_min = 100.f;
4230 out_iridescence->iridescence_thickness_max = 400.f;
4232 for (
int j = 0; j < size; ++j)
4234 CGLTF_CHECK_KEY(tokens[i]);
4236 if (cgltf_json_strcmp(tokens + i, json_chunk,
"iridescenceFactor") == 0)
4239 out_iridescence->iridescence_factor = cgltf_json_to_float(tokens + i, json_chunk);
4242 else if (cgltf_json_strcmp(tokens + i, json_chunk,
"iridescenceTexture") == 0)
4244 i = cgltf_parse_json_texture_view(options, tokens, i + 1, json_chunk, &out_iridescence->iridescence_texture);
4246 else if (cgltf_json_strcmp(tokens + i, json_chunk,
"iridescenceIor") == 0)
4249 out_iridescence->iridescence_ior = cgltf_json_to_float(tokens + i, json_chunk);
4252 else if (cgltf_json_strcmp(tokens + i, json_chunk,
"iridescenceThicknessMinimum") == 0)
4255 out_iridescence->iridescence_thickness_min = cgltf_json_to_float(tokens + i, json_chunk);
4258 else if (cgltf_json_strcmp(tokens + i, json_chunk,
"iridescenceThicknessMaximum") == 0)
4261 out_iridescence->iridescence_thickness_max = cgltf_json_to_float(tokens + i, json_chunk);
4264 else if (cgltf_json_strcmp(tokens + i, json_chunk,
"iridescenceThicknessTexture") == 0)
4266 i = cgltf_parse_json_texture_view(options, tokens, i + 1, json_chunk, &out_iridescence->iridescence_thickness_texture);
4270 i = cgltf_skip_json(tokens, i + 1);
4282static int cgltf_parse_json_anisotropy(
cgltf_options* options, jsmntok_t
const* tokens,
int i,
const uint8_t* json_chunk,
cgltf_anisotropy* out_anisotropy)
4284 CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
4285 int size = tokens[i].size;
4289 for (
int j = 0; j < size; ++j)
4291 CGLTF_CHECK_KEY(tokens[i]);
4293 if (cgltf_json_strcmp(tokens + i, json_chunk,
"anisotropyStrength") == 0)
4296 out_anisotropy->anisotropy_strength = cgltf_json_to_float(tokens + i, json_chunk);
4299 else if (cgltf_json_strcmp(tokens + i, json_chunk,
"anisotropyRotation") == 0)
4302 out_anisotropy->anisotropy_rotation = cgltf_json_to_float(tokens + i, json_chunk);
4305 else if (cgltf_json_strcmp(tokens + i, json_chunk,
"anisotropyTexture") == 0)
4307 i = cgltf_parse_json_texture_view(options, tokens, i + 1, json_chunk, &out_anisotropy->anisotropy_texture);
4311 i = cgltf_skip_json(tokens, i + 1);
4323static int cgltf_parse_json_dispersion(jsmntok_t
const* tokens,
int i,
const uint8_t* json_chunk,
cgltf_dispersion* out_dispersion)
4325 CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
4326 int size = tokens[i].size;
4330 for (
int j = 0; j < size; ++j)
4332 CGLTF_CHECK_KEY(tokens[i]);
4334 if (cgltf_json_strcmp(tokens + i, json_chunk,
"dispersion") == 0)
4337 out_dispersion->dispersion = cgltf_json_to_float(tokens + i, json_chunk);
4342 i = cgltf_skip_json(tokens, i + 1);
4354static int cgltf_parse_json_image(
cgltf_options* options, jsmntok_t
const* tokens,
int i,
const uint8_t* json_chunk,
cgltf_image* out_image)
4356 CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
4358 int size = tokens[i].size;
4361 for (
int j = 0; j < size; ++j)
4363 CGLTF_CHECK_KEY(tokens[i]);
4365 if (cgltf_json_strcmp(tokens + i, json_chunk,
"uri") == 0)
4367 i = cgltf_parse_json_string(options, tokens, i + 1, json_chunk, &out_image->uri);
4369 else if (cgltf_json_strcmp(tokens+i, json_chunk,
"bufferView") == 0)
4372 out_image->buffer_view = CGLTF_PTRINDEX(
cgltf_buffer_view, cgltf_json_to_int(tokens + i, json_chunk));
4375 else if (cgltf_json_strcmp(tokens + i, json_chunk,
"mimeType") == 0)
4377 i = cgltf_parse_json_string(options, tokens, i + 1, json_chunk, &out_image->mime_type);
4379 else if (cgltf_json_strcmp(tokens + i, json_chunk,
"name") == 0)
4381 i = cgltf_parse_json_string(options, tokens, i + 1, json_chunk, &out_image->name);
4383 else if (cgltf_json_strcmp(tokens + i, json_chunk,
"extras") == 0)
4385 i = cgltf_parse_json_extras(options, tokens, i + 1, json_chunk, &out_image->extras);
4387 else if (cgltf_json_strcmp(tokens + i, json_chunk,
"extensions") == 0)
4389 i = cgltf_parse_json_unprocessed_extensions(options, tokens, i, json_chunk, &out_image->extensions_count, &out_image->extensions);
4393 i = cgltf_skip_json(tokens, i + 1);
4405static int cgltf_parse_json_sampler(
cgltf_options* options, jsmntok_t
const* tokens,
int i,
const uint8_t* json_chunk,
cgltf_sampler* out_sampler)
4408 CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
4410 out_sampler->wrap_s = 10497;
4411 out_sampler->wrap_t = 10497;
4413 int size = tokens[i].size;
4416 for (
int j = 0; j < size; ++j)
4418 CGLTF_CHECK_KEY(tokens[i]);
4420 if (cgltf_json_strcmp(tokens + i, json_chunk,
"name") == 0)
4422 i = cgltf_parse_json_string(options, tokens, i + 1, json_chunk, &out_sampler->name);
4424 else if (cgltf_json_strcmp(tokens + i, json_chunk,
"magFilter") == 0)
4427 out_sampler->mag_filter
4428 = cgltf_json_to_int(tokens + i, json_chunk);
4431 else if (cgltf_json_strcmp(tokens + i, json_chunk,
"minFilter") == 0)
4434 out_sampler->min_filter
4435 = cgltf_json_to_int(tokens + i, json_chunk);
4438 else if (cgltf_json_strcmp(tokens + i, json_chunk,
"wrapS") == 0)
4442 = cgltf_json_to_int(tokens + i, json_chunk);
4445 else if (cgltf_json_strcmp(tokens + i, json_chunk,
"wrapT") == 0)
4449 = cgltf_json_to_int(tokens + i, json_chunk);
4452 else if (cgltf_json_strcmp(tokens + i, json_chunk,
"extras") == 0)
4454 i = cgltf_parse_json_extras(options, tokens, i + 1, json_chunk, &out_sampler->extras);
4456 else if (cgltf_json_strcmp(tokens + i, json_chunk,
"extensions") == 0)
4458 i = cgltf_parse_json_unprocessed_extensions(options, tokens, i, json_chunk, &out_sampler->extensions_count, &out_sampler->extensions);
4462 i = cgltf_skip_json(tokens, i + 1);
4474static int cgltf_parse_json_texture(
cgltf_options* options, jsmntok_t
const* tokens,
int i,
const uint8_t* json_chunk,
cgltf_texture* out_texture)
4476 CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
4478 int size = tokens[i].size;
4481 for (
int j = 0; j < size; ++j)
4483 CGLTF_CHECK_KEY(tokens[i]);
4485 if (cgltf_json_strcmp(tokens+i, json_chunk,
"name") == 0)
4487 i = cgltf_parse_json_string(options, tokens, i + 1, json_chunk, &out_texture->name);
4489 else if (cgltf_json_strcmp(tokens + i, json_chunk,
"sampler") == 0)
4492 out_texture->sampler = CGLTF_PTRINDEX(
cgltf_sampler, cgltf_json_to_int(tokens + i, json_chunk));
4495 else if (cgltf_json_strcmp(tokens + i, json_chunk,
"source") == 0)
4498 out_texture->image = CGLTF_PTRINDEX(
cgltf_image, cgltf_json_to_int(tokens + i, json_chunk));
4501 else if (cgltf_json_strcmp(tokens + i, json_chunk,
"extras") == 0)
4503 i = cgltf_parse_json_extras(options, tokens, i + 1, json_chunk, &out_texture->extras);
4505 else if (cgltf_json_strcmp(tokens + i, json_chunk,
"extensions") == 0)
4509 CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
4510 if (out_texture->extensions)
4512 return CGLTF_ERROR_JSON;
4515 int extensions_size = tokens[i].size;
4518 out_texture->extensions_count = 0;
4520 if (!out_texture->extensions)
4522 return CGLTF_ERROR_NOMEM;
4525 for (
int k = 0; k < extensions_size; ++k)
4527 CGLTF_CHECK_KEY(tokens[i]);
4529 if (cgltf_json_strcmp(tokens + i, json_chunk,
"KHR_texture_basisu") == 0)
4531 out_texture->has_basisu = 1;
4533 CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
4534 int num_properties = tokens[i].size;
4537 for (
int t = 0; t < num_properties; ++t)
4539 CGLTF_CHECK_KEY(tokens[i]);
4541 if (cgltf_json_strcmp(tokens + i, json_chunk,
"source") == 0)
4544 out_texture->basisu_image = CGLTF_PTRINDEX(
cgltf_image, cgltf_json_to_int(tokens + i, json_chunk));
4549 i = cgltf_skip_json(tokens, i + 1);
4557 else if (cgltf_json_strcmp(tokens + i, json_chunk,
"EXT_texture_webp") == 0)
4559 out_texture->has_webp = 1;
4561 CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
4562 int num_properties = tokens[i].size;
4565 for (
int t = 0; t < num_properties; ++t)
4567 CGLTF_CHECK_KEY(tokens[i]);
4569 if (cgltf_json_strcmp(tokens + i, json_chunk,
"source") == 0)
4572 out_texture->webp_image = CGLTF_PTRINDEX(
cgltf_image, cgltf_json_to_int(tokens + i, json_chunk));
4577 i = cgltf_skip_json(tokens, i + 1);
4587 i = cgltf_parse_json_unprocessed_extension(options, tokens, i, json_chunk, &(out_texture->extensions[out_texture->extensions_count++]));
4598 i = cgltf_skip_json(tokens, i + 1);
4610static int cgltf_parse_json_material(
cgltf_options* options, jsmntok_t
const* tokens,
int i,
const uint8_t* json_chunk,
cgltf_material* out_material)
4612 CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
4614 cgltf_fill_float_array(out_material->pbr_metallic_roughness.base_color_factor, 4, 1.0f);
4615 out_material->pbr_metallic_roughness.metallic_factor = 1.0f;
4616 out_material->pbr_metallic_roughness.roughness_factor = 1.0f;
4618 cgltf_fill_float_array(out_material->pbr_specular_glossiness.diffuse_factor, 4, 1.0f);
4619 cgltf_fill_float_array(out_material->pbr_specular_glossiness.specular_factor, 3, 1.0f);
4620 out_material->pbr_specular_glossiness.glossiness_factor = 1.0f;
4622 cgltf_fill_float_array(out_material->volume.attenuation_color, 3, 1.0f);
4623 out_material->volume.attenuation_distance = FLT_MAX;
4625 out_material->alpha_cutoff = 0.5f;
4627 int size = tokens[i].size;
4630 for (
int j = 0; j < size; ++j)
4632 CGLTF_CHECK_KEY(tokens[i]);
4634 if (cgltf_json_strcmp(tokens+i, json_chunk,
"name") == 0)
4636 i = cgltf_parse_json_string(options, tokens, i + 1, json_chunk, &out_material->name);
4638 else if (cgltf_json_strcmp(tokens+i, json_chunk,
"pbrMetallicRoughness") == 0)
4640 out_material->has_pbr_metallic_roughness = 1;
4641 i = cgltf_parse_json_pbr_metallic_roughness(options, tokens, i + 1, json_chunk, &out_material->pbr_metallic_roughness);
4643 else if (cgltf_json_strcmp(tokens+i, json_chunk,
"emissiveFactor") == 0)
4645 i = cgltf_parse_json_float_array(tokens, i + 1, json_chunk, out_material->emissive_factor, 3);
4647 else if (cgltf_json_strcmp(tokens + i, json_chunk,
"normalTexture") == 0)
4649 i = cgltf_parse_json_texture_view(options, tokens, i + 1, json_chunk,
4650 &out_material->normal_texture);
4652 else if (cgltf_json_strcmp(tokens + i, json_chunk,
"occlusionTexture") == 0)
4654 i = cgltf_parse_json_texture_view(options, tokens, i + 1, json_chunk,
4655 &out_material->occlusion_texture);
4657 else if (cgltf_json_strcmp(tokens + i, json_chunk,
"emissiveTexture") == 0)
4659 i = cgltf_parse_json_texture_view(options, tokens, i + 1, json_chunk,
4660 &out_material->emissive_texture);
4662 else if (cgltf_json_strcmp(tokens + i, json_chunk,
"alphaMode") == 0)
4665 if (cgltf_json_strcmp(tokens + i, json_chunk,
"OPAQUE") == 0)
4667 out_material->alpha_mode = cgltf_alpha_mode_opaque;
4669 else if (cgltf_json_strcmp(tokens + i, json_chunk,
"MASK") == 0)
4671 out_material->alpha_mode = cgltf_alpha_mode_mask;
4673 else if (cgltf_json_strcmp(tokens + i, json_chunk,
"BLEND") == 0)
4675 out_material->alpha_mode = cgltf_alpha_mode_blend;
4679 else if (cgltf_json_strcmp(tokens + i, json_chunk,
"alphaCutoff") == 0)
4682 out_material->alpha_cutoff = cgltf_json_to_float(tokens + i, json_chunk);
4685 else if (cgltf_json_strcmp(tokens + i, json_chunk,
"doubleSided") == 0)
4688 out_material->double_sided =
4689 cgltf_json_to_bool(tokens + i, json_chunk);
4692 else if (cgltf_json_strcmp(tokens + i, json_chunk,
"extras") == 0)
4694 i = cgltf_parse_json_extras(options, tokens, i + 1, json_chunk, &out_material->extras);
4696 else if (cgltf_json_strcmp(tokens + i, json_chunk,
"extensions") == 0)
4700 CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
4701 if(out_material->extensions)
4703 return CGLTF_ERROR_JSON;
4706 int extensions_size = tokens[i].size;
4709 out_material->extensions_count= 0;
4711 if (!out_material->extensions)
4713 return CGLTF_ERROR_NOMEM;
4716 for (
int k = 0; k < extensions_size; ++k)
4718 CGLTF_CHECK_KEY(tokens[i]);
4720 if (cgltf_json_strcmp(tokens+i, json_chunk,
"KHR_materials_pbrSpecularGlossiness") == 0)
4722 out_material->has_pbr_specular_glossiness = 1;
4723 i = cgltf_parse_json_pbr_specular_glossiness(options, tokens, i + 1, json_chunk, &out_material->pbr_specular_glossiness);
4725 else if (cgltf_json_strcmp(tokens+i, json_chunk,
"KHR_materials_unlit") == 0)
4727 out_material->unlit = 1;
4728 i = cgltf_skip_json(tokens, i+1);
4730 else if (cgltf_json_strcmp(tokens+i, json_chunk,
"KHR_materials_clearcoat") == 0)
4732 out_material->has_clearcoat = 1;
4733 i = cgltf_parse_json_clearcoat(options, tokens, i + 1, json_chunk, &out_material->clearcoat);
4735 else if (cgltf_json_strcmp(tokens+i, json_chunk,
"KHR_materials_ior") == 0)
4737 out_material->has_ior = 1;
4738 i = cgltf_parse_json_ior(tokens, i + 1, json_chunk, &out_material->ior);
4740 else if (cgltf_json_strcmp(tokens+i, json_chunk,
"KHR_materials_specular") == 0)
4742 out_material->has_specular = 1;
4743 i = cgltf_parse_json_specular(options, tokens, i + 1, json_chunk, &out_material->specular);
4745 else if (cgltf_json_strcmp(tokens+i, json_chunk,
"KHR_materials_transmission") == 0)
4747 out_material->has_transmission = 1;
4748 i = cgltf_parse_json_transmission(options, tokens, i + 1, json_chunk, &out_material->transmission);
4750 else if (cgltf_json_strcmp(tokens + i, json_chunk,
"KHR_materials_volume") == 0)
4752 out_material->has_volume = 1;
4753 i = cgltf_parse_json_volume(options, tokens, i + 1, json_chunk, &out_material->volume);
4755 else if (cgltf_json_strcmp(tokens+i, json_chunk,
"KHR_materials_sheen") == 0)
4757 out_material->has_sheen = 1;
4758 i = cgltf_parse_json_sheen(options, tokens, i + 1, json_chunk, &out_material->sheen);
4760 else if (cgltf_json_strcmp(tokens + i, json_chunk,
"KHR_materials_emissive_strength") == 0)
4762 out_material->has_emissive_strength = 1;
4763 i = cgltf_parse_json_emissive_strength(tokens, i + 1, json_chunk, &out_material->emissive_strength);
4765 else if (cgltf_json_strcmp(tokens + i, json_chunk,
"KHR_materials_iridescence") == 0)
4767 out_material->has_iridescence = 1;
4768 i = cgltf_parse_json_iridescence(options, tokens, i + 1, json_chunk, &out_material->iridescence);
4770 else if (cgltf_json_strcmp(tokens + i, json_chunk,
"KHR_materials_anisotropy") == 0)
4772 out_material->has_anisotropy = 1;
4773 i = cgltf_parse_json_anisotropy(options, tokens, i + 1, json_chunk, &out_material->anisotropy);
4775 else if (cgltf_json_strcmp(tokens + i, json_chunk,
"KHR_materials_dispersion") == 0)
4777 out_material->has_dispersion = 1;
4778 i = cgltf_parse_json_dispersion(tokens, i + 1, json_chunk, &out_material->dispersion);
4782 i = cgltf_parse_json_unprocessed_extension(options, tokens, i, json_chunk, &(out_material->extensions[out_material->extensions_count++]));
4793 i = cgltf_skip_json(tokens, i+1);
4805static int cgltf_parse_json_accessors(
cgltf_options* options, jsmntok_t
const* tokens,
int i,
const uint8_t* json_chunk,
cgltf_data* out_data)
4807 i = cgltf_parse_json_array(options, tokens, i, json_chunk,
sizeof(
cgltf_accessor), (
void**)&out_data->accessors, &out_data->accessors_count);
4813 for (cgltf_size j = 0; j < out_data->accessors_count; ++j)
4815 i = cgltf_parse_json_accessor(options, tokens, i, json_chunk, &out_data->accessors[j]);
4824static int cgltf_parse_json_materials(
cgltf_options* options, jsmntok_t
const* tokens,
int i,
const uint8_t* json_chunk,
cgltf_data* out_data)
4826 i = cgltf_parse_json_array(options, tokens, i, json_chunk,
sizeof(
cgltf_material), (
void**)&out_data->materials, &out_data->materials_count);
4832 for (cgltf_size j = 0; j < out_data->materials_count; ++j)
4834 i = cgltf_parse_json_material(options, tokens, i, json_chunk, &out_data->materials[j]);
4843static int cgltf_parse_json_images(
cgltf_options* options, jsmntok_t
const* tokens,
int i,
const uint8_t* json_chunk,
cgltf_data* out_data)
4845 i = cgltf_parse_json_array(options, tokens, i, json_chunk,
sizeof(
cgltf_image), (
void**)&out_data->images, &out_data->images_count);
4851 for (cgltf_size j = 0; j < out_data->images_count; ++j)
4853 i = cgltf_parse_json_image(options, tokens, i, json_chunk, &out_data->images[j]);
4862static int cgltf_parse_json_textures(
cgltf_options* options, jsmntok_t
const* tokens,
int i,
const uint8_t* json_chunk,
cgltf_data* out_data)
4864 i = cgltf_parse_json_array(options, tokens, i, json_chunk,
sizeof(
cgltf_texture), (
void**)&out_data->textures, &out_data->textures_count);
4870 for (cgltf_size j = 0; j < out_data->textures_count; ++j)
4872 i = cgltf_parse_json_texture(options, tokens, i, json_chunk, &out_data->textures[j]);
4881static int cgltf_parse_json_samplers(
cgltf_options* options, jsmntok_t
const* tokens,
int i,
const uint8_t* json_chunk,
cgltf_data* out_data)
4883 i = cgltf_parse_json_array(options, tokens, i, json_chunk,
sizeof(
cgltf_sampler), (
void**)&out_data->samplers, &out_data->samplers_count);
4889 for (cgltf_size j = 0; j < out_data->samplers_count; ++j)
4891 i = cgltf_parse_json_sampler(options, tokens, i, json_chunk, &out_data->samplers[j]);
4903 CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
4905 int size = tokens[i].size;
4908 for (
int j = 0; j < size; ++j)
4910 CGLTF_CHECK_KEY(tokens[i]);
4912 if (cgltf_json_strcmp(tokens+i, json_chunk,
"buffer") == 0)
4915 out_meshopt_compression->buffer = CGLTF_PTRINDEX(
cgltf_buffer, cgltf_json_to_int(tokens + i, json_chunk));
4918 else if (cgltf_json_strcmp(tokens+i, json_chunk,
"byteOffset") == 0)
4921 out_meshopt_compression->offset = cgltf_json_to_size(tokens+i, json_chunk);
4924 else if (cgltf_json_strcmp(tokens+i, json_chunk,
"byteLength") == 0)
4927 out_meshopt_compression->size = cgltf_json_to_size(tokens+i, json_chunk);
4930 else if (cgltf_json_strcmp(tokens+i, json_chunk,
"byteStride") == 0)
4933 out_meshopt_compression->stride = cgltf_json_to_size(tokens+i, json_chunk);
4936 else if (cgltf_json_strcmp(tokens+i, json_chunk,
"count") == 0)
4939 out_meshopt_compression->count = cgltf_json_to_size(tokens+i, json_chunk);
4942 else if (cgltf_json_strcmp(tokens+i, json_chunk,
"mode") == 0)
4945 if (cgltf_json_strcmp(tokens+i, json_chunk,
"ATTRIBUTES") == 0)
4947 out_meshopt_compression->mode = cgltf_meshopt_compression_mode_attributes;
4949 else if (cgltf_json_strcmp(tokens+i, json_chunk,
"TRIANGLES") == 0)
4951 out_meshopt_compression->mode = cgltf_meshopt_compression_mode_triangles;
4953 else if (cgltf_json_strcmp(tokens+i, json_chunk,
"INDICES") == 0)
4955 out_meshopt_compression->mode = cgltf_meshopt_compression_mode_indices;
4959 else if (cgltf_json_strcmp(tokens+i, json_chunk,
"filter") == 0)
4962 if (cgltf_json_strcmp(tokens+i, json_chunk,
"NONE") == 0)
4964 out_meshopt_compression->filter = cgltf_meshopt_compression_filter_none;
4966 else if (cgltf_json_strcmp(tokens+i, json_chunk,
"OCTAHEDRAL") == 0)
4968 out_meshopt_compression->filter = cgltf_meshopt_compression_filter_octahedral;
4970 else if (cgltf_json_strcmp(tokens+i, json_chunk,
"QUATERNION") == 0)
4972 out_meshopt_compression->filter = cgltf_meshopt_compression_filter_quaternion;
4974 else if (cgltf_json_strcmp(tokens+i, json_chunk,
"EXPONENTIAL") == 0)
4976 out_meshopt_compression->filter = cgltf_meshopt_compression_filter_exponential;
4982 i = cgltf_skip_json(tokens, i+1);
4994static 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)
4996 CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
4998 int size = tokens[i].size;
5001 for (
int j = 0; j < size; ++j)
5003 CGLTF_CHECK_KEY(tokens[i]);
5005 if (cgltf_json_strcmp(tokens + i, json_chunk,
"name") == 0)
5007 i = cgltf_parse_json_string(options, tokens, i + 1, json_chunk, &out_buffer_view->name);
5009 else if (cgltf_json_strcmp(tokens+i, json_chunk,
"buffer") == 0)
5012 out_buffer_view->buffer = CGLTF_PTRINDEX(
cgltf_buffer, cgltf_json_to_int(tokens + i, json_chunk));
5015 else if (cgltf_json_strcmp(tokens+i, json_chunk,
"byteOffset") == 0)
5018 out_buffer_view->offset =
5019 cgltf_json_to_size(tokens+i, json_chunk);
5022 else if (cgltf_json_strcmp(tokens+i, json_chunk,
"byteLength") == 0)
5025 out_buffer_view->size =
5026 cgltf_json_to_size(tokens+i, json_chunk);
5029 else if (cgltf_json_strcmp(tokens+i, json_chunk,
"byteStride") == 0)
5032 out_buffer_view->stride =
5033 cgltf_json_to_size(tokens+i, json_chunk);
5036 else if (cgltf_json_strcmp(tokens+i, json_chunk,
"target") == 0)
5039 int type = cgltf_json_to_int(tokens+i, json_chunk);
5043 type = cgltf_buffer_view_type_vertices;
5046 type = cgltf_buffer_view_type_indices;
5049 type = cgltf_buffer_view_type_invalid;
5052 out_buffer_view->type = (cgltf_buffer_view_type)type;
5055 else if (cgltf_json_strcmp(tokens + i, json_chunk,
"extras") == 0)
5057 i = cgltf_parse_json_extras(options, tokens, i + 1, json_chunk, &out_buffer_view->extras);
5059 else if (cgltf_json_strcmp(tokens + i, json_chunk,
"extensions") == 0)
5063 CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
5064 if(out_buffer_view->extensions)
5066 return CGLTF_ERROR_JSON;
5069 int extensions_size = tokens[i].size;
5070 out_buffer_view->extensions_count = 0;
5073 if (!out_buffer_view->extensions)
5075 return CGLTF_ERROR_NOMEM;
5079 for (
int k = 0; k < extensions_size; ++k)
5081 CGLTF_CHECK_KEY(tokens[i]);
5083 if (cgltf_json_strcmp(tokens+i, json_chunk,
"EXT_meshopt_compression") == 0)
5085 out_buffer_view->has_meshopt_compression = 1;
5086 i = cgltf_parse_json_meshopt_compression(options, tokens, i + 1, json_chunk, &out_buffer_view->meshopt_compression);
5090 i = cgltf_parse_json_unprocessed_extension(options, tokens, i, json_chunk, &(out_buffer_view->extensions[out_buffer_view->extensions_count++]));
5101 i = cgltf_skip_json(tokens, i+1);
5113static int cgltf_parse_json_buffer_views(
cgltf_options* options, jsmntok_t
const* tokens,
int i,
const uint8_t* json_chunk,
cgltf_data* out_data)
5115 i = cgltf_parse_json_array(options, tokens, i, json_chunk,
sizeof(
cgltf_buffer_view), (
void**)&out_data->buffer_views, &out_data->buffer_views_count);
5121 for (cgltf_size j = 0; j < out_data->buffer_views_count; ++j)
5123 i = cgltf_parse_json_buffer_view(options, tokens, i, json_chunk, &out_data->buffer_views[j]);
5132static int cgltf_parse_json_buffer(
cgltf_options* options, jsmntok_t
const* tokens,
int i,
const uint8_t* json_chunk,
cgltf_buffer* out_buffer)
5134 CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
5136 int size = tokens[i].size;
5139 for (
int j = 0; j < size; ++j)
5141 CGLTF_CHECK_KEY(tokens[i]);
5143 if (cgltf_json_strcmp(tokens + i, json_chunk,
"name") == 0)
5145 i = cgltf_parse_json_string(options, tokens, i + 1, json_chunk, &out_buffer->name);
5147 else if (cgltf_json_strcmp(tokens+i, json_chunk,
"byteLength") == 0)
5151 cgltf_json_to_size(tokens+i, json_chunk);
5154 else if (cgltf_json_strcmp(tokens+i, json_chunk,
"uri") == 0)
5156 i = cgltf_parse_json_string(options, tokens, i + 1, json_chunk, &out_buffer->uri);
5158 else if (cgltf_json_strcmp(tokens + i, json_chunk,
"extras") == 0)
5160 i = cgltf_parse_json_extras(options, tokens, i + 1, json_chunk, &out_buffer->extras);
5162 else if (cgltf_json_strcmp(tokens + i, json_chunk,
"extensions") == 0)
5164 i = cgltf_parse_json_unprocessed_extensions(options, tokens, i, json_chunk, &out_buffer->extensions_count, &out_buffer->extensions);
5168 i = cgltf_skip_json(tokens, i+1);
5180static int cgltf_parse_json_buffers(
cgltf_options* options, jsmntok_t
const* tokens,
int i,
const uint8_t* json_chunk,
cgltf_data* out_data)
5182 i = cgltf_parse_json_array(options, tokens, i, json_chunk,
sizeof(
cgltf_buffer), (
void**)&out_data->buffers, &out_data->buffers_count);
5188 for (cgltf_size j = 0; j < out_data->buffers_count; ++j)
5190 i = cgltf_parse_json_buffer(options, tokens, i, json_chunk, &out_data->buffers[j]);
5199static int cgltf_parse_json_skin(
cgltf_options* options, jsmntok_t
const* tokens,
int i,
const uint8_t* json_chunk,
cgltf_skin* out_skin)
5201 CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
5203 int size = tokens[i].size;
5206 for (
int j = 0; j < size; ++j)
5208 CGLTF_CHECK_KEY(tokens[i]);
5210 if (cgltf_json_strcmp(tokens+i, json_chunk,
"name") == 0)
5212 i = cgltf_parse_json_string(options, tokens, i + 1, json_chunk, &out_skin->name);
5214 else if (cgltf_json_strcmp(tokens+i, json_chunk,
"joints") == 0)
5216 i = cgltf_parse_json_array(options, tokens, i + 1, json_chunk,
sizeof(
cgltf_node*), (
void**)&out_skin->joints, &out_skin->joints_count);
5222 for (cgltf_size k = 0; k < out_skin->joints_count; ++k)
5224 out_skin->joints[k] = CGLTF_PTRINDEX(
cgltf_node, cgltf_json_to_int(tokens + i, json_chunk));
5228 else if (cgltf_json_strcmp(tokens+i, json_chunk,
"skeleton") == 0)
5231 CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_PRIMITIVE);
5232 out_skin->skeleton = CGLTF_PTRINDEX(
cgltf_node, cgltf_json_to_int(tokens + i, json_chunk));
5235 else if (cgltf_json_strcmp(tokens+i, json_chunk,
"inverseBindMatrices") == 0)
5238 CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_PRIMITIVE);
5239 out_skin->inverse_bind_matrices = CGLTF_PTRINDEX(
cgltf_accessor, cgltf_json_to_int(tokens + i, json_chunk));
5242 else if (cgltf_json_strcmp(tokens + i, json_chunk,
"extras") == 0)
5244 i = cgltf_parse_json_extras(options, tokens, i + 1, json_chunk, &out_skin->extras);
5246 else if (cgltf_json_strcmp(tokens + i, json_chunk,
"extensions") == 0)
5248 i = cgltf_parse_json_unprocessed_extensions(options, tokens, i, json_chunk, &out_skin->extensions_count, &out_skin->extensions);
5252 i = cgltf_skip_json(tokens, i+1);
5264static int cgltf_parse_json_skins(
cgltf_options* options, jsmntok_t
const* tokens,
int i,
const uint8_t* json_chunk,
cgltf_data* out_data)
5266 i = cgltf_parse_json_array(options, tokens, i, json_chunk,
sizeof(
cgltf_skin), (
void**)&out_data->skins, &out_data->skins_count);
5272 for (cgltf_size j = 0; j < out_data->skins_count; ++j)
5274 i = cgltf_parse_json_skin(options, tokens, i, json_chunk, &out_data->skins[j]);
5283static int cgltf_parse_json_camera(
cgltf_options* options, jsmntok_t
const* tokens,
int i,
const uint8_t* json_chunk,
cgltf_camera* out_camera)
5285 CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
5287 int size = tokens[i].size;
5290 for (
int j = 0; j < size; ++j)
5292 CGLTF_CHECK_KEY(tokens[i]);
5294 if (cgltf_json_strcmp(tokens+i, json_chunk,
"name") == 0)
5296 i = cgltf_parse_json_string(options, tokens, i + 1, json_chunk, &out_camera->name);
5298 else if (cgltf_json_strcmp(tokens+i, json_chunk,
"perspective") == 0)
5302 CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
5304 int data_size = tokens[i].size;
5307 if (out_camera->type != cgltf_camera_type_invalid)
5309 return CGLTF_ERROR_JSON;
5312 out_camera->type = cgltf_camera_type_perspective;
5314 for (
int k = 0; k < data_size; ++k)
5316 CGLTF_CHECK_KEY(tokens[i]);
5318 if (cgltf_json_strcmp(tokens+i, json_chunk,
"aspectRatio") == 0)
5321 out_camera->data.perspective.has_aspect_ratio = 1;
5322 out_camera->data.perspective.aspect_ratio = cgltf_json_to_float(tokens + i, json_chunk);
5325 else if (cgltf_json_strcmp(tokens+i, json_chunk,
"yfov") == 0)
5328 out_camera->data.perspective.yfov = cgltf_json_to_float(tokens + i, json_chunk);
5331 else if (cgltf_json_strcmp(tokens+i, json_chunk,
"zfar") == 0)
5334 out_camera->data.perspective.has_zfar = 1;
5335 out_camera->data.perspective.zfar = cgltf_json_to_float(tokens + i, json_chunk);
5338 else if (cgltf_json_strcmp(tokens+i, json_chunk,
"znear") == 0)
5341 out_camera->data.perspective.znear = cgltf_json_to_float(tokens + i, json_chunk);
5344 else if (cgltf_json_strcmp(tokens + i, json_chunk,
"extras") == 0)
5346 i = cgltf_parse_json_extras(options, tokens, i + 1, json_chunk, &out_camera->data.perspective.extras);
5350 i = cgltf_skip_json(tokens, i+1);
5359 else if (cgltf_json_strcmp(tokens+i, json_chunk,
"orthographic") == 0)
5363 CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
5365 int data_size = tokens[i].size;
5368 if (out_camera->type != cgltf_camera_type_invalid)
5370 return CGLTF_ERROR_JSON;
5373 out_camera->type = cgltf_camera_type_orthographic;
5375 for (
int k = 0; k < data_size; ++k)
5377 CGLTF_CHECK_KEY(tokens[i]);
5379 if (cgltf_json_strcmp(tokens+i, json_chunk,
"xmag") == 0)
5382 out_camera->data.orthographic.xmag = cgltf_json_to_float(tokens + i, json_chunk);
5385 else if (cgltf_json_strcmp(tokens+i, json_chunk,
"ymag") == 0)
5388 out_camera->data.orthographic.ymag = cgltf_json_to_float(tokens + i, json_chunk);
5391 else if (cgltf_json_strcmp(tokens+i, json_chunk,
"zfar") == 0)
5394 out_camera->data.orthographic.zfar = cgltf_json_to_float(tokens + i, json_chunk);
5397 else if (cgltf_json_strcmp(tokens+i, json_chunk,
"znear") == 0)
5400 out_camera->data.orthographic.znear = cgltf_json_to_float(tokens + i, json_chunk);
5403 else if (cgltf_json_strcmp(tokens + i, json_chunk,
"extras") == 0)
5405 i = cgltf_parse_json_extras(options, tokens, i + 1, json_chunk, &out_camera->data.orthographic.extras);
5409 i = cgltf_skip_json(tokens, i+1);
5418 else if (cgltf_json_strcmp(tokens + i, json_chunk,
"extras") == 0)
5420 i = cgltf_parse_json_extras(options, tokens, i + 1, json_chunk, &out_camera->extras);
5422 else if (cgltf_json_strcmp(tokens + i, json_chunk,
"extensions") == 0)
5424 i = cgltf_parse_json_unprocessed_extensions(options, tokens, i, json_chunk, &out_camera->extensions_count, &out_camera->extensions);
5428 i = cgltf_skip_json(tokens, i+1);
5440static int cgltf_parse_json_cameras(
cgltf_options* options, jsmntok_t
const* tokens,
int i,
const uint8_t* json_chunk,
cgltf_data* out_data)
5442 i = cgltf_parse_json_array(options, tokens, i, json_chunk,
sizeof(
cgltf_camera), (
void**)&out_data->cameras, &out_data->cameras_count);
5448 for (cgltf_size j = 0; j < out_data->cameras_count; ++j)
5450 i = cgltf_parse_json_camera(options, tokens, i, json_chunk, &out_data->cameras[j]);
5459static int cgltf_parse_json_light(
cgltf_options* options, jsmntok_t
const* tokens,
int i,
const uint8_t* json_chunk,
cgltf_light* out_light)
5461 CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
5463 out_light->color[0] = 1.f;
5464 out_light->color[1] = 1.f;
5465 out_light->color[2] = 1.f;
5466 out_light->intensity = 1.f;
5468 out_light->spot_inner_cone_angle = 0.f;
5469 out_light->spot_outer_cone_angle = 3.1415926535f / 4.0f;
5471 int size = tokens[i].size;
5474 for (
int j = 0; j < size; ++j)
5476 CGLTF_CHECK_KEY(tokens[i]);
5478 if (cgltf_json_strcmp(tokens+i, json_chunk,
"name") == 0)
5480 i = cgltf_parse_json_string(options, tokens, i + 1, json_chunk, &out_light->name);
5482 else if (cgltf_json_strcmp(tokens + i, json_chunk,
"color") == 0)
5484 i = cgltf_parse_json_float_array(tokens, i + 1, json_chunk, out_light->color, 3);
5486 else if (cgltf_json_strcmp(tokens + i, json_chunk,
"intensity") == 0)
5489 out_light->intensity = cgltf_json_to_float(tokens + i, json_chunk);
5492 else if (cgltf_json_strcmp(tokens+i, json_chunk,
"type") == 0)
5495 if (cgltf_json_strcmp(tokens + i, json_chunk,
"directional") == 0)
5497 out_light->type = cgltf_light_type_directional;
5499 else if (cgltf_json_strcmp(tokens + i, json_chunk,
"point") == 0)
5501 out_light->type = cgltf_light_type_point;
5503 else if (cgltf_json_strcmp(tokens + i, json_chunk,
"spot") == 0)
5505 out_light->type = cgltf_light_type_spot;
5509 else if (cgltf_json_strcmp(tokens + i, json_chunk,
"range") == 0)
5512 out_light->range = cgltf_json_to_float(tokens + i, json_chunk);
5515 else if (cgltf_json_strcmp(tokens+i, json_chunk,
"spot") == 0)
5519 CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
5521 int data_size = tokens[i].size;
5524 for (
int k = 0; k < data_size; ++k)
5526 CGLTF_CHECK_KEY(tokens[i]);
5528 if (cgltf_json_strcmp(tokens+i, json_chunk,
"innerConeAngle") == 0)
5531 out_light->spot_inner_cone_angle = cgltf_json_to_float(tokens + i, json_chunk);
5534 else if (cgltf_json_strcmp(tokens+i, json_chunk,
"outerConeAngle") == 0)
5537 out_light->spot_outer_cone_angle = cgltf_json_to_float(tokens + i, json_chunk);
5542 i = cgltf_skip_json(tokens, i+1);
5551 else if (cgltf_json_strcmp(tokens + i, json_chunk,
"extras") == 0)
5553 i = cgltf_parse_json_extras(options, tokens, i + 1, json_chunk, &out_light->extras);
5557 i = cgltf_skip_json(tokens, i+1);
5569static int cgltf_parse_json_lights(
cgltf_options* options, jsmntok_t
const* tokens,
int i,
const uint8_t* json_chunk,
cgltf_data* out_data)
5571 i = cgltf_parse_json_array(options, tokens, i, json_chunk,
sizeof(
cgltf_light), (
void**)&out_data->lights, &out_data->lights_count);
5577 for (cgltf_size j = 0; j < out_data->lights_count; ++j)
5579 i = cgltf_parse_json_light(options, tokens, i, json_chunk, &out_data->lights[j]);
5588static int cgltf_parse_json_node(
cgltf_options* options, jsmntok_t
const* tokens,
int i,
const uint8_t* json_chunk,
cgltf_node* out_node)
5590 CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
5592 out_node->rotation[3] = 1.0f;
5593 out_node->scale[0] = 1.0f;
5594 out_node->scale[1] = 1.0f;
5595 out_node->scale[2] = 1.0f;
5596 out_node->matrix[0] = 1.0f;
5597 out_node->matrix[5] = 1.0f;
5598 out_node->matrix[10] = 1.0f;
5599 out_node->matrix[15] = 1.0f;
5601 int size = tokens[i].size;
5604 for (
int j = 0; j < size; ++j)
5606 CGLTF_CHECK_KEY(tokens[i]);
5608 if (cgltf_json_strcmp(tokens+i, json_chunk,
"name") == 0)
5610 i = cgltf_parse_json_string(options, tokens, i + 1, json_chunk, &out_node->name);
5612 else if (cgltf_json_strcmp(tokens+i, json_chunk,
"children") == 0)
5614 i = cgltf_parse_json_array(options, tokens, i + 1, json_chunk,
sizeof(
cgltf_node*), (
void**)&out_node->children, &out_node->children_count);
5620 for (cgltf_size k = 0; k < out_node->children_count; ++k)
5622 out_node->children[k] = CGLTF_PTRINDEX(
cgltf_node, cgltf_json_to_int(tokens + i, json_chunk));
5626 else if (cgltf_json_strcmp(tokens+i, json_chunk,
"mesh") == 0)
5629 CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_PRIMITIVE);
5630 out_node->mesh = CGLTF_PTRINDEX(
cgltf_mesh, cgltf_json_to_int(tokens + i, json_chunk));
5633 else if (cgltf_json_strcmp(tokens+i, json_chunk,
"skin") == 0)
5636 CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_PRIMITIVE);
5637 out_node->skin = CGLTF_PTRINDEX(
cgltf_skin, cgltf_json_to_int(tokens + i, json_chunk));
5640 else if (cgltf_json_strcmp(tokens+i, json_chunk,
"camera") == 0)
5643 CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_PRIMITIVE);
5644 out_node->camera = CGLTF_PTRINDEX(
cgltf_camera, cgltf_json_to_int(tokens + i, json_chunk));
5647 else if (cgltf_json_strcmp(tokens+i, json_chunk,
"translation") == 0)
5649 out_node->has_translation = 1;
5650 i = cgltf_parse_json_float_array(tokens, i + 1, json_chunk, out_node->translation, 3);
5652 else if (cgltf_json_strcmp(tokens+i, json_chunk,
"rotation") == 0)
5654 out_node->has_rotation = 1;
5655 i = cgltf_parse_json_float_array(tokens, i + 1, json_chunk, out_node->rotation, 4);
5657 else if (cgltf_json_strcmp(tokens+i, json_chunk,
"scale") == 0)
5659 out_node->has_scale = 1;
5660 i = cgltf_parse_json_float_array(tokens, i + 1, json_chunk, out_node->scale, 3);
5662 else if (cgltf_json_strcmp(tokens+i, json_chunk,
"matrix") == 0)
5664 out_node->has_matrix = 1;
5665 i = cgltf_parse_json_float_array(tokens, i + 1, json_chunk, out_node->matrix, 16);
5667 else if (cgltf_json_strcmp(tokens + i, json_chunk,
"weights") == 0)
5669 i = cgltf_parse_json_array(options, tokens, i + 1, json_chunk,
sizeof(cgltf_float), (
void**)&out_node->weights, &out_node->weights_count);
5675 i = cgltf_parse_json_float_array(tokens, i - 1, json_chunk, out_node->weights, (
int)out_node->weights_count);
5677 else if (cgltf_json_strcmp(tokens + i, json_chunk,
"extras") == 0)
5679 i = cgltf_parse_json_extras(options, tokens, i + 1, json_chunk, &out_node->extras);
5681 else if (cgltf_json_strcmp(tokens + i, json_chunk,
"extensions") == 0)
5685 CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
5686 if(out_node->extensions)
5688 return CGLTF_ERROR_JSON;
5691 int extensions_size = tokens[i].size;
5692 out_node->extensions_count= 0;
5695 if (!out_node->extensions)
5697 return CGLTF_ERROR_NOMEM;
5702 for (
int k = 0; k < extensions_size; ++k)
5704 CGLTF_CHECK_KEY(tokens[i]);
5706 if (cgltf_json_strcmp(tokens+i, json_chunk,
"KHR_lights_punctual") == 0)
5710 CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
5712 int data_size = tokens[i].size;
5715 for (
int m = 0; m < data_size; ++m)
5717 CGLTF_CHECK_KEY(tokens[i]);
5719 if (cgltf_json_strcmp(tokens + i, json_chunk,
"light") == 0)
5722 CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_PRIMITIVE);
5723 out_node->light = CGLTF_PTRINDEX(
cgltf_light, cgltf_json_to_int(tokens + i, json_chunk));
5728 i = cgltf_skip_json(tokens, i + 1);
5737 else if (cgltf_json_strcmp(tokens + i, json_chunk,
"EXT_mesh_gpu_instancing") == 0)
5739 out_node->has_mesh_gpu_instancing = 1;
5740 i = cgltf_parse_json_mesh_gpu_instancing(options, tokens, i + 1, json_chunk, &out_node->mesh_gpu_instancing);
5744 i = cgltf_parse_json_unprocessed_extension(options, tokens, i, json_chunk, &(out_node->extensions[out_node->extensions_count++]));
5755 i = cgltf_skip_json(tokens, i+1);
5767static int cgltf_parse_json_nodes(
cgltf_options* options, jsmntok_t
const* tokens,
int i,
const uint8_t* json_chunk,
cgltf_data* out_data)
5769 i = cgltf_parse_json_array(options, tokens, i, json_chunk,
sizeof(
cgltf_node), (
void**)&out_data->nodes, &out_data->nodes_count);
5775 for (cgltf_size j = 0; j < out_data->nodes_count; ++j)
5777 i = cgltf_parse_json_node(options, tokens, i, json_chunk, &out_data->nodes[j]);
5786static int cgltf_parse_json_scene(
cgltf_options* options, jsmntok_t
const* tokens,
int i,
const uint8_t* json_chunk,
cgltf_scene* out_scene)
5788 CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
5790 int size = tokens[i].size;
5793 for (
int j = 0; j < size; ++j)
5795 CGLTF_CHECK_KEY(tokens[i]);
5797 if (cgltf_json_strcmp(tokens+i, json_chunk,
"name") == 0)
5799 i = cgltf_parse_json_string(options, tokens, i + 1, json_chunk, &out_scene->name);
5801 else if (cgltf_json_strcmp(tokens+i, json_chunk,
"nodes") == 0)
5803 i = cgltf_parse_json_array(options, tokens, i + 1, json_chunk,
sizeof(
cgltf_node*), (
void**)&out_scene->nodes, &out_scene->nodes_count);
5809 for (cgltf_size k = 0; k < out_scene->nodes_count; ++k)
5811 out_scene->nodes[k] = CGLTF_PTRINDEX(
cgltf_node, cgltf_json_to_int(tokens + i, json_chunk));
5815 else if (cgltf_json_strcmp(tokens + i, json_chunk,
"extras") == 0)
5817 i = cgltf_parse_json_extras(options, tokens, i + 1, json_chunk, &out_scene->extras);
5819 else if (cgltf_json_strcmp(tokens + i, json_chunk,
"extensions") == 0)
5821 i = cgltf_parse_json_unprocessed_extensions(options, tokens, i, json_chunk, &out_scene->extensions_count, &out_scene->extensions);
5825 i = cgltf_skip_json(tokens, i+1);
5837static int cgltf_parse_json_scenes(
cgltf_options* options, jsmntok_t
const* tokens,
int i,
const uint8_t* json_chunk,
cgltf_data* out_data)
5839 i = cgltf_parse_json_array(options, tokens, i, json_chunk,
sizeof(
cgltf_scene), (
void**)&out_data->scenes, &out_data->scenes_count);
5845 for (cgltf_size j = 0; j < out_data->scenes_count; ++j)
5847 i = cgltf_parse_json_scene(options, tokens, i, json_chunk, &out_data->scenes[j]);
5859 CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
5861 int size = tokens[i].size;
5864 for (
int j = 0; j < size; ++j)
5866 CGLTF_CHECK_KEY(tokens[i]);
5868 if (cgltf_json_strcmp(tokens+i, json_chunk,
"input") == 0)
5871 out_sampler->input = CGLTF_PTRINDEX(
cgltf_accessor, cgltf_json_to_int(tokens + i, json_chunk));
5874 else if (cgltf_json_strcmp(tokens+i, json_chunk,
"output") == 0)
5877 out_sampler->output = CGLTF_PTRINDEX(
cgltf_accessor, cgltf_json_to_int(tokens + i, json_chunk));
5880 else if (cgltf_json_strcmp(tokens+i, json_chunk,
"interpolation") == 0)
5883 if (cgltf_json_strcmp(tokens + i, json_chunk,
"LINEAR") == 0)
5885 out_sampler->interpolation = cgltf_interpolation_type_linear;
5887 else if (cgltf_json_strcmp(tokens + i, json_chunk,
"STEP") == 0)
5889 out_sampler->interpolation = cgltf_interpolation_type_step;
5891 else if (cgltf_json_strcmp(tokens + i, json_chunk,
"CUBICSPLINE") == 0)
5893 out_sampler->interpolation = cgltf_interpolation_type_cubic_spline;
5897 else if (cgltf_json_strcmp(tokens + i, json_chunk,
"extras") == 0)
5899 i = cgltf_parse_json_extras(options, tokens, i + 1, json_chunk, &out_sampler->extras);
5901 else if (cgltf_json_strcmp(tokens + i, json_chunk,
"extensions") == 0)
5903 i = cgltf_parse_json_unprocessed_extensions(options, tokens, i, json_chunk, &out_sampler->extensions_count, &out_sampler->extensions);
5907 i = cgltf_skip_json(tokens, i+1);
5922 CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
5924 int size = tokens[i].size;
5927 for (
int j = 0; j < size; ++j)
5929 CGLTF_CHECK_KEY(tokens[i]);
5931 if (cgltf_json_strcmp(tokens+i, json_chunk,
"sampler") == 0)
5937 else if (cgltf_json_strcmp(tokens+i, json_chunk,
"target") == 0)
5941 CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
5943 int target_size = tokens[i].size;
5946 for (
int k = 0; k < target_size; ++k)
5948 CGLTF_CHECK_KEY(tokens[i]);
5950 if (cgltf_json_strcmp(tokens+i, json_chunk,
"node") == 0)
5953 out_channel->target_node = CGLTF_PTRINDEX(
cgltf_node, cgltf_json_to_int(tokens + i, json_chunk));
5956 else if (cgltf_json_strcmp(tokens+i, json_chunk,
"path") == 0)
5959 if (cgltf_json_strcmp(tokens+i, json_chunk,
"translation") == 0)
5961 out_channel->target_path = cgltf_animation_path_type_translation;
5963 else if (cgltf_json_strcmp(tokens+i, json_chunk,
"rotation") == 0)
5965 out_channel->target_path = cgltf_animation_path_type_rotation;
5967 else if (cgltf_json_strcmp(tokens+i, json_chunk,
"scale") == 0)
5969 out_channel->target_path = cgltf_animation_path_type_scale;
5971 else if (cgltf_json_strcmp(tokens+i, json_chunk,
"weights") == 0)
5973 out_channel->target_path = cgltf_animation_path_type_weights;
5977 else if (cgltf_json_strcmp(tokens + i, json_chunk,
"extras") == 0)
5979 i = cgltf_parse_json_extras(options, tokens, i + 1, json_chunk, &out_channel->extras);
5981 else if (cgltf_json_strcmp(tokens + i, json_chunk,
"extensions") == 0)
5983 i = cgltf_parse_json_unprocessed_extensions(options, tokens, i, json_chunk, &out_channel->extensions_count, &out_channel->extensions);
5987 i = cgltf_skip_json(tokens, i+1);
5998 i = cgltf_skip_json(tokens, i+1);
6010static int cgltf_parse_json_animation(
cgltf_options* options, jsmntok_t
const* tokens,
int i,
const uint8_t* json_chunk,
cgltf_animation* out_animation)
6012 CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
6014 int size = tokens[i].size;
6017 for (
int j = 0; j < size; ++j)
6019 CGLTF_CHECK_KEY(tokens[i]);
6021 if (cgltf_json_strcmp(tokens+i, json_chunk,
"name") == 0)
6023 i = cgltf_parse_json_string(options, tokens, i + 1, json_chunk, &out_animation->name);
6025 else if (cgltf_json_strcmp(tokens+i, json_chunk,
"samplers") == 0)
6027 i = cgltf_parse_json_array(options, tokens, i + 1, json_chunk,
sizeof(
cgltf_animation_sampler), (
void**)&out_animation->samplers, &out_animation->samplers_count);
6033 for (cgltf_size k = 0; k < out_animation->samplers_count; ++k)
6035 i = cgltf_parse_json_animation_sampler(options, tokens, i, json_chunk, &out_animation->samplers[k]);
6042 else if (cgltf_json_strcmp(tokens+i, json_chunk,
"channels") == 0)
6044 i = cgltf_parse_json_array(options, tokens, i + 1, json_chunk,
sizeof(
cgltf_animation_channel), (
void**)&out_animation->channels, &out_animation->channels_count);
6050 for (cgltf_size k = 0; k < out_animation->channels_count; ++k)
6052 i = cgltf_parse_json_animation_channel(options, tokens, i, json_chunk, &out_animation->channels[k]);
6059 else if (cgltf_json_strcmp(tokens + i, json_chunk,
"extras") == 0)
6061 i = cgltf_parse_json_extras(options, tokens, i + 1, json_chunk, &out_animation->extras);
6063 else if (cgltf_json_strcmp(tokens + i, json_chunk,
"extensions") == 0)
6065 i = cgltf_parse_json_unprocessed_extensions(options, tokens, i, json_chunk, &out_animation->extensions_count, &out_animation->extensions);
6069 i = cgltf_skip_json(tokens, i+1);
6081static int cgltf_parse_json_animations(
cgltf_options* options, jsmntok_t
const* tokens,
int i,
const uint8_t* json_chunk,
cgltf_data* out_data)
6083 i = cgltf_parse_json_array(options, tokens, i, json_chunk,
sizeof(
cgltf_animation), (
void**)&out_data->animations, &out_data->animations_count);
6089 for (cgltf_size j = 0; j < out_data->animations_count; ++j)
6091 i = cgltf_parse_json_animation(options, tokens, i, json_chunk, &out_data->animations[j]);
6102 CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
6104 int size = tokens[i].size;
6107 for (
int j = 0; j < size; ++j)
6109 CGLTF_CHECK_KEY(tokens[i]);
6111 if (cgltf_json_strcmp(tokens+i, json_chunk,
"name") == 0)
6113 i = cgltf_parse_json_string(options, tokens, i + 1, json_chunk, &out_variant->name);
6115 else if (cgltf_json_strcmp(tokens + i, json_chunk,
"extras") == 0)
6117 i = cgltf_parse_json_extras(options, tokens, i + 1, json_chunk, &out_variant->extras);
6121 i = cgltf_skip_json(tokens, i+1);
6133static int cgltf_parse_json_variants(
cgltf_options* options, jsmntok_t
const* tokens,
int i,
const uint8_t* json_chunk,
cgltf_data* out_data)
6135 i = cgltf_parse_json_array(options, tokens, i, json_chunk,
sizeof(
cgltf_material_variant), (
void**)&out_data->variants, &out_data->variants_count);
6141 for (cgltf_size j = 0; j < out_data->variants_count; ++j)
6143 i = cgltf_parse_json_variant(options, tokens, i, json_chunk, &out_data->variants[j]);
6152static int cgltf_parse_json_asset(
cgltf_options* options, jsmntok_t
const* tokens,
int i,
const uint8_t* json_chunk,
cgltf_asset* out_asset)
6154 CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
6156 int size = tokens[i].size;
6159 for (
int j = 0; j < size; ++j)
6161 CGLTF_CHECK_KEY(tokens[i]);
6163 if (cgltf_json_strcmp(tokens+i, json_chunk,
"copyright") == 0)
6165 i = cgltf_parse_json_string(options, tokens, i + 1, json_chunk, &out_asset->copyright);
6167 else if (cgltf_json_strcmp(tokens+i, json_chunk,
"generator") == 0)
6169 i = cgltf_parse_json_string(options, tokens, i + 1, json_chunk, &out_asset->generator);
6171 else if (cgltf_json_strcmp(tokens+i, json_chunk,
"version") == 0)
6173 i = cgltf_parse_json_string(options, tokens, i + 1, json_chunk, &out_asset->version);
6175 else if (cgltf_json_strcmp(tokens+i, json_chunk,
"minVersion") == 0)
6177 i = cgltf_parse_json_string(options, tokens, i + 1, json_chunk, &out_asset->min_version);
6179 else if (cgltf_json_strcmp(tokens + i, json_chunk,
"extras") == 0)
6181 i = cgltf_parse_json_extras(options, tokens, i + 1, json_chunk, &out_asset->extras);
6183 else if (cgltf_json_strcmp(tokens + i, json_chunk,
"extensions") == 0)
6185 i = cgltf_parse_json_unprocessed_extensions(options, tokens, i, json_chunk, &out_asset->extensions_count, &out_asset->extensions);
6189 i = cgltf_skip_json(tokens, i+1);
6198 if (out_asset->version && CGLTF_ATOF(out_asset->version) < 2)
6200 return CGLTF_ERROR_LEGACY;
6206cgltf_size cgltf_num_components(cgltf_type type) {
6209 case cgltf_type_vec2:
6211 case cgltf_type_vec3:
6213 case cgltf_type_vec4:
6215 case cgltf_type_mat2:
6217 case cgltf_type_mat3:
6219 case cgltf_type_mat4:
6221 case cgltf_type_invalid:
6222 case cgltf_type_scalar:
6228cgltf_size cgltf_component_size(cgltf_component_type component_type) {
6229 switch (component_type)
6231 case cgltf_component_type_r_8:
6232 case cgltf_component_type_r_8u:
6234 case cgltf_component_type_r_16:
6235 case cgltf_component_type_r_16u:
6237 case cgltf_component_type_r_32u:
6238 case cgltf_component_type_r_32f:
6240 case cgltf_component_type_invalid:
6246cgltf_size cgltf_calc_size(cgltf_type type, cgltf_component_type component_type)
6248 cgltf_size component_size = cgltf_component_size(component_type);
6249 if (type == cgltf_type_mat2 && component_size == 1)
6251 return 8 * component_size;
6253 else if (type == cgltf_type_mat3 && (component_size == 1 || component_size == 2))
6255 return 12 * component_size;
6257 return component_size * cgltf_num_components(type);
6260static int cgltf_fixup_pointers(
cgltf_data* out_data);
6262static int cgltf_parse_json_root(
cgltf_options* options, jsmntok_t
const* tokens,
int i,
const uint8_t* json_chunk,
cgltf_data* out_data)
6264 CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
6266 int size = tokens[i].size;
6269 for (
int j = 0; j < size; ++j)
6271 CGLTF_CHECK_KEY(tokens[i]);
6273 if (cgltf_json_strcmp(tokens + i, json_chunk,
"asset") == 0)
6275 i = cgltf_parse_json_asset(options, tokens, i + 1, json_chunk, &out_data->asset);
6277 else if (cgltf_json_strcmp(tokens + i, json_chunk,
"meshes") == 0)
6279 i = cgltf_parse_json_meshes(options, tokens, i + 1, json_chunk, out_data);
6281 else if (cgltf_json_strcmp(tokens + i, json_chunk,
"accessors") == 0)
6283 i = cgltf_parse_json_accessors(options, tokens, i + 1, json_chunk, out_data);
6285 else if (cgltf_json_strcmp(tokens + i, json_chunk,
"bufferViews") == 0)
6287 i = cgltf_parse_json_buffer_views(options, tokens, i + 1, json_chunk, out_data);
6289 else if (cgltf_json_strcmp(tokens + i, json_chunk,
"buffers") == 0)
6291 i = cgltf_parse_json_buffers(options, tokens, i + 1, json_chunk, out_data);
6293 else if (cgltf_json_strcmp(tokens + i, json_chunk,
"materials") == 0)
6295 i = cgltf_parse_json_materials(options, tokens, i + 1, json_chunk, out_data);
6297 else if (cgltf_json_strcmp(tokens + i, json_chunk,
"images") == 0)
6299 i = cgltf_parse_json_images(options, tokens, i + 1, json_chunk, out_data);
6301 else if (cgltf_json_strcmp(tokens + i, json_chunk,
"textures") == 0)
6303 i = cgltf_parse_json_textures(options, tokens, i + 1, json_chunk, out_data);
6305 else if (cgltf_json_strcmp(tokens + i, json_chunk,
"samplers") == 0)
6307 i = cgltf_parse_json_samplers(options, tokens, i + 1, json_chunk, out_data);
6309 else if (cgltf_json_strcmp(tokens + i, json_chunk,
"skins") == 0)
6311 i = cgltf_parse_json_skins(options, tokens, i + 1, json_chunk, out_data);
6313 else if (cgltf_json_strcmp(tokens + i, json_chunk,
"cameras") == 0)
6315 i = cgltf_parse_json_cameras(options, tokens, i + 1, json_chunk, out_data);
6317 else if (cgltf_json_strcmp(tokens + i, json_chunk,
"nodes") == 0)
6319 i = cgltf_parse_json_nodes(options, tokens, i + 1, json_chunk, out_data);
6321 else if (cgltf_json_strcmp(tokens + i, json_chunk,
"scenes") == 0)
6323 i = cgltf_parse_json_scenes(options, tokens, i + 1, json_chunk, out_data);
6325 else if (cgltf_json_strcmp(tokens + i, json_chunk,
"scene") == 0)
6328 out_data->scene = CGLTF_PTRINDEX(
cgltf_scene, cgltf_json_to_int(tokens + i, json_chunk));
6331 else if (cgltf_json_strcmp(tokens + i, json_chunk,
"animations") == 0)
6333 i = cgltf_parse_json_animations(options, tokens, i + 1, json_chunk, out_data);
6335 else if (cgltf_json_strcmp(tokens+i, json_chunk,
"extras") == 0)
6337 i = cgltf_parse_json_extras(options, tokens, i + 1, json_chunk, &out_data->extras);
6339 else if (cgltf_json_strcmp(tokens + i, json_chunk,
"extensions") == 0)
6343 CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
6344 if(out_data->data_extensions)
6346 return CGLTF_ERROR_JSON;
6349 int extensions_size = tokens[i].size;
6350 out_data->data_extensions_count = 0;
6353 if (!out_data->data_extensions)
6355 return CGLTF_ERROR_NOMEM;
6360 for (
int k = 0; k < extensions_size; ++k)
6362 CGLTF_CHECK_KEY(tokens[i]);
6364 if (cgltf_json_strcmp(tokens+i, json_chunk,
"KHR_lights_punctual") == 0)
6368 CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
6370 int data_size = tokens[i].size;
6373 for (
int m = 0; m < data_size; ++m)
6375 CGLTF_CHECK_KEY(tokens[i]);
6377 if (cgltf_json_strcmp(tokens + i, json_chunk,
"lights") == 0)
6379 i = cgltf_parse_json_lights(options, tokens, i + 1, json_chunk, out_data);
6383 i = cgltf_skip_json(tokens, i + 1);
6392 else if (cgltf_json_strcmp(tokens+i, json_chunk,
"KHR_materials_variants") == 0)
6396 CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
6398 int data_size = tokens[i].size;
6401 for (
int m = 0; m < data_size; ++m)
6403 CGLTF_CHECK_KEY(tokens[i]);
6405 if (cgltf_json_strcmp(tokens + i, json_chunk,
"variants") == 0)
6407 i = cgltf_parse_json_variants(options, tokens, i + 1, json_chunk, out_data);
6411 i = cgltf_skip_json(tokens, i + 1);
6422 i = cgltf_parse_json_unprocessed_extension(options, tokens, i, json_chunk, &(out_data->data_extensions[out_data->data_extensions_count++]));
6431 else if (cgltf_json_strcmp(tokens + i, json_chunk,
"extensionsUsed") == 0)
6433 i = cgltf_parse_json_string_array(options, tokens, i + 1, json_chunk, &out_data->extensions_used, &out_data->extensions_used_count);
6435 else if (cgltf_json_strcmp(tokens + i, json_chunk,
"extensionsRequired") == 0)
6437 i = cgltf_parse_json_string_array(options, tokens, i + 1, json_chunk, &out_data->extensions_required, &out_data->extensions_required_count);
6441 i = cgltf_skip_json(tokens, i + 1);
6453cgltf_result cgltf_parse_json(
cgltf_options* options,
const uint8_t* json_chunk, cgltf_size size,
cgltf_data** out_data)
6455 jsmn_parser parser = { 0, 0, 0 };
6457 if (options->json_token_count == 0)
6459 int token_count = jsmn_parse(&parser, (
const char*)json_chunk, size, NULL, 0);
6461 if (token_count <= 0)
6463 return cgltf_result_invalid_json;
6466 options->json_token_count = token_count;
6469 jsmntok_t* tokens = (jsmntok_t*)options->memory.alloc_func(options->memory.user_data,
sizeof(jsmntok_t) * (options->json_token_count + 1));
6473 return cgltf_result_out_of_memory;
6478 int token_count = jsmn_parse(&parser, (
const char*)json_chunk, size, tokens, options->json_token_count);
6480 if (token_count <= 0)
6482 options->memory.free_func(options->memory.user_data, tokens);
6483 return cgltf_result_invalid_json;
6488 tokens[token_count].type = JSMN_UNDEFINED;
6494 options->memory.free_func(options->memory.user_data, tokens);
6495 return cgltf_result_out_of_memory;
6499 data->memory = options->memory;
6500 data->file = options->file;
6502 int i = cgltf_parse_json_root(options, tokens, 0, json_chunk, data);
6504 options->memory.free_func(options->memory.user_data, tokens);
6512 case CGLTF_ERROR_NOMEM:
return cgltf_result_out_of_memory;
6513 case CGLTF_ERROR_LEGACY:
return cgltf_result_legacy_gltf;
6514 default:
return cgltf_result_invalid_gltf;
6518 if (cgltf_fixup_pointers(data) < 0)
6521 return cgltf_result_invalid_gltf;
6524 data->json = (
const char*)json_chunk;
6525 data->json_size = size;
6529 return cgltf_result_success;
6532static int cgltf_fixup_pointers(
cgltf_data* data)
6534 for (cgltf_size i = 0; i < data->meshes_count; ++i)
6536 for (cgltf_size j = 0; j < data->meshes[i].primitives_count; ++j)
6538 CGLTF_PTRFIXUP(data->meshes[i].primitives[j].indices, data->accessors, data->accessors_count);
6539 CGLTF_PTRFIXUP(data->meshes[i].primitives[j].material, data->materials, data->materials_count);
6541 for (cgltf_size k = 0; k < data->meshes[i].primitives[j].attributes_count; ++k)
6543 CGLTF_PTRFIXUP_REQ(data->meshes[i].primitives[j].attributes[k].data, data->accessors, data->accessors_count);
6546 for (cgltf_size k = 0; k < data->meshes[i].primitives[j].targets_count; ++k)
6548 for (cgltf_size m = 0; m < data->meshes[i].primitives[j].targets[k].attributes_count; ++m)
6550 CGLTF_PTRFIXUP_REQ(data->meshes[i].primitives[j].targets[k].attributes[m].data, data->accessors, data->accessors_count);
6554 if (data->meshes[i].primitives[j].has_draco_mesh_compression)
6556 CGLTF_PTRFIXUP_REQ(data->meshes[i].primitives[j].draco_mesh_compression.buffer_view, data->buffer_views, data->buffer_views_count);
6557 for (cgltf_size m = 0; m < data->meshes[i].primitives[j].draco_mesh_compression.attributes_count; ++m)
6559 CGLTF_PTRFIXUP_REQ(data->meshes[i].primitives[j].draco_mesh_compression.attributes[m].data, data->accessors, data->accessors_count);
6563 for (cgltf_size k = 0; k < data->meshes[i].primitives[j].mappings_count; ++k)
6565 CGLTF_PTRFIXUP_REQ(data->meshes[i].primitives[j].mappings[k].material, data->materials, data->materials_count);
6570 for (cgltf_size i = 0; i < data->accessors_count; ++i)
6572 CGLTF_PTRFIXUP(data->accessors[i].buffer_view, data->buffer_views, data->buffer_views_count);
6574 if (data->accessors[i].is_sparse)
6576 CGLTF_PTRFIXUP_REQ(data->accessors[i].sparse.indices_buffer_view, data->buffer_views, data->buffer_views_count);
6577 CGLTF_PTRFIXUP_REQ(data->accessors[i].sparse.values_buffer_view, data->buffer_views, data->buffer_views_count);
6580 if (data->accessors[i].buffer_view)
6582 data->accessors[i].stride = data->accessors[i].buffer_view->stride;
6585 if (data->accessors[i].stride == 0)
6587 data->accessors[i].stride = cgltf_calc_size(data->accessors[i].type, data->accessors[i].component_type);
6591 for (cgltf_size i = 0; i < data->textures_count; ++i)
6593 CGLTF_PTRFIXUP(data->textures[i].image, data->images, data->images_count);
6594 CGLTF_PTRFIXUP(data->textures[i].basisu_image, data->images, data->images_count);
6595 CGLTF_PTRFIXUP(data->textures[i].webp_image, data->images, data->images_count);
6596 CGLTF_PTRFIXUP(data->textures[i].sampler, data->samplers, data->samplers_count);
6599 for (cgltf_size i = 0; i < data->images_count; ++i)
6601 CGLTF_PTRFIXUP(data->images[i].buffer_view, data->buffer_views, data->buffer_views_count);
6604 for (cgltf_size i = 0; i < data->materials_count; ++i)
6606 CGLTF_PTRFIXUP(data->materials[i].normal_texture.texture, data->textures, data->textures_count);
6607 CGLTF_PTRFIXUP(data->materials[i].emissive_texture.texture, data->textures, data->textures_count);
6608 CGLTF_PTRFIXUP(data->materials[i].occlusion_texture.texture, data->textures, data->textures_count);
6610 CGLTF_PTRFIXUP(data->materials[i].pbr_metallic_roughness.base_color_texture.texture, data->textures, data->textures_count);
6611 CGLTF_PTRFIXUP(data->materials[i].pbr_metallic_roughness.metallic_roughness_texture.texture, data->textures, data->textures_count);
6613 CGLTF_PTRFIXUP(data->materials[i].pbr_specular_glossiness.diffuse_texture.texture, data->textures, data->textures_count);
6614 CGLTF_PTRFIXUP(data->materials[i].pbr_specular_glossiness.specular_glossiness_texture.texture, data->textures, data->textures_count);
6616 CGLTF_PTRFIXUP(data->materials[i].clearcoat.clearcoat_texture.texture, data->textures, data->textures_count);
6617 CGLTF_PTRFIXUP(data->materials[i].clearcoat.clearcoat_roughness_texture.texture, data->textures, data->textures_count);
6618 CGLTF_PTRFIXUP(data->materials[i].clearcoat.clearcoat_normal_texture.texture, data->textures, data->textures_count);
6620 CGLTF_PTRFIXUP(data->materials[i].specular.specular_texture.texture, data->textures, data->textures_count);
6621 CGLTF_PTRFIXUP(data->materials[i].specular.specular_color_texture.texture, data->textures, data->textures_count);
6623 CGLTF_PTRFIXUP(data->materials[i].transmission.transmission_texture.texture, data->textures, data->textures_count);
6625 CGLTF_PTRFIXUP(data->materials[i].volume.thickness_texture.texture, data->textures, data->textures_count);
6627 CGLTF_PTRFIXUP(data->materials[i].sheen.sheen_color_texture.texture, data->textures, data->textures_count);
6628 CGLTF_PTRFIXUP(data->materials[i].sheen.sheen_roughness_texture.texture, data->textures, data->textures_count);
6630 CGLTF_PTRFIXUP(data->materials[i].iridescence.iridescence_texture.texture, data->textures, data->textures_count);
6631 CGLTF_PTRFIXUP(data->materials[i].iridescence.iridescence_thickness_texture.texture, data->textures, data->textures_count);
6633 CGLTF_PTRFIXUP(data->materials[i].anisotropy.anisotropy_texture.texture, data->textures, data->textures_count);
6636 for (cgltf_size i = 0; i < data->buffer_views_count; ++i)
6638 CGLTF_PTRFIXUP_REQ(data->buffer_views[i].buffer, data->buffers, data->buffers_count);
6640 if (data->buffer_views[i].has_meshopt_compression)
6642 CGLTF_PTRFIXUP_REQ(data->buffer_views[i].meshopt_compression.buffer, data->buffers, data->buffers_count);
6646 for (cgltf_size i = 0; i < data->skins_count; ++i)
6648 for (cgltf_size j = 0; j < data->skins[i].joints_count; ++j)
6650 CGLTF_PTRFIXUP_REQ(data->skins[i].joints[j], data->nodes, data->nodes_count);
6653 CGLTF_PTRFIXUP(data->skins[i].skeleton, data->nodes, data->nodes_count);
6654 CGLTF_PTRFIXUP(data->skins[i].inverse_bind_matrices, data->accessors, data->accessors_count);
6657 for (cgltf_size i = 0; i < data->nodes_count; ++i)
6659 for (cgltf_size j = 0; j < data->nodes[i].children_count; ++j)
6661 CGLTF_PTRFIXUP_REQ(data->nodes[i].children[j], data->nodes, data->nodes_count);
6663 if (data->nodes[i].children[j]->parent)
6665 return CGLTF_ERROR_JSON;
6668 data->nodes[i].children[j]->parent = &data->nodes[i];
6671 CGLTF_PTRFIXUP(data->nodes[i].mesh, data->meshes, data->meshes_count);
6672 CGLTF_PTRFIXUP(data->nodes[i].skin, data->skins, data->skins_count);
6673 CGLTF_PTRFIXUP(data->nodes[i].camera, data->cameras, data->cameras_count);
6674 CGLTF_PTRFIXUP(data->nodes[i].light, data->lights, data->lights_count);
6676 if (data->nodes[i].has_mesh_gpu_instancing)
6678 for (cgltf_size m = 0; m < data->nodes[i].mesh_gpu_instancing.attributes_count; ++m)
6680 CGLTF_PTRFIXUP_REQ(data->nodes[i].mesh_gpu_instancing.attributes[m].data, data->accessors, data->accessors_count);
6685 for (cgltf_size i = 0; i < data->scenes_count; ++i)
6687 for (cgltf_size j = 0; j < data->scenes[i].nodes_count; ++j)
6689 CGLTF_PTRFIXUP_REQ(data->scenes[i].nodes[j], data->nodes, data->nodes_count);
6691 if (data->scenes[i].nodes[j]->parent)
6693 return CGLTF_ERROR_JSON;
6698 CGLTF_PTRFIXUP(data->scene, data->scenes, data->scenes_count);
6700 for (cgltf_size i = 0; i < data->animations_count; ++i)
6702 for (cgltf_size j = 0; j < data->animations[i].samplers_count; ++j)
6704 CGLTF_PTRFIXUP_REQ(data->animations[i].samplers[j].input, data->accessors, data->accessors_count);
6705 CGLTF_PTRFIXUP_REQ(data->animations[i].samplers[j].output, data->accessors, data->accessors_count);
6708 for (cgltf_size j = 0; j < data->animations[i].channels_count; ++j)
6710 CGLTF_PTRFIXUP_REQ(data->animations[i].channels[j].sampler, data->animations[i].samplers, data->animations[i].samplers_count);
6711 CGLTF_PTRFIXUP(data->animations[i].channels[j].target_node, data->nodes, data->nodes_count);
6747static jsmntok_t *jsmn_alloc_token(jsmn_parser *parser,
6748 jsmntok_t *tokens,
size_t num_tokens) {
6750 if (parser->toknext >= num_tokens) {
6753 tok = &tokens[parser->toknext++];
6754 tok->start = tok->end = -1;
6756#ifdef JSMN_PARENT_LINKS
6765static void jsmn_fill_token(jsmntok_t *token, jsmntype_t type,
6766 ptrdiff_t start, ptrdiff_t end) {
6768 token->start = start;
6776static int jsmn_parse_primitive(jsmn_parser *parser,
const char *js,
6777 size_t len, jsmntok_t *tokens,
size_t num_tokens) {
6781 start = parser->pos;
6783 for (; parser->pos < len && js[parser->pos] !=
'\0'; parser->pos++) {
6784 switch (js[parser->pos]) {
6789 case '\t' :
case '\r' :
case '\n' :
case ' ' :
6790 case ',' :
case ']' :
case '}' :
6793 if (js[parser->pos] < 32 || js[parser->pos] >= 127) {
6794 parser->pos = start;
6795 return JSMN_ERROR_INVAL;
6800 parser->pos = start;
6801 return JSMN_ERROR_PART;
6805 if (tokens == NULL) {
6809 token = jsmn_alloc_token(parser, tokens, num_tokens);
6810 if (token == NULL) {
6811 parser->pos = start;
6812 return JSMN_ERROR_NOMEM;
6814 jsmn_fill_token(token, JSMN_PRIMITIVE, start, parser->pos);
6815#ifdef JSMN_PARENT_LINKS
6816 token->parent = parser->toksuper;
6825static int jsmn_parse_string(jsmn_parser *parser,
const char *js,
6826 size_t len, jsmntok_t *tokens,
size_t num_tokens) {
6829 ptrdiff_t start = parser->pos;
6834 for (; parser->pos < len && js[parser->pos] !=
'\0'; parser->pos++) {
6835 char c = js[parser->pos];
6839 if (tokens == NULL) {
6842 token = jsmn_alloc_token(parser, tokens, num_tokens);
6843 if (token == NULL) {
6844 parser->pos = start;
6845 return JSMN_ERROR_NOMEM;
6847 jsmn_fill_token(token, JSMN_STRING, start+1, parser->pos);
6848#ifdef JSMN_PARENT_LINKS
6849 token->parent = parser->toksuper;
6855 if (
c ==
'\\' && parser->pos + 1 < len) {
6858 switch (js[parser->pos]) {
6860 case '\"':
case '/' :
case '\\' :
case 'b' :
6861 case 'f' :
case 'r' :
case 'n' :
case 't' :
6866 for(i = 0; i < 4 && parser->pos < len && js[parser->pos] !=
'\0'; i++) {
6868 if(!((js[parser->pos] >= 48 && js[parser->pos] <= 57) ||
6869 (js[parser->pos] >= 65 && js[parser->pos] <= 70) ||
6870 (js[parser->pos] >= 97 && js[parser->pos] <= 102))) {
6871 parser->pos = start;
6872 return JSMN_ERROR_INVAL;
6880 parser->pos = start;
6881 return JSMN_ERROR_INVAL;
6885 parser->pos = start;
6886 return JSMN_ERROR_PART;
6892static int jsmn_parse(jsmn_parser *parser,
const char *js,
size_t len,
6893 jsmntok_t *tokens,
size_t num_tokens) {
6897 int count = parser->toknext;
6899 for (; parser->pos < len && js[parser->pos] !=
'\0'; parser->pos++) {
6903 c = js[parser->pos];
6907 if (tokens == NULL) {
6910 token = jsmn_alloc_token(parser, tokens, num_tokens);
6912 return JSMN_ERROR_NOMEM;
6913 if (parser->toksuper != -1) {
6914 tokens[parser->toksuper].size++;
6915#ifdef JSMN_PARENT_LINKS
6916 token->parent = parser->toksuper;
6919 token->type = (
c ==
'{' ? JSMN_OBJECT : JSMN_ARRAY);
6920 token->start = parser->pos;
6921 parser->toksuper = parser->toknext - 1;
6926 type = (
c ==
'}' ? JSMN_OBJECT : JSMN_ARRAY);
6927#ifdef JSMN_PARENT_LINKS
6928 if (parser->toknext < 1) {
6929 return JSMN_ERROR_INVAL;
6931 token = &tokens[parser->toknext - 1];
6933 if (token->start != -1 && token->end == -1) {
6934 if (token->type != type) {
6935 return JSMN_ERROR_INVAL;
6937 token->end = parser->pos + 1;
6938 parser->toksuper = token->parent;
6941 if (token->parent == -1) {
6942 if(token->type != type || parser->toksuper == -1) {
6943 return JSMN_ERROR_INVAL;
6947 token = &tokens[token->parent];
6950 for (i = parser->toknext - 1; i >= 0; i--) {
6952 if (token->start != -1 && token->end == -1) {
6953 if (token->type != type) {
6954 return JSMN_ERROR_INVAL;
6956 parser->toksuper = -1;
6957 token->end = parser->pos + 1;
6962 if (i == -1)
return JSMN_ERROR_INVAL;
6963 for (; i >= 0; i--) {
6965 if (token->start != -1 && token->end == -1) {
6966 parser->toksuper = i;
6973 r = jsmn_parse_string(parser, js, len, tokens, num_tokens);
6974 if (r < 0)
return r;
6976 if (parser->toksuper != -1 && tokens != NULL)
6977 tokens[parser->toksuper].size++;
6979 case '\t' :
case '\r' :
case '\n' :
case ' ':
6982 parser->toksuper = parser->toknext - 1;
6985 if (tokens != NULL && parser->toksuper != -1 &&
6986 tokens[parser->toksuper].type != JSMN_ARRAY &&
6987 tokens[parser->toksuper].type != JSMN_OBJECT) {
6988#ifdef JSMN_PARENT_LINKS
6989 parser->toksuper = tokens[parser->toksuper].parent;
6991 for (i = parser->toknext - 1; i >= 0; i--) {
6992 if (tokens[i].type == JSMN_ARRAY || tokens[i].type == JSMN_OBJECT) {
6993 if (tokens[i].start != -1 && tokens[i].end == -1) {
6994 parser->toksuper = i;
7004 case '-':
case '0':
case '1' :
case '2':
case '3' :
case '4':
7005 case '5':
case '6':
case '7' :
case '8':
case '9':
7006 case 't':
case 'f':
case 'n' :
7008 if (tokens != NULL && parser->toksuper != -1) {
7009 jsmntok_t *t = &tokens[parser->toksuper];
7010 if (t->type == JSMN_OBJECT ||
7011 (t->type == JSMN_STRING && t->size != 0)) {
7012 return JSMN_ERROR_INVAL;
7019 r = jsmn_parse_primitive(parser, js, len, tokens, num_tokens);
7020 if (r < 0)
return r;
7022 if (parser->toksuper != -1 && tokens != NULL)
7023 tokens[parser->toksuper].size++;
7029 return JSMN_ERROR_INVAL;
7034 if (tokens != NULL) {
7035 for (i = parser->toknext - 1; i >= 0; i--) {
7037 if (tokens[i].start != -1 && tokens[i].end == -1) {
7038 return JSMN_ERROR_PART;
7050static void jsmn_init(jsmn_parser *parser) {
7052 parser->toknext = 0;
7053 parser->toksuper = -1;