92#ifndef CGLTF_H_INCLUDED__
93#define CGLTF_H_INCLUDED__
101typedef size_t cgltf_size;
102typedef float cgltf_float;
103typedef int cgltf_int;
104typedef unsigned int cgltf_uint;
105typedef int cgltf_bool;
107typedef enum cgltf_file_type
109 cgltf_file_type_invalid,
110 cgltf_file_type_gltf,
114typedef enum cgltf_result
116 cgltf_result_success,
117 cgltf_result_data_too_short,
118 cgltf_result_unknown_format,
119 cgltf_result_invalid_json,
120 cgltf_result_invalid_gltf,
121 cgltf_result_invalid_options,
122 cgltf_result_file_not_found,
123 cgltf_result_io_error,
124 cgltf_result_out_of_memory,
125 cgltf_result_legacy_gltf,
130 void* (*alloc)(
void* user, cgltf_size size);
131 void (*free) (
void* user,
void* ptr);
144 cgltf_file_type type;
145 cgltf_size json_token_count;
150typedef enum cgltf_buffer_view_type
152 cgltf_buffer_view_type_invalid,
153 cgltf_buffer_view_type_indices,
154 cgltf_buffer_view_type_vertices,
155} cgltf_buffer_view_type;
157typedef enum cgltf_attribute_type
159 cgltf_attribute_type_invalid,
160 cgltf_attribute_type_position,
161 cgltf_attribute_type_normal,
162 cgltf_attribute_type_tangent,
163 cgltf_attribute_type_texcoord,
164 cgltf_attribute_type_color,
165 cgltf_attribute_type_joints,
166 cgltf_attribute_type_weights,
167} cgltf_attribute_type;
169typedef enum cgltf_component_type
171 cgltf_component_type_invalid,
172 cgltf_component_type_r_8,
173 cgltf_component_type_r_8u,
174 cgltf_component_type_r_16,
175 cgltf_component_type_r_16u,
176 cgltf_component_type_r_32u,
177 cgltf_component_type_r_32f,
178} cgltf_component_type;
180typedef enum cgltf_type
192typedef enum cgltf_primitive_type
194 cgltf_primitive_type_points,
195 cgltf_primitive_type_lines,
196 cgltf_primitive_type_line_loop,
197 cgltf_primitive_type_line_strip,
198 cgltf_primitive_type_triangles,
199 cgltf_primitive_type_triangle_strip,
200 cgltf_primitive_type_triangle_fan,
201} cgltf_primitive_type;
203typedef enum cgltf_alpha_mode
205 cgltf_alpha_mode_opaque,
206 cgltf_alpha_mode_mask,
207 cgltf_alpha_mode_blend,
210typedef enum cgltf_animation_path_type {
211 cgltf_animation_path_type_invalid,
212 cgltf_animation_path_type_translation,
213 cgltf_animation_path_type_rotation,
214 cgltf_animation_path_type_scale,
215 cgltf_animation_path_type_weights,
216} cgltf_animation_path_type;
218typedef enum cgltf_interpolation_type {
219 cgltf_interpolation_type_linear,
220 cgltf_interpolation_type_step,
221 cgltf_interpolation_type_cubic_spline,
222} cgltf_interpolation_type;
224typedef enum cgltf_camera_type {
225 cgltf_camera_type_invalid,
226 cgltf_camera_type_perspective,
227 cgltf_camera_type_orthographic,
230typedef enum cgltf_light_type {
231 cgltf_light_type_invalid,
232 cgltf_light_type_directional,
233 cgltf_light_type_point,
234 cgltf_light_type_spot,
238 cgltf_size start_offset;
239 cgltf_size end_offset;
256 cgltf_buffer_view_type type;
264 cgltf_size indices_byte_offset;
265 cgltf_component_type indices_component_type;
267 cgltf_size values_byte_offset;
275 cgltf_component_type component_type;
276 cgltf_bool normalized;
286 cgltf_bool is_sparse;
294 cgltf_attribute_type type;
310 cgltf_int mag_filter;
311 cgltf_int min_filter;
327 cgltf_float offset[2];
328 cgltf_float rotation;
329 cgltf_float scale[2];
338 cgltf_bool has_transform;
348 cgltf_float base_color_factor[4];
349 cgltf_float metallic_factor;
350 cgltf_float roughness_factor;
360 cgltf_float diffuse_factor[4];
361 cgltf_float specular_factor[3];
362 cgltf_float glossiness_factor;
371 cgltf_float clearcoat_factor;
372 cgltf_float clearcoat_roughness_factor;
378 cgltf_bool has_pbr_metallic_roughness;
379 cgltf_bool has_pbr_specular_glossiness;
380 cgltf_bool has_clearcoat;
387 cgltf_float emissive_factor[3];
388 cgltf_alpha_mode alpha_mode;
389 cgltf_float alpha_cutoff;
390 cgltf_bool double_sided;
397 cgltf_size attributes_count;
403 cgltf_size attributes_count;
407 cgltf_primitive_type type;
411 cgltf_size attributes_count;
413 cgltf_size targets_count;
415 cgltf_bool has_draco_mesh_compression;
422 cgltf_size primitives_count;
423 cgltf_float* weights;
424 cgltf_size weights_count;
426 cgltf_size target_names_count;
435 cgltf_size joints_count;
442 cgltf_float aspect_ratio;
459 cgltf_camera_type type;
469 cgltf_float color[3];
470 cgltf_float intensity;
471 cgltf_light_type type;
473 cgltf_float spot_inner_cone_angle;
474 cgltf_float spot_outer_cone_angle;
481 cgltf_size children_count;
486 cgltf_float* weights;
487 cgltf_size weights_count;
488 cgltf_bool has_translation;
489 cgltf_bool has_rotation;
490 cgltf_bool has_scale;
491 cgltf_bool has_matrix;
492 cgltf_float translation[3];
493 cgltf_float rotation[4];
494 cgltf_float scale[3];
495 cgltf_float matrix[16];
502 cgltf_size nodes_count;
509 cgltf_interpolation_type interpolation;
516 cgltf_animation_path_type target_path;
523 cgltf_size samplers_count;
525 cgltf_size channels_count;
539 cgltf_file_type file_type;
545 cgltf_size meshes_count;
548 cgltf_size materials_count;
551 cgltf_size accessors_count;
554 cgltf_size buffer_views_count;
557 cgltf_size buffers_count;
560 cgltf_size images_count;
563 cgltf_size textures_count;
566 cgltf_size samplers_count;
569 cgltf_size skins_count;
572 cgltf_size cameras_count;
575 cgltf_size lights_count;
578 cgltf_size nodes_count;
581 cgltf_size scenes_count;
586 cgltf_size animations_count;
590 char** extensions_used;
591 cgltf_size extensions_used_count;
593 char** extensions_required;
594 cgltf_size extensions_required_count;
597 cgltf_size json_size;
606cgltf_result cgltf_parse(
612cgltf_result cgltf_parse_file(
617cgltf_result cgltf_load_buffers(
620 const char* gltf_path);
622cgltf_result cgltf_load_buffer_base64(
const cgltf_options* options, cgltf_size size,
const char* base64,
void** out_data);
624void cgltf_decode_uri(
char* uri);
630void cgltf_node_transform_local(
const cgltf_node* node, cgltf_float* out_matrix);
631void cgltf_node_transform_world(
const cgltf_node* node, cgltf_float* out_matrix);
633cgltf_bool cgltf_accessor_read_float(
const cgltf_accessor* accessor, cgltf_size index, cgltf_float* out, cgltf_size element_size);
634cgltf_bool cgltf_accessor_read_uint(
const cgltf_accessor* accessor, cgltf_size index, cgltf_uint* out, cgltf_size element_size);
635cgltf_size cgltf_accessor_read_index(
const cgltf_accessor* accessor, cgltf_size index);
637cgltf_size cgltf_num_components(cgltf_type type);
639cgltf_size cgltf_accessor_unpack_floats(
const cgltf_accessor* accessor, cgltf_float* out, cgltf_size float_count);
641cgltf_result cgltf_copy_extras_json(
const cgltf_data* data,
const cgltf_extras* extras,
char* dest, cgltf_size* dest_size);
656#if defined(__INTELLISENSE__) || defined(__JETBRAINS_IDE__)
658#define CGLTF_IMPLEMENTATION
661#ifdef CGLTF_IMPLEMENTATION
668#if !defined(CGLTF_MALLOC) || !defined(CGLTF_FREE) || !defined(CGLTF_ATOI) || !defined(CGLTF_ATOF)
673#define JSMN_PARENT_LINKS
692 JSMN_ERROR_NOMEM = -1,
694 JSMN_ERROR_INVAL = -2,
703#ifdef JSMN_PARENT_LINKS
709 unsigned int toknext;
712static void jsmn_init(jsmn_parser *parser);
713static int jsmn_parse(jsmn_parser *parser,
const char *js,
size_t len, jsmntok_t *tokens,
size_t num_tokens);
719static const cgltf_size GlbHeaderSize = 12;
720static const cgltf_size GlbChunkHeaderSize = 8;
721static const uint32_t GlbVersion = 2;
722static const uint32_t GlbMagic = 0x46546C67;
723static const uint32_t GlbMagicJsonChunk = 0x4E4F534A;
724static const uint32_t GlbMagicBinChunk = 0x004E4942;
727#define CGLTF_MALLOC(size) malloc(size)
730#define CGLTF_FREE(ptr) free(ptr)
733#define CGLTF_ATOI(str) atoi(str)
736#define CGLTF_ATOF(str) atof(str)
739static void* cgltf_default_alloc(
void* user, cgltf_size size)
742 return CGLTF_MALLOC(size);
745static void cgltf_default_free(
void* user,
void* ptr)
751static void* cgltf_calloc(
cgltf_options* options,
size_t element_size, cgltf_size count)
753 if (SIZE_MAX / element_size < count)
757 void* result = options->memory.alloc(options->memory.user_data, element_size * count);
762 memset(result, 0, element_size * count);
766static 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)
769 void* (*memory_alloc)(
void*, cgltf_size) = memory_options->alloc ? memory_options->alloc : &cgltf_default_alloc;
770 void (*memory_free)(
void*,
void*) = memory_options->free ? memory_options->free : &cgltf_default_free;
772 FILE* file = fopen(path,
"rb");
775 return cgltf_result_file_not_found;
778 cgltf_size file_size = size ? *size : 0;
782 fseek(file, 0, SEEK_END);
784 long length = ftell(file);
788 return cgltf_result_io_error;
791 fseek(file, 0, SEEK_SET);
792 file_size = (cgltf_size)length;
795 char* file_data = (
char*)memory_alloc(memory_options->user_data, file_size);
799 return cgltf_result_out_of_memory;
802 cgltf_size read_size = fread(file_data, 1, file_size, file);
806 if (read_size != file_size)
808 memory_free(memory_options->user_data, file_data);
809 return cgltf_result_io_error;
821 return cgltf_result_success;
827 void (*memfree)(
void*,
void*) = memory_options->free ? memory_options->free : &cgltf_default_free;
828 memfree(memory_options->user_data, data);
831static cgltf_result cgltf_parse_json(
cgltf_options* options,
const uint8_t* json_chunk, cgltf_size size,
cgltf_data** out_data);
833cgltf_result cgltf_parse(
const cgltf_options* options,
const void* data, cgltf_size size,
cgltf_data** out_data)
835 if (size < GlbHeaderSize)
837 return cgltf_result_data_too_short;
842 return cgltf_result_invalid_options;
846 if (fixed_options.memory.alloc == NULL)
848 fixed_options.memory.alloc = &cgltf_default_alloc;
850 if (fixed_options.memory.free == NULL)
852 fixed_options.memory.free = &cgltf_default_free;
857 memcpy(&tmp, data, 4);
860 if (fixed_options.type == cgltf_file_type_invalid)
862 fixed_options.type = cgltf_file_type_gltf;
864 else if (fixed_options.type == cgltf_file_type_glb)
866 return cgltf_result_unknown_format;
870 if (fixed_options.type == cgltf_file_type_gltf)
872 cgltf_result json_result = cgltf_parse_json(&fixed_options, (
const uint8_t*)data, size, out_data);
873 if (json_result != cgltf_result_success)
878 (*out_data)->file_type = cgltf_file_type_gltf;
880 return cgltf_result_success;
883 const uint8_t* ptr = (
const uint8_t*)data;
885 memcpy(&tmp, ptr + 4, 4);
886 uint32_t version = tmp;
887 if (version != GlbVersion)
889 return version < GlbVersion ? cgltf_result_legacy_gltf : cgltf_result_unknown_format;
893 memcpy(&tmp, ptr + 8, 4);
896 return cgltf_result_data_too_short;
899 const uint8_t* json_chunk = ptr + GlbHeaderSize;
901 if (GlbHeaderSize + GlbChunkHeaderSize > size)
903 return cgltf_result_data_too_short;
907 uint32_t json_length;
908 memcpy(&json_length, json_chunk, 4);
909 if (GlbHeaderSize + GlbChunkHeaderSize + json_length > size)
911 return cgltf_result_data_too_short;
915 memcpy(&tmp, json_chunk + 4, 4);
916 if (tmp != GlbMagicJsonChunk)
918 return cgltf_result_unknown_format;
921 json_chunk += GlbChunkHeaderSize;
924 cgltf_size bin_size = 0;
926 if (GlbHeaderSize + GlbChunkHeaderSize + json_length + GlbChunkHeaderSize <= size)
929 const uint8_t* bin_chunk = json_chunk + json_length;
933 memcpy(&bin_length, bin_chunk, 4);
934 if (GlbHeaderSize + GlbChunkHeaderSize + json_length + GlbChunkHeaderSize + bin_length > size)
936 return cgltf_result_data_too_short;
940 memcpy(&tmp, bin_chunk + 4, 4);
941 if (tmp != GlbMagicBinChunk)
943 return cgltf_result_unknown_format;
946 bin_chunk += GlbChunkHeaderSize;
949 bin_size = bin_length;
952 cgltf_result json_result = cgltf_parse_json(&fixed_options, json_chunk, json_length, out_data);
953 if (json_result != cgltf_result_success)
958 (*out_data)->file_type = cgltf_file_type_glb;
959 (*out_data)->bin = bin;
960 (*out_data)->bin_size = bin_size;
962 return cgltf_result_success;
969 return cgltf_result_invalid_options;
972 void (*memory_free)(
void*,
void*) = options->memory.free ? options->memory.free : &cgltf_default_free;
973 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;
975 void* file_data = NULL;
976 cgltf_size file_size = 0;
977 cgltf_result result = file_read(&options->memory, &options->file, path, &file_size, &file_data);
978 if (result != cgltf_result_success)
983 result = cgltf_parse(options, file_data, file_size, out_data);
985 if (result != cgltf_result_success)
987 memory_free(options->memory.user_data, file_data);
991 (*out_data)->file_data = file_data;
993 return cgltf_result_success;
996static void cgltf_combine_paths(
char* path,
const char* base,
const char* uri)
998 const char* s0 = strrchr(base,
'/');
999 const char* s1 = strrchr(base,
'\\');
1000 const char* slash = s0 ? (s1 && s1 > s0 ? s1 : s0) : s1;
1004 size_t prefix = slash - base + 1;
1006 strncpy(path, base, prefix);
1007 strcpy(path + prefix, uri);
1015static cgltf_result cgltf_load_buffer_file(
const cgltf_options* options, cgltf_size size,
const char* uri,
const char* gltf_path,
void** out_data)
1017 void* (*memory_alloc)(
void*, cgltf_size) = options->memory.alloc ? options->memory.alloc : &cgltf_default_alloc;
1018 void (*memory_free)(
void*,
void*) = options->memory.free ? options->memory.free : &cgltf_default_free;
1019 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;
1021 char* path = (
char*)memory_alloc(options->memory.user_data, strlen(uri) + strlen(gltf_path) + 1);
1024 return cgltf_result_out_of_memory;
1027 cgltf_combine_paths(path, gltf_path, uri);
1030 cgltf_decode_uri(path + strlen(path) - strlen(uri));
1032 void* file_data = NULL;
1033 cgltf_result result = file_read(&options->memory, &options->file, path, &size, &file_data);
1035 memory_free(options->memory.user_data, path);
1037 *out_data = (result == cgltf_result_success) ? file_data : NULL;
1042cgltf_result cgltf_load_buffer_base64(
const cgltf_options* options, cgltf_size size,
const char* base64,
void** out_data)
1044 void* (*memory_alloc)(
void*, cgltf_size) = options->memory.alloc ? options->memory.alloc : &cgltf_default_alloc;
1045 void (*memory_free)(
void*,
void*) = options->memory.free ? options->memory.free : &cgltf_default_free;
1047 unsigned char* data = (
unsigned char*)memory_alloc(options->memory.user_data, size);
1050 return cgltf_result_out_of_memory;
1053 unsigned int buffer = 0;
1054 unsigned int buffer_bits = 0;
1056 for (cgltf_size i = 0; i < size; ++i)
1058 while (buffer_bits < 8)
1060 char ch = *base64++;
1063 (unsigned)(ch -
'A') < 26 ? (ch -
'A') :
1064 (unsigned)(ch -
'a') < 26 ? (ch -
'a') + 26 :
1065 (unsigned)(ch -
'0') < 10 ? (ch -
'0') + 52 :
1072 memory_free(options->memory.user_data, data);
1073 return cgltf_result_io_error;
1076 buffer = (buffer << 6) | index;
1080 data[i] = (
unsigned char)(buffer >> (buffer_bits - 8));
1086 return cgltf_result_success;
1089static int cgltf_unhex(
char ch)
1092 (
unsigned)(ch -
'0') < 10 ? (ch -
'0') :
1093 (unsigned)(ch -
'A') < 6 ? (ch -
'A') + 10 :
1094 (unsigned)(ch -
'a') < 6 ? (ch -
'a') + 10 :
1098void cgltf_decode_uri(
char* uri)
1107 int ch1 = cgltf_unhex(i[1]);
1111 int ch2 = cgltf_unhex(i[2]);
1115 *write++ = (char)(ch1 * 16 + ch2);
1130 if (options == NULL)
1132 return cgltf_result_invalid_options;
1135 if (data->buffers_count && data->buffers[0].data == NULL && data->buffers[0].uri == NULL && data->bin)
1137 if (data->bin_size < data->buffers[0].size)
1139 return cgltf_result_data_too_short;
1142 data->buffers[0].data = (
void*)data->bin;
1145 for (cgltf_size i = 0; i < data->buffers_count; ++i)
1147 if (data->buffers[i].data)
1152 const char* uri = data->buffers[i].uri;
1159 if (strncmp(uri,
"data:", 5) == 0)
1161 const char* comma = strchr(uri,
',');
1163 if (comma && comma - uri >= 7 && strncmp(comma - 7,
";base64", 7) == 0)
1165 cgltf_result res = cgltf_load_buffer_base64(options, data->buffers[i].size, comma + 1, &data->buffers[i].data);
1167 if (res != cgltf_result_success)
1174 return cgltf_result_unknown_format;
1177 else if (strstr(uri,
"://") == NULL && gltf_path)
1179 cgltf_result res = cgltf_load_buffer_file(options, data->buffers[i].size, uri, gltf_path, &data->buffers[i].data);
1181 if (res != cgltf_result_success)
1188 return cgltf_result_unknown_format;
1192 return cgltf_result_success;
1195static cgltf_size cgltf_calc_size(cgltf_type type, cgltf_component_type component_type);
1197static cgltf_size cgltf_calc_index_bound(
cgltf_buffer_view* buffer_view, cgltf_size offset, cgltf_component_type component_type, cgltf_size count)
1199 char* data = (
char*)buffer_view->buffer->data + offset + buffer_view->offset;
1200 cgltf_size bound = 0;
1202 switch (component_type)
1204 case cgltf_component_type_r_8u:
1205 for (
size_t i = 0; i < count; ++i)
1207 cgltf_size v = ((
unsigned char*)data)[i];
1208 bound = bound > v ? bound : v;
1212 case cgltf_component_type_r_16u:
1213 for (
size_t i = 0; i < count; ++i)
1215 cgltf_size v = ((
unsigned short*)data)[i];
1216 bound = bound > v ? bound : v;
1220 case cgltf_component_type_r_32u:
1221 for (
size_t i = 0; i < count; ++i)
1223 cgltf_size v = ((
unsigned int*)data)[i];
1224 bound = bound > v ? bound : v;
1237 for (cgltf_size i = 0; i < data->accessors_count; ++i)
1241 cgltf_size element_size = cgltf_calc_size(accessor->type, accessor->component_type);
1243 if (accessor->buffer_view)
1245 cgltf_size req_size = accessor->offset + accessor->stride * (accessor->count - 1) + element_size;
1247 if (accessor->buffer_view->size < req_size)
1249 return cgltf_result_data_too_short;
1253 if (accessor->is_sparse)
1257 cgltf_size indices_component_size = cgltf_calc_size(cgltf_type_scalar, sparse->indices_component_type);
1258 cgltf_size indices_req_size = sparse->indices_byte_offset + indices_component_size * sparse->count;
1259 cgltf_size values_req_size = sparse->values_byte_offset + element_size * sparse->count;
1261 if (sparse->indices_buffer_view->size < indices_req_size ||
1262 sparse->values_buffer_view->size < values_req_size)
1264 return cgltf_result_data_too_short;
1267 if (sparse->indices_component_type != cgltf_component_type_r_8u &&
1268 sparse->indices_component_type != cgltf_component_type_r_16u &&
1269 sparse->indices_component_type != cgltf_component_type_r_32u)
1271 return cgltf_result_invalid_gltf;
1274 if (sparse->indices_buffer_view->buffer->data)
1276 cgltf_size index_bound = cgltf_calc_index_bound(sparse->indices_buffer_view, sparse->indices_byte_offset, sparse->indices_component_type, sparse->count);
1278 if (index_bound >= accessor->count)
1280 return cgltf_result_data_too_short;
1286 for (cgltf_size i = 0; i < data->buffer_views_count; ++i)
1288 cgltf_size req_size = data->buffer_views[i].offset + data->buffer_views[i].size;
1290 if (data->buffer_views[i].buffer && data->buffer_views[i].buffer->size < req_size)
1292 return cgltf_result_data_too_short;
1296 for (cgltf_size i = 0; i < data->meshes_count; ++i)
1298 if (data->meshes[i].weights)
1300 if (data->meshes[i].primitives_count && data->meshes[i].primitives[0].targets_count != data->meshes[i].weights_count)
1302 return cgltf_result_invalid_gltf;
1306 if (data->meshes[i].target_names)
1308 if (data->meshes[i].primitives_count && data->meshes[i].primitives[0].targets_count != data->meshes[i].target_names_count)
1310 return cgltf_result_invalid_gltf;
1314 for (cgltf_size j = 0; j < data->meshes[i].primitives_count; ++j)
1316 if (data->meshes[i].primitives[j].targets_count != data->meshes[i].primitives[0].targets_count)
1318 return cgltf_result_invalid_gltf;
1321 if (data->meshes[i].primitives[j].attributes_count)
1323 cgltf_accessor* first = data->meshes[i].primitives[j].attributes[0].data;
1325 for (cgltf_size k = 0; k < data->meshes[i].primitives[j].attributes_count; ++k)
1327 if (data->meshes[i].primitives[j].attributes[k].data->count != first->count)
1329 return cgltf_result_invalid_gltf;
1333 for (cgltf_size k = 0; k < data->meshes[i].primitives[j].targets_count; ++k)
1335 for (cgltf_size m = 0; m < data->meshes[i].primitives[j].targets[k].attributes_count; ++m)
1337 if (data->meshes[i].primitives[j].targets[k].attributes[m].data->count != first->count)
1339 return cgltf_result_invalid_gltf;
1347 indices->component_type != cgltf_component_type_r_8u &&
1348 indices->component_type != cgltf_component_type_r_16u &&
1349 indices->component_type != cgltf_component_type_r_32u)
1351 return cgltf_result_invalid_gltf;
1354 if (indices && indices->buffer_view && indices->buffer_view->buffer->data)
1356 cgltf_size index_bound = cgltf_calc_index_bound(indices->buffer_view, indices->offset, indices->component_type, indices->count);
1358 if (index_bound >= first->count)
1360 return cgltf_result_data_too_short;
1367 for (cgltf_size i = 0; i < data->nodes_count; ++i)
1369 if (data->nodes[i].weights && data->nodes[i].mesh)
1371 if (data->nodes[i].mesh->primitives_count && data->nodes[i].mesh->primitives[0].targets_count != data->nodes[i].weights_count)
1373 return cgltf_result_invalid_gltf;
1378 for (cgltf_size i = 0; i < data->nodes_count; ++i)
1387 return cgltf_result_invalid_gltf;
1391 p2 = p2->parent ? p2->parent->parent : NULL;
1395 for (cgltf_size i = 0; i < data->scenes_count; ++i)
1397 for (cgltf_size j = 0; j < data->scenes[i].nodes_count; ++j)
1399 if (data->scenes[i].nodes[j]->parent)
1401 return cgltf_result_invalid_gltf;
1406 for (cgltf_size i = 0; i < data->animations_count; ++i)
1408 for (cgltf_size j = 0; j < data->animations[i].channels_count; ++j)
1412 if (!channel->target_node)
1417 cgltf_size components = 1;
1419 if (channel->target_path == cgltf_animation_path_type_weights)
1421 if (!channel->target_node->mesh || !channel->target_node->mesh->primitives_count)
1423 return cgltf_result_invalid_gltf;
1426 components = channel->target_node->mesh->primitives[0].targets_count;
1429 cgltf_size values = channel->sampler->interpolation == cgltf_interpolation_type_cubic_spline ? 3 : 1;
1431 if (channel->sampler->input->count * components * values != channel->sampler->output->count)
1433 return cgltf_result_data_too_short;
1438 return cgltf_result_success;
1441cgltf_result cgltf_copy_extras_json(
const cgltf_data* data,
const cgltf_extras* extras,
char* dest, cgltf_size* dest_size)
1443 cgltf_size json_size = extras->end_offset - extras->start_offset;
1449 *dest_size = json_size + 1;
1450 return cgltf_result_success;
1452 return cgltf_result_invalid_options;
1455 if (*dest_size + 1 < json_size)
1457 strncpy(dest, data->json + extras->start_offset, *dest_size - 1);
1458 dest[*dest_size - 1] = 0;
1462 strncpy(dest, data->json + extras->start_offset, json_size);
1463 dest[json_size] = 0;
1466 return cgltf_result_success;
1478 data->memory.free(data->memory.user_data, data->asset.copyright);
1479 data->memory.free(data->memory.user_data, data->asset.generator);
1480 data->memory.free(data->memory.user_data, data->asset.version);
1481 data->memory.free(data->memory.user_data, data->asset.min_version);
1483 data->memory.free(data->memory.user_data, data->accessors);
1484 data->memory.free(data->memory.user_data, data->buffer_views);
1486 for (cgltf_size i = 0; i < data->buffers_count; ++i)
1488 if (data->buffers[i].data != data->bin)
1490 file_release(&data->memory, &data->file, data->buffers[i].data);
1493 data->memory.free(data->memory.user_data, data->buffers[i].uri);
1496 data->memory.free(data->memory.user_data, data->buffers);
1498 for (cgltf_size i = 0; i < data->meshes_count; ++i)
1500 data->memory.free(data->memory.user_data, data->meshes[i].name);
1502 for (cgltf_size j = 0; j < data->meshes[i].primitives_count; ++j)
1504 for (cgltf_size k = 0; k < data->meshes[i].primitives[j].attributes_count; ++k)
1506 data->memory.free(data->memory.user_data, data->meshes[i].primitives[j].attributes[k].name);
1509 data->memory.free(data->memory.user_data, data->meshes[i].primitives[j].attributes);
1511 for (cgltf_size k = 0; k < data->meshes[i].primitives[j].targets_count; ++k)
1513 for (cgltf_size m = 0; m < data->meshes[i].primitives[j].targets[k].attributes_count; ++m)
1515 data->memory.free(data->memory.user_data, data->meshes[i].primitives[j].targets[k].attributes[m].name);
1518 data->memory.free(data->memory.user_data, data->meshes[i].primitives[j].targets[k].attributes);
1521 data->memory.free(data->memory.user_data, data->meshes[i].primitives[j].targets);
1523 if (data->meshes[i].primitives[j].has_draco_mesh_compression)
1525 for (cgltf_size k = 0; k < data->meshes[i].primitives[j].draco_mesh_compression.attributes_count; ++k)
1527 data->memory.free(data->memory.user_data, data->meshes[i].primitives[j].draco_mesh_compression.attributes[k].name);
1530 data->memory.free(data->memory.user_data, data->meshes[i].primitives[j].draco_mesh_compression.attributes);
1534 data->memory.free(data->memory.user_data, data->meshes[i].primitives);
1535 data->memory.free(data->memory.user_data, data->meshes[i].weights);
1537 for (cgltf_size j = 0; j < data->meshes[i].target_names_count; ++j)
1539 data->memory.free(data->memory.user_data, data->meshes[i].target_names[j]);
1542 data->memory.free(data->memory.user_data, data->meshes[i].target_names);
1545 data->memory.free(data->memory.user_data, data->meshes);
1547 for (cgltf_size i = 0; i < data->materials_count; ++i)
1549 data->memory.free(data->memory.user_data, data->materials[i].name);
1552 data->memory.free(data->memory.user_data, data->materials);
1554 for (cgltf_size i = 0; i < data->images_count; ++i)
1556 data->memory.free(data->memory.user_data, data->images[i].name);
1557 data->memory.free(data->memory.user_data, data->images[i].uri);
1558 data->memory.free(data->memory.user_data, data->images[i].mime_type);
1561 data->memory.free(data->memory.user_data, data->images);
1563 for (cgltf_size i = 0; i < data->textures_count; ++i)
1565 data->memory.free(data->memory.user_data, data->textures[i].name);
1568 data->memory.free(data->memory.user_data, data->textures);
1570 data->memory.free(data->memory.user_data, data->samplers);
1572 for (cgltf_size i = 0; i < data->skins_count; ++i)
1574 data->memory.free(data->memory.user_data, data->skins[i].name);
1575 data->memory.free(data->memory.user_data, data->skins[i].joints);
1578 data->memory.free(data->memory.user_data, data->skins);
1580 for (cgltf_size i = 0; i < data->cameras_count; ++i)
1582 data->memory.free(data->memory.user_data, data->cameras[i].name);
1585 data->memory.free(data->memory.user_data, data->cameras);
1587 for (cgltf_size i = 0; i < data->lights_count; ++i)
1589 data->memory.free(data->memory.user_data, data->lights[i].name);
1592 data->memory.free(data->memory.user_data, data->lights);
1594 for (cgltf_size i = 0; i < data->nodes_count; ++i)
1596 data->memory.free(data->memory.user_data, data->nodes[i].name);
1597 data->memory.free(data->memory.user_data, data->nodes[i].children);
1598 data->memory.free(data->memory.user_data, data->nodes[i].weights);
1601 data->memory.free(data->memory.user_data, data->nodes);
1603 for (cgltf_size i = 0; i < data->scenes_count; ++i)
1605 data->memory.free(data->memory.user_data, data->scenes[i].name);
1606 data->memory.free(data->memory.user_data, data->scenes[i].nodes);
1609 data->memory.free(data->memory.user_data, data->scenes);
1611 for (cgltf_size i = 0; i < data->animations_count; ++i)
1613 data->memory.free(data->memory.user_data, data->animations[i].name);
1614 data->memory.free(data->memory.user_data, data->animations[i].samplers);
1615 data->memory.free(data->memory.user_data, data->animations[i].channels);
1618 data->memory.free(data->memory.user_data, data->animations);
1620 for (cgltf_size i = 0; i < data->extensions_used_count; ++i)
1622 data->memory.free(data->memory.user_data, data->extensions_used[i]);
1625 data->memory.free(data->memory.user_data, data->extensions_used);
1627 for (cgltf_size i = 0; i < data->extensions_required_count; ++i)
1629 data->memory.free(data->memory.user_data, data->extensions_required[i]);
1632 data->memory.free(data->memory.user_data, data->extensions_required);
1634 file_release(&data->memory, &data->file, data->file_data);
1636 data->memory.free(data->memory.user_data, data);
1639void cgltf_node_transform_local(
const cgltf_node* node, cgltf_float* out_matrix)
1641 cgltf_float* lm = out_matrix;
1643 if (node->has_matrix)
1645 memcpy(lm, node->matrix,
sizeof(
float) * 16);
1649 float tx = node->translation[0];
1650 float ty = node->translation[1];
1651 float tz = node->translation[2];
1653 float qx = node->rotation[0];
1654 float qy = node->rotation[1];
1655 float qz = node->rotation[2];
1656 float qw = node->rotation[3];
1658 float sx = node->scale[0];
1659 float sy = node->scale[1];
1660 float sz = node->scale[2];
1662 lm[0] = (1 - 2 * qy*qy - 2 * qz*qz) * sx;
1663 lm[1] = (2 * qx*qy + 2 * qz*qw) * sx;
1664 lm[2] = (2 * qx*qz - 2 * qy*qw) * sx;
1667 lm[4] = (2 * qx*qy - 2 * qz*qw) * sy;
1668 lm[5] = (1 - 2 * qx*qx - 2 * qz*qz) * sy;
1669 lm[6] = (2 * qy*qz + 2 * qx*qw) * sy;
1672 lm[8] = (2 * qx*qz + 2 * qy*qw) * sz;
1673 lm[9] = (2 * qy*qz - 2 * qx*qw) * sz;
1674 lm[10] = (1 - 2 * qx*qx - 2 * qy*qy) * sz;
1684void cgltf_node_transform_world(
const cgltf_node* node, cgltf_float* out_matrix)
1686 cgltf_float* lm = out_matrix;
1687 cgltf_node_transform_local(node, lm);
1694 cgltf_node_transform_local(parent, pm);
1696 for (
int i = 0; i < 4; ++i)
1698 float l0 = lm[i * 4 + 0];
1699 float l1 = lm[i * 4 + 1];
1700 float l2 = lm[i * 4 + 2];
1702 float r0 = l0 * pm[0] + l1 * pm[4] + l2 * pm[8];
1703 float r1 = l0 * pm[1] + l1 * pm[5] + l2 * pm[9];
1704 float r2 = l0 * pm[2] + l1 * pm[6] + l2 * pm[10];
1715 parent = parent->parent;
1719static cgltf_size cgltf_component_read_index(
const void* in, cgltf_component_type component_type)
1721 switch (component_type)
1723 case cgltf_component_type_r_16:
1724 return *((
const int16_t*) in);
1725 case cgltf_component_type_r_16u:
1726 return *((
const uint16_t*) in);
1727 case cgltf_component_type_r_32u:
1728 return *((
const uint32_t*) in);
1729 case cgltf_component_type_r_32f:
1730 return (cgltf_size)*((
const float*) in);
1731 case cgltf_component_type_r_8:
1732 return *((
const int8_t*) in);
1733 case cgltf_component_type_r_8u:
1734 return *((
const uint8_t*) in);
1740static cgltf_float cgltf_component_read_float(
const void* in, cgltf_component_type component_type, cgltf_bool normalized)
1742 if (component_type == cgltf_component_type_r_32f)
1744 return *((
const float*) in);
1749 switch (component_type)
1752 case cgltf_component_type_r_16:
1753 return *((
const int16_t*) in) / (cgltf_float)32767;
1754 case cgltf_component_type_r_16u:
1755 return *((
const uint16_t*) in) / (cgltf_float)65535;
1756 case cgltf_component_type_r_8:
1757 return *((
const int8_t*) in) / (cgltf_float)127;
1758 case cgltf_component_type_r_8u:
1759 return *((
const uint8_t*) in) / (cgltf_float)255;
1765 return (cgltf_float)cgltf_component_read_index(in, component_type);
1768static cgltf_size cgltf_component_size(cgltf_component_type component_type);
1770static 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)
1772 cgltf_size num_components = cgltf_num_components(type);
1774 if (element_size < num_components) {
1780 cgltf_size component_size = cgltf_component_size(component_type);
1782 if (type == cgltf_type_mat2 && component_size == 1)
1784 out[0] = cgltf_component_read_float(element, component_type, normalized);
1785 out[1] = cgltf_component_read_float(element + 1, component_type, normalized);
1786 out[2] = cgltf_component_read_float(element + 4, component_type, normalized);
1787 out[3] = cgltf_component_read_float(element + 5, component_type, normalized);
1791 if (type == cgltf_type_mat3 && component_size == 1)
1793 out[0] = cgltf_component_read_float(element, component_type, normalized);
1794 out[1] = cgltf_component_read_float(element + 1, component_type, normalized);
1795 out[2] = cgltf_component_read_float(element + 2, component_type, normalized);
1796 out[3] = cgltf_component_read_float(element + 4, component_type, normalized);
1797 out[4] = cgltf_component_read_float(element + 5, component_type, normalized);
1798 out[5] = cgltf_component_read_float(element + 6, component_type, normalized);
1799 out[6] = cgltf_component_read_float(element + 8, component_type, normalized);
1800 out[7] = cgltf_component_read_float(element + 9, component_type, normalized);
1801 out[8] = cgltf_component_read_float(element + 10, component_type, normalized);
1805 if (type == cgltf_type_mat3 && component_size == 2)
1807 out[0] = cgltf_component_read_float(element, component_type, normalized);
1808 out[1] = cgltf_component_read_float(element + 2, component_type, normalized);
1809 out[2] = cgltf_component_read_float(element + 4, component_type, normalized);
1810 out[3] = cgltf_component_read_float(element + 8, component_type, normalized);
1811 out[4] = cgltf_component_read_float(element + 10, component_type, normalized);
1812 out[5] = cgltf_component_read_float(element + 12, component_type, normalized);
1813 out[6] = cgltf_component_read_float(element + 16, component_type, normalized);
1814 out[7] = cgltf_component_read_float(element + 18, component_type, normalized);
1815 out[8] = cgltf_component_read_float(element + 20, component_type, normalized);
1819 for (cgltf_size i = 0; i < num_components; ++i)
1821 out[i] = cgltf_component_read_float(element + component_size * i, component_type, normalized);
1826cgltf_bool cgltf_accessor_read_float(
const cgltf_accessor* accessor, cgltf_size index, cgltf_float* out, cgltf_size element_size)
1828 if (accessor->is_sparse)
1832 if (accessor->buffer_view == NULL)
1834 memset(out, 0, element_size *
sizeof(cgltf_float));
1837 if (accessor->buffer_view->buffer->data == NULL)
1841 cgltf_size offset = accessor->offset + accessor->buffer_view->offset;
1842 const uint8_t* element = (
const uint8_t*) accessor->buffer_view->buffer->data;
1843 element += offset + accessor->stride * index;
1844 return cgltf_element_read_float(element, accessor->type, accessor->component_type, accessor->normalized, out, element_size);
1847cgltf_size cgltf_accessor_unpack_floats(
const cgltf_accessor* accessor, cgltf_float* out, cgltf_size float_count)
1849 cgltf_size floats_per_element = cgltf_num_components(accessor->type);
1850 cgltf_size available_floats = accessor->count * floats_per_element;
1853 return available_floats;
1856 float_count = available_floats < float_count ? available_floats : float_count;
1857 cgltf_size element_count = float_count / floats_per_element;
1860 cgltf_float* dest = out;
1862 dense.is_sparse = 0;
1863 for (cgltf_size index = 0; index < element_count; index++, dest += floats_per_element)
1865 if (!cgltf_accessor_read_float(&dense, index, dest, floats_per_element))
1872 if (accessor->is_sparse)
1876 if (sparse->indices_buffer_view->buffer->data == NULL || sparse->values_buffer_view->buffer->data == NULL)
1881 const uint8_t* index_data = (
const uint8_t*) sparse->indices_buffer_view->buffer->data;
1882 index_data += sparse->indices_byte_offset + sparse->indices_buffer_view->offset;
1883 cgltf_size index_stride = cgltf_component_size(sparse->indices_component_type);
1884 const uint8_t* reader_head = (
const uint8_t*) sparse->values_buffer_view->buffer->data;
1885 reader_head += sparse->values_byte_offset + sparse->values_buffer_view->offset;
1886 for (cgltf_size reader_index = 0; reader_index < sparse->count; reader_index++, index_data += index_stride)
1888 size_t writer_index = cgltf_component_read_index(index_data, sparse->indices_component_type);
1889 float* writer_head = out + writer_index * floats_per_element;
1891 if (!cgltf_element_read_float(reader_head, dense.type, dense.component_type, dense.normalized, writer_head, floats_per_element))
1896 reader_head += dense.stride;
1900 return element_count * floats_per_element;
1903static cgltf_uint cgltf_component_read_uint(
const void* in, cgltf_component_type component_type)
1905 switch (component_type)
1907 case cgltf_component_type_r_8:
1908 return *((
const int8_t*) in);
1910 case cgltf_component_type_r_8u:
1911 return *((
const uint8_t*) in);
1913 case cgltf_component_type_r_16:
1914 return *((
const int16_t*) in);
1916 case cgltf_component_type_r_16u:
1917 return *((
const uint16_t*) in);
1919 case cgltf_component_type_r_32u:
1920 return *((
const uint32_t*) in);
1927static 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)
1929 cgltf_size num_components = cgltf_num_components(type);
1931 if (element_size < num_components)
1937 if (type == cgltf_type_mat2 || type == cgltf_type_mat3 || type == cgltf_type_mat4)
1942 cgltf_size component_size = cgltf_component_size(component_type);
1944 for (cgltf_size i = 0; i < num_components; ++i)
1946 out[i] = cgltf_component_read_uint(element + component_size * i, component_type);
1951cgltf_bool cgltf_accessor_read_uint(
const cgltf_accessor* accessor, cgltf_size index, cgltf_uint* out, cgltf_size element_size)
1953 if (accessor->is_sparse)
1957 if (accessor->buffer_view == NULL)
1959 memset(out, 0, element_size *
sizeof( cgltf_uint ));
1962 if (accessor->buffer_view->buffer->data == NULL)
1966 cgltf_size offset = accessor->offset + accessor->buffer_view->offset;
1967 const uint8_t* element = (
const uint8_t*) accessor->buffer_view->buffer->data;
1968 element += offset + accessor->stride * index;
1969 return cgltf_element_read_uint(element, accessor->type, accessor->component_type, out, element_size);
1972cgltf_size cgltf_accessor_read_index(
const cgltf_accessor* accessor, cgltf_size index)
1974 if (accessor->is_sparse)
1978 if (accessor->buffer_view == NULL)
1982 if (accessor->buffer_view->buffer->data == NULL)
1987 cgltf_size offset = accessor->offset + accessor->buffer_view->offset;
1988 const uint8_t* element = (
const uint8_t*) accessor->buffer_view->buffer->data;
1989 element += offset + accessor->stride * index;
1990 return cgltf_component_read_index(element, accessor->component_type);
1993#define CGLTF_ERROR_JSON -1
1994#define CGLTF_ERROR_NOMEM -2
1995#define CGLTF_ERROR_LEGACY -3
1997#define CGLTF_CHECK_TOKTYPE(tok_, type_) if ((tok_).type != (type_)) { return CGLTF_ERROR_JSON; }
1998#define CGLTF_CHECK_KEY(tok_) if ((tok_).type != JSMN_STRING || (tok_).size == 0) { return CGLTF_ERROR_JSON; }
2000#define CGLTF_PTRINDEX(type, idx) (type*)((cgltf_size)idx + 1)
2001#define CGLTF_PTRFIXUP(var, data, size) if (var) { if ((cgltf_size)var > size) { return CGLTF_ERROR_JSON; } var = &data[(cgltf_size)var-1]; }
2002#define CGLTF_PTRFIXUP_REQ(var, data, size) if (!var || (cgltf_size)var > size) { return CGLTF_ERROR_JSON; } var = &data[(cgltf_size)var-1];
2004static int cgltf_json_strcmp(jsmntok_t
const* tok,
const uint8_t* json_chunk,
const char* str)
2006 CGLTF_CHECK_TOKTYPE(*tok, JSMN_STRING);
2007 size_t const str_len = strlen(str);
2008 size_t const name_length = tok->end - tok->start;
2009 return (str_len == name_length) ? strncmp((
const char*)json_chunk + tok->start, str, str_len) : 128;
2012static int cgltf_json_to_int(jsmntok_t
const* tok,
const uint8_t* json_chunk)
2014 CGLTF_CHECK_TOKTYPE(*tok, JSMN_PRIMITIVE);
2016 int size = (cgltf_size)(tok->end - tok->start) <
sizeof(tmp) ? tok->end - tok->start : (int)(sizeof(tmp) - 1);
2017 strncpy(tmp, (
const char*)json_chunk + tok->start, size);
2019 return CGLTF_ATOI(tmp);
2022static cgltf_float cgltf_json_to_float(jsmntok_t
const* tok,
const uint8_t* json_chunk)
2024 CGLTF_CHECK_TOKTYPE(*tok, JSMN_PRIMITIVE);
2026 int size = (cgltf_size)(tok->end - tok->start) <
sizeof(tmp) ? tok->end - tok->start : (int)(sizeof(tmp) - 1);
2027 strncpy(tmp, (
const char*)json_chunk + tok->start, size);
2029 return (cgltf_float)CGLTF_ATOF(tmp);
2032static cgltf_bool cgltf_json_to_bool(jsmntok_t
const* tok,
const uint8_t* json_chunk)
2034 int size = tok->end - tok->start;
2035 return size == 4 && memcmp(json_chunk + tok->start,
"true", 4) == 0;
2038static int cgltf_skip_json(jsmntok_t
const* tokens,
int i)
2044 switch (tokens[i].type)
2047 end += tokens[i].size * 2;
2051 end += tokens[i].size;
2054 case JSMN_PRIMITIVE:
2068static void cgltf_fill_float_array(
float* out_array,
int size,
float value)
2070 for (
int j = 0; j < size; ++j)
2072 out_array[j] = value;
2076static int cgltf_parse_json_float_array(jsmntok_t
const* tokens,
int i,
const uint8_t* json_chunk,
float* out_array,
int size)
2078 CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_ARRAY);
2079 if (tokens[i].size != size)
2081 return CGLTF_ERROR_JSON;
2084 for (
int j = 0; j < size; ++j)
2086 CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_PRIMITIVE);
2087 out_array[j] = cgltf_json_to_float(tokens + i, json_chunk);
2093static int cgltf_parse_json_string(
cgltf_options* options, jsmntok_t
const* tokens,
int i,
const uint8_t* json_chunk,
char** out_string)
2095 CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_STRING);
2098 return CGLTF_ERROR_JSON;
2100 int size = tokens[i].end - tokens[i].start;
2101 char* result = (
char*)options->memory.alloc(options->memory.user_data, size + 1);
2104 return CGLTF_ERROR_NOMEM;
2106 strncpy(result, (
const char*)json_chunk + tokens[i].start, size);
2108 *out_string = result;
2112static 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)
2115 if (tokens[i].type != JSMN_ARRAY)
2117 return tokens[i].type == JSMN_OBJECT ? CGLTF_ERROR_LEGACY : CGLTF_ERROR_JSON;
2121 return CGLTF_ERROR_JSON;
2123 int size = tokens[i].size;
2124 void* result = cgltf_calloc(options, element_size, size);
2127 return CGLTF_ERROR_NOMEM;
2129 *out_array = result;
2134static 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)
2136 CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_ARRAY);
2137 i = cgltf_parse_json_array(options, tokens, i, json_chunk,
sizeof(
char*), (
void**)out_array, out_size);
2143 for (cgltf_size j = 0; j < *out_size; ++j)
2145 i = cgltf_parse_json_string(options, tokens, i, json_chunk, j + (*out_array));
2154static void cgltf_parse_attribute_type(
const char* name, cgltf_attribute_type* out_type,
int* out_index)
2156 const char* us = strchr(name,
'_');
2157 size_t len = us ? (size_t)(us - name) : strlen(name);
2159 if (len == 8 && strncmp(name,
"POSITION", 8) == 0)
2161 *out_type = cgltf_attribute_type_position;
2163 else if (len == 6 && strncmp(name,
"NORMAL", 6) == 0)
2165 *out_type = cgltf_attribute_type_normal;
2167 else if (len == 7 && strncmp(name,
"TANGENT", 7) == 0)
2169 *out_type = cgltf_attribute_type_tangent;
2171 else if (len == 8 && strncmp(name,
"TEXCOORD", 8) == 0)
2173 *out_type = cgltf_attribute_type_texcoord;
2175 else if (len == 5 && strncmp(name,
"COLOR", 5) == 0)
2177 *out_type = cgltf_attribute_type_color;
2179 else if (len == 6 && strncmp(name,
"JOINTS", 6) == 0)
2181 *out_type = cgltf_attribute_type_joints;
2183 else if (len == 7 && strncmp(name,
"WEIGHTS", 7) == 0)
2185 *out_type = cgltf_attribute_type_weights;
2189 *out_type = cgltf_attribute_type_invalid;
2192 if (us && *out_type != cgltf_attribute_type_invalid)
2194 *out_index = CGLTF_ATOI(us + 1);
2198static 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)
2200 CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
2202 if (*out_attributes)
2204 return CGLTF_ERROR_JSON;
2207 *out_attributes_count = tokens[i].size;
2211 if (!*out_attributes)
2213 return CGLTF_ERROR_NOMEM;
2216 for (cgltf_size j = 0; j < *out_attributes_count; ++j)
2218 CGLTF_CHECK_KEY(tokens[i]);
2220 i = cgltf_parse_json_string(options, tokens, i, json_chunk, &(*out_attributes)[j].name);
2223 return CGLTF_ERROR_JSON;
2226 cgltf_parse_attribute_type((*out_attributes)[j].name, &(*out_attributes)[j].type, &(*out_attributes)[j].index);
2228 (*out_attributes)[j].data = CGLTF_PTRINDEX(
cgltf_accessor, cgltf_json_to_int(tokens + i, json_chunk));
2235static int cgltf_parse_json_extras(jsmntok_t
const* tokens,
int i,
const uint8_t* json_chunk,
cgltf_extras* out_extras)
2238 out_extras->start_offset = tokens[i].start;
2239 out_extras->end_offset = tokens[i].end;
2240 i = cgltf_skip_json(tokens, i);
2246 CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
2248 int size = tokens[i].size;
2251 for (
int j = 0; j < size; ++j)
2253 CGLTF_CHECK_KEY(tokens[i]);
2255 if (cgltf_json_strcmp(tokens + i, json_chunk,
"attributes") == 0)
2257 i = cgltf_parse_json_attribute_list(options, tokens, i + 1, json_chunk, &out_draco_mesh_compression->attributes, &out_draco_mesh_compression->attributes_count);
2259 else if (cgltf_json_strcmp(tokens + i, json_chunk,
"bufferView") == 0)
2262 out_draco_mesh_compression->buffer_view = CGLTF_PTRINDEX(
cgltf_buffer_view, cgltf_json_to_int(tokens + i, json_chunk));
2270static int cgltf_parse_json_primitive(
cgltf_options* options, jsmntok_t
const* tokens,
int i,
const uint8_t* json_chunk,
cgltf_primitive* out_prim)
2272 CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
2274 out_prim->type = cgltf_primitive_type_triangles;
2276 int size = tokens[i].size;
2279 for (
int j = 0; j < size; ++j)
2281 CGLTF_CHECK_KEY(tokens[i]);
2283 if (cgltf_json_strcmp(tokens+i, json_chunk,
"mode") == 0)
2287 = (cgltf_primitive_type)
2288 cgltf_json_to_int(tokens+i, json_chunk);
2291 else if (cgltf_json_strcmp(tokens+i, json_chunk,
"indices") == 0)
2294 out_prim->indices = CGLTF_PTRINDEX(
cgltf_accessor, cgltf_json_to_int(tokens + i, json_chunk));
2297 else if (cgltf_json_strcmp(tokens+i, json_chunk,
"material") == 0)
2300 out_prim->material = CGLTF_PTRINDEX(
cgltf_material, cgltf_json_to_int(tokens + i, json_chunk));
2303 else if (cgltf_json_strcmp(tokens+i, json_chunk,
"attributes") == 0)
2305 i = cgltf_parse_json_attribute_list(options, tokens, i + 1, json_chunk, &out_prim->attributes, &out_prim->attributes_count);
2307 else if (cgltf_json_strcmp(tokens+i, json_chunk,
"targets") == 0)
2309 i = cgltf_parse_json_array(options, tokens, i + 1, json_chunk,
sizeof(
cgltf_morph_target), (
void**)&out_prim->targets, &out_prim->targets_count);
2315 for (cgltf_size k = 0; k < out_prim->targets_count; ++k)
2317 i = cgltf_parse_json_attribute_list(options, tokens, i, json_chunk, &out_prim->targets[k].attributes, &out_prim->targets[k].attributes_count);
2324 else if (cgltf_json_strcmp(tokens + i, json_chunk,
"extras") == 0)
2326 i = cgltf_parse_json_extras(tokens, i + 1, json_chunk, &out_prim->extras);
2328 else if (cgltf_json_strcmp(tokens + i, json_chunk,
"extensions") == 0)
2332 CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
2334 int extensions_size = tokens[i].size;
2337 for (
int k = 0; k < extensions_size; ++k)
2339 CGLTF_CHECK_KEY(tokens[i]);
2341 if (cgltf_json_strcmp(tokens+i, json_chunk,
"KHR_draco_mesh_compression") == 0)
2343 out_prim->has_draco_mesh_compression = 1;
2344 i = cgltf_parse_json_draco_mesh_compression(options, tokens, i + 1, json_chunk, &out_prim->draco_mesh_compression);
2348 i = cgltf_skip_json(tokens, i+1);
2359 i = cgltf_skip_json(tokens, i+1);
2371static int cgltf_parse_json_mesh(
cgltf_options* options, jsmntok_t
const* tokens,
int i,
const uint8_t* json_chunk,
cgltf_mesh* out_mesh)
2373 CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
2375 int size = tokens[i].size;
2378 for (
int j = 0; j < size; ++j)
2380 CGLTF_CHECK_KEY(tokens[i]);
2382 if (cgltf_json_strcmp(tokens+i, json_chunk,
"name") == 0)
2384 i = cgltf_parse_json_string(options, tokens, i + 1, json_chunk, &out_mesh->name);
2386 else if (cgltf_json_strcmp(tokens+i, json_chunk,
"primitives") == 0)
2388 i = cgltf_parse_json_array(options, tokens, i + 1, json_chunk,
sizeof(
cgltf_primitive), (
void**)&out_mesh->primitives, &out_mesh->primitives_count);
2394 for (cgltf_size prim_index = 0; prim_index < out_mesh->primitives_count; ++prim_index)
2396 i = cgltf_parse_json_primitive(options, tokens, i, json_chunk, &out_mesh->primitives[prim_index]);
2403 else if (cgltf_json_strcmp(tokens + i, json_chunk,
"weights") == 0)
2405 i = cgltf_parse_json_array(options, tokens, i + 1, json_chunk,
sizeof(cgltf_float), (
void**)&out_mesh->weights, &out_mesh->weights_count);
2411 i = cgltf_parse_json_float_array(tokens, i - 1, json_chunk, out_mesh->weights, (
int)out_mesh->weights_count);
2413 else if (cgltf_json_strcmp(tokens + i, json_chunk,
"extras") == 0)
2417 out_mesh->extras.start_offset = tokens[i].start;
2418 out_mesh->extras.end_offset = tokens[i].end;
2420 if (tokens[i].type == JSMN_OBJECT)
2422 int extras_size = tokens[i].size;
2425 for (
int k = 0; k < extras_size; ++k)
2427 CGLTF_CHECK_KEY(tokens[i]);
2429 if (cgltf_json_strcmp(tokens+i, json_chunk,
"targetNames") == 0)
2431 i = cgltf_parse_json_string_array(options, tokens, i + 1, json_chunk, &out_mesh->target_names, &out_mesh->target_names_count);
2435 i = cgltf_skip_json(tokens, i+1);
2446 i = cgltf_skip_json(tokens, i);
2451 i = cgltf_skip_json(tokens, i+1);
2463static int cgltf_parse_json_meshes(
cgltf_options* options, jsmntok_t
const* tokens,
int i,
const uint8_t* json_chunk,
cgltf_data* out_data)
2465 i = cgltf_parse_json_array(options, tokens, i, json_chunk,
sizeof(
cgltf_mesh), (
void**)&out_data->meshes, &out_data->meshes_count);
2471 for (cgltf_size j = 0; j < out_data->meshes_count; ++j)
2473 i = cgltf_parse_json_mesh(options, tokens, i, json_chunk, &out_data->meshes[j]);
2482static cgltf_component_type cgltf_json_to_component_type(jsmntok_t
const* tok,
const uint8_t* json_chunk)
2484 int type = cgltf_json_to_int(tok, json_chunk);
2489 return cgltf_component_type_r_8;
2491 return cgltf_component_type_r_8u;
2493 return cgltf_component_type_r_16;
2495 return cgltf_component_type_r_16u;
2497 return cgltf_component_type_r_32u;
2499 return cgltf_component_type_r_32f;
2501 return cgltf_component_type_invalid;
2505static int cgltf_parse_json_accessor_sparse(jsmntok_t
const* tokens,
int i,
const uint8_t* json_chunk,
cgltf_accessor_sparse* out_sparse)
2507 CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
2509 int size = tokens[i].size;
2512 for (
int j = 0; j < size; ++j)
2514 CGLTF_CHECK_KEY(tokens[i]);
2516 if (cgltf_json_strcmp(tokens+i, json_chunk,
"count") == 0)
2519 out_sparse->count = cgltf_json_to_int(tokens + i, json_chunk);
2522 else if (cgltf_json_strcmp(tokens+i, json_chunk,
"indices") == 0)
2525 CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
2527 int indices_size = tokens[i].size;
2530 for (
int k = 0; k < indices_size; ++k)
2532 CGLTF_CHECK_KEY(tokens[i]);
2534 if (cgltf_json_strcmp(tokens+i, json_chunk,
"bufferView") == 0)
2537 out_sparse->indices_buffer_view = CGLTF_PTRINDEX(
cgltf_buffer_view, cgltf_json_to_int(tokens + i, json_chunk));
2540 else if (cgltf_json_strcmp(tokens+i, json_chunk,
"byteOffset") == 0)
2543 out_sparse->indices_byte_offset = cgltf_json_to_int(tokens + i, json_chunk);
2546 else if (cgltf_json_strcmp(tokens+i, json_chunk,
"componentType") == 0)
2549 out_sparse->indices_component_type = cgltf_json_to_component_type(tokens + i, json_chunk);
2552 else if (cgltf_json_strcmp(tokens + i, json_chunk,
"extras") == 0)
2554 i = cgltf_parse_json_extras(tokens, i + 1, json_chunk, &out_sparse->indices_extras);
2558 i = cgltf_skip_json(tokens, i+1);
2567 else if (cgltf_json_strcmp(tokens+i, json_chunk,
"values") == 0)
2570 CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
2572 int values_size = tokens[i].size;
2575 for (
int k = 0; k < values_size; ++k)
2577 CGLTF_CHECK_KEY(tokens[i]);
2579 if (cgltf_json_strcmp(tokens+i, json_chunk,
"bufferView") == 0)
2582 out_sparse->values_buffer_view = CGLTF_PTRINDEX(
cgltf_buffer_view, cgltf_json_to_int(tokens + i, json_chunk));
2585 else if (cgltf_json_strcmp(tokens+i, json_chunk,
"byteOffset") == 0)
2588 out_sparse->values_byte_offset = cgltf_json_to_int(tokens + i, json_chunk);
2591 else if (cgltf_json_strcmp(tokens + i, json_chunk,
"extras") == 0)
2593 i = cgltf_parse_json_extras(tokens, i + 1, json_chunk, &out_sparse->values_extras);
2597 i = cgltf_skip_json(tokens, i+1);
2606 else if (cgltf_json_strcmp(tokens + i, json_chunk,
"extras") == 0)
2608 i = cgltf_parse_json_extras(tokens, i + 1, json_chunk, &out_sparse->extras);
2612 i = cgltf_skip_json(tokens, i+1);
2624static int cgltf_parse_json_accessor(jsmntok_t
const* tokens,
int i,
const uint8_t* json_chunk,
cgltf_accessor* out_accessor)
2626 CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
2628 int size = tokens[i].size;
2631 for (
int j = 0; j < size; ++j)
2633 CGLTF_CHECK_KEY(tokens[i]);
2635 if (cgltf_json_strcmp(tokens+i, json_chunk,
"bufferView") == 0)
2638 out_accessor->buffer_view = CGLTF_PTRINDEX(
cgltf_buffer_view, cgltf_json_to_int(tokens + i, json_chunk));
2641 else if (cgltf_json_strcmp(tokens+i, json_chunk,
"byteOffset") == 0)
2644 out_accessor->offset =
2645 cgltf_json_to_int(tokens+i, json_chunk);
2648 else if (cgltf_json_strcmp(tokens+i, json_chunk,
"componentType") == 0)
2651 out_accessor->component_type = cgltf_json_to_component_type(tokens + i, json_chunk);
2654 else if (cgltf_json_strcmp(tokens+i, json_chunk,
"normalized") == 0)
2657 out_accessor->normalized = cgltf_json_to_bool(tokens+i, json_chunk);
2660 else if (cgltf_json_strcmp(tokens+i, json_chunk,
"count") == 0)
2663 out_accessor->count =
2664 cgltf_json_to_int(tokens+i, json_chunk);
2667 else if (cgltf_json_strcmp(tokens+i, json_chunk,
"type") == 0)
2670 if (cgltf_json_strcmp(tokens+i, json_chunk,
"SCALAR") == 0)
2672 out_accessor->type = cgltf_type_scalar;
2674 else if (cgltf_json_strcmp(tokens+i, json_chunk,
"VEC2") == 0)
2676 out_accessor->type = cgltf_type_vec2;
2678 else if (cgltf_json_strcmp(tokens+i, json_chunk,
"VEC3") == 0)
2680 out_accessor->type = cgltf_type_vec3;
2682 else if (cgltf_json_strcmp(tokens+i, json_chunk,
"VEC4") == 0)
2684 out_accessor->type = cgltf_type_vec4;
2686 else if (cgltf_json_strcmp(tokens+i, json_chunk,
"MAT2") == 0)
2688 out_accessor->type = cgltf_type_mat2;
2690 else if (cgltf_json_strcmp(tokens+i, json_chunk,
"MAT3") == 0)
2692 out_accessor->type = cgltf_type_mat3;
2694 else if (cgltf_json_strcmp(tokens+i, json_chunk,
"MAT4") == 0)
2696 out_accessor->type = cgltf_type_mat4;
2700 else if (cgltf_json_strcmp(tokens + i, json_chunk,
"min") == 0)
2703 out_accessor->has_min = 1;
2705 int min_size = tokens[i].size > 16 ? 16 : tokens[i].size;
2706 i = cgltf_parse_json_float_array(tokens, i, json_chunk, out_accessor->min, min_size);
2708 else if (cgltf_json_strcmp(tokens + i, json_chunk,
"max") == 0)
2711 out_accessor->has_max = 1;
2713 int max_size = tokens[i].size > 16 ? 16 : tokens[i].size;
2714 i = cgltf_parse_json_float_array(tokens, i, json_chunk, out_accessor->max, max_size);
2716 else if (cgltf_json_strcmp(tokens + i, json_chunk,
"sparse") == 0)
2718 out_accessor->is_sparse = 1;
2719 i = cgltf_parse_json_accessor_sparse(tokens, i + 1, json_chunk, &out_accessor->sparse);
2721 else if (cgltf_json_strcmp(tokens + i, json_chunk,
"extras") == 0)
2723 i = cgltf_parse_json_extras(tokens, i + 1, json_chunk, &out_accessor->extras);
2727 i = cgltf_skip_json(tokens, i+1);
2739static int cgltf_parse_json_texture_transform(jsmntok_t
const* tokens,
int i,
const uint8_t* json_chunk,
cgltf_texture_transform* out_texture_transform)
2741 CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
2743 int size = tokens[i].size;
2746 for (
int j = 0; j < size; ++j)
2748 CGLTF_CHECK_KEY(tokens[i]);
2750 if (cgltf_json_strcmp(tokens + i, json_chunk,
"offset") == 0)
2752 i = cgltf_parse_json_float_array(tokens, i + 1, json_chunk, out_texture_transform->offset, 2);
2754 else if (cgltf_json_strcmp(tokens + i, json_chunk,
"rotation") == 0)
2757 out_texture_transform->rotation = cgltf_json_to_float(tokens + i, json_chunk);
2760 else if (cgltf_json_strcmp(tokens + i, json_chunk,
"scale") == 0)
2762 i = cgltf_parse_json_float_array(tokens, i + 1, json_chunk, out_texture_transform->scale, 2);
2764 else if (cgltf_json_strcmp(tokens + i, json_chunk,
"texCoord") == 0)
2767 out_texture_transform->texcoord = cgltf_json_to_int(tokens + i, json_chunk);
2772 i = cgltf_skip_json(tokens, i + 1);
2784static int cgltf_parse_json_texture_view(jsmntok_t
const* tokens,
int i,
const uint8_t* json_chunk,
cgltf_texture_view* out_texture_view)
2786 CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
2788 out_texture_view->scale = 1.0f;
2789 cgltf_fill_float_array(out_texture_view->transform.scale, 2, 1.0f);
2791 int size = tokens[i].size;
2794 for (
int j = 0; j < size; ++j)
2796 CGLTF_CHECK_KEY(tokens[i]);
2798 if (cgltf_json_strcmp(tokens + i, json_chunk,
"index") == 0)
2801 out_texture_view->texture = CGLTF_PTRINDEX(
cgltf_texture, cgltf_json_to_int(tokens + i, json_chunk));
2804 else if (cgltf_json_strcmp(tokens + i, json_chunk,
"texCoord") == 0)
2807 out_texture_view->texcoord = cgltf_json_to_int(tokens + i, json_chunk);
2810 else if (cgltf_json_strcmp(tokens + i, json_chunk,
"scale") == 0)
2813 out_texture_view->scale = cgltf_json_to_float(tokens + i, json_chunk);
2816 else if (cgltf_json_strcmp(tokens + i, json_chunk,
"strength") == 0)
2819 out_texture_view->scale = cgltf_json_to_float(tokens + i, json_chunk);
2822 else if (cgltf_json_strcmp(tokens + i, json_chunk,
"extras") == 0)
2824 i = cgltf_parse_json_extras(tokens, i + 1, json_chunk, &out_texture_view->extras);
2826 else if (cgltf_json_strcmp(tokens + i, json_chunk,
"extensions") == 0)
2830 CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
2832 int extensions_size = tokens[i].size;
2835 for (
int k = 0; k < extensions_size; ++k)
2837 CGLTF_CHECK_KEY(tokens[i]);
2839 if (cgltf_json_strcmp(tokens+i, json_chunk,
"KHR_texture_transform") == 0)
2841 out_texture_view->has_transform = 1;
2842 i = cgltf_parse_json_texture_transform(tokens, i + 1, json_chunk, &out_texture_view->transform);
2846 i = cgltf_skip_json(tokens, i+1);
2857 i = cgltf_skip_json(tokens, i + 1);
2869static int cgltf_parse_json_pbr_metallic_roughness(jsmntok_t
const* tokens,
int i,
const uint8_t* json_chunk,
cgltf_pbr_metallic_roughness* out_pbr)
2871 CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
2873 int size = tokens[i].size;
2876 for (
int j = 0; j < size; ++j)
2878 CGLTF_CHECK_KEY(tokens[i]);
2880 if (cgltf_json_strcmp(tokens+i, json_chunk,
"metallicFactor") == 0)
2883 out_pbr->metallic_factor =
2884 cgltf_json_to_float(tokens + i, json_chunk);
2887 else if (cgltf_json_strcmp(tokens+i, json_chunk,
"roughnessFactor") == 0)
2890 out_pbr->roughness_factor =
2891 cgltf_json_to_float(tokens+i, json_chunk);
2894 else if (cgltf_json_strcmp(tokens+i, json_chunk,
"baseColorFactor") == 0)
2896 i = cgltf_parse_json_float_array(tokens, i + 1, json_chunk, out_pbr->base_color_factor, 4);
2898 else if (cgltf_json_strcmp(tokens+i, json_chunk,
"baseColorTexture") == 0)
2900 i = cgltf_parse_json_texture_view(tokens, i + 1, json_chunk,
2901 &out_pbr->base_color_texture);
2903 else if (cgltf_json_strcmp(tokens + i, json_chunk,
"metallicRoughnessTexture") == 0)
2905 i = cgltf_parse_json_texture_view(tokens, i + 1, json_chunk,
2906 &out_pbr->metallic_roughness_texture);
2908 else if (cgltf_json_strcmp(tokens + i, json_chunk,
"extras") == 0)
2910 i = cgltf_parse_json_extras(tokens, i + 1, json_chunk, &out_pbr->extras);
2914 i = cgltf_skip_json(tokens, i+1);
2926static int cgltf_parse_json_pbr_specular_glossiness(jsmntok_t
const* tokens,
int i,
const uint8_t* json_chunk,
cgltf_pbr_specular_glossiness* out_pbr)
2928 CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
2929 int size = tokens[i].size;
2932 for (
int j = 0; j < size; ++j)
2934 CGLTF_CHECK_KEY(tokens[i]);
2936 if (cgltf_json_strcmp(tokens+i, json_chunk,
"diffuseFactor") == 0)
2938 i = cgltf_parse_json_float_array(tokens, i + 1, json_chunk, out_pbr->diffuse_factor, 4);
2940 else if (cgltf_json_strcmp(tokens+i, json_chunk,
"specularFactor") == 0)
2942 i = cgltf_parse_json_float_array(tokens, i + 1, json_chunk, out_pbr->specular_factor, 3);
2944 else if (cgltf_json_strcmp(tokens+i, json_chunk,
"glossinessFactor") == 0)
2947 out_pbr->glossiness_factor = cgltf_json_to_float(tokens + i, json_chunk);
2950 else if (cgltf_json_strcmp(tokens+i, json_chunk,
"diffuseTexture") == 0)
2952 i = cgltf_parse_json_texture_view(tokens, i + 1, json_chunk, &out_pbr->diffuse_texture);
2954 else if (cgltf_json_strcmp(tokens+i, json_chunk,
"specularGlossinessTexture") == 0)
2956 i = cgltf_parse_json_texture_view(tokens, i + 1, json_chunk, &out_pbr->specular_glossiness_texture);
2960 i = cgltf_skip_json(tokens, i+1);
2972static int cgltf_parse_json_clearcoat(jsmntok_t
const* tokens,
int i,
const uint8_t* json_chunk,
cgltf_clearcoat* out_clearcoat)
2974 CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
2975 int size = tokens[i].size;
2978 for (
int j = 0; j < size; ++j)
2980 CGLTF_CHECK_KEY(tokens[i]);
2982 if (cgltf_json_strcmp(tokens+i, json_chunk,
"clearcoatFactor") == 0)
2985 out_clearcoat->clearcoat_factor = cgltf_json_to_float(tokens + i, json_chunk);
2988 else if (cgltf_json_strcmp(tokens+i, json_chunk,
"clearcoatRoughnessFactor") == 0)
2991 out_clearcoat->clearcoat_roughness_factor = cgltf_json_to_float(tokens + i, json_chunk);
2994 else if (cgltf_json_strcmp(tokens+i, json_chunk,
"clearcoatTexture") == 0)
2996 i = cgltf_parse_json_texture_view(tokens, i + 1, json_chunk, &out_clearcoat->clearcoat_texture);
2998 else if (cgltf_json_strcmp(tokens+i, json_chunk,
"clearcoatRoughnessTexture") == 0)
3000 i = cgltf_parse_json_texture_view(tokens, i + 1, json_chunk, &out_clearcoat->clearcoat_roughness_texture);
3002 else if (cgltf_json_strcmp(tokens+i, json_chunk,
"clearcoatNormalTexture") == 0)
3004 i = cgltf_parse_json_texture_view(tokens, i + 1, json_chunk, &out_clearcoat->clearcoat_normal_texture);
3008 i = cgltf_skip_json(tokens, i+1);
3020static int cgltf_parse_json_image(
cgltf_options* options, jsmntok_t
const* tokens,
int i,
const uint8_t* json_chunk,
cgltf_image* out_image)
3022 CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
3024 int size = tokens[i].size;
3027 for (
int j = 0; j < size; ++j)
3029 CGLTF_CHECK_KEY(tokens[i]);
3031 if (cgltf_json_strcmp(tokens + i, json_chunk,
"uri") == 0)
3033 i = cgltf_parse_json_string(options, tokens, i + 1, json_chunk, &out_image->uri);
3035 else if (cgltf_json_strcmp(tokens+i, json_chunk,
"bufferView") == 0)
3038 out_image->buffer_view = CGLTF_PTRINDEX(
cgltf_buffer_view, cgltf_json_to_int(tokens + i, json_chunk));
3041 else if (cgltf_json_strcmp(tokens + i, json_chunk,
"mimeType") == 0)
3043 i = cgltf_parse_json_string(options, tokens, i + 1, json_chunk, &out_image->mime_type);
3045 else if (cgltf_json_strcmp(tokens + i, json_chunk,
"name") == 0)
3047 i = cgltf_parse_json_string(options, tokens, i + 1, json_chunk, &out_image->name);
3049 else if (cgltf_json_strcmp(tokens + i, json_chunk,
"extras") == 0)
3051 i = cgltf_parse_json_extras(tokens, i + 1, json_chunk, &out_image->extras);
3055 i = cgltf_skip_json(tokens, i + 1);
3067static int cgltf_parse_json_sampler(
cgltf_options* options, jsmntok_t
const* tokens,
int i,
const uint8_t* json_chunk,
cgltf_sampler* out_sampler)
3070 CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
3072 out_sampler->wrap_s = 10497;
3073 out_sampler->wrap_t = 10497;
3075 int size = tokens[i].size;
3078 for (
int j = 0; j < size; ++j)
3080 CGLTF_CHECK_KEY(tokens[i]);
3082 if (cgltf_json_strcmp(tokens + i, json_chunk,
"magFilter") == 0)
3085 out_sampler->mag_filter
3086 = cgltf_json_to_int(tokens + i, json_chunk);
3089 else if (cgltf_json_strcmp(tokens + i, json_chunk,
"minFilter") == 0)
3092 out_sampler->min_filter
3093 = cgltf_json_to_int(tokens + i, json_chunk);
3096 else if (cgltf_json_strcmp(tokens + i, json_chunk,
"wrapS") == 0)
3100 = cgltf_json_to_int(tokens + i, json_chunk);
3103 else if (cgltf_json_strcmp(tokens + i, json_chunk,
"wrapT") == 0)
3107 = cgltf_json_to_int(tokens + i, json_chunk);
3110 else if (cgltf_json_strcmp(tokens + i, json_chunk,
"extras") == 0)
3112 i = cgltf_parse_json_extras(tokens, i + 1, json_chunk, &out_sampler->extras);
3116 i = cgltf_skip_json(tokens, i + 1);
3129static int cgltf_parse_json_texture(
cgltf_options* options, jsmntok_t
const* tokens,
int i,
const uint8_t* json_chunk,
cgltf_texture* out_texture)
3131 CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
3133 int size = tokens[i].size;
3136 for (
int j = 0; j < size; ++j)
3138 CGLTF_CHECK_KEY(tokens[i]);
3140 if (cgltf_json_strcmp(tokens+i, json_chunk,
"name") == 0)
3142 i = cgltf_parse_json_string(options, tokens, i + 1, json_chunk, &out_texture->name);
3144 else if (cgltf_json_strcmp(tokens + i, json_chunk,
"sampler") == 0)
3147 out_texture->sampler = CGLTF_PTRINDEX(
cgltf_sampler, cgltf_json_to_int(tokens + i, json_chunk));
3150 else if (cgltf_json_strcmp(tokens + i, json_chunk,
"source") == 0)
3153 out_texture->image = CGLTF_PTRINDEX(
cgltf_image, cgltf_json_to_int(tokens + i, json_chunk));
3156 else if (cgltf_json_strcmp(tokens + i, json_chunk,
"extras") == 0)
3158 i = cgltf_parse_json_extras(tokens, i + 1, json_chunk, &out_texture->extras);
3162 i = cgltf_skip_json(tokens, i + 1);
3174static int cgltf_parse_json_material(
cgltf_options* options, jsmntok_t
const* tokens,
int i,
const uint8_t* json_chunk,
cgltf_material* out_material)
3176 CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
3178 cgltf_fill_float_array(out_material->pbr_metallic_roughness.base_color_factor, 4, 1.0f);
3179 out_material->pbr_metallic_roughness.metallic_factor = 1.0f;
3180 out_material->pbr_metallic_roughness.roughness_factor = 1.0f;
3182 cgltf_fill_float_array(out_material->pbr_specular_glossiness.diffuse_factor, 4, 1.0f);
3183 cgltf_fill_float_array(out_material->pbr_specular_glossiness.specular_factor, 3, 1.0f);
3184 out_material->pbr_specular_glossiness.glossiness_factor = 1.0f;
3186 out_material->alpha_cutoff = 0.5f;
3188 int size = tokens[i].size;
3191 for (
int j = 0; j < size; ++j)
3193 CGLTF_CHECK_KEY(tokens[i]);
3195 if (cgltf_json_strcmp(tokens+i, json_chunk,
"name") == 0)
3197 i = cgltf_parse_json_string(options, tokens, i + 1, json_chunk, &out_material->name);
3199 else if (cgltf_json_strcmp(tokens+i, json_chunk,
"pbrMetallicRoughness") == 0)
3201 out_material->has_pbr_metallic_roughness = 1;
3202 i = cgltf_parse_json_pbr_metallic_roughness(tokens, i + 1, json_chunk, &out_material->pbr_metallic_roughness);
3204 else if (cgltf_json_strcmp(tokens+i, json_chunk,
"emissiveFactor") == 0)
3206 i = cgltf_parse_json_float_array(tokens, i + 1, json_chunk, out_material->emissive_factor, 3);
3208 else if (cgltf_json_strcmp(tokens + i, json_chunk,
"normalTexture") == 0)
3210 i = cgltf_parse_json_texture_view(tokens, i + 1, json_chunk,
3211 &out_material->normal_texture);
3213 else if (cgltf_json_strcmp(tokens + i, json_chunk,
"occlusionTexture") == 0)
3215 i = cgltf_parse_json_texture_view(tokens, i + 1, json_chunk,
3216 &out_material->occlusion_texture);
3218 else if (cgltf_json_strcmp(tokens + i, json_chunk,
"emissiveTexture") == 0)
3220 i = cgltf_parse_json_texture_view(tokens, i + 1, json_chunk,
3221 &out_material->emissive_texture);
3223 else if (cgltf_json_strcmp(tokens + i, json_chunk,
"alphaMode") == 0)
3226 if (cgltf_json_strcmp(tokens + i, json_chunk,
"OPAQUE") == 0)
3228 out_material->alpha_mode = cgltf_alpha_mode_opaque;
3230 else if (cgltf_json_strcmp(tokens + i, json_chunk,
"MASK") == 0)
3232 out_material->alpha_mode = cgltf_alpha_mode_mask;
3234 else if (cgltf_json_strcmp(tokens + i, json_chunk,
"BLEND") == 0)
3236 out_material->alpha_mode = cgltf_alpha_mode_blend;
3240 else if (cgltf_json_strcmp(tokens + i, json_chunk,
"alphaCutoff") == 0)
3243 out_material->alpha_cutoff = cgltf_json_to_float(tokens + i, json_chunk);
3246 else if (cgltf_json_strcmp(tokens + i, json_chunk,
"doubleSided") == 0)
3249 out_material->double_sided =
3250 cgltf_json_to_bool(tokens + i, json_chunk);
3253 else if (cgltf_json_strcmp(tokens + i, json_chunk,
"extras") == 0)
3255 i = cgltf_parse_json_extras(tokens, i + 1, json_chunk, &out_material->extras);
3257 else if (cgltf_json_strcmp(tokens + i, json_chunk,
"extensions") == 0)
3261 CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
3263 int extensions_size = tokens[i].size;
3266 for (
int k = 0; k < extensions_size; ++k)
3268 CGLTF_CHECK_KEY(tokens[i]);
3270 if (cgltf_json_strcmp(tokens+i, json_chunk,
"KHR_materials_pbrSpecularGlossiness") == 0)
3272 out_material->has_pbr_specular_glossiness = 1;
3273 i = cgltf_parse_json_pbr_specular_glossiness(tokens, i + 1, json_chunk, &out_material->pbr_specular_glossiness);
3275 else if (cgltf_json_strcmp(tokens+i, json_chunk,
"KHR_materials_unlit") == 0)
3277 out_material->unlit = 1;
3278 i = cgltf_skip_json(tokens, i+1);
3280 else if (cgltf_json_strcmp(tokens+i, json_chunk,
"KHR_materials_clearcoat") == 0)
3282 out_material->has_clearcoat = 1;
3283 i = cgltf_parse_json_clearcoat(tokens, i + 1, json_chunk, &out_material->clearcoat);
3287 i = cgltf_skip_json(tokens, i+1);
3298 i = cgltf_skip_json(tokens, i+1);
3310static int cgltf_parse_json_accessors(
cgltf_options* options, jsmntok_t
const* tokens,
int i,
const uint8_t* json_chunk,
cgltf_data* out_data)
3312 i = cgltf_parse_json_array(options, tokens, i, json_chunk,
sizeof(
cgltf_accessor), (
void**)&out_data->accessors, &out_data->accessors_count);
3318 for (cgltf_size j = 0; j < out_data->accessors_count; ++j)
3320 i = cgltf_parse_json_accessor(tokens, i, json_chunk, &out_data->accessors[j]);
3329static int cgltf_parse_json_materials(
cgltf_options* options, jsmntok_t
const* tokens,
int i,
const uint8_t* json_chunk,
cgltf_data* out_data)
3331 i = cgltf_parse_json_array(options, tokens, i, json_chunk,
sizeof(
cgltf_material), (
void**)&out_data->materials, &out_data->materials_count);
3337 for (cgltf_size j = 0; j < out_data->materials_count; ++j)
3339 i = cgltf_parse_json_material(options, tokens, i, json_chunk, &out_data->materials[j]);
3348static int cgltf_parse_json_images(
cgltf_options* options, jsmntok_t
const* tokens,
int i,
const uint8_t* json_chunk,
cgltf_data* out_data)
3350 i = cgltf_parse_json_array(options, tokens, i, json_chunk,
sizeof(
cgltf_image), (
void**)&out_data->images, &out_data->images_count);
3356 for (cgltf_size j = 0; j < out_data->images_count; ++j)
3358 i = cgltf_parse_json_image(options, tokens, i, json_chunk, &out_data->images[j]);
3367static int cgltf_parse_json_textures(
cgltf_options* options, jsmntok_t
const* tokens,
int i,
const uint8_t* json_chunk,
cgltf_data* out_data)
3369 i = cgltf_parse_json_array(options, tokens, i, json_chunk,
sizeof(
cgltf_texture), (
void**)&out_data->textures, &out_data->textures_count);
3375 for (cgltf_size j = 0; j < out_data->textures_count; ++j)
3377 i = cgltf_parse_json_texture(options, tokens, i, json_chunk, &out_data->textures[j]);
3386static int cgltf_parse_json_samplers(
cgltf_options* options, jsmntok_t
const* tokens,
int i,
const uint8_t* json_chunk,
cgltf_data* out_data)
3388 i = cgltf_parse_json_array(options, tokens, i, json_chunk,
sizeof(
cgltf_sampler), (
void**)&out_data->samplers, &out_data->samplers_count);
3394 for (cgltf_size j = 0; j < out_data->samplers_count; ++j)
3396 i = cgltf_parse_json_sampler(options, tokens, i, json_chunk, &out_data->samplers[j]);
3405static int cgltf_parse_json_buffer_view(jsmntok_t
const* tokens,
int i,
const uint8_t* json_chunk,
cgltf_buffer_view* out_buffer_view)
3407 CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
3409 int size = tokens[i].size;
3412 for (
int j = 0; j < size; ++j)
3414 CGLTF_CHECK_KEY(tokens[i]);
3416 if (cgltf_json_strcmp(tokens+i, json_chunk,
"buffer") == 0)
3419 out_buffer_view->buffer = CGLTF_PTRINDEX(
cgltf_buffer, cgltf_json_to_int(tokens + i, json_chunk));
3422 else if (cgltf_json_strcmp(tokens+i, json_chunk,
"byteOffset") == 0)
3425 out_buffer_view->offset =
3426 cgltf_json_to_int(tokens+i, json_chunk);
3429 else if (cgltf_json_strcmp(tokens+i, json_chunk,
"byteLength") == 0)
3432 out_buffer_view->size =
3433 cgltf_json_to_int(tokens+i, json_chunk);
3436 else if (cgltf_json_strcmp(tokens+i, json_chunk,
"byteStride") == 0)
3439 out_buffer_view->stride =
3440 cgltf_json_to_int(tokens+i, json_chunk);
3443 else if (cgltf_json_strcmp(tokens+i, json_chunk,
"target") == 0)
3446 int type = cgltf_json_to_int(tokens+i, json_chunk);
3450 type = cgltf_buffer_view_type_vertices;
3453 type = cgltf_buffer_view_type_indices;
3456 type = cgltf_buffer_view_type_invalid;
3459 out_buffer_view->type = (cgltf_buffer_view_type)type;
3462 else if (cgltf_json_strcmp(tokens + i, json_chunk,
"extras") == 0)
3464 i = cgltf_parse_json_extras(tokens, i + 1, json_chunk, &out_buffer_view->extras);
3468 i = cgltf_skip_json(tokens, i+1);
3480static int cgltf_parse_json_buffer_views(
cgltf_options* options, jsmntok_t
const* tokens,
int i,
const uint8_t* json_chunk,
cgltf_data* out_data)
3482 i = cgltf_parse_json_array(options, tokens, i, json_chunk,
sizeof(
cgltf_buffer_view), (
void**)&out_data->buffer_views, &out_data->buffer_views_count);
3488 for (cgltf_size j = 0; j < out_data->buffer_views_count; ++j)
3490 i = cgltf_parse_json_buffer_view(tokens, i, json_chunk, &out_data->buffer_views[j]);
3499static int cgltf_parse_json_buffer(
cgltf_options* options, jsmntok_t
const* tokens,
int i,
const uint8_t* json_chunk,
cgltf_buffer* out_buffer)
3501 CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
3503 int size = tokens[i].size;
3506 for (
int j = 0; j < size; ++j)
3508 CGLTF_CHECK_KEY(tokens[i]);
3510 if (cgltf_json_strcmp(tokens+i, json_chunk,
"byteLength") == 0)
3514 cgltf_json_to_int(tokens+i, json_chunk);
3517 else if (cgltf_json_strcmp(tokens+i, json_chunk,
"uri") == 0)
3519 i = cgltf_parse_json_string(options, tokens, i + 1, json_chunk, &out_buffer->uri);
3521 else if (cgltf_json_strcmp(tokens + i, json_chunk,
"extras") == 0)
3523 i = cgltf_parse_json_extras(tokens, i + 1, json_chunk, &out_buffer->extras);
3527 i = cgltf_skip_json(tokens, i+1);
3539static int cgltf_parse_json_buffers(
cgltf_options* options, jsmntok_t
const* tokens,
int i,
const uint8_t* json_chunk,
cgltf_data* out_data)
3541 i = cgltf_parse_json_array(options, tokens, i, json_chunk,
sizeof(
cgltf_buffer), (
void**)&out_data->buffers, &out_data->buffers_count);
3547 for (cgltf_size j = 0; j < out_data->buffers_count; ++j)
3549 i = cgltf_parse_json_buffer(options, tokens, i, json_chunk, &out_data->buffers[j]);
3558static int cgltf_parse_json_skin(
cgltf_options* options, jsmntok_t
const* tokens,
int i,
const uint8_t* json_chunk,
cgltf_skin* out_skin)
3560 CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
3562 int size = tokens[i].size;
3565 for (
int j = 0; j < size; ++j)
3567 CGLTF_CHECK_KEY(tokens[i]);
3569 if (cgltf_json_strcmp(tokens+i, json_chunk,
"name") == 0)
3571 i = cgltf_parse_json_string(options, tokens, i + 1, json_chunk, &out_skin->name);
3573 else if (cgltf_json_strcmp(tokens+i, json_chunk,
"joints") == 0)
3575 i = cgltf_parse_json_array(options, tokens, i + 1, json_chunk,
sizeof(
cgltf_node*), (
void**)&out_skin->joints, &out_skin->joints_count);
3581 for (cgltf_size k = 0; k < out_skin->joints_count; ++k)
3583 out_skin->joints[k] = CGLTF_PTRINDEX(
cgltf_node, cgltf_json_to_int(tokens + i, json_chunk));
3587 else if (cgltf_json_strcmp(tokens+i, json_chunk,
"skeleton") == 0)
3590 CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_PRIMITIVE);
3591 out_skin->skeleton = CGLTF_PTRINDEX(
cgltf_node, cgltf_json_to_int(tokens + i, json_chunk));
3594 else if (cgltf_json_strcmp(tokens+i, json_chunk,
"inverseBindMatrices") == 0)
3597 CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_PRIMITIVE);
3598 out_skin->inverse_bind_matrices = CGLTF_PTRINDEX(
cgltf_accessor, cgltf_json_to_int(tokens + i, json_chunk));
3601 else if (cgltf_json_strcmp(tokens + i, json_chunk,
"extras") == 0)
3603 i = cgltf_parse_json_extras(tokens, i + 1, json_chunk, &out_skin->extras);
3607 i = cgltf_skip_json(tokens, i+1);
3619static int cgltf_parse_json_skins(
cgltf_options* options, jsmntok_t
const* tokens,
int i,
const uint8_t* json_chunk,
cgltf_data* out_data)
3621 i = cgltf_parse_json_array(options, tokens, i, json_chunk,
sizeof(
cgltf_skin), (
void**)&out_data->skins, &out_data->skins_count);
3627 for (cgltf_size j = 0; j < out_data->skins_count; ++j)
3629 i = cgltf_parse_json_skin(options, tokens, i, json_chunk, &out_data->skins[j]);
3638static int cgltf_parse_json_camera(
cgltf_options* options, jsmntok_t
const* tokens,
int i,
const uint8_t* json_chunk,
cgltf_camera* out_camera)
3640 CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
3642 int size = tokens[i].size;
3645 for (
int j = 0; j < size; ++j)
3647 CGLTF_CHECK_KEY(tokens[i]);
3649 if (cgltf_json_strcmp(tokens+i, json_chunk,
"name") == 0)
3651 i = cgltf_parse_json_string(options, tokens, i + 1, json_chunk, &out_camera->name);
3653 else if (cgltf_json_strcmp(tokens+i, json_chunk,
"type") == 0)
3656 if (cgltf_json_strcmp(tokens + i, json_chunk,
"perspective") == 0)
3658 out_camera->type = cgltf_camera_type_perspective;
3660 else if (cgltf_json_strcmp(tokens + i, json_chunk,
"orthographic") == 0)
3662 out_camera->type = cgltf_camera_type_orthographic;
3666 else if (cgltf_json_strcmp(tokens+i, json_chunk,
"perspective") == 0)
3670 CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
3672 int data_size = tokens[i].size;
3675 out_camera->type = cgltf_camera_type_perspective;
3677 for (
int k = 0; k < data_size; ++k)
3679 CGLTF_CHECK_KEY(tokens[i]);
3681 if (cgltf_json_strcmp(tokens+i, json_chunk,
"aspectRatio") == 0)
3684 out_camera->data.perspective.aspect_ratio = cgltf_json_to_float(tokens + i, json_chunk);
3687 else if (cgltf_json_strcmp(tokens+i, json_chunk,
"yfov") == 0)
3690 out_camera->data.perspective.yfov = cgltf_json_to_float(tokens + i, json_chunk);
3693 else if (cgltf_json_strcmp(tokens+i, json_chunk,
"zfar") == 0)
3696 out_camera->data.perspective.zfar = cgltf_json_to_float(tokens + i, json_chunk);
3699 else if (cgltf_json_strcmp(tokens+i, json_chunk,
"znear") == 0)
3702 out_camera->data.perspective.znear = cgltf_json_to_float(tokens + i, json_chunk);
3705 else if (cgltf_json_strcmp(tokens + i, json_chunk,
"extras") == 0)
3707 i = cgltf_parse_json_extras(tokens, i + 1, json_chunk, &out_camera->data.perspective.extras);
3711 i = cgltf_skip_json(tokens, i+1);
3720 else if (cgltf_json_strcmp(tokens+i, json_chunk,
"orthographic") == 0)
3724 CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
3726 int data_size = tokens[i].size;
3729 out_camera->type = cgltf_camera_type_orthographic;
3731 for (
int k = 0; k < data_size; ++k)
3733 CGLTF_CHECK_KEY(tokens[i]);
3735 if (cgltf_json_strcmp(tokens+i, json_chunk,
"xmag") == 0)
3738 out_camera->data.orthographic.xmag = cgltf_json_to_float(tokens + i, json_chunk);
3741 else if (cgltf_json_strcmp(tokens+i, json_chunk,
"ymag") == 0)
3744 out_camera->data.orthographic.ymag = cgltf_json_to_float(tokens + i, json_chunk);
3747 else if (cgltf_json_strcmp(tokens+i, json_chunk,
"zfar") == 0)
3750 out_camera->data.orthographic.zfar = cgltf_json_to_float(tokens + i, json_chunk);
3753 else if (cgltf_json_strcmp(tokens+i, json_chunk,
"znear") == 0)
3756 out_camera->data.orthographic.znear = cgltf_json_to_float(tokens + i, json_chunk);
3759 else if (cgltf_json_strcmp(tokens + i, json_chunk,
"extras") == 0)
3761 i = cgltf_parse_json_extras(tokens, i + 1, json_chunk, &out_camera->data.orthographic.extras);
3765 i = cgltf_skip_json(tokens, i+1);
3774 else if (cgltf_json_strcmp(tokens + i, json_chunk,
"extras") == 0)
3776 i = cgltf_parse_json_extras(tokens, i + 1, json_chunk, &out_camera->extras);
3780 i = cgltf_skip_json(tokens, i+1);
3792static int cgltf_parse_json_cameras(
cgltf_options* options, jsmntok_t
const* tokens,
int i,
const uint8_t* json_chunk,
cgltf_data* out_data)
3794 i = cgltf_parse_json_array(options, tokens, i, json_chunk,
sizeof(
cgltf_camera), (
void**)&out_data->cameras, &out_data->cameras_count);
3800 for (cgltf_size j = 0; j < out_data->cameras_count; ++j)
3802 i = cgltf_parse_json_camera(options, tokens, i, json_chunk, &out_data->cameras[j]);
3811static int cgltf_parse_json_light(
cgltf_options* options, jsmntok_t
const* tokens,
int i,
const uint8_t* json_chunk,
cgltf_light* out_light)
3813 CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
3815 int size = tokens[i].size;
3818 for (
int j = 0; j < size; ++j)
3820 CGLTF_CHECK_KEY(tokens[i]);
3822 if (cgltf_json_strcmp(tokens+i, json_chunk,
"name") == 0)
3824 i = cgltf_parse_json_string(options, tokens, i + 1, json_chunk, &out_light->name);
3826 else if (cgltf_json_strcmp(tokens + i, json_chunk,
"color") == 0)
3828 i = cgltf_parse_json_float_array(tokens, i + 1, json_chunk, out_light->color, 3);
3830 else if (cgltf_json_strcmp(tokens + i, json_chunk,
"intensity") == 0)
3833 out_light->intensity = cgltf_json_to_float(tokens + i, json_chunk);
3836 else if (cgltf_json_strcmp(tokens+i, json_chunk,
"type") == 0)
3839 if (cgltf_json_strcmp(tokens + i, json_chunk,
"directional") == 0)
3841 out_light->type = cgltf_light_type_directional;
3843 else if (cgltf_json_strcmp(tokens + i, json_chunk,
"point") == 0)
3845 out_light->type = cgltf_light_type_point;
3847 else if (cgltf_json_strcmp(tokens + i, json_chunk,
"spot") == 0)
3849 out_light->type = cgltf_light_type_spot;
3853 else if (cgltf_json_strcmp(tokens + i, json_chunk,
"range") == 0)
3856 out_light->range = cgltf_json_to_float(tokens + i, json_chunk);
3859 else if (cgltf_json_strcmp(tokens+i, json_chunk,
"spot") == 0)
3863 CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
3865 int data_size = tokens[i].size;
3868 for (
int k = 0; k < data_size; ++k)
3870 CGLTF_CHECK_KEY(tokens[i]);
3872 if (cgltf_json_strcmp(tokens+i, json_chunk,
"innerConeAngle") == 0)
3875 out_light->spot_inner_cone_angle = cgltf_json_to_float(tokens + i, json_chunk);
3878 else if (cgltf_json_strcmp(tokens+i, json_chunk,
"outerConeAngle") == 0)
3881 out_light->spot_outer_cone_angle = cgltf_json_to_float(tokens + i, json_chunk);
3886 i = cgltf_skip_json(tokens, i+1);
3897 i = cgltf_skip_json(tokens, i+1);
3909static int cgltf_parse_json_lights(
cgltf_options* options, jsmntok_t
const* tokens,
int i,
const uint8_t* json_chunk,
cgltf_data* out_data)
3911 i = cgltf_parse_json_array(options, tokens, i, json_chunk,
sizeof(
cgltf_light), (
void**)&out_data->lights, &out_data->lights_count);
3917 for (cgltf_size j = 0; j < out_data->lights_count; ++j)
3919 i = cgltf_parse_json_light(options, tokens, i, json_chunk, &out_data->lights[j]);
3928static int cgltf_parse_json_node(
cgltf_options* options, jsmntok_t
const* tokens,
int i,
const uint8_t* json_chunk,
cgltf_node* out_node)
3930 CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
3932 out_node->rotation[3] = 1.0f;
3933 out_node->scale[0] = 1.0f;
3934 out_node->scale[1] = 1.0f;
3935 out_node->scale[2] = 1.0f;
3936 out_node->matrix[0] = 1.0f;
3937 out_node->matrix[5] = 1.0f;
3938 out_node->matrix[10] = 1.0f;
3939 out_node->matrix[15] = 1.0f;
3941 int size = tokens[i].size;
3944 for (
int j = 0; j < size; ++j)
3946 CGLTF_CHECK_KEY(tokens[i]);
3948 if (cgltf_json_strcmp(tokens+i, json_chunk,
"name") == 0)
3950 i = cgltf_parse_json_string(options, tokens, i + 1, json_chunk, &out_node->name);
3952 else if (cgltf_json_strcmp(tokens+i, json_chunk,
"children") == 0)
3954 i = cgltf_parse_json_array(options, tokens, i + 1, json_chunk,
sizeof(
cgltf_node*), (
void**)&out_node->children, &out_node->children_count);
3960 for (cgltf_size k = 0; k < out_node->children_count; ++k)
3962 out_node->children[k] = CGLTF_PTRINDEX(
cgltf_node, cgltf_json_to_int(tokens + i, json_chunk));
3966 else if (cgltf_json_strcmp(tokens+i, json_chunk,
"mesh") == 0)
3969 CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_PRIMITIVE);
3970 out_node->mesh = CGLTF_PTRINDEX(
cgltf_mesh, cgltf_json_to_int(tokens + i, json_chunk));
3973 else if (cgltf_json_strcmp(tokens+i, json_chunk,
"skin") == 0)
3976 CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_PRIMITIVE);
3977 out_node->skin = CGLTF_PTRINDEX(
cgltf_skin, cgltf_json_to_int(tokens + i, json_chunk));
3980 else if (cgltf_json_strcmp(tokens+i, json_chunk,
"camera") == 0)
3983 CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_PRIMITIVE);
3984 out_node->camera = CGLTF_PTRINDEX(
cgltf_camera, cgltf_json_to_int(tokens + i, json_chunk));
3987 else if (cgltf_json_strcmp(tokens+i, json_chunk,
"translation") == 0)
3989 out_node->has_translation = 1;
3990 i = cgltf_parse_json_float_array(tokens, i + 1, json_chunk, out_node->translation, 3);
3992 else if (cgltf_json_strcmp(tokens+i, json_chunk,
"rotation") == 0)
3994 out_node->has_rotation = 1;
3995 i = cgltf_parse_json_float_array(tokens, i + 1, json_chunk, out_node->rotation, 4);
3997 else if (cgltf_json_strcmp(tokens+i, json_chunk,
"scale") == 0)
3999 out_node->has_scale = 1;
4000 i = cgltf_parse_json_float_array(tokens, i + 1, json_chunk, out_node->scale, 3);
4002 else if (cgltf_json_strcmp(tokens+i, json_chunk,
"matrix") == 0)
4004 out_node->has_matrix = 1;
4005 i = cgltf_parse_json_float_array(tokens, i + 1, json_chunk, out_node->matrix, 16);
4007 else if (cgltf_json_strcmp(tokens + i, json_chunk,
"weights") == 0)
4009 i = cgltf_parse_json_array(options, tokens, i + 1, json_chunk,
sizeof(cgltf_float), (
void**)&out_node->weights, &out_node->weights_count);
4015 i = cgltf_parse_json_float_array(tokens, i - 1, json_chunk, out_node->weights, (
int)out_node->weights_count);
4017 else if (cgltf_json_strcmp(tokens + i, json_chunk,
"extras") == 0)
4019 i = cgltf_parse_json_extras(tokens, i + 1, json_chunk, &out_node->extras);
4021 else if (cgltf_json_strcmp(tokens + i, json_chunk,
"extensions") == 0)
4025 CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
4027 int extensions_size = tokens[i].size;
4030 for (
int k = 0; k < extensions_size; ++k)
4032 CGLTF_CHECK_KEY(tokens[i]);
4034 if (cgltf_json_strcmp(tokens+i, json_chunk,
"KHR_lights_punctual") == 0)
4038 CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
4040 int data_size = tokens[i].size;
4043 for (
int m = 0; m < data_size; ++m)
4045 CGLTF_CHECK_KEY(tokens[i]);
4047 if (cgltf_json_strcmp(tokens + i, json_chunk,
"light") == 0)
4050 CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_PRIMITIVE);
4051 out_node->light = CGLTF_PTRINDEX(
cgltf_light, cgltf_json_to_int(tokens + i, json_chunk));
4056 i = cgltf_skip_json(tokens, i + 1);
4067 i = cgltf_skip_json(tokens, i+1);
4078 i = cgltf_skip_json(tokens, i+1);
4090static int cgltf_parse_json_nodes(
cgltf_options* options, jsmntok_t
const* tokens,
int i,
const uint8_t* json_chunk,
cgltf_data* out_data)
4092 i = cgltf_parse_json_array(options, tokens, i, json_chunk,
sizeof(
cgltf_node), (
void**)&out_data->nodes, &out_data->nodes_count);
4098 for (cgltf_size j = 0; j < out_data->nodes_count; ++j)
4100 i = cgltf_parse_json_node(options, tokens, i, json_chunk, &out_data->nodes[j]);
4109static int cgltf_parse_json_scene(
cgltf_options* options, jsmntok_t
const* tokens,
int i,
const uint8_t* json_chunk,
cgltf_scene* out_scene)
4111 CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
4113 int size = tokens[i].size;
4116 for (
int j = 0; j < size; ++j)
4118 CGLTF_CHECK_KEY(tokens[i]);
4120 if (cgltf_json_strcmp(tokens+i, json_chunk,
"name") == 0)
4122 i = cgltf_parse_json_string(options, tokens, i + 1, json_chunk, &out_scene->name);
4124 else if (cgltf_json_strcmp(tokens+i, json_chunk,
"nodes") == 0)
4126 i = cgltf_parse_json_array(options, tokens, i + 1, json_chunk,
sizeof(
cgltf_node*), (
void**)&out_scene->nodes, &out_scene->nodes_count);
4132 for (cgltf_size k = 0; k < out_scene->nodes_count; ++k)
4134 out_scene->nodes[k] = CGLTF_PTRINDEX(
cgltf_node, cgltf_json_to_int(tokens + i, json_chunk));
4138 else if (cgltf_json_strcmp(tokens + i, json_chunk,
"extras") == 0)
4140 i = cgltf_parse_json_extras(tokens, i + 1, json_chunk, &out_scene->extras);
4144 i = cgltf_skip_json(tokens, i+1);
4156static int cgltf_parse_json_scenes(
cgltf_options* options, jsmntok_t
const* tokens,
int i,
const uint8_t* json_chunk,
cgltf_data* out_data)
4158 i = cgltf_parse_json_array(options, tokens, i, json_chunk,
sizeof(
cgltf_scene), (
void**)&out_data->scenes, &out_data->scenes_count);
4164 for (cgltf_size j = 0; j < out_data->scenes_count; ++j)
4166 i = cgltf_parse_json_scene(options, tokens, i, json_chunk, &out_data->scenes[j]);
4178 CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
4180 int size = tokens[i].size;
4183 for (
int j = 0; j < size; ++j)
4185 CGLTF_CHECK_KEY(tokens[i]);
4187 if (cgltf_json_strcmp(tokens+i, json_chunk,
"input") == 0)
4190 out_sampler->input = CGLTF_PTRINDEX(
cgltf_accessor, cgltf_json_to_int(tokens + i, json_chunk));
4193 else if (cgltf_json_strcmp(tokens+i, json_chunk,
"output") == 0)
4196 out_sampler->output = CGLTF_PTRINDEX(
cgltf_accessor, cgltf_json_to_int(tokens + i, json_chunk));
4199 else if (cgltf_json_strcmp(tokens+i, json_chunk,
"interpolation") == 0)
4202 if (cgltf_json_strcmp(tokens + i, json_chunk,
"LINEAR") == 0)
4204 out_sampler->interpolation = cgltf_interpolation_type_linear;
4206 else if (cgltf_json_strcmp(tokens + i, json_chunk,
"STEP") == 0)
4208 out_sampler->interpolation = cgltf_interpolation_type_step;
4210 else if (cgltf_json_strcmp(tokens + i, json_chunk,
"CUBICSPLINE") == 0)
4212 out_sampler->interpolation = cgltf_interpolation_type_cubic_spline;
4216 else if (cgltf_json_strcmp(tokens + i, json_chunk,
"extras") == 0)
4218 i = cgltf_parse_json_extras(tokens, i + 1, json_chunk, &out_sampler->extras);
4222 i = cgltf_skip_json(tokens, i+1);
4237 CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
4239 int size = tokens[i].size;
4242 for (
int j = 0; j < size; ++j)
4244 CGLTF_CHECK_KEY(tokens[i]);
4246 if (cgltf_json_strcmp(tokens+i, json_chunk,
"sampler") == 0)
4252 else if (cgltf_json_strcmp(tokens+i, json_chunk,
"target") == 0)
4256 CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
4258 int target_size = tokens[i].size;
4261 for (
int k = 0; k < target_size; ++k)
4263 CGLTF_CHECK_KEY(tokens[i]);
4265 if (cgltf_json_strcmp(tokens+i, json_chunk,
"node") == 0)
4268 out_channel->target_node = CGLTF_PTRINDEX(
cgltf_node, cgltf_json_to_int(tokens + i, json_chunk));
4271 else if (cgltf_json_strcmp(tokens+i, json_chunk,
"path") == 0)
4274 if (cgltf_json_strcmp(tokens+i, json_chunk,
"translation") == 0)
4276 out_channel->target_path = cgltf_animation_path_type_translation;
4278 else if (cgltf_json_strcmp(tokens+i, json_chunk,
"rotation") == 0)
4280 out_channel->target_path = cgltf_animation_path_type_rotation;
4282 else if (cgltf_json_strcmp(tokens+i, json_chunk,
"scale") == 0)
4284 out_channel->target_path = cgltf_animation_path_type_scale;
4286 else if (cgltf_json_strcmp(tokens+i, json_chunk,
"weights") == 0)
4288 out_channel->target_path = cgltf_animation_path_type_weights;
4292 else if (cgltf_json_strcmp(tokens + i, json_chunk,
"extras") == 0)
4294 i = cgltf_parse_json_extras(tokens, i + 1, json_chunk, &out_channel->extras);
4298 i = cgltf_skip_json(tokens, i+1);
4309 i = cgltf_skip_json(tokens, i+1);
4321static int cgltf_parse_json_animation(
cgltf_options* options, jsmntok_t
const* tokens,
int i,
const uint8_t* json_chunk,
cgltf_animation* out_animation)
4323 CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
4325 int size = tokens[i].size;
4328 for (
int j = 0; j < size; ++j)
4330 CGLTF_CHECK_KEY(tokens[i]);
4332 if (cgltf_json_strcmp(tokens+i, json_chunk,
"name") == 0)
4334 i = cgltf_parse_json_string(options, tokens, i + 1, json_chunk, &out_animation->name);
4336 else if (cgltf_json_strcmp(tokens+i, json_chunk,
"samplers") == 0)
4338 i = cgltf_parse_json_array(options, tokens, i + 1, json_chunk,
sizeof(
cgltf_animation_sampler), (
void**)&out_animation->samplers, &out_animation->samplers_count);
4344 for (cgltf_size k = 0; k < out_animation->samplers_count; ++k)
4346 i = cgltf_parse_json_animation_sampler(options, tokens, i, json_chunk, &out_animation->samplers[k]);
4353 else if (cgltf_json_strcmp(tokens+i, json_chunk,
"channels") == 0)
4355 i = cgltf_parse_json_array(options, tokens, i + 1, json_chunk,
sizeof(
cgltf_animation_channel), (
void**)&out_animation->channels, &out_animation->channels_count);
4361 for (cgltf_size k = 0; k < out_animation->channels_count; ++k)
4363 i = cgltf_parse_json_animation_channel(options, tokens, i, json_chunk, &out_animation->channels[k]);
4370 else if (cgltf_json_strcmp(tokens + i, json_chunk,
"extras") == 0)
4372 i = cgltf_parse_json_extras(tokens, i + 1, json_chunk, &out_animation->extras);
4376 i = cgltf_skip_json(tokens, i+1);
4388static int cgltf_parse_json_animations(
cgltf_options* options, jsmntok_t
const* tokens,
int i,
const uint8_t* json_chunk,
cgltf_data* out_data)
4390 i = cgltf_parse_json_array(options, tokens, i, json_chunk,
sizeof(
cgltf_animation), (
void**)&out_data->animations, &out_data->animations_count);
4396 for (cgltf_size j = 0; j < out_data->animations_count; ++j)
4398 i = cgltf_parse_json_animation(options, tokens, i, json_chunk, &out_data->animations[j]);
4407static int cgltf_parse_json_asset(
cgltf_options* options, jsmntok_t
const* tokens,
int i,
const uint8_t* json_chunk,
cgltf_asset* out_asset)
4409 CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
4411 int size = tokens[i].size;
4414 for (
int j = 0; j < size; ++j)
4416 CGLTF_CHECK_KEY(tokens[i]);
4418 if (cgltf_json_strcmp(tokens+i, json_chunk,
"copyright") == 0)
4420 i = cgltf_parse_json_string(options, tokens, i + 1, json_chunk, &out_asset->copyright);
4422 else if (cgltf_json_strcmp(tokens+i, json_chunk,
"generator") == 0)
4424 i = cgltf_parse_json_string(options, tokens, i + 1, json_chunk, &out_asset->generator);
4426 else if (cgltf_json_strcmp(tokens+i, json_chunk,
"version") == 0)
4428 i = cgltf_parse_json_string(options, tokens, i + 1, json_chunk, &out_asset->version);
4430 else if (cgltf_json_strcmp(tokens+i, json_chunk,
"minVersion") == 0)
4432 i = cgltf_parse_json_string(options, tokens, i + 1, json_chunk, &out_asset->min_version);
4434 else if (cgltf_json_strcmp(tokens + i, json_chunk,
"extras") == 0)
4436 i = cgltf_parse_json_extras(tokens, i + 1, json_chunk, &out_asset->extras);
4440 i = cgltf_skip_json(tokens, i+1);
4449 if (out_asset->version && CGLTF_ATOF(out_asset->version) < 2)
4451 return CGLTF_ERROR_LEGACY;
4457cgltf_size cgltf_num_components(cgltf_type type) {
4460 case cgltf_type_vec2:
4462 case cgltf_type_vec3:
4464 case cgltf_type_vec4:
4466 case cgltf_type_mat2:
4468 case cgltf_type_mat3:
4470 case cgltf_type_mat4:
4472 case cgltf_type_invalid:
4473 case cgltf_type_scalar:
4479static cgltf_size cgltf_component_size(cgltf_component_type component_type) {
4480 switch (component_type)
4482 case cgltf_component_type_r_8:
4483 case cgltf_component_type_r_8u:
4485 case cgltf_component_type_r_16:
4486 case cgltf_component_type_r_16u:
4488 case cgltf_component_type_r_32u:
4489 case cgltf_component_type_r_32f:
4491 case cgltf_component_type_invalid:
4497static cgltf_size cgltf_calc_size(cgltf_type type, cgltf_component_type component_type)
4499 cgltf_size component_size = cgltf_component_size(component_type);
4500 if (type == cgltf_type_mat2 && component_size == 1)
4502 return 8 * component_size;
4504 else if (type == cgltf_type_mat3 && (component_size == 1 || component_size == 2))
4506 return 12 * component_size;
4508 return component_size * cgltf_num_components(type);
4511static int cgltf_fixup_pointers(
cgltf_data* out_data);
4513static int cgltf_parse_json_root(
cgltf_options* options, jsmntok_t
const* tokens,
int i,
const uint8_t* json_chunk,
cgltf_data* out_data)
4515 CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
4517 int size = tokens[i].size;
4520 for (
int j = 0; j < size; ++j)
4522 CGLTF_CHECK_KEY(tokens[i]);
4524 if (cgltf_json_strcmp(tokens + i, json_chunk,
"asset") == 0)
4526 i = cgltf_parse_json_asset(options, tokens, i + 1, json_chunk, &out_data->asset);
4528 else if (cgltf_json_strcmp(tokens + i, json_chunk,
"meshes") == 0)
4530 i = cgltf_parse_json_meshes(options, tokens, i + 1, json_chunk, out_data);
4532 else if (cgltf_json_strcmp(tokens + i, json_chunk,
"accessors") == 0)
4534 i = cgltf_parse_json_accessors(options, tokens, i + 1, json_chunk, out_data);
4536 else if (cgltf_json_strcmp(tokens + i, json_chunk,
"bufferViews") == 0)
4538 i = cgltf_parse_json_buffer_views(options, tokens, i + 1, json_chunk, out_data);
4540 else if (cgltf_json_strcmp(tokens + i, json_chunk,
"buffers") == 0)
4542 i = cgltf_parse_json_buffers(options, tokens, i + 1, json_chunk, out_data);
4544 else if (cgltf_json_strcmp(tokens + i, json_chunk,
"materials") == 0)
4546 i = cgltf_parse_json_materials(options, tokens, i + 1, json_chunk, out_data);
4548 else if (cgltf_json_strcmp(tokens + i, json_chunk,
"images") == 0)
4550 i = cgltf_parse_json_images(options, tokens, i + 1, json_chunk, out_data);
4552 else if (cgltf_json_strcmp(tokens + i, json_chunk,
"textures") == 0)
4554 i = cgltf_parse_json_textures(options, tokens, i + 1, json_chunk, out_data);
4556 else if (cgltf_json_strcmp(tokens + i, json_chunk,
"samplers") == 0)
4558 i = cgltf_parse_json_samplers(options, tokens, i + 1, json_chunk, out_data);
4560 else if (cgltf_json_strcmp(tokens + i, json_chunk,
"skins") == 0)
4562 i = cgltf_parse_json_skins(options, tokens, i + 1, json_chunk, out_data);
4564 else if (cgltf_json_strcmp(tokens + i, json_chunk,
"cameras") == 0)
4566 i = cgltf_parse_json_cameras(options, tokens, i + 1, json_chunk, out_data);
4568 else if (cgltf_json_strcmp(tokens + i, json_chunk,
"nodes") == 0)
4570 i = cgltf_parse_json_nodes(options, tokens, i + 1, json_chunk, out_data);
4572 else if (cgltf_json_strcmp(tokens + i, json_chunk,
"scenes") == 0)
4574 i = cgltf_parse_json_scenes(options, tokens, i + 1, json_chunk, out_data);
4576 else if (cgltf_json_strcmp(tokens + i, json_chunk,
"scene") == 0)
4579 out_data->scene = CGLTF_PTRINDEX(
cgltf_scene, cgltf_json_to_int(tokens + i, json_chunk));
4582 else if (cgltf_json_strcmp(tokens + i, json_chunk,
"animations") == 0)
4584 i = cgltf_parse_json_animations(options, tokens, i + 1, json_chunk, out_data);
4586 else if (cgltf_json_strcmp(tokens+i, json_chunk,
"extras") == 0)
4588 i = cgltf_parse_json_extras(tokens, i + 1, json_chunk, &out_data->extras);
4590 else if (cgltf_json_strcmp(tokens + i, json_chunk,
"extensions") == 0)
4594 CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
4596 int extensions_size = tokens[i].size;
4599 for (
int k = 0; k < extensions_size; ++k)
4601 CGLTF_CHECK_KEY(tokens[i]);
4603 if (cgltf_json_strcmp(tokens+i, json_chunk,
"KHR_lights_punctual") == 0)
4607 CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
4609 int data_size = tokens[i].size;
4612 for (
int m = 0; m < data_size; ++m)
4614 CGLTF_CHECK_KEY(tokens[i]);
4616 if (cgltf_json_strcmp(tokens + i, json_chunk,
"lights") == 0)
4618 i = cgltf_parse_json_lights(options, tokens, i + 1, json_chunk, out_data);
4622 i = cgltf_skip_json(tokens, i + 1);
4633 i = cgltf_skip_json(tokens, i + 1);
4642 else if (cgltf_json_strcmp(tokens + i, json_chunk,
"extensionsUsed") == 0)
4644 i = cgltf_parse_json_string_array(options, tokens, i + 1, json_chunk, &out_data->extensions_used, &out_data->extensions_used_count);
4646 else if (cgltf_json_strcmp(tokens + i, json_chunk,
"extensionsRequired") == 0)
4648 i = cgltf_parse_json_string_array(options, tokens, i + 1, json_chunk, &out_data->extensions_required, &out_data->extensions_required_count);
4652 i = cgltf_skip_json(tokens, i + 1);
4664cgltf_result cgltf_parse_json(
cgltf_options* options,
const uint8_t* json_chunk, cgltf_size size,
cgltf_data** out_data)
4666 jsmn_parser parser = { 0, 0, 0 };
4668 if (options->json_token_count == 0)
4670 int token_count = jsmn_parse(&parser, (
const char*)json_chunk, size, NULL, 0);
4672 if (token_count <= 0)
4674 return cgltf_result_invalid_json;
4677 options->json_token_count = token_count;
4680 jsmntok_t* tokens = (jsmntok_t*)options->memory.alloc(options->memory.user_data,
sizeof(jsmntok_t) * (options->json_token_count + 1));
4684 return cgltf_result_out_of_memory;
4689 int token_count = jsmn_parse(&parser, (
const char*)json_chunk, size, tokens, options->json_token_count);
4691 if (token_count <= 0)
4693 options->memory.free(options->memory.user_data, tokens);
4694 return cgltf_result_invalid_json;
4699 tokens[token_count].type = JSMN_UNDEFINED;
4705 options->memory.free(options->memory.user_data, tokens);
4706 return cgltf_result_out_of_memory;
4710 data->memory = options->memory;
4711 data->file = options->file;
4713 int i = cgltf_parse_json_root(options, tokens, 0, json_chunk, data);
4715 options->memory.free(options->memory.user_data, tokens);
4723 case CGLTF_ERROR_NOMEM:
return cgltf_result_out_of_memory;
4724 case CGLTF_ERROR_LEGACY:
return cgltf_result_legacy_gltf;
4725 default:
return cgltf_result_invalid_gltf;
4729 if (cgltf_fixup_pointers(data) < 0)
4732 return cgltf_result_invalid_gltf;
4735 data->json = (
const char*)json_chunk;
4736 data->json_size = size;
4740 return cgltf_result_success;
4743static int cgltf_fixup_pointers(
cgltf_data* data)
4745 for (cgltf_size i = 0; i < data->meshes_count; ++i)
4747 for (cgltf_size j = 0; j < data->meshes[i].primitives_count; ++j)
4749 CGLTF_PTRFIXUP(data->meshes[i].primitives[j].indices, data->accessors, data->accessors_count);
4750 CGLTF_PTRFIXUP(data->meshes[i].primitives[j].material, data->materials, data->materials_count);
4752 for (cgltf_size k = 0; k < data->meshes[i].primitives[j].attributes_count; ++k)
4754 CGLTF_PTRFIXUP_REQ(data->meshes[i].primitives[j].attributes[k].data, data->accessors, data->accessors_count);
4757 for (cgltf_size k = 0; k < data->meshes[i].primitives[j].targets_count; ++k)
4759 for (cgltf_size m = 0; m < data->meshes[i].primitives[j].targets[k].attributes_count; ++m)
4761 CGLTF_PTRFIXUP_REQ(data->meshes[i].primitives[j].targets[k].attributes[m].data, data->accessors, data->accessors_count);
4765 if (data->meshes[i].primitives[j].has_draco_mesh_compression)
4767 CGLTF_PTRFIXUP_REQ(data->meshes[i].primitives[j].draco_mesh_compression.buffer_view, data->buffer_views, data->buffer_views_count);
4768 for (cgltf_size m = 0; m < data->meshes[i].primitives[j].draco_mesh_compression.attributes_count; ++m)
4770 CGLTF_PTRFIXUP_REQ(data->meshes[i].primitives[j].draco_mesh_compression.attributes[m].data, data->accessors, data->accessors_count);
4776 for (cgltf_size i = 0; i < data->accessors_count; ++i)
4778 CGLTF_PTRFIXUP(data->accessors[i].buffer_view, data->buffer_views, data->buffer_views_count);
4780 if (data->accessors[i].is_sparse)
4782 CGLTF_PTRFIXUP_REQ(data->accessors[i].sparse.indices_buffer_view, data->buffer_views, data->buffer_views_count);
4783 CGLTF_PTRFIXUP_REQ(data->accessors[i].sparse.values_buffer_view, data->buffer_views, data->buffer_views_count);
4786 if (data->accessors[i].buffer_view)
4788 data->accessors[i].stride = data->accessors[i].buffer_view->stride;
4791 if (data->accessors[i].stride == 0)
4793 data->accessors[i].stride = cgltf_calc_size(data->accessors[i].type, data->accessors[i].component_type);
4797 for (cgltf_size i = 0; i < data->textures_count; ++i)
4799 CGLTF_PTRFIXUP(data->textures[i].image, data->images, data->images_count);
4800 CGLTF_PTRFIXUP(data->textures[i].sampler, data->samplers, data->samplers_count);
4803 for (cgltf_size i = 0; i < data->images_count; ++i)
4805 CGLTF_PTRFIXUP(data->images[i].buffer_view, data->buffer_views, data->buffer_views_count);
4808 for (cgltf_size i = 0; i < data->materials_count; ++i)
4810 CGLTF_PTRFIXUP(data->materials[i].normal_texture.texture, data->textures, data->textures_count);
4811 CGLTF_PTRFIXUP(data->materials[i].emissive_texture.texture, data->textures, data->textures_count);
4812 CGLTF_PTRFIXUP(data->materials[i].occlusion_texture.texture, data->textures, data->textures_count);
4814 CGLTF_PTRFIXUP(data->materials[i].pbr_metallic_roughness.base_color_texture.texture, data->textures, data->textures_count);
4815 CGLTF_PTRFIXUP(data->materials[i].pbr_metallic_roughness.metallic_roughness_texture.texture, data->textures, data->textures_count);
4817 CGLTF_PTRFIXUP(data->materials[i].pbr_specular_glossiness.diffuse_texture.texture, data->textures, data->textures_count);
4818 CGLTF_PTRFIXUP(data->materials[i].pbr_specular_glossiness.specular_glossiness_texture.texture, data->textures, data->textures_count);
4820 CGLTF_PTRFIXUP(data->materials[i].clearcoat.clearcoat_texture.texture, data->textures, data->textures_count);
4821 CGLTF_PTRFIXUP(data->materials[i].clearcoat.clearcoat_roughness_texture.texture, data->textures, data->textures_count);
4822 CGLTF_PTRFIXUP(data->materials[i].clearcoat.clearcoat_normal_texture.texture, data->textures, data->textures_count);
4825 for (cgltf_size i = 0; i < data->buffer_views_count; ++i)
4827 CGLTF_PTRFIXUP_REQ(data->buffer_views[i].buffer, data->buffers, data->buffers_count);
4830 for (cgltf_size i = 0; i < data->skins_count; ++i)
4832 for (cgltf_size j = 0; j < data->skins[i].joints_count; ++j)
4834 CGLTF_PTRFIXUP_REQ(data->skins[i].joints[j], data->nodes, data->nodes_count);
4837 CGLTF_PTRFIXUP(data->skins[i].skeleton, data->nodes, data->nodes_count);
4838 CGLTF_PTRFIXUP(data->skins[i].inverse_bind_matrices, data->accessors, data->accessors_count);
4841 for (cgltf_size i = 0; i < data->nodes_count; ++i)
4843 for (cgltf_size j = 0; j < data->nodes[i].children_count; ++j)
4845 CGLTF_PTRFIXUP_REQ(data->nodes[i].children[j], data->nodes, data->nodes_count);
4847 if (data->nodes[i].children[j]->parent)
4849 return CGLTF_ERROR_JSON;
4852 data->nodes[i].children[j]->parent = &data->nodes[i];
4855 CGLTF_PTRFIXUP(data->nodes[i].mesh, data->meshes, data->meshes_count);
4856 CGLTF_PTRFIXUP(data->nodes[i].skin, data->skins, data->skins_count);
4857 CGLTF_PTRFIXUP(data->nodes[i].camera, data->cameras, data->cameras_count);
4858 CGLTF_PTRFIXUP(data->nodes[i].light, data->lights, data->lights_count);
4861 for (cgltf_size i = 0; i < data->scenes_count; ++i)
4863 for (cgltf_size j = 0; j < data->scenes[i].nodes_count; ++j)
4865 CGLTF_PTRFIXUP_REQ(data->scenes[i].nodes[j], data->nodes, data->nodes_count);
4867 if (data->scenes[i].nodes[j]->parent)
4869 return CGLTF_ERROR_JSON;
4874 CGLTF_PTRFIXUP(data->scene, data->scenes, data->scenes_count);
4876 for (cgltf_size i = 0; i < data->animations_count; ++i)
4878 for (cgltf_size j = 0; j < data->animations[i].samplers_count; ++j)
4880 CGLTF_PTRFIXUP_REQ(data->animations[i].samplers[j].input, data->accessors, data->accessors_count);
4881 CGLTF_PTRFIXUP_REQ(data->animations[i].samplers[j].output, data->accessors, data->accessors_count);
4884 for (cgltf_size j = 0; j < data->animations[i].channels_count; ++j)
4886 CGLTF_PTRFIXUP_REQ(data->animations[i].channels[j].sampler, data->animations[i].samplers, data->animations[i].samplers_count);
4887 CGLTF_PTRFIXUP(data->animations[i].channels[j].target_node, data->nodes, data->nodes_count);
4923static jsmntok_t *jsmn_alloc_token(jsmn_parser *parser,
4924 jsmntok_t *tokens,
size_t num_tokens) {
4926 if (parser->toknext >= num_tokens) {
4929 tok = &tokens[parser->toknext++];
4930 tok->start = tok->end = -1;
4932#ifdef JSMN_PARENT_LINKS
4941static void jsmn_fill_token(jsmntok_t *token, jsmntype_t type,
4942 int start,
int end) {
4944 token->start = start;
4952static int jsmn_parse_primitive(jsmn_parser *parser,
const char *js,
4953 size_t len, jsmntok_t *tokens,
size_t num_tokens) {
4957 start = parser->pos;
4959 for (; parser->pos < len && js[parser->pos] !=
'\0'; parser->pos++) {
4960 switch (js[parser->pos]) {
4965 case '\t' :
case '\r' :
case '\n' :
case ' ' :
4966 case ',' :
case ']' :
case '}' :
4969 if (js[parser->pos] < 32 || js[parser->pos] >= 127) {
4970 parser->pos = start;
4971 return JSMN_ERROR_INVAL;
4976 parser->pos = start;
4977 return JSMN_ERROR_PART;
4981 if (tokens == NULL) {
4985 token = jsmn_alloc_token(parser, tokens, num_tokens);
4986 if (token == NULL) {
4987 parser->pos = start;
4988 return JSMN_ERROR_NOMEM;
4990 jsmn_fill_token(token, JSMN_PRIMITIVE, start, parser->pos);
4991#ifdef JSMN_PARENT_LINKS
4992 token->parent = parser->toksuper;
5001static int jsmn_parse_string(jsmn_parser *parser,
const char *js,
5002 size_t len, jsmntok_t *tokens,
size_t num_tokens) {
5005 int start = parser->pos;
5010 for (; parser->pos < len && js[parser->pos] !=
'\0'; parser->pos++) {
5011 char c = js[parser->pos];
5015 if (tokens == NULL) {
5018 token = jsmn_alloc_token(parser, tokens, num_tokens);
5019 if (token == NULL) {
5020 parser->pos = start;
5021 return JSMN_ERROR_NOMEM;
5023 jsmn_fill_token(token, JSMN_STRING, start+1, parser->pos);
5024#ifdef JSMN_PARENT_LINKS
5025 token->parent = parser->toksuper;
5031 if (c ==
'\\' && parser->pos + 1 < len) {
5034 switch (js[parser->pos]) {
5036 case '\"':
case '/' :
case '\\' :
case 'b' :
5037 case 'f' :
case 'r' :
case 'n' :
case 't' :
5042 for(i = 0; i < 4 && parser->pos < len && js[parser->pos] !=
'\0'; i++) {
5044 if(!((js[parser->pos] >= 48 && js[parser->pos] <= 57) ||
5045 (js[parser->pos] >= 65 && js[parser->pos] <= 70) ||
5046 (js[parser->pos] >= 97 && js[parser->pos] <= 102))) {
5047 parser->pos = start;
5048 return JSMN_ERROR_INVAL;
5056 parser->pos = start;
5057 return JSMN_ERROR_INVAL;
5061 parser->pos = start;
5062 return JSMN_ERROR_PART;
5068static int jsmn_parse(jsmn_parser *parser,
const char *js,
size_t len,
5069 jsmntok_t *tokens,
size_t num_tokens) {
5073 int count = parser->toknext;
5075 for (; parser->pos < len && js[parser->pos] !=
'\0'; parser->pos++) {
5079 c = js[parser->pos];
5083 if (tokens == NULL) {
5086 token = jsmn_alloc_token(parser, tokens, num_tokens);
5088 return JSMN_ERROR_NOMEM;
5089 if (parser->toksuper != -1) {
5090 tokens[parser->toksuper].size++;
5091#ifdef JSMN_PARENT_LINKS
5092 token->parent = parser->toksuper;
5095 token->type = (c ==
'{' ? JSMN_OBJECT : JSMN_ARRAY);
5096 token->start = parser->pos;
5097 parser->toksuper = parser->toknext - 1;
5102 type = (c ==
'}' ? JSMN_OBJECT : JSMN_ARRAY);
5103#ifdef JSMN_PARENT_LINKS
5104 if (parser->toknext < 1) {
5105 return JSMN_ERROR_INVAL;
5107 token = &tokens[parser->toknext - 1];
5109 if (token->start != -1 && token->end == -1) {
5110 if (token->type != type) {
5111 return JSMN_ERROR_INVAL;
5113 token->end = parser->pos + 1;
5114 parser->toksuper = token->parent;
5117 if (token->parent == -1) {
5118 if(token->type != type || parser->toksuper == -1) {
5119 return JSMN_ERROR_INVAL;
5123 token = &tokens[token->parent];
5126 for (i = parser->toknext - 1; i >= 0; i--) {
5128 if (token->start != -1 && token->end == -1) {
5129 if (token->type != type) {
5130 return JSMN_ERROR_INVAL;
5132 parser->toksuper = -1;
5133 token->end = parser->pos + 1;
5138 if (i == -1)
return JSMN_ERROR_INVAL;
5139 for (; i >= 0; i--) {
5141 if (token->start != -1 && token->end == -1) {
5142 parser->toksuper = i;
5149 r = jsmn_parse_string(parser, js, len, tokens, num_tokens);
5150 if (r < 0)
return r;
5152 if (parser->toksuper != -1 && tokens != NULL)
5153 tokens[parser->toksuper].size++;
5155 case '\t' :
case '\r' :
case '\n' :
case ' ':
5158 parser->toksuper = parser->toknext - 1;
5161 if (tokens != NULL && parser->toksuper != -1 &&
5162 tokens[parser->toksuper].type != JSMN_ARRAY &&
5163 tokens[parser->toksuper].type != JSMN_OBJECT) {
5164#ifdef JSMN_PARENT_LINKS
5165 parser->toksuper = tokens[parser->toksuper].parent;
5167 for (i = parser->toknext - 1; i >= 0; i--) {
5168 if (tokens[i].type == JSMN_ARRAY || tokens[i].type == JSMN_OBJECT) {
5169 if (tokens[i].start != -1 && tokens[i].end == -1) {
5170 parser->toksuper = i;
5180 case '-':
case '0':
case '1' :
case '2':
case '3' :
case '4':
5181 case '5':
case '6':
case '7' :
case '8':
case '9':
5182 case 't':
case 'f':
case 'n' :
5184 if (tokens != NULL && parser->toksuper != -1) {
5185 jsmntok_t *t = &tokens[parser->toksuper];
5186 if (t->type == JSMN_OBJECT ||
5187 (t->type == JSMN_STRING && t->size != 0)) {
5188 return JSMN_ERROR_INVAL;
5195 r = jsmn_parse_primitive(parser, js, len, tokens, num_tokens);
5196 if (r < 0)
return r;
5198 if (parser->toksuper != -1 && tokens != NULL)
5199 tokens[parser->toksuper].size++;
5205 return JSMN_ERROR_INVAL;
5210 if (tokens != NULL) {
5211 for (i = parser->toknext - 1; i >= 0; i--) {
5213 if (tokens[i].start != -1 && tokens[i].end == -1) {
5214 return JSMN_ERROR_PART;
5226static void jsmn_init(jsmn_parser *parser) {
5228 parser->toknext = 0;
5229 parser->toksuper = -1;