cgltf.h (117448B)
1 /** 2 * cgltf - a single-file glTF 2.0 parser written in C99. 3 * 4 * Version: 1.1 5 * 6 * Website: https://github.com/jkuhlmann/cgltf 7 * 8 * Distributed under the MIT License, see notice at the end of this file. 9 * 10 * Building: 11 * Include this file where you need the struct and function 12 * declarations. Have exactly one source file where you define 13 * `CGLTF_IMPLEMENTATION` before including this file to get the 14 * function definitions. 15 * 16 * Reference: 17 * `cgltf_result cgltf_parse(const cgltf_options*, const void*, 18 * cgltf_size, cgltf_data**)` parses both glTF and GLB data. If 19 * this function returns `cgltf_result_success`, you have to call 20 * `cgltf_free()` on the created `cgltf_data*` variable. 21 * Note that contents of external files for buffers and images are not 22 * automatically loaded. You'll need to read these files yourself using 23 * URIs in the `cgltf_data` structure. 24 * 25 * `cgltf_options` is the struct passed to `cgltf_parse()` to control 26 * parts of the parsing process. You can use it to force the file type 27 * and provide memory allocation callbacks. Should be zero-initialized 28 * to trigger default behavior. 29 * 30 * `cgltf_data` is the struct allocated and filled by `cgltf_parse()`. 31 * It generally mirrors the glTF format as described by the spec (see 32 * https://github.com/KhronosGroup/glTF/tree/master/specification/2.0). 33 * 34 * `void cgltf_free(cgltf_data*)` frees the allocated `cgltf_data` 35 * variable. 36 * 37 * `cgltf_result cgltf_load_buffers(const cgltf_options*, cgltf_data*, 38 * const char* gltf_path)` can be optionally called to open and read buffer 39 * files using the `FILE*` APIs. The `gltf_path` argument is the path to 40 * the original glTF file, which allows the parser to resolve the path to 41 * buffer files. 42 * 43 * `cgltf_result cgltf_load_buffer_base64(const cgltf_options* options, 44 * cgltf_size size, const char* base64, void** out_data)` decodes 45 * base64-encoded data content. Used internally by `cgltf_load_buffers()` 46 * and may be useful if you're not dealing with normal files. 47 * 48 * `cgltf_result cgltf_parse_file(const cgltf_options* options, const 49 * char* path, cgltf_data** out_data)` can be used to open the given 50 * file using `FILE*` APIs and parse the data using `cgltf_parse()`. 51 * 52 * `cgltf_result cgltf_validate(cgltf_data*)` can be used to do additional 53 * checks to make sure the parsed glTF data is valid. 54 * 55 * `cgltf_node_transform_local` converts the translation / rotation / scale properties of a node 56 * into a mat4. 57 * 58 * `cgltf_node_transform_world` calls `cgltf_node_transform_local` on every ancestor in order 59 * to compute the root-to-node transformation. 60 * 61 * `cgltf_accessor_read_float` reads a certain element from an accessor and converts it to 62 * floating point, assuming that `cgltf_load_buffers` has already been called. The passed-in element 63 * size is the number of floats in the output buffer, which should be in the range [1, 16]. Returns 64 * false if the passed-in element_size is too small, or if the accessor is sparse. 65 * 66 * `cgltf_accessor_read_index` is similar to its floating-point counterpart, but it returns size_t 67 * and only works with single-component data types. 68 */ 69 #ifndef CGLTF_H_INCLUDED__ 70 #define CGLTF_H_INCLUDED__ 71 72 #include <stddef.h> 73 74 #ifdef __cplusplus 75 extern "C" { 76 #endif 77 78 typedef size_t cgltf_size; 79 typedef float cgltf_float; 80 typedef int cgltf_int; 81 typedef int cgltf_bool; 82 83 typedef enum cgltf_file_type 84 { 85 cgltf_file_type_invalid, 86 cgltf_file_type_gltf, 87 cgltf_file_type_glb, 88 } cgltf_file_type; 89 90 typedef struct cgltf_options 91 { 92 cgltf_file_type type; /* invalid == auto detect */ 93 cgltf_size json_token_count; /* 0 == auto */ 94 void* (*memory_alloc)(void* user, cgltf_size size); 95 void (*memory_free) (void* user, void* ptr); 96 void* memory_user_data; 97 } cgltf_options; 98 99 typedef enum cgltf_result 100 { 101 cgltf_result_success, 102 cgltf_result_data_too_short, 103 cgltf_result_unknown_format, 104 cgltf_result_invalid_json, 105 cgltf_result_invalid_gltf, 106 cgltf_result_invalid_options, 107 cgltf_result_file_not_found, 108 cgltf_result_io_error, 109 cgltf_result_out_of_memory, 110 } cgltf_result; 111 112 typedef enum cgltf_buffer_view_type 113 { 114 cgltf_buffer_view_type_invalid, 115 cgltf_buffer_view_type_indices, 116 cgltf_buffer_view_type_vertices, 117 } cgltf_buffer_view_type; 118 119 typedef enum cgltf_attribute_type 120 { 121 cgltf_attribute_type_invalid, 122 cgltf_attribute_type_position, 123 cgltf_attribute_type_normal, 124 cgltf_attribute_type_tangent, 125 cgltf_attribute_type_texcoord, 126 cgltf_attribute_type_color, 127 cgltf_attribute_type_joints, 128 cgltf_attribute_type_weights, 129 } cgltf_attribute_type; 130 131 typedef enum cgltf_component_type 132 { 133 cgltf_component_type_invalid, 134 cgltf_component_type_r_8, /* BYTE */ 135 cgltf_component_type_r_8u, /* UNSIGNED_BYTE */ 136 cgltf_component_type_r_16, /* SHORT */ 137 cgltf_component_type_r_16u, /* UNSIGNED_SHORT */ 138 cgltf_component_type_r_32u, /* UNSIGNED_INT */ 139 cgltf_component_type_r_32f, /* FLOAT */ 140 } cgltf_component_type; 141 142 typedef enum cgltf_type 143 { 144 cgltf_type_invalid, 145 cgltf_type_scalar, 146 cgltf_type_vec2, 147 cgltf_type_vec3, 148 cgltf_type_vec4, 149 cgltf_type_mat2, 150 cgltf_type_mat3, 151 cgltf_type_mat4, 152 } cgltf_type; 153 154 typedef enum cgltf_primitive_type 155 { 156 cgltf_primitive_type_points, 157 cgltf_primitive_type_lines, 158 cgltf_primitive_type_line_loop, 159 cgltf_primitive_type_line_strip, 160 cgltf_primitive_type_triangles, 161 cgltf_primitive_type_triangle_strip, 162 cgltf_primitive_type_triangle_fan, 163 } cgltf_primitive_type; 164 165 typedef enum cgltf_alpha_mode 166 { 167 cgltf_alpha_mode_opaque, 168 cgltf_alpha_mode_mask, 169 cgltf_alpha_mode_blend, 170 } cgltf_alpha_mode; 171 172 typedef enum cgltf_animation_path_type { 173 cgltf_animation_path_type_invalid, 174 cgltf_animation_path_type_translation, 175 cgltf_animation_path_type_rotation, 176 cgltf_animation_path_type_scale, 177 cgltf_animation_path_type_weights, 178 } cgltf_animation_path_type; 179 180 typedef enum cgltf_interpolation_type { 181 cgltf_interpolation_type_linear, 182 cgltf_interpolation_type_step, 183 cgltf_interpolation_type_cubic_spline, 184 } cgltf_interpolation_type; 185 186 typedef enum cgltf_camera_type { 187 cgltf_camera_type_invalid, 188 cgltf_camera_type_perspective, 189 cgltf_camera_type_orthographic, 190 } cgltf_camera_type; 191 192 typedef enum cgltf_light_type { 193 cgltf_light_type_invalid, 194 cgltf_light_type_directional, 195 cgltf_light_type_point, 196 cgltf_light_type_spot, 197 } cgltf_light_type; 198 199 typedef struct cgltf_buffer 200 { 201 cgltf_size size; 202 char* uri; 203 void* data; /* loaded by cgltf_load_buffers */ 204 } cgltf_buffer; 205 206 typedef struct cgltf_buffer_view 207 { 208 cgltf_buffer* buffer; 209 cgltf_size offset; 210 cgltf_size size; 211 cgltf_size stride; /* 0 == automatically determined by accessor */ 212 cgltf_buffer_view_type type; 213 } cgltf_buffer_view; 214 215 typedef struct cgltf_accessor_sparse 216 { 217 cgltf_size count; 218 cgltf_buffer_view* indices_buffer_view; 219 cgltf_size indices_byte_offset; 220 cgltf_component_type indices_component_type; 221 cgltf_buffer_view* values_buffer_view; 222 cgltf_size values_byte_offset; 223 } cgltf_accessor_sparse; 224 225 typedef struct cgltf_accessor 226 { 227 cgltf_component_type component_type; 228 cgltf_bool normalized; 229 cgltf_type type; 230 cgltf_size offset; 231 cgltf_size count; 232 cgltf_size stride; 233 cgltf_buffer_view* buffer_view; 234 cgltf_bool has_min; 235 cgltf_float min[16]; 236 cgltf_bool has_max; 237 cgltf_float max[16]; 238 cgltf_bool is_sparse; 239 cgltf_accessor_sparse sparse; 240 } cgltf_accessor; 241 242 typedef struct cgltf_attribute 243 { 244 char* name; 245 cgltf_attribute_type type; 246 cgltf_int index; 247 cgltf_accessor* data; 248 } cgltf_attribute; 249 250 typedef struct cgltf_image 251 { 252 char* name; 253 char* uri; 254 cgltf_buffer_view* buffer_view; 255 char* mime_type; 256 } cgltf_image; 257 258 typedef struct cgltf_sampler 259 { 260 cgltf_int mag_filter; 261 cgltf_int min_filter; 262 cgltf_int wrap_s; 263 cgltf_int wrap_t; 264 } cgltf_sampler; 265 266 typedef struct cgltf_texture 267 { 268 char* name; 269 cgltf_image* image; 270 cgltf_sampler* sampler; 271 } cgltf_texture; 272 273 typedef struct cgltf_texture_transform 274 { 275 cgltf_float offset[2]; 276 cgltf_float rotation; 277 cgltf_float scale[2]; 278 cgltf_int texcoord; 279 } cgltf_texture_transform; 280 281 typedef struct cgltf_texture_view 282 { 283 cgltf_texture* texture; 284 cgltf_int texcoord; 285 cgltf_float scale; /* equivalent to strength for occlusion_texture */ 286 cgltf_bool has_transform; 287 cgltf_texture_transform transform; 288 } cgltf_texture_view; 289 290 typedef struct cgltf_pbr_metallic_roughness 291 { 292 cgltf_texture_view base_color_texture; 293 cgltf_texture_view metallic_roughness_texture; 294 295 cgltf_float base_color_factor[4]; 296 cgltf_float metallic_factor; 297 cgltf_float roughness_factor; 298 } cgltf_pbr_metallic_roughness; 299 300 typedef struct cgltf_pbr_specular_glossiness 301 { 302 cgltf_texture_view diffuse_texture; 303 cgltf_texture_view specular_glossiness_texture; 304 305 cgltf_float diffuse_factor[4]; 306 cgltf_float specular_factor[3]; 307 cgltf_float glossiness_factor; 308 } cgltf_pbr_specular_glossiness; 309 310 typedef struct cgltf_material 311 { 312 char* name; 313 cgltf_bool has_pbr_metallic_roughness; 314 cgltf_bool has_pbr_specular_glossiness; 315 cgltf_pbr_metallic_roughness pbr_metallic_roughness; 316 cgltf_pbr_specular_glossiness pbr_specular_glossiness; 317 cgltf_texture_view normal_texture; 318 cgltf_texture_view occlusion_texture; 319 cgltf_texture_view emissive_texture; 320 cgltf_float emissive_factor[3]; 321 cgltf_alpha_mode alpha_mode; 322 cgltf_float alpha_cutoff; 323 cgltf_bool double_sided; 324 cgltf_bool unlit; 325 } cgltf_material; 326 327 typedef struct cgltf_morph_target { 328 cgltf_attribute* attributes; 329 cgltf_size attributes_count; 330 } cgltf_morph_target; 331 332 typedef struct cgltf_primitive { 333 cgltf_primitive_type type; 334 cgltf_accessor* indices; 335 cgltf_material* material; 336 cgltf_attribute* attributes; 337 cgltf_size attributes_count; 338 cgltf_morph_target* targets; 339 cgltf_size targets_count; 340 } cgltf_primitive; 341 342 typedef struct cgltf_mesh { 343 char* name; 344 cgltf_primitive* primitives; 345 cgltf_size primitives_count; 346 cgltf_float* weights; 347 cgltf_size weights_count; 348 } cgltf_mesh; 349 350 typedef struct cgltf_node cgltf_node; 351 352 typedef struct cgltf_skin { 353 char* name; 354 cgltf_node** joints; 355 cgltf_size joints_count; 356 cgltf_node* skeleton; 357 cgltf_accessor* inverse_bind_matrices; 358 } cgltf_skin; 359 360 typedef struct cgltf_camera_perspective { 361 cgltf_float aspect_ratio; 362 cgltf_float yfov; 363 cgltf_float zfar; 364 cgltf_float znear; 365 } cgltf_camera_perspective; 366 367 typedef struct cgltf_camera_orthographic { 368 cgltf_float xmag; 369 cgltf_float ymag; 370 cgltf_float zfar; 371 cgltf_float znear; 372 } cgltf_camera_orthographic; 373 374 typedef struct cgltf_camera { 375 char* name; 376 cgltf_camera_type type; 377 union { 378 cgltf_camera_perspective perspective; 379 cgltf_camera_orthographic orthographic; 380 }; 381 } cgltf_camera; 382 383 typedef struct cgltf_light { 384 char* name; 385 cgltf_float color[3]; 386 cgltf_float intensity; 387 cgltf_light_type type; 388 cgltf_float range; 389 cgltf_float spot_inner_cone_angle; 390 cgltf_float spot_outer_cone_angle; 391 } cgltf_light; 392 393 typedef struct cgltf_node { 394 char* name; 395 cgltf_node* parent; 396 cgltf_node** children; 397 cgltf_size children_count; 398 cgltf_skin* skin; 399 cgltf_mesh* mesh; 400 cgltf_camera* camera; 401 cgltf_light* light; 402 cgltf_float* weights; 403 cgltf_size weights_count; 404 cgltf_bool has_translation; 405 cgltf_bool has_rotation; 406 cgltf_bool has_scale; 407 cgltf_bool has_matrix; 408 cgltf_float translation[3]; 409 cgltf_float rotation[4]; 410 cgltf_float scale[3]; 411 cgltf_float matrix[16]; 412 } cgltf_node; 413 414 typedef struct cgltf_scene { 415 char* name; 416 cgltf_node** nodes; 417 cgltf_size nodes_count; 418 } cgltf_scene; 419 420 typedef struct cgltf_animation_sampler { 421 cgltf_accessor* input; 422 cgltf_accessor* output; 423 cgltf_interpolation_type interpolation; 424 } cgltf_animation_sampler; 425 426 typedef struct cgltf_animation_channel { 427 cgltf_animation_sampler* sampler; 428 cgltf_node* target_node; 429 cgltf_animation_path_type target_path; 430 } cgltf_animation_channel; 431 432 typedef struct cgltf_animation { 433 char* name; 434 cgltf_animation_sampler* samplers; 435 cgltf_size samplers_count; 436 cgltf_animation_channel* channels; 437 cgltf_size channels_count; 438 } cgltf_animation; 439 440 typedef struct cgltf_asset { 441 char* copyright; 442 char* generator; 443 char* version; 444 char* min_version; 445 } cgltf_asset; 446 447 typedef struct cgltf_data 448 { 449 cgltf_file_type file_type; 450 void* file_data; 451 452 cgltf_asset asset; 453 454 cgltf_mesh* meshes; 455 cgltf_size meshes_count; 456 457 cgltf_material* materials; 458 cgltf_size materials_count; 459 460 cgltf_accessor* accessors; 461 cgltf_size accessors_count; 462 463 cgltf_buffer_view* buffer_views; 464 cgltf_size buffer_views_count; 465 466 cgltf_buffer* buffers; 467 cgltf_size buffers_count; 468 469 cgltf_image* images; 470 cgltf_size images_count; 471 472 cgltf_texture* textures; 473 cgltf_size textures_count; 474 475 cgltf_sampler* samplers; 476 cgltf_size samplers_count; 477 478 cgltf_skin* skins; 479 cgltf_size skins_count; 480 481 cgltf_camera* cameras; 482 cgltf_size cameras_count; 483 484 cgltf_light* lights; 485 cgltf_size lights_count; 486 487 cgltf_node* nodes; 488 cgltf_size nodes_count; 489 490 cgltf_scene* scenes; 491 cgltf_size scenes_count; 492 493 cgltf_scene* scene; 494 495 cgltf_animation* animations; 496 cgltf_size animations_count; 497 498 const void* bin; 499 cgltf_size bin_size; 500 501 void (*memory_free) (void* user, void* ptr); 502 void* memory_user_data; 503 } cgltf_data; 504 505 cgltf_result cgltf_parse( 506 const cgltf_options* options, 507 const void* data, 508 cgltf_size size, 509 cgltf_data** out_data); 510 511 cgltf_result cgltf_parse_file( 512 const cgltf_options* options, 513 const char* path, 514 cgltf_data** out_data); 515 516 cgltf_result cgltf_load_buffers( 517 const cgltf_options* options, 518 cgltf_data* data, 519 const char* gltf_path); 520 521 522 cgltf_result cgltf_load_buffer_base64(const cgltf_options* options, cgltf_size size, const char* base64, void** out_data); 523 524 cgltf_result cgltf_validate( 525 cgltf_data* data); 526 527 void cgltf_free(cgltf_data* data); 528 529 void cgltf_node_transform_local(const cgltf_node* node, cgltf_float* out_matrix); 530 void cgltf_node_transform_world(const cgltf_node* node, cgltf_float* out_matrix); 531 532 cgltf_bool cgltf_accessor_read_float(const cgltf_accessor* accessor, cgltf_size index, cgltf_float* out, cgltf_size element_size); 533 cgltf_size cgltf_accessor_read_index(const cgltf_accessor* accessor, cgltf_size index); 534 535 #ifdef __cplusplus 536 } 537 #endif 538 539 #endif /* #ifndef CGLTF_H_INCLUDED__ */ 540 541 /* 542 * 543 * Stop now, if you are only interested in the API. 544 * Below, you find the implementation. 545 * 546 */ 547 548 #ifdef __INTELLISENSE__ 549 /* This makes MSVC intellisense work. */ 550 #define CGLTF_IMPLEMENTATION 551 #endif 552 553 #ifdef CGLTF_IMPLEMENTATION 554 555 #include <stdint.h> /* For uint8_t, uint32_t */ 556 #include <string.h> /* For strncpy */ 557 #include <stdlib.h> /* For malloc, free */ 558 #include <stdio.h> /* For fopen */ 559 #include <limits.h> /* For UINT_MAX etc */ 560 561 /* 562 * -- jsmn.h start -- 563 * Source: https://github.com/zserge/jsmn 564 * License: MIT 565 */ 566 typedef enum { 567 JSMN_UNDEFINED = 0, 568 JSMN_OBJECT = 1, 569 JSMN_ARRAY = 2, 570 JSMN_STRING = 3, 571 JSMN_PRIMITIVE = 4 572 } jsmntype_t; 573 enum jsmnerr { 574 /* Not enough tokens were provided */ 575 JSMN_ERROR_NOMEM = -1, 576 /* Invalid character inside JSON string */ 577 JSMN_ERROR_INVAL = -2, 578 /* The string is not a full JSON packet, more bytes expected */ 579 JSMN_ERROR_PART = -3 580 }; 581 typedef struct { 582 jsmntype_t type; 583 int start; 584 int end; 585 int size; 586 #ifdef JSMN_PARENT_LINKS 587 int parent; 588 #endif 589 } jsmntok_t; 590 typedef struct { 591 unsigned int pos; /* offset in the JSON string */ 592 unsigned int toknext; /* next token to allocate */ 593 int toksuper; /* superior token node, e.g parent object or array */ 594 } jsmn_parser; 595 static void jsmn_init(jsmn_parser *parser); 596 static int jsmn_parse(jsmn_parser *parser, const char *js, size_t len, jsmntok_t *tokens, size_t num_tokens); 597 /* 598 * -- jsmn.h end -- 599 */ 600 601 602 static const cgltf_size GlbHeaderSize = 12; 603 static const cgltf_size GlbChunkHeaderSize = 8; 604 static const uint32_t GlbVersion = 2; 605 static const uint32_t GlbMagic = 0x46546C67; 606 static const uint32_t GlbMagicJsonChunk = 0x4E4F534A; 607 static const uint32_t GlbMagicBinChunk = 0x004E4942; 608 609 static void* cgltf_default_alloc(void* user, cgltf_size size) 610 { 611 (void)user; 612 return malloc(size); 613 } 614 615 static void cgltf_default_free(void* user, void* ptr) 616 { 617 (void)user; 618 free(ptr); 619 } 620 621 static void* cgltf_calloc(cgltf_options* options, size_t element_size, cgltf_size count) 622 { 623 if (SIZE_MAX / element_size < count) 624 { 625 return NULL; 626 } 627 void* result = options->memory_alloc(options->memory_user_data, element_size * count); 628 if (!result) 629 { 630 return NULL; 631 } 632 memset(result, 0, element_size * count); 633 return result; 634 } 635 636 static cgltf_result cgltf_parse_json(cgltf_options* options, const uint8_t* json_chunk, cgltf_size size, cgltf_data** out_data); 637 638 cgltf_result cgltf_parse(const cgltf_options* options, const void* data, cgltf_size size, cgltf_data** out_data) 639 { 640 if (size < GlbHeaderSize) 641 { 642 return cgltf_result_data_too_short; 643 } 644 645 if (options == NULL) 646 { 647 return cgltf_result_invalid_options; 648 } 649 650 cgltf_options fixed_options = *options; 651 if (fixed_options.memory_alloc == NULL) 652 { 653 fixed_options.memory_alloc = &cgltf_default_alloc; 654 } 655 if (fixed_options.memory_free == NULL) 656 { 657 fixed_options.memory_free = &cgltf_default_free; 658 } 659 660 uint32_t tmp; 661 // Magic 662 memcpy(&tmp, data, 4); 663 if (tmp != GlbMagic) 664 { 665 if (fixed_options.type == cgltf_file_type_invalid) 666 { 667 fixed_options.type = cgltf_file_type_gltf; 668 } 669 else if (fixed_options.type == cgltf_file_type_glb) 670 { 671 return cgltf_result_unknown_format; 672 } 673 } 674 675 if (fixed_options.type == cgltf_file_type_gltf) 676 { 677 cgltf_result json_result = cgltf_parse_json(&fixed_options, (const uint8_t*)data, size, out_data); 678 if (json_result != cgltf_result_success) 679 { 680 return json_result; 681 } 682 683 (*out_data)->file_type = cgltf_file_type_gltf; 684 685 return cgltf_result_success; 686 } 687 688 const uint8_t* ptr = (const uint8_t*)data; 689 // Version 690 memcpy(&tmp, ptr + 4, 4); 691 uint32_t version = tmp; 692 if (version != GlbVersion) 693 { 694 return cgltf_result_unknown_format; 695 } 696 697 // Total length 698 memcpy(&tmp, ptr + 8, 4); 699 if (tmp > size) 700 { 701 return cgltf_result_data_too_short; 702 } 703 704 const uint8_t* json_chunk = ptr + GlbHeaderSize; 705 706 if (GlbHeaderSize + GlbChunkHeaderSize > size) 707 { 708 return cgltf_result_data_too_short; 709 } 710 711 // JSON chunk: length 712 uint32_t json_length; 713 memcpy(&json_length, json_chunk, 4); 714 if (GlbHeaderSize + GlbChunkHeaderSize + json_length > size) 715 { 716 return cgltf_result_data_too_short; 717 } 718 719 // JSON chunk: magic 720 memcpy(&tmp, json_chunk + 4, 4); 721 if (tmp != GlbMagicJsonChunk) 722 { 723 return cgltf_result_unknown_format; 724 } 725 726 json_chunk += GlbChunkHeaderSize; 727 728 const void* bin = 0; 729 cgltf_size bin_size = 0; 730 731 if (GlbHeaderSize + GlbChunkHeaderSize + json_length + GlbChunkHeaderSize <= size) 732 { 733 // We can read another chunk 734 const uint8_t* bin_chunk = json_chunk + json_length; 735 736 // Bin chunk: length 737 uint32_t bin_length; 738 memcpy(&bin_length, bin_chunk, 4); 739 if (GlbHeaderSize + GlbChunkHeaderSize + json_length + GlbChunkHeaderSize + bin_length > size) 740 { 741 return cgltf_result_data_too_short; 742 } 743 744 // Bin chunk: magic 745 memcpy(&tmp, bin_chunk + 4, 4); 746 if (tmp != GlbMagicBinChunk) 747 { 748 return cgltf_result_unknown_format; 749 } 750 751 bin_chunk += GlbChunkHeaderSize; 752 753 bin = bin_chunk; 754 bin_size = bin_length; 755 } 756 757 cgltf_result json_result = cgltf_parse_json(&fixed_options, json_chunk, json_length, out_data); 758 if (json_result != cgltf_result_success) 759 { 760 return json_result; 761 } 762 763 (*out_data)->file_type = cgltf_file_type_glb; 764 (*out_data)->bin = bin; 765 (*out_data)->bin_size = bin_size; 766 767 return cgltf_result_success; 768 } 769 770 cgltf_result cgltf_parse_file(const cgltf_options* options, const char* path, cgltf_data** out_data) 771 { 772 if (options == NULL) 773 { 774 return cgltf_result_invalid_options; 775 } 776 777 void* (*memory_alloc)(void*, cgltf_size) = options->memory_alloc ? options->memory_alloc : &cgltf_default_alloc; 778 void (*memory_free)(void*, void*) = options->memory_free ? options->memory_free : &cgltf_default_free; 779 780 FILE* file = fopen(path, "rb"); 781 if (!file) 782 { 783 return cgltf_result_file_not_found; 784 } 785 786 fseek(file, 0, SEEK_END); 787 788 long length = ftell(file); 789 if (length < 0) 790 { 791 fclose(file); 792 return cgltf_result_io_error; 793 } 794 795 fseek(file, 0, SEEK_SET); 796 797 char* file_data = (char*)memory_alloc(options->memory_user_data, length); 798 if (!file_data) 799 { 800 fclose(file); 801 return cgltf_result_out_of_memory; 802 } 803 804 cgltf_size file_size = (cgltf_size)length; 805 cgltf_size read_size = fread(file_data, 1, file_size, file); 806 807 fclose(file); 808 809 if (read_size != file_size) 810 { 811 memory_free(options->memory_user_data, file_data); 812 return cgltf_result_io_error; 813 } 814 815 cgltf_result result = cgltf_parse(options, file_data, file_size, out_data); 816 817 if (result != cgltf_result_success) 818 { 819 memory_free(options->memory_user_data, file_data); 820 return result; 821 } 822 823 (*out_data)->file_data = file_data; 824 825 return cgltf_result_success; 826 } 827 828 static void cgltf_combine_paths(char* path, const char* base, const char* uri) 829 { 830 const char* s0 = strrchr(base, '/'); 831 const char* s1 = strrchr(base, '\\'); 832 const char* slash = s0 ? (s1 && s1 > s0 ? s1 : s0) : s1; 833 834 if (slash) 835 { 836 size_t prefix = slash - base + 1; 837 838 strncpy(path, base, prefix); 839 strcpy(path + prefix, uri); 840 } 841 else 842 { 843 strcpy(path, base); 844 } 845 } 846 847 static cgltf_result cgltf_load_buffer_file(const cgltf_options* options, cgltf_size size, const char* uri, const char* gltf_path, void** out_data) 848 { 849 void* (*memory_alloc)(void*, cgltf_size) = options->memory_alloc ? options->memory_alloc : &cgltf_default_alloc; 850 void (*memory_free)(void*, void*) = options->memory_free ? options->memory_free : &cgltf_default_free; 851 852 char* path = (char*)memory_alloc(options->memory_user_data, strlen(uri) + strlen(gltf_path) + 1); 853 if (!path) 854 { 855 return cgltf_result_out_of_memory; 856 } 857 858 cgltf_combine_paths(path, gltf_path, uri); 859 860 FILE* file = fopen(path, "rb"); 861 862 memory_free(options->memory_user_data, path); 863 864 if (!file) 865 { 866 return cgltf_result_file_not_found; 867 } 868 869 char* file_data = (char*)memory_alloc(options->memory_user_data, size); 870 if (!file_data) 871 { 872 fclose(file); 873 return cgltf_result_out_of_memory; 874 } 875 876 cgltf_size read_size = fread(file_data, 1, size, file); 877 878 fclose(file); 879 880 if (read_size != size) 881 { 882 memory_free(options->memory_user_data, file_data); 883 return cgltf_result_io_error; 884 } 885 886 *out_data = file_data; 887 888 return cgltf_result_success; 889 } 890 891 cgltf_result cgltf_load_buffer_base64(const cgltf_options* options, cgltf_size size, const char* base64, void** out_data) 892 { 893 void* (*memory_alloc)(void*, cgltf_size) = options->memory_alloc ? options->memory_alloc : &cgltf_default_alloc; 894 void (*memory_free)(void*, void*) = options->memory_free ? options->memory_free : &cgltf_default_free; 895 896 unsigned char* data = (unsigned char*)memory_alloc(options->memory_user_data, size); 897 if (!data) 898 { 899 return cgltf_result_out_of_memory; 900 } 901 902 unsigned int buffer = 0; 903 unsigned int buffer_bits = 0; 904 905 for (cgltf_size i = 0; i < size; ++i) 906 { 907 while (buffer_bits < 8) 908 { 909 char ch = *base64++; 910 911 int index = 912 (unsigned)(ch - 'A') < 26 ? (ch - 'A') : 913 (unsigned)(ch - 'a') < 26 ? (ch - 'a') + 26 : 914 (unsigned)(ch - '0') < 10 ? (ch - '0') + 52 : 915 ch == '+' ? 62 : 916 ch == '/' ? 63 : 917 -1; 918 919 if (index < 0) 920 { 921 memory_free(options->memory_user_data, data); 922 return cgltf_result_io_error; 923 } 924 925 buffer = (buffer << 6) | index; 926 buffer_bits += 6; 927 } 928 929 data[i] = (unsigned char)(buffer >> (buffer_bits - 8)); 930 buffer_bits -= 8; 931 } 932 933 *out_data = data; 934 935 return cgltf_result_success; 936 } 937 938 cgltf_result cgltf_load_buffers(const cgltf_options* options, cgltf_data* data, const char* gltf_path) 939 { 940 if (options == NULL) 941 { 942 return cgltf_result_invalid_options; 943 } 944 945 if (data->buffers_count && data->buffers[0].data == NULL && data->buffers[0].uri == NULL && data->bin) 946 { 947 if (data->bin_size < data->buffers[0].size) 948 { 949 return cgltf_result_data_too_short; 950 } 951 952 data->buffers[0].data = (void*)data->bin; 953 } 954 955 for (cgltf_size i = 0; i < data->buffers_count; ++i) 956 { 957 if (data->buffers[i].data) 958 { 959 continue; 960 } 961 962 const char* uri = data->buffers[i].uri; 963 964 if (uri == NULL) 965 { 966 continue; 967 } 968 969 if (strncmp(uri, "data:", 5) == 0) 970 { 971 const char* comma = strchr(uri, ','); 972 973 if (comma && comma - uri >= 7 && strncmp(comma - 7, ";base64", 7) == 0) 974 { 975 cgltf_result res = cgltf_load_buffer_base64(options, data->buffers[i].size, comma + 1, &data->buffers[i].data); 976 977 if (res != cgltf_result_success) 978 { 979 return res; 980 } 981 } 982 else 983 { 984 return cgltf_result_unknown_format; 985 } 986 } 987 else if (strstr(uri, "://") == NULL) 988 { 989 cgltf_result res = cgltf_load_buffer_file(options, data->buffers[i].size, uri, gltf_path, &data->buffers[i].data); 990 991 if (res != cgltf_result_success) 992 { 993 return res; 994 } 995 } 996 else 997 { 998 return cgltf_result_unknown_format; 999 } 1000 } 1001 1002 return cgltf_result_success; 1003 } 1004 1005 static cgltf_size cgltf_calc_size(cgltf_type type, cgltf_component_type component_type); 1006 1007 static cgltf_size cgltf_calc_index_bound(cgltf_buffer_view* buffer_view, cgltf_size offset, cgltf_component_type component_type, cgltf_size count) 1008 { 1009 char* data = (char*)buffer_view->buffer->data + offset + buffer_view->offset; 1010 cgltf_size bound = 0; 1011 1012 switch (component_type) 1013 { 1014 case cgltf_component_type_r_8u: 1015 for (size_t i = 0; i < count; ++i) 1016 { 1017 cgltf_size v = ((unsigned char*)data)[i]; 1018 bound = bound > v ? bound : v; 1019 } 1020 break; 1021 1022 case cgltf_component_type_r_16u: 1023 for (size_t i = 0; i < count; ++i) 1024 { 1025 cgltf_size v = ((unsigned short*)data)[i]; 1026 bound = bound > v ? bound : v; 1027 } 1028 break; 1029 1030 case cgltf_component_type_r_32u: 1031 for (size_t i = 0; i < count; ++i) 1032 { 1033 cgltf_size v = ((unsigned int*)data)[i]; 1034 bound = bound > v ? bound : v; 1035 } 1036 break; 1037 1038 default: 1039 ; 1040 } 1041 1042 return bound; 1043 } 1044 1045 cgltf_result cgltf_validate(cgltf_data* data) 1046 { 1047 for (cgltf_size i = 0; i < data->accessors_count; ++i) 1048 { 1049 cgltf_accessor* accessor = &data->accessors[i]; 1050 1051 cgltf_size element_size = cgltf_calc_size(accessor->type, accessor->component_type); 1052 1053 if (accessor->buffer_view) 1054 { 1055 cgltf_size req_size = accessor->offset + accessor->stride * (accessor->count - 1) + element_size; 1056 1057 if (accessor->buffer_view->size < req_size) 1058 { 1059 return cgltf_result_data_too_short; 1060 } 1061 } 1062 1063 if (accessor->is_sparse) 1064 { 1065 cgltf_accessor_sparse* sparse = &accessor->sparse; 1066 1067 cgltf_size indices_component_size = cgltf_calc_size(cgltf_type_scalar, sparse->indices_component_type); 1068 cgltf_size indices_req_size = sparse->indices_byte_offset + indices_component_size * sparse->count; 1069 cgltf_size values_req_size = sparse->values_byte_offset + element_size * sparse->count; 1070 1071 if (sparse->indices_buffer_view->size < indices_req_size || 1072 sparse->values_buffer_view->size < values_req_size) 1073 { 1074 return cgltf_result_data_too_short; 1075 } 1076 1077 if (sparse->indices_component_type != cgltf_component_type_r_8u && 1078 sparse->indices_component_type != cgltf_component_type_r_16u && 1079 sparse->indices_component_type != cgltf_component_type_r_32u) 1080 { 1081 return cgltf_result_invalid_gltf; 1082 } 1083 1084 if (sparse->indices_buffer_view->buffer->data) 1085 { 1086 cgltf_size index_bound = cgltf_calc_index_bound(sparse->indices_buffer_view, sparse->indices_byte_offset, sparse->indices_component_type, sparse->count); 1087 1088 if (index_bound >= accessor->count) 1089 { 1090 return cgltf_result_data_too_short; 1091 } 1092 } 1093 } 1094 } 1095 1096 for (cgltf_size i = 0; i < data->buffer_views_count; ++i) 1097 { 1098 cgltf_size req_size = data->buffer_views[i].offset + data->buffer_views[i].size; 1099 1100 if (data->buffer_views[i].buffer && data->buffer_views[i].buffer->size < req_size) 1101 { 1102 return cgltf_result_data_too_short; 1103 } 1104 } 1105 1106 for (cgltf_size i = 0; i < data->meshes_count; ++i) 1107 { 1108 if (data->meshes[i].weights) 1109 { 1110 if (data->meshes[i].primitives_count && data->meshes[i].primitives[0].targets_count != data->meshes[i].weights_count) 1111 { 1112 return cgltf_result_invalid_gltf; 1113 } 1114 } 1115 1116 for (cgltf_size j = 0; j < data->meshes[i].primitives_count; ++j) 1117 { 1118 if (data->meshes[i].primitives[j].targets_count != data->meshes[i].primitives[0].targets_count) 1119 { 1120 return cgltf_result_invalid_gltf; 1121 } 1122 1123 if (data->meshes[i].primitives[j].attributes_count) 1124 { 1125 cgltf_accessor* first = data->meshes[i].primitives[j].attributes[0].data; 1126 1127 for (cgltf_size k = 0; k < data->meshes[i].primitives[j].attributes_count; ++k) 1128 { 1129 if (data->meshes[i].primitives[j].attributes[k].data->count != first->count) 1130 { 1131 return cgltf_result_invalid_gltf; 1132 } 1133 } 1134 1135 for (cgltf_size k = 0; k < data->meshes[i].primitives[j].targets_count; ++k) 1136 { 1137 for (cgltf_size m = 0; m < data->meshes[i].primitives[j].targets[k].attributes_count; ++m) 1138 { 1139 if (data->meshes[i].primitives[j].targets[k].attributes[m].data->count != first->count) 1140 { 1141 return cgltf_result_invalid_gltf; 1142 } 1143 } 1144 } 1145 1146 cgltf_accessor* indices = data->meshes[i].primitives[j].indices; 1147 1148 if (indices && 1149 indices->component_type != cgltf_component_type_r_8u && 1150 indices->component_type != cgltf_component_type_r_16u && 1151 indices->component_type != cgltf_component_type_r_32u) 1152 { 1153 return cgltf_result_invalid_gltf; 1154 } 1155 1156 if (indices && indices->buffer_view && indices->buffer_view->buffer->data) 1157 { 1158 cgltf_size index_bound = cgltf_calc_index_bound(indices->buffer_view, indices->offset, indices->component_type, indices->count); 1159 1160 if (index_bound >= first->count) 1161 { 1162 return cgltf_result_data_too_short; 1163 } 1164 } 1165 } 1166 } 1167 } 1168 1169 for (cgltf_size i = 0; i < data->nodes_count; ++i) 1170 { 1171 if (data->nodes[i].weights && data->nodes[i].mesh) 1172 { 1173 if (data->nodes[i].mesh->primitives_count && data->nodes[i].mesh->primitives[0].targets_count != data->nodes[i].weights_count) 1174 { 1175 return cgltf_result_invalid_gltf; 1176 } 1177 } 1178 } 1179 1180 return cgltf_result_success; 1181 } 1182 1183 void cgltf_free(cgltf_data* data) 1184 { 1185 if (!data) 1186 { 1187 return; 1188 } 1189 1190 data->memory_free(data->memory_user_data, data->asset.copyright); 1191 data->memory_free(data->memory_user_data, data->asset.generator); 1192 data->memory_free(data->memory_user_data, data->asset.version); 1193 data->memory_free(data->memory_user_data, data->asset.min_version); 1194 1195 data->memory_free(data->memory_user_data, data->accessors); 1196 data->memory_free(data->memory_user_data, data->buffer_views); 1197 1198 for (cgltf_size i = 0; i < data->buffers_count; ++i) 1199 { 1200 if (data->buffers[i].data != data->bin) 1201 { 1202 data->memory_free(data->memory_user_data, data->buffers[i].data); 1203 } 1204 1205 data->memory_free(data->memory_user_data, data->buffers[i].uri); 1206 } 1207 1208 data->memory_free(data->memory_user_data, data->buffers); 1209 1210 for (cgltf_size i = 0; i < data->meshes_count; ++i) 1211 { 1212 data->memory_free(data->memory_user_data, data->meshes[i].name); 1213 1214 for (cgltf_size j = 0; j < data->meshes[i].primitives_count; ++j) 1215 { 1216 for (cgltf_size k = 0; k < data->meshes[i].primitives[j].attributes_count; ++k) 1217 { 1218 data->memory_free(data->memory_user_data, data->meshes[i].primitives[j].attributes[k].name); 1219 } 1220 1221 data->memory_free(data->memory_user_data, data->meshes[i].primitives[j].attributes); 1222 1223 for (cgltf_size k = 0; k < data->meshes[i].primitives[j].targets_count; ++k) 1224 { 1225 for (cgltf_size m = 0; m < data->meshes[i].primitives[j].targets[k].attributes_count; ++m) 1226 { 1227 data->memory_free(data->memory_user_data, data->meshes[i].primitives[j].targets[k].attributes[m].name); 1228 } 1229 1230 data->memory_free(data->memory_user_data, data->meshes[i].primitives[j].targets[k].attributes); 1231 } 1232 1233 data->memory_free(data->memory_user_data, data->meshes[i].primitives[j].targets); 1234 } 1235 1236 data->memory_free(data->memory_user_data, data->meshes[i].primitives); 1237 data->memory_free(data->memory_user_data, data->meshes[i].weights); 1238 } 1239 1240 data->memory_free(data->memory_user_data, data->meshes); 1241 1242 for (cgltf_size i = 0; i < data->materials_count; ++i) 1243 { 1244 data->memory_free(data->memory_user_data, data->materials[i].name); 1245 } 1246 1247 data->memory_free(data->memory_user_data, data->materials); 1248 1249 for (cgltf_size i = 0; i < data->images_count; ++i) 1250 { 1251 data->memory_free(data->memory_user_data, data->images[i].name); 1252 data->memory_free(data->memory_user_data, data->images[i].uri); 1253 data->memory_free(data->memory_user_data, data->images[i].mime_type); 1254 } 1255 1256 data->memory_free(data->memory_user_data, data->images); 1257 1258 for (cgltf_size i = 0; i < data->textures_count; ++i) 1259 { 1260 data->memory_free(data->memory_user_data, data->textures[i].name); 1261 } 1262 1263 data->memory_free(data->memory_user_data, data->textures); 1264 1265 data->memory_free(data->memory_user_data, data->samplers); 1266 1267 for (cgltf_size i = 0; i < data->skins_count; ++i) 1268 { 1269 data->memory_free(data->memory_user_data, data->skins[i].name); 1270 data->memory_free(data->memory_user_data, data->skins[i].joints); 1271 } 1272 1273 data->memory_free(data->memory_user_data, data->skins); 1274 1275 for (cgltf_size i = 0; i < data->cameras_count; ++i) 1276 { 1277 data->memory_free(data->memory_user_data, data->cameras[i].name); 1278 } 1279 1280 data->memory_free(data->memory_user_data, data->cameras); 1281 1282 for (cgltf_size i = 0; i < data->lights_count; ++i) 1283 { 1284 data->memory_free(data->memory_user_data, data->lights[i].name); 1285 } 1286 1287 data->memory_free(data->memory_user_data, data->lights); 1288 1289 for (cgltf_size i = 0; i < data->nodes_count; ++i) 1290 { 1291 data->memory_free(data->memory_user_data, data->nodes[i].name); 1292 data->memory_free(data->memory_user_data, data->nodes[i].children); 1293 data->memory_free(data->memory_user_data, data->nodes[i].weights); 1294 } 1295 1296 data->memory_free(data->memory_user_data, data->nodes); 1297 1298 for (cgltf_size i = 0; i < data->scenes_count; ++i) 1299 { 1300 data->memory_free(data->memory_user_data, data->scenes[i].name); 1301 data->memory_free(data->memory_user_data, data->scenes[i].nodes); 1302 } 1303 1304 data->memory_free(data->memory_user_data, data->scenes); 1305 1306 for (cgltf_size i = 0; i < data->animations_count; ++i) 1307 { 1308 data->memory_free(data->memory_user_data, data->animations[i].name); 1309 data->memory_free(data->memory_user_data, data->animations[i].samplers); 1310 data->memory_free(data->memory_user_data, data->animations[i].channels); 1311 } 1312 1313 data->memory_free(data->memory_user_data, data->animations); 1314 1315 data->memory_free(data->memory_user_data, data->file_data); 1316 1317 data->memory_free(data->memory_user_data, data); 1318 } 1319 1320 void cgltf_node_transform_local(const cgltf_node* node, cgltf_float* out_matrix) 1321 { 1322 cgltf_float* lm = out_matrix; 1323 1324 if (node->has_matrix) 1325 { 1326 memcpy(lm, node->matrix, sizeof(float) * 16); 1327 } 1328 else 1329 { 1330 float tx = node->translation[0]; 1331 float ty = node->translation[1]; 1332 float tz = node->translation[2]; 1333 1334 float qx = node->rotation[0]; 1335 float qy = node->rotation[1]; 1336 float qz = node->rotation[2]; 1337 float qw = node->rotation[3]; 1338 1339 float sx = node->scale[0]; 1340 float sy = node->scale[1]; 1341 float sz = node->scale[2]; 1342 1343 lm[0] = (1 - 2 * qy*qy - 2 * qz*qz) * sx; 1344 lm[1] = (2 * qx*qy + 2 * qz*qw) * sy; 1345 lm[2] = (2 * qx*qz - 2 * qy*qw) * sz; 1346 lm[3] = 0.f; 1347 1348 lm[4] = (2 * qx*qy - 2 * qz*qw) * sx; 1349 lm[5] = (1 - 2 * qx*qx - 2 * qz*qz) * sy; 1350 lm[6] = (2 * qy*qz + 2 * qx*qw) * sz; 1351 lm[7] = 0.f; 1352 1353 lm[8] = (2 * qx*qz + 2 * qy*qw) * sx; 1354 lm[9] = (2 * qy*qz - 2 * qx*qw) * sy; 1355 lm[10] = (1 - 2 * qx*qx - 2 * qy*qy) * sz; 1356 lm[11] = 0.f; 1357 1358 lm[12] = tx; 1359 lm[13] = ty; 1360 lm[14] = tz; 1361 lm[15] = 1.f; 1362 } 1363 } 1364 1365 void cgltf_node_transform_world(const cgltf_node* node, cgltf_float* out_matrix) 1366 { 1367 cgltf_float* lm = out_matrix; 1368 cgltf_node_transform_local(node, lm); 1369 1370 const cgltf_node* parent = node->parent; 1371 1372 while (parent) 1373 { 1374 float pm[16]; 1375 cgltf_node_transform_local(parent, pm); 1376 1377 for (int i = 0; i < 4; ++i) 1378 { 1379 float l0 = lm[i * 4 + 0]; 1380 float l1 = lm[i * 4 + 1]; 1381 float l2 = lm[i * 4 + 2]; 1382 1383 float r0 = l0 * pm[0] + l1 * pm[4] + l2 * pm[8]; 1384 float r1 = l0 * pm[1] + l1 * pm[5] + l2 * pm[9]; 1385 float r2 = l0 * pm[2] + l1 * pm[6] + l2 * pm[10]; 1386 1387 lm[i * 4 + 0] = r0; 1388 lm[i * 4 + 1] = r1; 1389 lm[i * 4 + 2] = r2; 1390 } 1391 1392 lm[12] += pm[12]; 1393 lm[13] += pm[13]; 1394 lm[14] += pm[14]; 1395 1396 parent = parent->parent; 1397 } 1398 } 1399 1400 static cgltf_size cgltf_component_read_index(const void* in, cgltf_component_type component_type) 1401 { 1402 switch (component_type) 1403 { 1404 case cgltf_component_type_r_16: 1405 return *((const int16_t*) in); 1406 case cgltf_component_type_r_16u: 1407 return *((const uint16_t*) in); 1408 case cgltf_component_type_r_32u: 1409 return *((const uint32_t*) in); 1410 case cgltf_component_type_r_32f: 1411 return *((const float*) in); 1412 case cgltf_component_type_r_8: 1413 return *((const int8_t*) in); 1414 case cgltf_component_type_r_8u: 1415 case cgltf_component_type_invalid: 1416 default: 1417 return *((const uint8_t*) in); 1418 } 1419 } 1420 1421 static cgltf_float cgltf_component_read_float(const void* in, cgltf_component_type component_type, cgltf_bool normalized) 1422 { 1423 if (component_type == cgltf_component_type_r_32f) 1424 { 1425 return *((const float*) in); 1426 } 1427 1428 if (normalized) 1429 { 1430 switch (component_type) 1431 { 1432 case cgltf_component_type_r_32u: 1433 return *((const uint32_t*) in) / (float) UINT_MAX; 1434 case cgltf_component_type_r_16: 1435 return *((const int16_t*) in) / (float) SHRT_MAX; 1436 case cgltf_component_type_r_16u: 1437 return *((const uint16_t*) in) / (float) USHRT_MAX; 1438 case cgltf_component_type_r_8: 1439 return *((const int8_t*) in) / (float) SCHAR_MAX; 1440 case cgltf_component_type_r_8u: 1441 case cgltf_component_type_invalid: 1442 default: 1443 return *((const uint8_t*) in) / (float) CHAR_MAX; 1444 } 1445 } 1446 1447 return cgltf_component_read_index(in, component_type); 1448 } 1449 1450 static cgltf_size cgltf_num_components(cgltf_type type); 1451 static cgltf_size cgltf_component_size(cgltf_component_type component_type); 1452 1453 static 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) 1454 { 1455 cgltf_size num_components = cgltf_num_components(type); 1456 1457 if (element_size < num_components) { 1458 return 0; 1459 } 1460 1461 // There are three special cases for component extraction, see #data-alignment in the 2.0 spec. 1462 1463 cgltf_size component_size = cgltf_component_size(component_type); 1464 1465 if (type == cgltf_type_mat2 && component_size == 1) 1466 { 1467 out[0] = cgltf_component_read_float(element, component_type, normalized); 1468 out[1] = cgltf_component_read_float(element + 1, component_type, normalized); 1469 out[2] = cgltf_component_read_float(element + 4, component_type, normalized); 1470 out[3] = cgltf_component_read_float(element + 5, component_type, normalized); 1471 return 1; 1472 } 1473 1474 if (type == cgltf_type_mat3 && component_size == 1) 1475 { 1476 out[0] = cgltf_component_read_float(element, component_type, normalized); 1477 out[1] = cgltf_component_read_float(element + 1, component_type, normalized); 1478 out[2] = cgltf_component_read_float(element + 2, component_type, normalized); 1479 out[3] = cgltf_component_read_float(element + 4, component_type, normalized); 1480 out[4] = cgltf_component_read_float(element + 5, component_type, normalized); 1481 out[5] = cgltf_component_read_float(element + 6, component_type, normalized); 1482 out[6] = cgltf_component_read_float(element + 8, component_type, normalized); 1483 out[7] = cgltf_component_read_float(element + 9, component_type, normalized); 1484 out[8] = cgltf_component_read_float(element + 10, component_type, normalized); 1485 return 1; 1486 } 1487 1488 if (type == cgltf_type_mat3 && component_size == 2) 1489 { 1490 out[0] = cgltf_component_read_float(element, component_type, normalized); 1491 out[1] = cgltf_component_read_float(element + 2, component_type, normalized); 1492 out[2] = cgltf_component_read_float(element + 4, component_type, normalized); 1493 out[3] = cgltf_component_read_float(element + 8, component_type, normalized); 1494 out[4] = cgltf_component_read_float(element + 10, component_type, normalized); 1495 out[5] = cgltf_component_read_float(element + 12, component_type, normalized); 1496 out[6] = cgltf_component_read_float(element + 16, component_type, normalized); 1497 out[7] = cgltf_component_read_float(element + 18, component_type, normalized); 1498 out[8] = cgltf_component_read_float(element + 20, component_type, normalized); 1499 return 1; 1500 } 1501 1502 for (cgltf_size i = 0; i < num_components; ++i) 1503 { 1504 out[i] = cgltf_component_read_float(element + component_size * i, component_type, normalized); 1505 } 1506 return 1; 1507 } 1508 1509 1510 cgltf_bool cgltf_accessor_read_float(const cgltf_accessor* accessor, cgltf_size index, cgltf_float* out, cgltf_size element_size) 1511 { 1512 if (accessor->is_sparse || accessor->buffer_view == NULL) 1513 { 1514 return 0; 1515 } 1516 1517 cgltf_size offset = accessor->offset + accessor->buffer_view->offset; 1518 const uint8_t* element = (const uint8_t*) accessor->buffer_view->buffer->data; 1519 element += offset + accessor->stride * index; 1520 return cgltf_element_read_float(element, accessor->type, accessor->component_type, accessor->normalized, out, element_size); 1521 } 1522 1523 cgltf_size cgltf_accessor_read_index(const cgltf_accessor* accessor, cgltf_size index) 1524 { 1525 if (accessor->buffer_view) 1526 { 1527 cgltf_size offset = accessor->offset + accessor->buffer_view->offset; 1528 const uint8_t* element = (const uint8_t*) accessor->buffer_view->buffer->data; 1529 element += offset + accessor->stride * index; 1530 return cgltf_component_read_index(element, accessor->component_type); 1531 } 1532 1533 return 0; 1534 } 1535 1536 #define CGLTF_ERROR_JSON -1 1537 #define CGLTF_ERROR_NOMEM -2 1538 1539 #define CGLTF_CHECK_TOKTYPE(tok_, type_) if ((tok_).type != (type_)) { return CGLTF_ERROR_JSON; } 1540 #define CGLTF_CHECK_KEY(tok_) if ((tok_).type != JSMN_STRING || (tok_).size == 0) { return CGLTF_ERROR_JSON; } /* checking size for 0 verifies that a value follows the key */ 1541 1542 #define CGLTF_PTRINDEX(type, idx) (type*)(cgltf_size)(idx + 1) 1543 #define CGLTF_PTRFIXUP(var, data, size) if (var) { if ((cgltf_size)var > size) { return CGLTF_ERROR_JSON; } var = &data[(cgltf_size)var-1]; } 1544 #define CGLTF_PTRFIXUP_REQ(var, data, size) if (!var || (cgltf_size)var > size) { return CGLTF_ERROR_JSON; } var = &data[(cgltf_size)var-1]; 1545 1546 static int cgltf_json_strcmp(jsmntok_t const* tok, const uint8_t* json_chunk, const char* str) 1547 { 1548 CGLTF_CHECK_TOKTYPE(*tok, JSMN_STRING); 1549 size_t const str_len = strlen(str); 1550 size_t const name_length = tok->end - tok->start; 1551 return (str_len == name_length) ? strncmp((const char*)json_chunk + tok->start, str, str_len) : 128; 1552 } 1553 1554 static int cgltf_json_to_int(jsmntok_t const* tok, const uint8_t* json_chunk) 1555 { 1556 CGLTF_CHECK_TOKTYPE(*tok, JSMN_PRIMITIVE); 1557 char tmp[128]; 1558 int size = (cgltf_size)(tok->end - tok->start) < sizeof(tmp) ? tok->end - tok->start : sizeof(tmp) - 1; 1559 strncpy(tmp, (const char*)json_chunk + tok->start, size); 1560 tmp[size] = 0; 1561 return atoi(tmp); 1562 } 1563 1564 static cgltf_float cgltf_json_to_float(jsmntok_t const* tok, const uint8_t* json_chunk) 1565 { 1566 CGLTF_CHECK_TOKTYPE(*tok, JSMN_PRIMITIVE); 1567 char tmp[128]; 1568 int size = (cgltf_size)(tok->end - tok->start) < sizeof(tmp) ? tok->end - tok->start : sizeof(tmp) - 1; 1569 strncpy(tmp, (const char*)json_chunk + tok->start, size); 1570 tmp[size] = 0; 1571 return (cgltf_float)atof(tmp); 1572 } 1573 1574 static cgltf_bool cgltf_json_to_bool(jsmntok_t const* tok, const uint8_t* json_chunk) 1575 { 1576 int size = tok->end - tok->start; 1577 return size == 4 && memcmp(json_chunk + tok->start, "true", 4) == 0; 1578 } 1579 1580 static int cgltf_skip_json(jsmntok_t const* tokens, int i) 1581 { 1582 if (tokens[i].type == JSMN_ARRAY) 1583 { 1584 int size = tokens[i].size; 1585 ++i; 1586 for (int j = 0; j < size; ++j) 1587 { 1588 i = cgltf_skip_json(tokens, i); 1589 if (i < 0) 1590 { 1591 return i; 1592 } 1593 } 1594 } 1595 else if (tokens[i].type == JSMN_OBJECT) 1596 { 1597 int size = tokens[i].size; 1598 ++i; 1599 for (int j = 0; j < size; ++j) 1600 { 1601 CGLTF_CHECK_KEY(tokens[i]); 1602 ++i; 1603 i = cgltf_skip_json(tokens, i); 1604 if (i < 0) 1605 { 1606 return i; 1607 } 1608 } 1609 } 1610 else if (tokens[i].type == JSMN_PRIMITIVE 1611 || tokens[i].type == JSMN_STRING) 1612 { 1613 return i + 1; 1614 } 1615 return i; 1616 } 1617 1618 static void cgltf_fill_float_array(float* out_array, int size, float value) 1619 { 1620 for (int j = 0; j < size; ++j) 1621 { 1622 out_array[j] = value; 1623 } 1624 } 1625 1626 static int cgltf_parse_json_float_array(jsmntok_t const* tokens, int i, const uint8_t* json_chunk, float* out_array, int size) 1627 { 1628 CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_ARRAY); 1629 if (tokens[i].size != size) 1630 { 1631 return CGLTF_ERROR_JSON; 1632 } 1633 ++i; 1634 for (int j = 0; j < size; ++j) 1635 { 1636 CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_PRIMITIVE); 1637 out_array[j] = cgltf_json_to_float(tokens + i, json_chunk); 1638 ++i; 1639 } 1640 return i; 1641 } 1642 1643 static int cgltf_parse_json_string(cgltf_options* options, jsmntok_t const* tokens, int i, const uint8_t* json_chunk, char** out_string) 1644 { 1645 CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_STRING); 1646 if (*out_string) 1647 { 1648 return CGLTF_ERROR_JSON; 1649 } 1650 int size = tokens[i].end - tokens[i].start; 1651 char* result = (char*)options->memory_alloc(options->memory_user_data, size + 1); 1652 if (!result) 1653 { 1654 return CGLTF_ERROR_NOMEM; 1655 } 1656 strncpy(result, (const char*)json_chunk + tokens[i].start, size); 1657 result[size] = 0; 1658 *out_string = result; 1659 return i + 1; 1660 } 1661 1662 static 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) 1663 { 1664 (void)json_chunk; 1665 CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_ARRAY); 1666 if (*out_array) 1667 { 1668 return CGLTF_ERROR_JSON; 1669 } 1670 int size = tokens[i].size; 1671 void* result = cgltf_calloc(options, element_size, size); 1672 if (!result) 1673 { 1674 return CGLTF_ERROR_NOMEM; 1675 } 1676 *out_array = result; 1677 *out_size = size; 1678 return i + 1; 1679 } 1680 1681 static void cgltf_parse_attribute_type(const char* name, cgltf_attribute_type* out_type, int* out_index) 1682 { 1683 const char* us = strchr(name, '_'); 1684 size_t len = us ? us - name : strlen(name); 1685 1686 if (len == 8 && strncmp(name, "POSITION", 8) == 0) 1687 { 1688 *out_type = cgltf_attribute_type_position; 1689 } 1690 else if (len == 6 && strncmp(name, "NORMAL", 6) == 0) 1691 { 1692 *out_type = cgltf_attribute_type_normal; 1693 } 1694 else if (len == 7 && strncmp(name, "TANGENT", 7) == 0) 1695 { 1696 *out_type = cgltf_attribute_type_tangent; 1697 } 1698 else if (len == 8 && strncmp(name, "TEXCOORD", 8) == 0) 1699 { 1700 *out_type = cgltf_attribute_type_texcoord; 1701 } 1702 else if (len == 5 && strncmp(name, "COLOR", 5) == 0) 1703 { 1704 *out_type = cgltf_attribute_type_color; 1705 } 1706 else if (len == 6 && strncmp(name, "JOINTS", 6) == 0) 1707 { 1708 *out_type = cgltf_attribute_type_joints; 1709 } 1710 else if (len == 7 && strncmp(name, "WEIGHTS", 7) == 0) 1711 { 1712 *out_type = cgltf_attribute_type_weights; 1713 } 1714 else 1715 { 1716 *out_type = cgltf_attribute_type_invalid; 1717 } 1718 1719 if (us && *out_type != cgltf_attribute_type_invalid) 1720 { 1721 *out_index = atoi(us + 1); 1722 } 1723 } 1724 1725 static 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) 1726 { 1727 CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT); 1728 1729 if (*out_attributes) 1730 { 1731 return CGLTF_ERROR_JSON; 1732 } 1733 1734 *out_attributes_count = tokens[i].size; 1735 *out_attributes = (cgltf_attribute*)cgltf_calloc(options, sizeof(cgltf_attribute), *out_attributes_count); 1736 ++i; 1737 1738 if (!*out_attributes) 1739 { 1740 return CGLTF_ERROR_NOMEM; 1741 } 1742 1743 for (cgltf_size j = 0; j < *out_attributes_count; ++j) 1744 { 1745 CGLTF_CHECK_KEY(tokens[i]); 1746 1747 i = cgltf_parse_json_string(options, tokens, i, json_chunk, &(*out_attributes)[j].name); 1748 if (i < 0) 1749 { 1750 return CGLTF_ERROR_JSON; 1751 } 1752 1753 cgltf_parse_attribute_type((*out_attributes)[j].name, &(*out_attributes)[j].type, &(*out_attributes)[j].index); 1754 1755 (*out_attributes)[j].data = CGLTF_PTRINDEX(cgltf_accessor, cgltf_json_to_int(tokens + i, json_chunk)); 1756 ++i; 1757 } 1758 1759 return i; 1760 } 1761 1762 static int cgltf_parse_json_primitive(cgltf_options* options, jsmntok_t const* tokens, int i, const uint8_t* json_chunk, cgltf_primitive* out_prim) 1763 { 1764 CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT); 1765 1766 out_prim->type = cgltf_primitive_type_triangles; 1767 1768 int size = tokens[i].size; 1769 ++i; 1770 1771 for (int j = 0; j < size; ++j) 1772 { 1773 CGLTF_CHECK_KEY(tokens[i]); 1774 1775 if (cgltf_json_strcmp(tokens+i, json_chunk, "mode") == 0) 1776 { 1777 ++i; 1778 out_prim->type 1779 = (cgltf_primitive_type) 1780 cgltf_json_to_int(tokens+i, json_chunk); 1781 ++i; 1782 } 1783 else if (cgltf_json_strcmp(tokens+i, json_chunk, "indices") == 0) 1784 { 1785 ++i; 1786 out_prim->indices = CGLTF_PTRINDEX(cgltf_accessor, cgltf_json_to_int(tokens + i, json_chunk)); 1787 ++i; 1788 } 1789 else if (cgltf_json_strcmp(tokens+i, json_chunk, "material") == 0) 1790 { 1791 ++i; 1792 out_prim->material = CGLTF_PTRINDEX(cgltf_material, cgltf_json_to_int(tokens + i, json_chunk)); 1793 ++i; 1794 } 1795 else if (cgltf_json_strcmp(tokens+i, json_chunk, "attributes") == 0) 1796 { 1797 i = cgltf_parse_json_attribute_list(options, tokens, i + 1, json_chunk, &out_prim->attributes, &out_prim->attributes_count); 1798 } 1799 else if (cgltf_json_strcmp(tokens+i, json_chunk, "targets") == 0) 1800 { 1801 i = cgltf_parse_json_array(options, tokens, i + 1, json_chunk, sizeof(cgltf_morph_target), (void**)&out_prim->targets, &out_prim->targets_count); 1802 if (i < 0) 1803 { 1804 return i; 1805 } 1806 1807 for (cgltf_size k = 0; k < out_prim->targets_count; ++k) 1808 { 1809 i = cgltf_parse_json_attribute_list(options, tokens, i, json_chunk, &out_prim->targets[k].attributes, &out_prim->targets[k].attributes_count); 1810 if (i < 0) 1811 { 1812 return i; 1813 } 1814 } 1815 } 1816 else 1817 { 1818 i = cgltf_skip_json(tokens, i+1); 1819 } 1820 1821 if (i < 0) 1822 { 1823 return i; 1824 } 1825 } 1826 1827 return i; 1828 } 1829 1830 static int cgltf_parse_json_mesh(cgltf_options* options, jsmntok_t const* tokens, int i, const uint8_t* json_chunk, cgltf_mesh* out_mesh) 1831 { 1832 CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT); 1833 1834 int size = tokens[i].size; 1835 ++i; 1836 1837 for (int j = 0; j < size; ++j) 1838 { 1839 CGLTF_CHECK_KEY(tokens[i]); 1840 1841 if (cgltf_json_strcmp(tokens+i, json_chunk, "name") == 0) 1842 { 1843 i = cgltf_parse_json_string(options, tokens, i + 1, json_chunk, &out_mesh->name); 1844 } 1845 else if (cgltf_json_strcmp(tokens+i, json_chunk, "primitives") == 0) 1846 { 1847 i = cgltf_parse_json_array(options, tokens, i + 1, json_chunk, sizeof(cgltf_primitive), (void**)&out_mesh->primitives, &out_mesh->primitives_count); 1848 if (i < 0) 1849 { 1850 return i; 1851 } 1852 1853 for (cgltf_size prim_index = 0; prim_index < out_mesh->primitives_count; ++prim_index) 1854 { 1855 i = cgltf_parse_json_primitive(options, tokens, i, json_chunk, &out_mesh->primitives[prim_index]); 1856 if (i < 0) 1857 { 1858 return i; 1859 } 1860 } 1861 } 1862 else if (cgltf_json_strcmp(tokens + i, json_chunk, "weights") == 0) 1863 { 1864 i = cgltf_parse_json_array(options, tokens, i + 1, json_chunk, sizeof(cgltf_float), (void**)&out_mesh->weights, &out_mesh->weights_count); 1865 if (i < 0) 1866 { 1867 return i; 1868 } 1869 1870 i = cgltf_parse_json_float_array(tokens, i - 1, json_chunk, out_mesh->weights, (int)out_mesh->weights_count); 1871 } 1872 else 1873 { 1874 i = cgltf_skip_json(tokens, i+1); 1875 } 1876 1877 if (i < 0) 1878 { 1879 return i; 1880 } 1881 } 1882 1883 return i; 1884 } 1885 1886 static int cgltf_parse_json_meshes(cgltf_options* options, jsmntok_t const* tokens, int i, const uint8_t* json_chunk, cgltf_data* out_data) 1887 { 1888 i = cgltf_parse_json_array(options, tokens, i, json_chunk, sizeof(cgltf_mesh), (void**)&out_data->meshes, &out_data->meshes_count); 1889 if (i < 0) 1890 { 1891 return i; 1892 } 1893 1894 for (cgltf_size j = 0; j < out_data->meshes_count; ++j) 1895 { 1896 i = cgltf_parse_json_mesh(options, tokens, i, json_chunk, &out_data->meshes[j]); 1897 if (i < 0) 1898 { 1899 return i; 1900 } 1901 } 1902 return i; 1903 } 1904 1905 static cgltf_component_type cgltf_json_to_component_type(jsmntok_t const* tok, const uint8_t* json_chunk) 1906 { 1907 int type = cgltf_json_to_int(tok, json_chunk); 1908 1909 switch (type) 1910 { 1911 case 5120: 1912 return cgltf_component_type_r_8; 1913 case 5121: 1914 return cgltf_component_type_r_8u; 1915 case 5122: 1916 return cgltf_component_type_r_16; 1917 case 5123: 1918 return cgltf_component_type_r_16u; 1919 case 5125: 1920 return cgltf_component_type_r_32u; 1921 case 5126: 1922 return cgltf_component_type_r_32f; 1923 default: 1924 return cgltf_component_type_invalid; 1925 } 1926 } 1927 1928 static int cgltf_parse_json_accessor_sparse(jsmntok_t const* tokens, int i, const uint8_t* json_chunk, cgltf_accessor_sparse* out_sparse) 1929 { 1930 CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT); 1931 1932 int size = tokens[i].size; 1933 ++i; 1934 1935 for (int j = 0; j < size; ++j) 1936 { 1937 CGLTF_CHECK_KEY(tokens[i]); 1938 1939 if (cgltf_json_strcmp(tokens+i, json_chunk, "count") == 0) 1940 { 1941 ++i; 1942 out_sparse->count = cgltf_json_to_int(tokens + i, json_chunk); 1943 ++i; 1944 } 1945 else if (cgltf_json_strcmp(tokens+i, json_chunk, "indices") == 0) 1946 { 1947 ++i; 1948 CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT); 1949 1950 int indices_size = tokens[i].size; 1951 ++i; 1952 1953 for (int k = 0; k < indices_size; ++k) 1954 { 1955 CGLTF_CHECK_KEY(tokens[i]); 1956 1957 if (cgltf_json_strcmp(tokens+i, json_chunk, "bufferView") == 0) 1958 { 1959 ++i; 1960 out_sparse->indices_buffer_view = CGLTF_PTRINDEX(cgltf_buffer_view, cgltf_json_to_int(tokens + i, json_chunk)); 1961 ++i; 1962 } 1963 else if (cgltf_json_strcmp(tokens+i, json_chunk, "byteOffset") == 0) 1964 { 1965 ++i; 1966 out_sparse->indices_byte_offset = cgltf_json_to_int(tokens + i, json_chunk); 1967 ++i; 1968 } 1969 else if (cgltf_json_strcmp(tokens+i, json_chunk, "componentType") == 0) 1970 { 1971 ++i; 1972 out_sparse->indices_component_type = cgltf_json_to_component_type(tokens + i, json_chunk); 1973 ++i; 1974 } 1975 else 1976 { 1977 i = cgltf_skip_json(tokens, i+1); 1978 } 1979 1980 if (i < 0) 1981 { 1982 return i; 1983 } 1984 } 1985 } 1986 else if (cgltf_json_strcmp(tokens+i, json_chunk, "values") == 0) 1987 { 1988 ++i; 1989 CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT); 1990 1991 int values_size = tokens[i].size; 1992 ++i; 1993 1994 for (int k = 0; k < values_size; ++k) 1995 { 1996 CGLTF_CHECK_KEY(tokens[i]); 1997 1998 if (cgltf_json_strcmp(tokens+i, json_chunk, "bufferView") == 0) 1999 { 2000 ++i; 2001 out_sparse->values_buffer_view = CGLTF_PTRINDEX(cgltf_buffer_view, cgltf_json_to_int(tokens + i, json_chunk)); 2002 ++i; 2003 } 2004 else if (cgltf_json_strcmp(tokens+i, json_chunk, "byteOffset") == 0) 2005 { 2006 ++i; 2007 out_sparse->values_byte_offset = cgltf_json_to_int(tokens + i, json_chunk); 2008 ++i; 2009 } 2010 else 2011 { 2012 i = cgltf_skip_json(tokens, i+1); 2013 } 2014 2015 if (i < 0) 2016 { 2017 return i; 2018 } 2019 } 2020 } 2021 else 2022 { 2023 i = cgltf_skip_json(tokens, i+1); 2024 } 2025 2026 if (i < 0) 2027 { 2028 return i; 2029 } 2030 } 2031 2032 return i; 2033 } 2034 2035 static int cgltf_parse_json_accessor(jsmntok_t const* tokens, int i, const uint8_t* json_chunk, cgltf_accessor* out_accessor) 2036 { 2037 CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT); 2038 2039 int size = tokens[i].size; 2040 ++i; 2041 2042 for (int j = 0; j < size; ++j) 2043 { 2044 CGLTF_CHECK_KEY(tokens[i]); 2045 2046 if (cgltf_json_strcmp(tokens+i, json_chunk, "bufferView") == 0) 2047 { 2048 ++i; 2049 out_accessor->buffer_view = CGLTF_PTRINDEX(cgltf_buffer_view, cgltf_json_to_int(tokens + i, json_chunk)); 2050 ++i; 2051 } 2052 else if (cgltf_json_strcmp(tokens+i, json_chunk, "byteOffset") == 0) 2053 { 2054 ++i; 2055 out_accessor->offset = 2056 cgltf_json_to_int(tokens+i, json_chunk); 2057 ++i; 2058 } 2059 else if (cgltf_json_strcmp(tokens+i, json_chunk, "componentType") == 0) 2060 { 2061 ++i; 2062 out_accessor->component_type = cgltf_json_to_component_type(tokens + i, json_chunk); 2063 ++i; 2064 } 2065 else if (cgltf_json_strcmp(tokens+i, json_chunk, "normalized") == 0) 2066 { 2067 ++i; 2068 out_accessor->normalized = cgltf_json_to_bool(tokens+i, json_chunk); 2069 ++i; 2070 } 2071 else if (cgltf_json_strcmp(tokens+i, json_chunk, "count") == 0) 2072 { 2073 ++i; 2074 out_accessor->count = 2075 cgltf_json_to_int(tokens+i, json_chunk); 2076 ++i; 2077 } 2078 else if (cgltf_json_strcmp(tokens+i, json_chunk, "type") == 0) 2079 { 2080 ++i; 2081 if (cgltf_json_strcmp(tokens+i, json_chunk, "SCALAR") == 0) 2082 { 2083 out_accessor->type = cgltf_type_scalar; 2084 } 2085 else if (cgltf_json_strcmp(tokens+i, json_chunk, "VEC2") == 0) 2086 { 2087 out_accessor->type = cgltf_type_vec2; 2088 } 2089 else if (cgltf_json_strcmp(tokens+i, json_chunk, "VEC3") == 0) 2090 { 2091 out_accessor->type = cgltf_type_vec3; 2092 } 2093 else if (cgltf_json_strcmp(tokens+i, json_chunk, "VEC4") == 0) 2094 { 2095 out_accessor->type = cgltf_type_vec4; 2096 } 2097 else if (cgltf_json_strcmp(tokens+i, json_chunk, "MAT2") == 0) 2098 { 2099 out_accessor->type = cgltf_type_mat2; 2100 } 2101 else if (cgltf_json_strcmp(tokens+i, json_chunk, "MAT3") == 0) 2102 { 2103 out_accessor->type = cgltf_type_mat3; 2104 } 2105 else if (cgltf_json_strcmp(tokens+i, json_chunk, "MAT4") == 0) 2106 { 2107 out_accessor->type = cgltf_type_mat4; 2108 } 2109 ++i; 2110 } 2111 else if (cgltf_json_strcmp(tokens + i, json_chunk, "min") == 0) 2112 { 2113 ++i; 2114 out_accessor->has_min = 1; 2115 // note: we can't parse the precise number of elements since type may not have been computed yet 2116 int min_size = tokens[i].size > 16 ? 16 : tokens[i].size; 2117 i = cgltf_parse_json_float_array(tokens, i, json_chunk, out_accessor->min, min_size); 2118 } 2119 else if (cgltf_json_strcmp(tokens + i, json_chunk, "max") == 0) 2120 { 2121 ++i; 2122 out_accessor->has_max = 1; 2123 // note: we can't parse the precise number of elements since type may not have been computed yet 2124 int max_size = tokens[i].size > 16 ? 16 : tokens[i].size; 2125 i = cgltf_parse_json_float_array(tokens, i, json_chunk, out_accessor->max, max_size); 2126 } 2127 else if (cgltf_json_strcmp(tokens + i, json_chunk, "sparse") == 0) 2128 { 2129 out_accessor->is_sparse = 1; 2130 i = cgltf_parse_json_accessor_sparse(tokens, i + 1, json_chunk, &out_accessor->sparse); 2131 } 2132 else 2133 { 2134 i = cgltf_skip_json(tokens, i+1); 2135 } 2136 2137 if (i < 0) 2138 { 2139 return i; 2140 } 2141 } 2142 2143 return i; 2144 } 2145 2146 static int cgltf_parse_json_texture_transform(jsmntok_t const* tokens, int i, const uint8_t* json_chunk, cgltf_texture_transform* out_texture_transform) 2147 { 2148 CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT); 2149 2150 int size = tokens[i].size; 2151 ++i; 2152 2153 for (int j = 0; j < size; ++j) 2154 { 2155 CGLTF_CHECK_KEY(tokens[i]); 2156 2157 if (cgltf_json_strcmp(tokens + i, json_chunk, "offset") == 0) 2158 { 2159 i = cgltf_parse_json_float_array(tokens, i + 1, json_chunk, out_texture_transform->offset, 2); 2160 } 2161 else if (cgltf_json_strcmp(tokens + i, json_chunk, "rotation") == 0) 2162 { 2163 ++i; 2164 out_texture_transform->rotation = cgltf_json_to_float(tokens + i, json_chunk); 2165 ++i; 2166 } 2167 else if (cgltf_json_strcmp(tokens + i, json_chunk, "scale") == 0) 2168 { 2169 i = cgltf_parse_json_float_array(tokens, i + 1, json_chunk, out_texture_transform->scale, 2); 2170 } 2171 else if (cgltf_json_strcmp(tokens + i, json_chunk, "texCoord") == 0) 2172 { 2173 ++i; 2174 out_texture_transform->texcoord = cgltf_json_to_int(tokens + i, json_chunk); 2175 ++i; 2176 } 2177 else 2178 { 2179 i = cgltf_skip_json(tokens, i + 1); 2180 } 2181 2182 if (i < 0) 2183 { 2184 return i; 2185 } 2186 } 2187 2188 return i; 2189 } 2190 2191 static int cgltf_parse_json_texture_view(jsmntok_t const* tokens, int i, const uint8_t* json_chunk, cgltf_texture_view* out_texture_view) 2192 { 2193 CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT); 2194 2195 out_texture_view->scale = 1.0f; 2196 cgltf_fill_float_array(out_texture_view->transform.scale, 2, 1.0f); 2197 2198 int size = tokens[i].size; 2199 ++i; 2200 2201 for (int j = 0; j < size; ++j) 2202 { 2203 CGLTF_CHECK_KEY(tokens[i]); 2204 2205 if (cgltf_json_strcmp(tokens + i, json_chunk, "index") == 0) 2206 { 2207 ++i; 2208 out_texture_view->texture = CGLTF_PTRINDEX(cgltf_texture, cgltf_json_to_int(tokens + i, json_chunk)); 2209 ++i; 2210 } 2211 else if (cgltf_json_strcmp(tokens + i, json_chunk, "texCoord") == 0) 2212 { 2213 ++i; 2214 out_texture_view->texcoord = cgltf_json_to_int(tokens + i, json_chunk); 2215 ++i; 2216 } 2217 else if (cgltf_json_strcmp(tokens + i, json_chunk, "scale") == 0) 2218 { 2219 ++i; 2220 out_texture_view->scale = cgltf_json_to_float(tokens + i, json_chunk); 2221 ++i; 2222 } 2223 else if (cgltf_json_strcmp(tokens + i, json_chunk, "strength") == 0) 2224 { 2225 ++i; 2226 out_texture_view->scale = cgltf_json_to_float(tokens + i, json_chunk); 2227 ++i; 2228 } 2229 else if (cgltf_json_strcmp(tokens + i, json_chunk, "extensions") == 0) 2230 { 2231 ++i; 2232 2233 CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT); 2234 2235 int extensions_size = tokens[i].size; 2236 ++i; 2237 2238 for (int k = 0; k < extensions_size; ++k) 2239 { 2240 if (cgltf_json_strcmp(tokens+i, json_chunk, "KHR_texture_transform") == 0) 2241 { 2242 out_texture_view->has_transform = 1; 2243 i = cgltf_parse_json_texture_transform(tokens, i + 1, json_chunk, &out_texture_view->transform); 2244 } 2245 else 2246 { 2247 i = cgltf_skip_json(tokens, i+1); 2248 } 2249 } 2250 } 2251 else 2252 { 2253 i = cgltf_skip_json(tokens, i + 1); 2254 } 2255 2256 if (i < 0) 2257 { 2258 return i; 2259 } 2260 } 2261 2262 return i; 2263 } 2264 2265 static int cgltf_parse_json_pbr_metallic_roughness(jsmntok_t const* tokens, int i, const uint8_t* json_chunk, cgltf_pbr_metallic_roughness* out_pbr) 2266 { 2267 CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT); 2268 2269 int size = tokens[i].size; 2270 ++i; 2271 2272 for (int j = 0; j < size; ++j) 2273 { 2274 CGLTF_CHECK_KEY(tokens[i]); 2275 2276 if (cgltf_json_strcmp(tokens+i, json_chunk, "metallicFactor") == 0) 2277 { 2278 ++i; 2279 out_pbr->metallic_factor = 2280 cgltf_json_to_float(tokens + i, json_chunk); 2281 ++i; 2282 } 2283 else if (cgltf_json_strcmp(tokens+i, json_chunk, "roughnessFactor") == 0) 2284 { 2285 ++i; 2286 out_pbr->roughness_factor = 2287 cgltf_json_to_float(tokens+i, json_chunk); 2288 ++i; 2289 } 2290 else if (cgltf_json_strcmp(tokens+i, json_chunk, "baseColorFactor") == 0) 2291 { 2292 i = cgltf_parse_json_float_array(tokens, i + 1, json_chunk, out_pbr->base_color_factor, 4); 2293 } 2294 else if (cgltf_json_strcmp(tokens+i, json_chunk, "baseColorTexture") == 0) 2295 { 2296 i = cgltf_parse_json_texture_view(tokens, i + 1, json_chunk, 2297 &out_pbr->base_color_texture); 2298 } 2299 else if (cgltf_json_strcmp(tokens + i, json_chunk, "metallicRoughnessTexture") == 0) 2300 { 2301 i = cgltf_parse_json_texture_view(tokens, i + 1, json_chunk, 2302 &out_pbr->metallic_roughness_texture); 2303 } 2304 else 2305 { 2306 i = cgltf_skip_json(tokens, i+1); 2307 } 2308 2309 if (i < 0) 2310 { 2311 return i; 2312 } 2313 } 2314 2315 return i; 2316 } 2317 2318 static int cgltf_parse_json_pbr_specular_glossiness(jsmntok_t const* tokens, int i, const uint8_t* json_chunk, cgltf_pbr_specular_glossiness* out_pbr) 2319 { 2320 CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT); 2321 int size = tokens[i].size; 2322 ++i; 2323 2324 for (int j = 0; j < size; ++j) 2325 { 2326 CGLTF_CHECK_KEY(tokens[i]); 2327 2328 if (cgltf_json_strcmp(tokens+i, json_chunk, "diffuseFactor") == 0) 2329 { 2330 i = cgltf_parse_json_float_array(tokens, i + 1, json_chunk, out_pbr->diffuse_factor, 4); 2331 if (i < 0) 2332 { 2333 return i; 2334 } 2335 } 2336 else if (cgltf_json_strcmp(tokens+i, json_chunk, "specularFactor") == 0) 2337 { 2338 i = cgltf_parse_json_float_array(tokens, i + 1, json_chunk, out_pbr->specular_factor, 3); 2339 if (i < 0) 2340 { 2341 return i; 2342 } 2343 } 2344 else if (cgltf_json_strcmp(tokens+i, json_chunk, "glossinessFactor") == 0) 2345 { 2346 ++i; 2347 out_pbr->glossiness_factor = cgltf_json_to_float(tokens + i, json_chunk); 2348 ++i; 2349 } 2350 else if (cgltf_json_strcmp(tokens+i, json_chunk, "diffuseTexture") == 0) 2351 { 2352 i = cgltf_parse_json_texture_view(tokens, i + 1, json_chunk, &out_pbr->diffuse_texture); 2353 if (i < 0) 2354 { 2355 return i; 2356 } 2357 } 2358 else if (cgltf_json_strcmp(tokens+i, json_chunk, "specularGlossinessTexture") == 0) 2359 { 2360 i = cgltf_parse_json_texture_view(tokens, i + 1, json_chunk, &out_pbr->specular_glossiness_texture); 2361 if (i < 0) 2362 { 2363 return i; 2364 } 2365 } 2366 else 2367 { 2368 i = cgltf_skip_json(tokens, i+1); 2369 } 2370 2371 if (i < 0) 2372 { 2373 return i; 2374 } 2375 2376 } 2377 2378 return i; 2379 } 2380 2381 static int cgltf_parse_json_image(cgltf_options* options, jsmntok_t const* tokens, int i, const uint8_t* json_chunk, cgltf_image* out_image) 2382 { 2383 CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT); 2384 2385 int size = tokens[i].size; 2386 ++i; 2387 2388 for (int j = 0; j < size; ++j) 2389 { 2390 CGLTF_CHECK_KEY(tokens[i]); 2391 2392 if (cgltf_json_strcmp(tokens + i, json_chunk, "uri") == 0) 2393 { 2394 i = cgltf_parse_json_string(options, tokens, i + 1, json_chunk, &out_image->uri); 2395 } 2396 else if (cgltf_json_strcmp(tokens+i, json_chunk, "bufferView") == 0) 2397 { 2398 ++i; 2399 out_image->buffer_view = CGLTF_PTRINDEX(cgltf_buffer_view, cgltf_json_to_int(tokens + i, json_chunk)); 2400 ++i; 2401 } 2402 else if (cgltf_json_strcmp(tokens + i, json_chunk, "mimeType") == 0) 2403 { 2404 i = cgltf_parse_json_string(options, tokens, i + 1, json_chunk, &out_image->mime_type); 2405 } 2406 else if (cgltf_json_strcmp(tokens + i, json_chunk, "name") == 0) 2407 { 2408 i = cgltf_parse_json_string(options, tokens, i + 1, json_chunk, &out_image->name); 2409 } 2410 else 2411 { 2412 i = cgltf_skip_json(tokens, i + 1); 2413 } 2414 2415 if (i < 0) 2416 { 2417 return i; 2418 } 2419 } 2420 2421 return i; 2422 } 2423 2424 static int cgltf_parse_json_sampler(cgltf_options* options, jsmntok_t const* tokens, int i, const uint8_t* json_chunk, cgltf_sampler* out_sampler) 2425 { 2426 (void)options; 2427 CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT); 2428 2429 out_sampler->wrap_s = 10497; 2430 out_sampler->wrap_t = 10497; 2431 2432 int size = tokens[i].size; 2433 ++i; 2434 2435 for (int j = 0; j < size; ++j) 2436 { 2437 CGLTF_CHECK_KEY(tokens[i]); 2438 2439 if (cgltf_json_strcmp(tokens + i, json_chunk, "magFilter") == 0) 2440 { 2441 ++i; 2442 out_sampler->mag_filter 2443 = cgltf_json_to_int(tokens + i, json_chunk); 2444 ++i; 2445 } 2446 else if (cgltf_json_strcmp(tokens + i, json_chunk, "minFilter") == 0) 2447 { 2448 ++i; 2449 out_sampler->min_filter 2450 = cgltf_json_to_int(tokens + i, json_chunk); 2451 ++i; 2452 } 2453 else if (cgltf_json_strcmp(tokens + i, json_chunk, "wrapS") == 0) 2454 { 2455 ++i; 2456 out_sampler->wrap_s 2457 = cgltf_json_to_int(tokens + i, json_chunk); 2458 ++i; 2459 } 2460 else if (cgltf_json_strcmp(tokens + i, json_chunk, "wrapT") == 0) 2461 { 2462 ++i; 2463 out_sampler->wrap_t 2464 = cgltf_json_to_int(tokens + i, json_chunk); 2465 ++i; 2466 } 2467 else 2468 { 2469 i = cgltf_skip_json(tokens, i + 1); 2470 } 2471 2472 if (i < 0) 2473 { 2474 return i; 2475 } 2476 } 2477 2478 return i; 2479 } 2480 2481 2482 static int cgltf_parse_json_texture(cgltf_options* options, jsmntok_t const* tokens, int i, const uint8_t* json_chunk, cgltf_texture* out_texture) 2483 { 2484 CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT); 2485 2486 int size = tokens[i].size; 2487 ++i; 2488 2489 for (int j = 0; j < size; ++j) 2490 { 2491 CGLTF_CHECK_KEY(tokens[i]); 2492 2493 if (cgltf_json_strcmp(tokens+i, json_chunk, "name") == 0) 2494 { 2495 i = cgltf_parse_json_string(options, tokens, i + 1, json_chunk, &out_texture->name); 2496 } 2497 else if (cgltf_json_strcmp(tokens + i, json_chunk, "sampler") == 0) 2498 { 2499 ++i; 2500 out_texture->sampler = CGLTF_PTRINDEX(cgltf_sampler, cgltf_json_to_int(tokens + i, json_chunk)); 2501 ++i; 2502 } 2503 else if (cgltf_json_strcmp(tokens + i, json_chunk, "source") == 0) 2504 { 2505 ++i; 2506 out_texture->image = CGLTF_PTRINDEX(cgltf_image, cgltf_json_to_int(tokens + i, json_chunk)); 2507 ++i; 2508 } 2509 else 2510 { 2511 i = cgltf_skip_json(tokens, i + 1); 2512 } 2513 2514 if (i < 0) 2515 { 2516 return i; 2517 } 2518 } 2519 2520 return i; 2521 } 2522 2523 static int cgltf_parse_json_material(cgltf_options* options, jsmntok_t const* tokens, int i, const uint8_t* json_chunk, cgltf_material* out_material) 2524 { 2525 CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT); 2526 2527 cgltf_fill_float_array(out_material->pbr_metallic_roughness.base_color_factor, 4, 1.0f); 2528 out_material->pbr_metallic_roughness.metallic_factor = 1.0f; 2529 out_material->pbr_metallic_roughness.roughness_factor = 1.0f; 2530 2531 cgltf_fill_float_array(out_material->pbr_specular_glossiness.diffuse_factor, 4, 1.0f); 2532 cgltf_fill_float_array(out_material->pbr_specular_glossiness.specular_factor, 3, 1.0f); 2533 out_material->pbr_specular_glossiness.glossiness_factor = 1.0f; 2534 2535 out_material->alpha_cutoff = 0.5f; 2536 2537 int size = tokens[i].size; 2538 ++i; 2539 2540 for (int j = 0; j < size; ++j) 2541 { 2542 CGLTF_CHECK_KEY(tokens[i]); 2543 2544 if (cgltf_json_strcmp(tokens+i, json_chunk, "name") == 0) 2545 { 2546 i = cgltf_parse_json_string(options, tokens, i + 1, json_chunk, &out_material->name); 2547 } 2548 else if (cgltf_json_strcmp(tokens+i, json_chunk, "pbrMetallicRoughness") == 0) 2549 { 2550 out_material->has_pbr_metallic_roughness = 1; 2551 i = cgltf_parse_json_pbr_metallic_roughness(tokens, i + 1, json_chunk, &out_material->pbr_metallic_roughness); 2552 } 2553 else if (cgltf_json_strcmp(tokens+i, json_chunk, "emissiveFactor") == 0) 2554 { 2555 i = cgltf_parse_json_float_array(tokens, i + 1, json_chunk, out_material->emissive_factor, 3); 2556 } 2557 else if (cgltf_json_strcmp(tokens + i, json_chunk, "normalTexture") == 0) 2558 { 2559 i = cgltf_parse_json_texture_view(tokens, i + 1, json_chunk, 2560 &out_material->normal_texture); 2561 } 2562 else if (cgltf_json_strcmp(tokens + i, json_chunk, "occlusionTexture") == 0) 2563 { 2564 i = cgltf_parse_json_texture_view(tokens, i + 1, json_chunk, 2565 &out_material->occlusion_texture); 2566 } 2567 else if (cgltf_json_strcmp(tokens + i, json_chunk, "emissiveTexture") == 0) 2568 { 2569 i = cgltf_parse_json_texture_view(tokens, i + 1, json_chunk, 2570 &out_material->emissive_texture); 2571 } 2572 else if (cgltf_json_strcmp(tokens + i, json_chunk, "alphaMode") == 0) 2573 { 2574 ++i; 2575 if (cgltf_json_strcmp(tokens + i, json_chunk, "OPAQUE") == 0) 2576 { 2577 out_material->alpha_mode = cgltf_alpha_mode_opaque; 2578 } 2579 else if (cgltf_json_strcmp(tokens + i, json_chunk, "MASK") == 0) 2580 { 2581 out_material->alpha_mode = cgltf_alpha_mode_mask; 2582 } 2583 else if (cgltf_json_strcmp(tokens + i, json_chunk, "BLEND") == 0) 2584 { 2585 out_material->alpha_mode = cgltf_alpha_mode_blend; 2586 } 2587 ++i; 2588 } 2589 else if (cgltf_json_strcmp(tokens + i, json_chunk, "alphaCutoff") == 0) 2590 { 2591 ++i; 2592 out_material->alpha_cutoff = cgltf_json_to_float(tokens + i, json_chunk); 2593 ++i; 2594 } 2595 else if (cgltf_json_strcmp(tokens + i, json_chunk, "doubleSided") == 0) 2596 { 2597 ++i; 2598 out_material->double_sided = 2599 cgltf_json_to_bool(tokens + i, json_chunk); 2600 ++i; 2601 } 2602 else if (cgltf_json_strcmp(tokens + i, json_chunk, "extensions") == 0) 2603 { 2604 ++i; 2605 2606 CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT); 2607 2608 int extensions_size = tokens[i].size; 2609 ++i; 2610 2611 for (int k = 0; k < extensions_size; ++k) 2612 { 2613 CGLTF_CHECK_KEY(tokens[i]); 2614 2615 if (cgltf_json_strcmp(tokens+i, json_chunk, "KHR_materials_pbrSpecularGlossiness") == 0) 2616 { 2617 out_material->has_pbr_specular_glossiness = 1; 2618 i = cgltf_parse_json_pbr_specular_glossiness(tokens, i + 1, json_chunk, &out_material->pbr_specular_glossiness); 2619 } 2620 else if (cgltf_json_strcmp(tokens+i, json_chunk, "KHR_materials_unlit") == 0) 2621 { 2622 out_material->unlit = 1; 2623 i = cgltf_skip_json(tokens, i+1); 2624 } 2625 else 2626 { 2627 i = cgltf_skip_json(tokens, i+1); 2628 } 2629 2630 if (i < 0) 2631 { 2632 return i; 2633 } 2634 } 2635 } 2636 else 2637 { 2638 i = cgltf_skip_json(tokens, i+1); 2639 } 2640 2641 if (i < 0) 2642 { 2643 return i; 2644 } 2645 } 2646 2647 return i; 2648 } 2649 2650 static int cgltf_parse_json_accessors(cgltf_options* options, jsmntok_t const* tokens, int i, const uint8_t* json_chunk, cgltf_data* out_data) 2651 { 2652 i = cgltf_parse_json_array(options, tokens, i, json_chunk, sizeof(cgltf_accessor), (void**)&out_data->accessors, &out_data->accessors_count); 2653 if (i < 0) 2654 { 2655 return i; 2656 } 2657 2658 for (cgltf_size j = 0; j < out_data->accessors_count; ++j) 2659 { 2660 i = cgltf_parse_json_accessor(tokens, i, json_chunk, &out_data->accessors[j]); 2661 if (i < 0) 2662 { 2663 return i; 2664 } 2665 } 2666 return i; 2667 } 2668 2669 static int cgltf_parse_json_materials(cgltf_options* options, jsmntok_t const* tokens, int i, const uint8_t* json_chunk, cgltf_data* out_data) 2670 { 2671 i = cgltf_parse_json_array(options, tokens, i, json_chunk, sizeof(cgltf_material), (void**)&out_data->materials, &out_data->materials_count); 2672 if (i < 0) 2673 { 2674 return i; 2675 } 2676 2677 for (cgltf_size j = 0; j < out_data->materials_count; ++j) 2678 { 2679 i = cgltf_parse_json_material(options, tokens, i, json_chunk, &out_data->materials[j]); 2680 if (i < 0) 2681 { 2682 return i; 2683 } 2684 } 2685 return i; 2686 } 2687 2688 static int cgltf_parse_json_images(cgltf_options* options, jsmntok_t const* tokens, int i, const uint8_t* json_chunk, cgltf_data* out_data) 2689 { 2690 i = cgltf_parse_json_array(options, tokens, i, json_chunk, sizeof(cgltf_image), (void**)&out_data->images, &out_data->images_count); 2691 if (i < 0) 2692 { 2693 return i; 2694 } 2695 2696 for (cgltf_size j = 0; j < out_data->images_count; ++j) 2697 { 2698 i = cgltf_parse_json_image(options, tokens, i, json_chunk, &out_data->images[j]); 2699 if (i < 0) 2700 { 2701 return i; 2702 } 2703 } 2704 return i; 2705 } 2706 2707 static int cgltf_parse_json_textures(cgltf_options* options, jsmntok_t const* tokens, int i, const uint8_t* json_chunk, cgltf_data* out_data) 2708 { 2709 i = cgltf_parse_json_array(options, tokens, i, json_chunk, sizeof(cgltf_texture), (void**)&out_data->textures, &out_data->textures_count); 2710 if (i < 0) 2711 { 2712 return i; 2713 } 2714 2715 for (cgltf_size j = 0; j < out_data->textures_count; ++j) 2716 { 2717 i = cgltf_parse_json_texture(options, tokens, i, json_chunk, &out_data->textures[j]); 2718 if (i < 0) 2719 { 2720 return i; 2721 } 2722 } 2723 return i; 2724 } 2725 2726 static int cgltf_parse_json_samplers(cgltf_options* options, jsmntok_t const* tokens, int i, const uint8_t* json_chunk, cgltf_data* out_data) 2727 { 2728 i = cgltf_parse_json_array(options, tokens, i, json_chunk, sizeof(cgltf_sampler), (void**)&out_data->samplers, &out_data->samplers_count); 2729 if (i < 0) 2730 { 2731 return i; 2732 } 2733 2734 for (cgltf_size j = 0; j < out_data->samplers_count; ++j) 2735 { 2736 i = cgltf_parse_json_sampler(options, tokens, i, json_chunk, &out_data->samplers[j]); 2737 if (i < 0) 2738 { 2739 return i; 2740 } 2741 } 2742 return i; 2743 } 2744 2745 static int cgltf_parse_json_buffer_view(jsmntok_t const* tokens, int i, const uint8_t* json_chunk, cgltf_buffer_view* out_buffer_view) 2746 { 2747 CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT); 2748 2749 int size = tokens[i].size; 2750 ++i; 2751 2752 for (int j = 0; j < size; ++j) 2753 { 2754 CGLTF_CHECK_KEY(tokens[i]); 2755 2756 if (cgltf_json_strcmp(tokens+i, json_chunk, "buffer") == 0) 2757 { 2758 ++i; 2759 out_buffer_view->buffer = CGLTF_PTRINDEX(cgltf_buffer, cgltf_json_to_int(tokens + i, json_chunk)); 2760 ++i; 2761 } 2762 else if (cgltf_json_strcmp(tokens+i, json_chunk, "byteOffset") == 0) 2763 { 2764 ++i; 2765 out_buffer_view->offset = 2766 cgltf_json_to_int(tokens+i, json_chunk); 2767 ++i; 2768 } 2769 else if (cgltf_json_strcmp(tokens+i, json_chunk, "byteLength") == 0) 2770 { 2771 ++i; 2772 out_buffer_view->size = 2773 cgltf_json_to_int(tokens+i, json_chunk); 2774 ++i; 2775 } 2776 else if (cgltf_json_strcmp(tokens+i, json_chunk, "byteStride") == 0) 2777 { 2778 ++i; 2779 out_buffer_view->stride = 2780 cgltf_json_to_int(tokens+i, json_chunk); 2781 ++i; 2782 } 2783 else if (cgltf_json_strcmp(tokens+i, json_chunk, "target") == 0) 2784 { 2785 ++i; 2786 int type = cgltf_json_to_int(tokens+i, json_chunk); 2787 switch (type) 2788 { 2789 case 34962: 2790 type = cgltf_buffer_view_type_vertices; 2791 break; 2792 case 34963: 2793 type = cgltf_buffer_view_type_indices; 2794 break; 2795 default: 2796 type = cgltf_buffer_view_type_invalid; 2797 break; 2798 } 2799 out_buffer_view->type = (cgltf_buffer_view_type)type; 2800 ++i; 2801 } 2802 else 2803 { 2804 i = cgltf_skip_json(tokens, i+1); 2805 } 2806 2807 if (i < 0) 2808 { 2809 return i; 2810 } 2811 } 2812 2813 return i; 2814 } 2815 2816 static int cgltf_parse_json_buffer_views(cgltf_options* options, jsmntok_t const* tokens, int i, const uint8_t* json_chunk, cgltf_data* out_data) 2817 { 2818 i = cgltf_parse_json_array(options, tokens, i, json_chunk, sizeof(cgltf_buffer_view), (void**)&out_data->buffer_views, &out_data->buffer_views_count); 2819 if (i < 0) 2820 { 2821 return i; 2822 } 2823 2824 for (cgltf_size j = 0; j < out_data->buffer_views_count; ++j) 2825 { 2826 i = cgltf_parse_json_buffer_view(tokens, i, json_chunk, &out_data->buffer_views[j]); 2827 if (i < 0) 2828 { 2829 return i; 2830 } 2831 } 2832 return i; 2833 } 2834 2835 static int cgltf_parse_json_buffer(cgltf_options* options, jsmntok_t const* tokens, int i, const uint8_t* json_chunk, cgltf_buffer* out_buffer) 2836 { 2837 CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT); 2838 2839 int size = tokens[i].size; 2840 ++i; 2841 2842 for (int j = 0; j < size; ++j) 2843 { 2844 CGLTF_CHECK_KEY(tokens[i]); 2845 2846 if (cgltf_json_strcmp(tokens+i, json_chunk, "byteLength") == 0) 2847 { 2848 ++i; 2849 out_buffer->size = 2850 cgltf_json_to_int(tokens+i, json_chunk); 2851 ++i; 2852 } 2853 else if (cgltf_json_strcmp(tokens+i, json_chunk, "uri") == 0) 2854 { 2855 i = cgltf_parse_json_string(options, tokens, i + 1, json_chunk, &out_buffer->uri); 2856 } 2857 else 2858 { 2859 i = cgltf_skip_json(tokens, i+1); 2860 } 2861 2862 if (i < 0) 2863 { 2864 return i; 2865 } 2866 } 2867 2868 return i; 2869 } 2870 2871 static int cgltf_parse_json_buffers(cgltf_options* options, jsmntok_t const* tokens, int i, const uint8_t* json_chunk, cgltf_data* out_data) 2872 { 2873 i = cgltf_parse_json_array(options, tokens, i, json_chunk, sizeof(cgltf_buffer), (void**)&out_data->buffers, &out_data->buffers_count); 2874 if (i < 0) 2875 { 2876 return i; 2877 } 2878 2879 for (cgltf_size j = 0; j < out_data->buffers_count; ++j) 2880 { 2881 i = cgltf_parse_json_buffer(options, tokens, i, json_chunk, &out_data->buffers[j]); 2882 if (i < 0) 2883 { 2884 return i; 2885 } 2886 } 2887 return i; 2888 } 2889 2890 static int cgltf_parse_json_skin(cgltf_options* options, jsmntok_t const* tokens, int i, const uint8_t* json_chunk, cgltf_skin* out_skin) 2891 { 2892 CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT); 2893 2894 int size = tokens[i].size; 2895 ++i; 2896 2897 for (int j = 0; j < size; ++j) 2898 { 2899 CGLTF_CHECK_KEY(tokens[i]); 2900 2901 if (cgltf_json_strcmp(tokens+i, json_chunk, "name") == 0) 2902 { 2903 i = cgltf_parse_json_string(options, tokens, i + 1, json_chunk, &out_skin->name); 2904 } 2905 else if (cgltf_json_strcmp(tokens+i, json_chunk, "joints") == 0) 2906 { 2907 i = cgltf_parse_json_array(options, tokens, i + 1, json_chunk, sizeof(cgltf_node*), (void**)&out_skin->joints, &out_skin->joints_count); 2908 if (i < 0) 2909 { 2910 return i; 2911 } 2912 2913 for (cgltf_size k = 0; k < out_skin->joints_count; ++k) 2914 { 2915 out_skin->joints[k] = CGLTF_PTRINDEX(cgltf_node, cgltf_json_to_int(tokens + i, json_chunk)); 2916 ++i; 2917 } 2918 } 2919 else if (cgltf_json_strcmp(tokens+i, json_chunk, "skeleton") == 0) 2920 { 2921 ++i; 2922 CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_PRIMITIVE); 2923 out_skin->skeleton = CGLTF_PTRINDEX(cgltf_node, cgltf_json_to_int(tokens + i, json_chunk)); 2924 ++i; 2925 } 2926 else if (cgltf_json_strcmp(tokens+i, json_chunk, "inverseBindMatrices") == 0) 2927 { 2928 ++i; 2929 CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_PRIMITIVE); 2930 out_skin->inverse_bind_matrices = CGLTF_PTRINDEX(cgltf_accessor, cgltf_json_to_int(tokens + i, json_chunk)); 2931 ++i; 2932 } 2933 else 2934 { 2935 i = cgltf_skip_json(tokens, i+1); 2936 } 2937 2938 if (i < 0) 2939 { 2940 return i; 2941 } 2942 } 2943 2944 return i; 2945 } 2946 2947 static int cgltf_parse_json_skins(cgltf_options* options, jsmntok_t const* tokens, int i, const uint8_t* json_chunk, cgltf_data* out_data) 2948 { 2949 i = cgltf_parse_json_array(options, tokens, i, json_chunk, sizeof(cgltf_skin), (void**)&out_data->skins, &out_data->skins_count); 2950 if (i < 0) 2951 { 2952 return i; 2953 } 2954 2955 for (cgltf_size j = 0; j < out_data->skins_count; ++j) 2956 { 2957 i = cgltf_parse_json_skin(options, tokens, i, json_chunk, &out_data->skins[j]); 2958 if (i < 0) 2959 { 2960 return i; 2961 } 2962 } 2963 return i; 2964 } 2965 2966 static int cgltf_parse_json_camera(cgltf_options* options, jsmntok_t const* tokens, int i, const uint8_t* json_chunk, cgltf_camera* out_camera) 2967 { 2968 CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT); 2969 2970 int size = tokens[i].size; 2971 ++i; 2972 2973 for (int j = 0; j < size; ++j) 2974 { 2975 CGLTF_CHECK_KEY(tokens[i]); 2976 2977 if (cgltf_json_strcmp(tokens+i, json_chunk, "name") == 0) 2978 { 2979 i = cgltf_parse_json_string(options, tokens, i + 1, json_chunk, &out_camera->name); 2980 } 2981 else if (cgltf_json_strcmp(tokens+i, json_chunk, "type") == 0) 2982 { 2983 ++i; 2984 if (cgltf_json_strcmp(tokens + i, json_chunk, "perspective") == 0) 2985 { 2986 out_camera->type = cgltf_camera_type_perspective; 2987 } 2988 else if (cgltf_json_strcmp(tokens + i, json_chunk, "orthographic") == 0) 2989 { 2990 out_camera->type = cgltf_camera_type_orthographic; 2991 } 2992 ++i; 2993 } 2994 else if (cgltf_json_strcmp(tokens+i, json_chunk, "perspective") == 0) 2995 { 2996 ++i; 2997 2998 CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT); 2999 3000 int data_size = tokens[i].size; 3001 ++i; 3002 3003 out_camera->type = cgltf_camera_type_perspective; 3004 3005 for (int k = 0; k < data_size; ++k) 3006 { 3007 CGLTF_CHECK_KEY(tokens[i]); 3008 3009 if (cgltf_json_strcmp(tokens+i, json_chunk, "aspectRatio") == 0) 3010 { 3011 ++i; 3012 out_camera->perspective.aspect_ratio = cgltf_json_to_float(tokens + i, json_chunk); 3013 ++i; 3014 } 3015 else if (cgltf_json_strcmp(tokens+i, json_chunk, "yfov") == 0) 3016 { 3017 ++i; 3018 out_camera->perspective.yfov = cgltf_json_to_float(tokens + i, json_chunk); 3019 ++i; 3020 } 3021 else if (cgltf_json_strcmp(tokens+i, json_chunk, "zfar") == 0) 3022 { 3023 ++i; 3024 out_camera->perspective.zfar = cgltf_json_to_float(tokens + i, json_chunk); 3025 ++i; 3026 } 3027 else if (cgltf_json_strcmp(tokens+i, json_chunk, "znear") == 0) 3028 { 3029 ++i; 3030 out_camera->perspective.znear = cgltf_json_to_float(tokens + i, json_chunk); 3031 ++i; 3032 } 3033 else 3034 { 3035 i = cgltf_skip_json(tokens, i+1); 3036 } 3037 3038 if (i < 0) 3039 { 3040 return i; 3041 } 3042 } 3043 } 3044 else if (cgltf_json_strcmp(tokens+i, json_chunk, "orthographic") == 0) 3045 { 3046 ++i; 3047 3048 CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT); 3049 3050 int data_size = tokens[i].size; 3051 ++i; 3052 3053 out_camera->type = cgltf_camera_type_orthographic; 3054 3055 for (int k = 0; k < data_size; ++k) 3056 { 3057 CGLTF_CHECK_KEY(tokens[i]); 3058 3059 if (cgltf_json_strcmp(tokens+i, json_chunk, "xmag") == 0) 3060 { 3061 ++i; 3062 out_camera->orthographic.xmag = cgltf_json_to_float(tokens + i, json_chunk); 3063 ++i; 3064 } 3065 else if (cgltf_json_strcmp(tokens+i, json_chunk, "ymag") == 0) 3066 { 3067 ++i; 3068 out_camera->orthographic.ymag = cgltf_json_to_float(tokens + i, json_chunk); 3069 ++i; 3070 } 3071 else if (cgltf_json_strcmp(tokens+i, json_chunk, "zfar") == 0) 3072 { 3073 ++i; 3074 out_camera->orthographic.zfar = cgltf_json_to_float(tokens + i, json_chunk); 3075 ++i; 3076 } 3077 else if (cgltf_json_strcmp(tokens+i, json_chunk, "znear") == 0) 3078 { 3079 ++i; 3080 out_camera->orthographic.znear = cgltf_json_to_float(tokens + i, json_chunk); 3081 ++i; 3082 } 3083 else 3084 { 3085 i = cgltf_skip_json(tokens, i+1); 3086 } 3087 3088 if (i < 0) 3089 { 3090 return i; 3091 } 3092 } 3093 } 3094 else 3095 { 3096 i = cgltf_skip_json(tokens, i+1); 3097 } 3098 3099 if (i < 0) 3100 { 3101 return i; 3102 } 3103 } 3104 3105 return i; 3106 } 3107 3108 static int cgltf_parse_json_cameras(cgltf_options* options, jsmntok_t const* tokens, int i, const uint8_t* json_chunk, cgltf_data* out_data) 3109 { 3110 i = cgltf_parse_json_array(options, tokens, i, json_chunk, sizeof(cgltf_camera), (void**)&out_data->cameras, &out_data->cameras_count); 3111 if (i < 0) 3112 { 3113 return i; 3114 } 3115 3116 for (cgltf_size j = 0; j < out_data->cameras_count; ++j) 3117 { 3118 i = cgltf_parse_json_camera(options, tokens, i, json_chunk, &out_data->cameras[j]); 3119 if (i < 0) 3120 { 3121 return i; 3122 } 3123 } 3124 return i; 3125 } 3126 3127 static int cgltf_parse_json_light(cgltf_options* options, jsmntok_t const* tokens, int i, const uint8_t* json_chunk, cgltf_light* out_light) 3128 { 3129 CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT); 3130 3131 int size = tokens[i].size; 3132 ++i; 3133 3134 for (int j = 0; j < size; ++j) 3135 { 3136 CGLTF_CHECK_KEY(tokens[i]); 3137 3138 if (cgltf_json_strcmp(tokens+i, json_chunk, "name") == 0) 3139 { 3140 i = cgltf_parse_json_string(options, tokens, i + 1, json_chunk, &out_light->name); 3141 } 3142 else if (cgltf_json_strcmp(tokens + i, json_chunk, "color") == 0) 3143 { 3144 i = cgltf_parse_json_float_array(tokens, i + 1, json_chunk, out_light->color, 3); 3145 } 3146 else if (cgltf_json_strcmp(tokens + i, json_chunk, "intensity") == 0) 3147 { 3148 ++i; 3149 out_light->intensity = cgltf_json_to_float(tokens + i, json_chunk); 3150 ++i; 3151 } 3152 else if (cgltf_json_strcmp(tokens+i, json_chunk, "type") == 0) 3153 { 3154 ++i; 3155 if (cgltf_json_strcmp(tokens + i, json_chunk, "directional") == 0) 3156 { 3157 out_light->type = cgltf_light_type_directional; 3158 } 3159 else if (cgltf_json_strcmp(tokens + i, json_chunk, "point") == 0) 3160 { 3161 out_light->type = cgltf_light_type_point; 3162 } 3163 else if (cgltf_json_strcmp(tokens + i, json_chunk, "spot") == 0) 3164 { 3165 out_light->type = cgltf_light_type_spot; 3166 } 3167 ++i; 3168 } 3169 else if (cgltf_json_strcmp(tokens + i, json_chunk, "range") == 0) 3170 { 3171 ++i; 3172 out_light->range = cgltf_json_to_float(tokens + i, json_chunk); 3173 ++i; 3174 } 3175 else if (cgltf_json_strcmp(tokens+i, json_chunk, "spot") == 0) 3176 { 3177 ++i; 3178 3179 CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT); 3180 3181 int data_size = tokens[i].size; 3182 ++i; 3183 3184 for (int k = 0; k < data_size; ++k) 3185 { 3186 CGLTF_CHECK_KEY(tokens[i]); 3187 3188 if (cgltf_json_strcmp(tokens+i, json_chunk, "innerConeAngle") == 0) 3189 { 3190 ++i; 3191 out_light->spot_inner_cone_angle = cgltf_json_to_float(tokens + i, json_chunk); 3192 ++i; 3193 } 3194 else if (cgltf_json_strcmp(tokens+i, json_chunk, "outerConeAngle") == 0) 3195 { 3196 ++i; 3197 out_light->spot_outer_cone_angle = cgltf_json_to_float(tokens + i, json_chunk); 3198 ++i; 3199 } 3200 else 3201 { 3202 i = cgltf_skip_json(tokens, i+1); 3203 } 3204 3205 if (i < 0) 3206 { 3207 return i; 3208 } 3209 } 3210 } 3211 else 3212 { 3213 i = cgltf_skip_json(tokens, i+1); 3214 } 3215 3216 if (i < 0) 3217 { 3218 return i; 3219 } 3220 } 3221 3222 return i; 3223 } 3224 3225 static int cgltf_parse_json_lights(cgltf_options* options, jsmntok_t const* tokens, int i, const uint8_t* json_chunk, cgltf_data* out_data) 3226 { 3227 i = cgltf_parse_json_array(options, tokens, i, json_chunk, sizeof(cgltf_light), (void**)&out_data->lights, &out_data->lights_count); 3228 if (i < 0) 3229 { 3230 return i; 3231 } 3232 3233 for (cgltf_size j = 0; j < out_data->lights_count; ++j) 3234 { 3235 i = cgltf_parse_json_light(options, tokens, i, json_chunk, &out_data->lights[j]); 3236 if (i < 0) 3237 { 3238 return i; 3239 } 3240 } 3241 return i; 3242 } 3243 3244 static int cgltf_parse_json_node(cgltf_options* options, jsmntok_t const* tokens, int i, const uint8_t* json_chunk, cgltf_node* out_node) 3245 { 3246 CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT); 3247 3248 out_node->rotation[3] = 1.0f; 3249 out_node->scale[0] = 1.0f; 3250 out_node->scale[1] = 1.0f; 3251 out_node->scale[2] = 1.0f; 3252 out_node->matrix[0] = 1.0f; 3253 out_node->matrix[5] = 1.0f; 3254 out_node->matrix[10] = 1.0f; 3255 out_node->matrix[15] = 1.0f; 3256 3257 int size = tokens[i].size; 3258 ++i; 3259 3260 for (int j = 0; j < size; ++j) 3261 { 3262 CGLTF_CHECK_KEY(tokens[i]); 3263 3264 if (cgltf_json_strcmp(tokens+i, json_chunk, "name") == 0) 3265 { 3266 i = cgltf_parse_json_string(options, tokens, i + 1, json_chunk, &out_node->name); 3267 } 3268 else if (cgltf_json_strcmp(tokens+i, json_chunk, "children") == 0) 3269 { 3270 i = cgltf_parse_json_array(options, tokens, i + 1, json_chunk, sizeof(cgltf_node*), (void**)&out_node->children, &out_node->children_count); 3271 if (i < 0) 3272 { 3273 return i; 3274 } 3275 3276 for (cgltf_size k = 0; k < out_node->children_count; ++k) 3277 { 3278 out_node->children[k] = CGLTF_PTRINDEX(cgltf_node, cgltf_json_to_int(tokens + i, json_chunk)); 3279 ++i; 3280 } 3281 } 3282 else if (cgltf_json_strcmp(tokens+i, json_chunk, "mesh") == 0) 3283 { 3284 ++i; 3285 CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_PRIMITIVE); 3286 out_node->mesh = CGLTF_PTRINDEX(cgltf_mesh, cgltf_json_to_int(tokens + i, json_chunk)); 3287 ++i; 3288 } 3289 else if (cgltf_json_strcmp(tokens+i, json_chunk, "skin") == 0) 3290 { 3291 ++i; 3292 CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_PRIMITIVE); 3293 out_node->skin = CGLTF_PTRINDEX(cgltf_skin, cgltf_json_to_int(tokens + i, json_chunk)); 3294 ++i; 3295 } 3296 else if (cgltf_json_strcmp(tokens+i, json_chunk, "camera") == 0) 3297 { 3298 ++i; 3299 CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_PRIMITIVE); 3300 out_node->camera = CGLTF_PTRINDEX(cgltf_camera, cgltf_json_to_int(tokens + i, json_chunk)); 3301 ++i; 3302 } 3303 else if (cgltf_json_strcmp(tokens+i, json_chunk, "translation") == 0) 3304 { 3305 out_node->has_translation = 1; 3306 i = cgltf_parse_json_float_array(tokens, i + 1, json_chunk, out_node->translation, 3); 3307 } 3308 else if (cgltf_json_strcmp(tokens+i, json_chunk, "rotation") == 0) 3309 { 3310 out_node->has_rotation = 1; 3311 i = cgltf_parse_json_float_array(tokens, i + 1, json_chunk, out_node->rotation, 4); 3312 } 3313 else if (cgltf_json_strcmp(tokens+i, json_chunk, "scale") == 0) 3314 { 3315 out_node->has_scale = 1; 3316 i = cgltf_parse_json_float_array(tokens, i + 1, json_chunk, out_node->scale, 3); 3317 } 3318 else if (cgltf_json_strcmp(tokens+i, json_chunk, "matrix") == 0) 3319 { 3320 out_node->has_matrix = 1; 3321 i = cgltf_parse_json_float_array(tokens, i + 1, json_chunk, out_node->matrix, 16); 3322 } 3323 else if (cgltf_json_strcmp(tokens + i, json_chunk, "weights") == 0) 3324 { 3325 i = cgltf_parse_json_array(options, tokens, i + 1, json_chunk, sizeof(cgltf_float), (void**)&out_node->weights, &out_node->weights_count); 3326 if (i < 0) 3327 { 3328 return i; 3329 } 3330 3331 i = cgltf_parse_json_float_array(tokens, i - 1, json_chunk, out_node->weights, (int)out_node->weights_count); 3332 } 3333 else if (cgltf_json_strcmp(tokens + i, json_chunk, "extensions") == 0) 3334 { 3335 ++i; 3336 3337 CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT); 3338 3339 int extensions_size = tokens[i].size; 3340 ++i; 3341 3342 for (int k = 0; k < extensions_size; ++k) 3343 { 3344 CGLTF_CHECK_KEY(tokens[i]); 3345 3346 if (cgltf_json_strcmp(tokens+i, json_chunk, "KHR_lights_punctual") == 0) 3347 { 3348 ++i; 3349 3350 CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT); 3351 3352 int data_size = tokens[i].size; 3353 ++i; 3354 3355 for (int m = 0; m < data_size; ++m) 3356 { 3357 CGLTF_CHECK_KEY(tokens[i]); 3358 3359 if (cgltf_json_strcmp(tokens + i, json_chunk, "light") == 0) 3360 { 3361 ++i; 3362 CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_PRIMITIVE); 3363 out_node->light = CGLTF_PTRINDEX(cgltf_light, cgltf_json_to_int(tokens + i, json_chunk)); 3364 ++i; 3365 } 3366 else 3367 { 3368 i = cgltf_skip_json(tokens, i + 1); 3369 } 3370 3371 if (i < 0) 3372 { 3373 return i; 3374 } 3375 } 3376 } 3377 else 3378 { 3379 i = cgltf_skip_json(tokens, i+1); 3380 } 3381 3382 if (i < 0) 3383 { 3384 return i; 3385 } 3386 } 3387 } 3388 else 3389 { 3390 i = cgltf_skip_json(tokens, i+1); 3391 } 3392 3393 if (i < 0) 3394 { 3395 return i; 3396 } 3397 } 3398 3399 return i; 3400 } 3401 3402 static int cgltf_parse_json_nodes(cgltf_options* options, jsmntok_t const* tokens, int i, const uint8_t* json_chunk, cgltf_data* out_data) 3403 { 3404 i = cgltf_parse_json_array(options, tokens, i, json_chunk, sizeof(cgltf_node), (void**)&out_data->nodes, &out_data->nodes_count); 3405 if (i < 0) 3406 { 3407 return i; 3408 } 3409 3410 for (cgltf_size j = 0; j < out_data->nodes_count; ++j) 3411 { 3412 i = cgltf_parse_json_node(options, tokens, i, json_chunk, &out_data->nodes[j]); 3413 if (i < 0) 3414 { 3415 return i; 3416 } 3417 } 3418 return i; 3419 } 3420 3421 static int cgltf_parse_json_scene(cgltf_options* options, jsmntok_t const* tokens, int i, const uint8_t* json_chunk, cgltf_scene* out_scene) 3422 { 3423 CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT); 3424 3425 int size = tokens[i].size; 3426 ++i; 3427 3428 for (int j = 0; j < size; ++j) 3429 { 3430 CGLTF_CHECK_KEY(tokens[i]); 3431 3432 if (cgltf_json_strcmp(tokens+i, json_chunk, "name") == 0) 3433 { 3434 i = cgltf_parse_json_string(options, tokens, i + 1, json_chunk, &out_scene->name); 3435 } 3436 else if (cgltf_json_strcmp(tokens+i, json_chunk, "nodes") == 0) 3437 { 3438 i = cgltf_parse_json_array(options, tokens, i + 1, json_chunk, sizeof(cgltf_node*), (void**)&out_scene->nodes, &out_scene->nodes_count); 3439 if (i < 0) 3440 { 3441 return i; 3442 } 3443 3444 for (cgltf_size k = 0; k < out_scene->nodes_count; ++k) 3445 { 3446 out_scene->nodes[k] = CGLTF_PTRINDEX(cgltf_node, cgltf_json_to_int(tokens + i, json_chunk)); 3447 ++i; 3448 } 3449 } 3450 else 3451 { 3452 i = cgltf_skip_json(tokens, i+1); 3453 } 3454 3455 if (i < 0) 3456 { 3457 return i; 3458 } 3459 } 3460 3461 return i; 3462 } 3463 3464 static int cgltf_parse_json_scenes(cgltf_options* options, jsmntok_t const* tokens, int i, const uint8_t* json_chunk, cgltf_data* out_data) 3465 { 3466 i = cgltf_parse_json_array(options, tokens, i, json_chunk, sizeof(cgltf_scene), (void**)&out_data->scenes, &out_data->scenes_count); 3467 if (i < 0) 3468 { 3469 return i; 3470 } 3471 3472 for (cgltf_size j = 0; j < out_data->scenes_count; ++j) 3473 { 3474 i = cgltf_parse_json_scene(options, tokens, i, json_chunk, &out_data->scenes[j]); 3475 if (i < 0) 3476 { 3477 return i; 3478 } 3479 } 3480 return i; 3481 } 3482 3483 static int cgltf_parse_json_animation_sampler(cgltf_options* options, jsmntok_t const* tokens, int i, const uint8_t* json_chunk, cgltf_animation_sampler* out_sampler) 3484 { 3485 (void)options; 3486 CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT); 3487 3488 int size = tokens[i].size; 3489 ++i; 3490 3491 for (int j = 0; j < size; ++j) 3492 { 3493 CGLTF_CHECK_KEY(tokens[i]); 3494 3495 if (cgltf_json_strcmp(tokens+i, json_chunk, "input") == 0) 3496 { 3497 ++i; 3498 out_sampler->input = CGLTF_PTRINDEX(cgltf_accessor, cgltf_json_to_int(tokens + i, json_chunk)); 3499 ++i; 3500 } 3501 else if (cgltf_json_strcmp(tokens+i, json_chunk, "output") == 0) 3502 { 3503 ++i; 3504 out_sampler->output = CGLTF_PTRINDEX(cgltf_accessor, cgltf_json_to_int(tokens + i, json_chunk)); 3505 ++i; 3506 } 3507 else if (cgltf_json_strcmp(tokens+i, json_chunk, "interpolation") == 0) 3508 { 3509 ++i; 3510 if (cgltf_json_strcmp(tokens + i, json_chunk, "LINEAR") == 0) 3511 { 3512 out_sampler->interpolation = cgltf_interpolation_type_linear; 3513 } 3514 else if (cgltf_json_strcmp(tokens + i, json_chunk, "STEP") == 0) 3515 { 3516 out_sampler->interpolation = cgltf_interpolation_type_step; 3517 } 3518 else if (cgltf_json_strcmp(tokens + i, json_chunk, "CUBICSPLINE") == 0) 3519 { 3520 out_sampler->interpolation = cgltf_interpolation_type_cubic_spline; 3521 } 3522 ++i; 3523 } 3524 else 3525 { 3526 i = cgltf_skip_json(tokens, i+1); 3527 } 3528 3529 if (i < 0) 3530 { 3531 return i; 3532 } 3533 } 3534 3535 return i; 3536 } 3537 3538 static int cgltf_parse_json_animation_channel(cgltf_options* options, jsmntok_t const* tokens, int i, const uint8_t* json_chunk, cgltf_animation_channel* out_channel) 3539 { 3540 (void)options; 3541 CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT); 3542 3543 int size = tokens[i].size; 3544 ++i; 3545 3546 for (int j = 0; j < size; ++j) 3547 { 3548 CGLTF_CHECK_KEY(tokens[i]); 3549 3550 if (cgltf_json_strcmp(tokens+i, json_chunk, "sampler") == 0) 3551 { 3552 ++i; 3553 out_channel->sampler = CGLTF_PTRINDEX(cgltf_animation_sampler, cgltf_json_to_int(tokens + i, json_chunk)); 3554 ++i; 3555 } 3556 else if (cgltf_json_strcmp(tokens+i, json_chunk, "target") == 0) 3557 { 3558 ++i; 3559 3560 CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT); 3561 3562 int target_size = tokens[i].size; 3563 ++i; 3564 3565 for (int k = 0; k < target_size; ++k) 3566 { 3567 CGLTF_CHECK_KEY(tokens[i]); 3568 3569 if (cgltf_json_strcmp(tokens+i, json_chunk, "node") == 0) 3570 { 3571 ++i; 3572 out_channel->target_node = CGLTF_PTRINDEX(cgltf_node, cgltf_json_to_int(tokens + i, json_chunk)); 3573 ++i; 3574 } 3575 else if (cgltf_json_strcmp(tokens+i, json_chunk, "path") == 0) 3576 { 3577 ++i; 3578 if (cgltf_json_strcmp(tokens+i, json_chunk, "translation") == 0) 3579 { 3580 out_channel->target_path = cgltf_animation_path_type_translation; 3581 } 3582 else if (cgltf_json_strcmp(tokens+i, json_chunk, "rotation") == 0) 3583 { 3584 out_channel->target_path = cgltf_animation_path_type_rotation; 3585 } 3586 else if (cgltf_json_strcmp(tokens+i, json_chunk, "scale") == 0) 3587 { 3588 out_channel->target_path = cgltf_animation_path_type_scale; 3589 } 3590 else if (cgltf_json_strcmp(tokens+i, json_chunk, "weights") == 0) 3591 { 3592 out_channel->target_path = cgltf_animation_path_type_weights; 3593 } 3594 ++i; 3595 } 3596 else 3597 { 3598 i = cgltf_skip_json(tokens, i+1); 3599 } 3600 3601 if (i < 0) 3602 { 3603 return i; 3604 } 3605 } 3606 } 3607 else 3608 { 3609 i = cgltf_skip_json(tokens, i+1); 3610 } 3611 3612 if (i < 0) 3613 { 3614 return i; 3615 } 3616 } 3617 3618 return i; 3619 } 3620 3621 static int cgltf_parse_json_animation(cgltf_options* options, jsmntok_t const* tokens, int i, const uint8_t* json_chunk, cgltf_animation* out_animation) 3622 { 3623 CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT); 3624 3625 int size = tokens[i].size; 3626 ++i; 3627 3628 for (int j = 0; j < size; ++j) 3629 { 3630 CGLTF_CHECK_KEY(tokens[i]); 3631 3632 if (cgltf_json_strcmp(tokens+i, json_chunk, "name") == 0) 3633 { 3634 i = cgltf_parse_json_string(options, tokens, i + 1, json_chunk, &out_animation->name); 3635 } 3636 else if (cgltf_json_strcmp(tokens+i, json_chunk, "samplers") == 0) 3637 { 3638 i = cgltf_parse_json_array(options, tokens, i + 1, json_chunk, sizeof(cgltf_animation_sampler), (void**)&out_animation->samplers, &out_animation->samplers_count); 3639 if (i < 0) 3640 { 3641 return i; 3642 } 3643 3644 for (cgltf_size k = 0; k < out_animation->samplers_count; ++k) 3645 { 3646 i = cgltf_parse_json_animation_sampler(options, tokens, i, json_chunk, &out_animation->samplers[k]); 3647 if (i < 0) 3648 { 3649 return i; 3650 } 3651 } 3652 } 3653 else if (cgltf_json_strcmp(tokens+i, json_chunk, "channels") == 0) 3654 { 3655 i = cgltf_parse_json_array(options, tokens, i + 1, json_chunk, sizeof(cgltf_animation_channel), (void**)&out_animation->channels, &out_animation->channels_count); 3656 if (i < 0) 3657 { 3658 return i; 3659 } 3660 3661 for (cgltf_size k = 0; k < out_animation->channels_count; ++k) 3662 { 3663 i = cgltf_parse_json_animation_channel(options, tokens, i, json_chunk, &out_animation->channels[k]); 3664 if (i < 0) 3665 { 3666 return i; 3667 } 3668 } 3669 } 3670 else 3671 { 3672 i = cgltf_skip_json(tokens, i+1); 3673 } 3674 3675 if (i < 0) 3676 { 3677 return i; 3678 } 3679 } 3680 3681 return i; 3682 } 3683 3684 static int cgltf_parse_json_animations(cgltf_options* options, jsmntok_t const* tokens, int i, const uint8_t* json_chunk, cgltf_data* out_data) 3685 { 3686 i = cgltf_parse_json_array(options, tokens, i, json_chunk, sizeof(cgltf_animation), (void**)&out_data->animations, &out_data->animations_count); 3687 if (i < 0) 3688 { 3689 return i; 3690 } 3691 3692 for (cgltf_size j = 0; j < out_data->animations_count; ++j) 3693 { 3694 i = cgltf_parse_json_animation(options, tokens, i, json_chunk, &out_data->animations[j]); 3695 if (i < 0) 3696 { 3697 return i; 3698 } 3699 } 3700 return i; 3701 } 3702 3703 static int cgltf_parse_json_asset(cgltf_options* options, jsmntok_t const* tokens, int i, const uint8_t* json_chunk, cgltf_asset* out_asset) 3704 { 3705 CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT); 3706 3707 int size = tokens[i].size; 3708 ++i; 3709 3710 for (int j = 0; j < size; ++j) 3711 { 3712 CGLTF_CHECK_KEY(tokens[i]); 3713 3714 if (cgltf_json_strcmp(tokens+i, json_chunk, "copyright") == 0) 3715 { 3716 i = cgltf_parse_json_string(options, tokens, i + 1, json_chunk, &out_asset->copyright); 3717 } 3718 else if (cgltf_json_strcmp(tokens+i, json_chunk, "generator") == 0) 3719 { 3720 i = cgltf_parse_json_string(options, tokens, i + 1, json_chunk, &out_asset->generator); 3721 } 3722 else if (cgltf_json_strcmp(tokens+i, json_chunk, "version") == 0) 3723 { 3724 i = cgltf_parse_json_string(options, tokens, i + 1, json_chunk, &out_asset->version); 3725 } 3726 else if (cgltf_json_strcmp(tokens+i, json_chunk, "minVersion") == 0) 3727 { 3728 i = cgltf_parse_json_string(options, tokens, i + 1, json_chunk, &out_asset->min_version); 3729 } 3730 else 3731 { 3732 i = cgltf_skip_json(tokens, i+1); 3733 } 3734 3735 if (i < 0) 3736 { 3737 return i; 3738 } 3739 } 3740 3741 return i; 3742 } 3743 3744 static cgltf_size cgltf_num_components(cgltf_type type) { 3745 switch (type) 3746 { 3747 case cgltf_type_vec2: 3748 return 2; 3749 case cgltf_type_vec3: 3750 return 3; 3751 case cgltf_type_vec4: 3752 return 4; 3753 case cgltf_type_mat2: 3754 return 4; 3755 case cgltf_type_mat3: 3756 return 9; 3757 case cgltf_type_mat4: 3758 return 16; 3759 case cgltf_type_invalid: 3760 case cgltf_type_scalar: 3761 default: 3762 return 1; 3763 } 3764 } 3765 3766 static cgltf_size cgltf_component_size(cgltf_component_type component_type) { 3767 switch (component_type) 3768 { 3769 case cgltf_component_type_r_8: 3770 case cgltf_component_type_r_8u: 3771 return 1; 3772 case cgltf_component_type_r_16: 3773 case cgltf_component_type_r_16u: 3774 return 2; 3775 case cgltf_component_type_r_32u: 3776 case cgltf_component_type_r_32f: 3777 return 4; 3778 case cgltf_component_type_invalid: 3779 default: 3780 return 0; 3781 } 3782 } 3783 3784 static cgltf_size cgltf_calc_size(cgltf_type type, cgltf_component_type component_type) 3785 { 3786 cgltf_size component_size = cgltf_component_size(component_type); 3787 if (type == cgltf_type_mat2 && component_size == 1) 3788 { 3789 return 8 * component_size; 3790 } 3791 else if (type == cgltf_type_mat3 && (component_size == 1 || component_size == 2)) 3792 { 3793 return 12 * component_size; 3794 } 3795 return component_size * cgltf_num_components(type); 3796 } 3797 3798 static int cgltf_fixup_pointers(cgltf_data* out_data); 3799 3800 static int cgltf_parse_json_root(cgltf_options* options, jsmntok_t const* tokens, int i, const uint8_t* json_chunk, cgltf_data* out_data) 3801 { 3802 CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT); 3803 3804 int size = tokens[i].size; 3805 ++i; 3806 3807 for (int j = 0; j < size; ++j) 3808 { 3809 CGLTF_CHECK_KEY(tokens[i]); 3810 3811 if (cgltf_json_strcmp(tokens + i, json_chunk, "asset") == 0) 3812 { 3813 i = cgltf_parse_json_asset(options, tokens, i + 1, json_chunk, &out_data->asset); 3814 } 3815 else if (cgltf_json_strcmp(tokens + i, json_chunk, "meshes") == 0) 3816 { 3817 i = cgltf_parse_json_meshes(options, tokens, i + 1, json_chunk, out_data); 3818 } 3819 else if (cgltf_json_strcmp(tokens + i, json_chunk, "accessors") == 0) 3820 { 3821 i = cgltf_parse_json_accessors(options, tokens, i + 1, json_chunk, out_data); 3822 } 3823 else if (cgltf_json_strcmp(tokens + i, json_chunk, "bufferViews") == 0) 3824 { 3825 i = cgltf_parse_json_buffer_views(options, tokens, i + 1, json_chunk, out_data); 3826 } 3827 else if (cgltf_json_strcmp(tokens + i, json_chunk, "buffers") == 0) 3828 { 3829 i = cgltf_parse_json_buffers(options, tokens, i + 1, json_chunk, out_data); 3830 } 3831 else if (cgltf_json_strcmp(tokens + i, json_chunk, "materials") == 0) 3832 { 3833 i = cgltf_parse_json_materials(options, tokens, i + 1, json_chunk, out_data); 3834 } 3835 else if (cgltf_json_strcmp(tokens + i, json_chunk, "images") == 0) 3836 { 3837 i = cgltf_parse_json_images(options, tokens, i + 1, json_chunk, out_data); 3838 } 3839 else if (cgltf_json_strcmp(tokens + i, json_chunk, "textures") == 0) 3840 { 3841 i = cgltf_parse_json_textures(options, tokens, i + 1, json_chunk, out_data); 3842 } 3843 else if (cgltf_json_strcmp(tokens + i, json_chunk, "samplers") == 0) 3844 { 3845 i = cgltf_parse_json_samplers(options, tokens, i + 1, json_chunk, out_data); 3846 } 3847 else if (cgltf_json_strcmp(tokens + i, json_chunk, "skins") == 0) 3848 { 3849 i = cgltf_parse_json_skins(options, tokens, i + 1, json_chunk, out_data); 3850 } 3851 else if (cgltf_json_strcmp(tokens + i, json_chunk, "cameras") == 0) 3852 { 3853 i = cgltf_parse_json_cameras(options, tokens, i + 1, json_chunk, out_data); 3854 } 3855 else if (cgltf_json_strcmp(tokens + i, json_chunk, "nodes") == 0) 3856 { 3857 i = cgltf_parse_json_nodes(options, tokens, i + 1, json_chunk, out_data); 3858 } 3859 else if (cgltf_json_strcmp(tokens + i, json_chunk, "scenes") == 0) 3860 { 3861 i = cgltf_parse_json_scenes(options, tokens, i + 1, json_chunk, out_data); 3862 } 3863 else if (cgltf_json_strcmp(tokens + i, json_chunk, "scene") == 0) 3864 { 3865 ++i; 3866 out_data->scene = CGLTF_PTRINDEX(cgltf_scene, cgltf_json_to_int(tokens + i, json_chunk)); 3867 ++i; 3868 } 3869 else if (cgltf_json_strcmp(tokens + i, json_chunk, "animations") == 0) 3870 { 3871 i = cgltf_parse_json_animations(options, tokens, i + 1, json_chunk, out_data); 3872 } 3873 else if (cgltf_json_strcmp(tokens + i, json_chunk, "extensions") == 0) 3874 { 3875 ++i; 3876 3877 CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT); 3878 3879 int extensions_size = tokens[i].size; 3880 ++i; 3881 3882 for (int k = 0; k < extensions_size; ++k) 3883 { 3884 CGLTF_CHECK_KEY(tokens[i]); 3885 3886 if (cgltf_json_strcmp(tokens+i, json_chunk, "KHR_lights_punctual") == 0) 3887 { 3888 ++i; 3889 3890 CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT); 3891 3892 int data_size = tokens[i].size; 3893 ++i; 3894 3895 for (int m = 0; m < data_size; ++m) 3896 { 3897 CGLTF_CHECK_KEY(tokens[i]); 3898 3899 if (cgltf_json_strcmp(tokens + i, json_chunk, "lights") == 0) 3900 { 3901 i = cgltf_parse_json_lights(options, tokens, i + 1, json_chunk, out_data); 3902 } 3903 else 3904 { 3905 i = cgltf_skip_json(tokens, i + 1); 3906 } 3907 3908 if (i < 0) 3909 { 3910 return i; 3911 } 3912 } 3913 } 3914 else 3915 { 3916 i = cgltf_skip_json(tokens, i+1); 3917 } 3918 3919 if (i < 0) 3920 { 3921 return i; 3922 } 3923 } 3924 } 3925 else 3926 { 3927 i = cgltf_skip_json(tokens, i + 1); 3928 } 3929 3930 if (i < 0) 3931 { 3932 return i; 3933 } 3934 } 3935 3936 return i; 3937 } 3938 3939 cgltf_result cgltf_parse_json(cgltf_options* options, const uint8_t* json_chunk, cgltf_size size, cgltf_data** out_data) 3940 { 3941 jsmn_parser parser = { 0, 0, 0 }; 3942 3943 if (options->json_token_count == 0) 3944 { 3945 int token_count = jsmn_parse(&parser, (const char*)json_chunk, size, NULL, 0); 3946 3947 if (token_count <= 0) 3948 { 3949 return cgltf_result_invalid_json; 3950 } 3951 3952 options->json_token_count = token_count; 3953 } 3954 3955 jsmntok_t* tokens = (jsmntok_t*)options->memory_alloc(options->memory_user_data, sizeof(jsmntok_t) * options->json_token_count); 3956 3957 if (!tokens) 3958 { 3959 return cgltf_result_out_of_memory; 3960 } 3961 3962 jsmn_init(&parser); 3963 3964 int token_count = jsmn_parse(&parser, (const char*)json_chunk, size, tokens, options->json_token_count); 3965 3966 if (token_count <= 0) 3967 { 3968 options->memory_free(options->memory_user_data, tokens); 3969 return cgltf_result_invalid_json; 3970 } 3971 3972 cgltf_data* data = (cgltf_data*)options->memory_alloc(options->memory_user_data, sizeof(cgltf_data)); 3973 3974 if (!data) 3975 { 3976 options->memory_free(options->memory_user_data, tokens); 3977 return cgltf_result_out_of_memory; 3978 } 3979 3980 memset(data, 0, sizeof(cgltf_data)); 3981 data->memory_free = options->memory_free; 3982 data->memory_user_data = options->memory_user_data; 3983 3984 int i = cgltf_parse_json_root(options, tokens, 0, json_chunk, data); 3985 3986 options->memory_free(options->memory_user_data, tokens); 3987 3988 if (i < 0) 3989 { 3990 cgltf_free(data); 3991 return (i == CGLTF_ERROR_NOMEM) ? cgltf_result_out_of_memory : cgltf_result_invalid_gltf; 3992 } 3993 3994 if (cgltf_fixup_pointers(data) < 0) 3995 { 3996 cgltf_free(data); 3997 return cgltf_result_invalid_gltf; 3998 } 3999 4000 *out_data = data; 4001 4002 return cgltf_result_success; 4003 } 4004 4005 static int cgltf_fixup_pointers(cgltf_data* data) 4006 { 4007 for (cgltf_size i = 0; i < data->meshes_count; ++i) 4008 { 4009 for (cgltf_size j = 0; j < data->meshes[i].primitives_count; ++j) 4010 { 4011 CGLTF_PTRFIXUP(data->meshes[i].primitives[j].indices, data->accessors, data->accessors_count); 4012 CGLTF_PTRFIXUP(data->meshes[i].primitives[j].material, data->materials, data->materials_count); 4013 4014 for (cgltf_size k = 0; k < data->meshes[i].primitives[j].attributes_count; ++k) 4015 { 4016 CGLTF_PTRFIXUP_REQ(data->meshes[i].primitives[j].attributes[k].data, data->accessors, data->accessors_count); 4017 } 4018 4019 for (cgltf_size k = 0; k < data->meshes[i].primitives[j].targets_count; ++k) 4020 { 4021 for (cgltf_size m = 0; m < data->meshes[i].primitives[j].targets[k].attributes_count; ++m) 4022 { 4023 CGLTF_PTRFIXUP_REQ(data->meshes[i].primitives[j].targets[k].attributes[m].data, data->accessors, data->accessors_count); 4024 } 4025 } 4026 } 4027 } 4028 4029 for (cgltf_size i = 0; i < data->accessors_count; ++i) 4030 { 4031 CGLTF_PTRFIXUP(data->accessors[i].buffer_view, data->buffer_views, data->buffer_views_count); 4032 4033 if (data->accessors[i].is_sparse) 4034 { 4035 CGLTF_PTRFIXUP_REQ(data->accessors[i].sparse.indices_buffer_view, data->buffer_views, data->buffer_views_count); 4036 CGLTF_PTRFIXUP_REQ(data->accessors[i].sparse.values_buffer_view, data->buffer_views, data->buffer_views_count); 4037 } 4038 4039 if (data->accessors[i].buffer_view) 4040 { 4041 data->accessors[i].stride = data->accessors[i].buffer_view->stride; 4042 } 4043 4044 if (data->accessors[i].stride == 0) 4045 { 4046 data->accessors[i].stride = cgltf_calc_size(data->accessors[i].type, data->accessors[i].component_type); 4047 } 4048 } 4049 4050 for (cgltf_size i = 0; i < data->textures_count; ++i) 4051 { 4052 CGLTF_PTRFIXUP(data->textures[i].image, data->images, data->images_count); 4053 CGLTF_PTRFIXUP(data->textures[i].sampler, data->samplers, data->samplers_count); 4054 } 4055 4056 for (cgltf_size i = 0; i < data->images_count; ++i) 4057 { 4058 CGLTF_PTRFIXUP(data->images[i].buffer_view, data->buffer_views, data->buffer_views_count); 4059 } 4060 4061 for (cgltf_size i = 0; i < data->materials_count; ++i) 4062 { 4063 CGLTF_PTRFIXUP(data->materials[i].normal_texture.texture, data->textures, data->textures_count); 4064 CGLTF_PTRFIXUP(data->materials[i].emissive_texture.texture, data->textures, data->textures_count); 4065 CGLTF_PTRFIXUP(data->materials[i].occlusion_texture.texture, data->textures, data->textures_count); 4066 4067 CGLTF_PTRFIXUP(data->materials[i].pbr_metallic_roughness.base_color_texture.texture, data->textures, data->textures_count); 4068 CGLTF_PTRFIXUP(data->materials[i].pbr_metallic_roughness.metallic_roughness_texture.texture, data->textures, data->textures_count); 4069 4070 CGLTF_PTRFIXUP(data->materials[i].pbr_specular_glossiness.diffuse_texture.texture, data->textures, data->textures_count); 4071 CGLTF_PTRFIXUP(data->materials[i].pbr_specular_glossiness.specular_glossiness_texture.texture, data->textures, data->textures_count); 4072 } 4073 4074 for (cgltf_size i = 0; i < data->buffer_views_count; ++i) 4075 { 4076 CGLTF_PTRFIXUP_REQ(data->buffer_views[i].buffer, data->buffers, data->buffers_count); 4077 } 4078 4079 for (cgltf_size i = 0; i < data->skins_count; ++i) 4080 { 4081 for (cgltf_size j = 0; j < data->skins[i].joints_count; ++j) 4082 { 4083 CGLTF_PTRFIXUP_REQ(data->skins[i].joints[j], data->nodes, data->nodes_count); 4084 } 4085 4086 CGLTF_PTRFIXUP(data->skins[i].skeleton, data->nodes, data->nodes_count); 4087 CGLTF_PTRFIXUP(data->skins[i].inverse_bind_matrices, data->accessors, data->accessors_count); 4088 } 4089 4090 for (cgltf_size i = 0; i < data->nodes_count; ++i) 4091 { 4092 for (cgltf_size j = 0; j < data->nodes[i].children_count; ++j) 4093 { 4094 CGLTF_PTRFIXUP_REQ(data->nodes[i].children[j], data->nodes, data->nodes_count); 4095 4096 if (data->nodes[i].children[j]->parent) 4097 { 4098 return CGLTF_ERROR_JSON; 4099 } 4100 4101 data->nodes[i].children[j]->parent = &data->nodes[i]; 4102 } 4103 4104 CGLTF_PTRFIXUP(data->nodes[i].mesh, data->meshes, data->meshes_count); 4105 CGLTF_PTRFIXUP(data->nodes[i].skin, data->skins, data->skins_count); 4106 CGLTF_PTRFIXUP(data->nodes[i].camera, data->cameras, data->cameras_count); 4107 CGLTF_PTRFIXUP(data->nodes[i].light, data->lights, data->lights_count); 4108 } 4109 4110 for (cgltf_size i = 0; i < data->scenes_count; ++i) 4111 { 4112 for (cgltf_size j = 0; j < data->scenes[i].nodes_count; ++j) 4113 { 4114 CGLTF_PTRFIXUP_REQ(data->scenes[i].nodes[j], data->nodes, data->nodes_count); 4115 4116 if (data->scenes[i].nodes[j]->parent) 4117 { 4118 return CGLTF_ERROR_JSON; 4119 } 4120 } 4121 } 4122 4123 CGLTF_PTRFIXUP(data->scene, data->scenes, data->scenes_count); 4124 4125 for (cgltf_size i = 0; i < data->animations_count; ++i) 4126 { 4127 for (cgltf_size j = 0; j < data->animations[i].samplers_count; ++j) 4128 { 4129 CGLTF_PTRFIXUP_REQ(data->animations[i].samplers[j].input, data->accessors, data->accessors_count); 4130 CGLTF_PTRFIXUP_REQ(data->animations[i].samplers[j].output, data->accessors, data->accessors_count); 4131 } 4132 4133 for (cgltf_size j = 0; j < data->animations[i].channels_count; ++j) 4134 { 4135 CGLTF_PTRFIXUP_REQ(data->animations[i].channels[j].sampler, data->animations[i].samplers, data->animations[i].samplers_count); 4136 CGLTF_PTRFIXUP(data->animations[i].channels[j].target_node, data->nodes, data->nodes_count); 4137 } 4138 } 4139 4140 return 0; 4141 } 4142 4143 /* 4144 * -- jsmn.c start -- 4145 * Source: https://github.com/zserge/jsmn 4146 * License: MIT 4147 * 4148 * Copyright (c) 2010 Serge A. Zaitsev 4149 4150 * Permission is hereby granted, free of charge, to any person obtaining a copy 4151 * of this software and associated documentation files (the "Software"), to deal 4152 * in the Software without restriction, including without limitation the rights 4153 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 4154 * copies of the Software, and to permit persons to whom the Software is 4155 * furnished to do so, subject to the following conditions: 4156 4157 * The above copyright notice and this permission notice shall be included in 4158 * all copies or substantial portions of the Software. 4159 4160 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 4161 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 4162 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 4163 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 4164 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 4165 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 4166 * THE SOFTWARE. 4167 */ 4168 4169 /** 4170 * Allocates a fresh unused token from the token pull. 4171 */ 4172 static jsmntok_t *jsmn_alloc_token(jsmn_parser *parser, 4173 jsmntok_t *tokens, size_t num_tokens) { 4174 jsmntok_t *tok; 4175 if (parser->toknext >= num_tokens) { 4176 return NULL; 4177 } 4178 tok = &tokens[parser->toknext++]; 4179 tok->start = tok->end = -1; 4180 tok->size = 0; 4181 #ifdef JSMN_PARENT_LINKS 4182 tok->parent = -1; 4183 #endif 4184 return tok; 4185 } 4186 4187 /** 4188 * Fills token type and boundaries. 4189 */ 4190 static void jsmn_fill_token(jsmntok_t *token, jsmntype_t type, 4191 int start, int end) { 4192 token->type = type; 4193 token->start = start; 4194 token->end = end; 4195 token->size = 0; 4196 } 4197 4198 /** 4199 * Fills next available token with JSON primitive. 4200 */ 4201 static int jsmn_parse_primitive(jsmn_parser *parser, const char *js, 4202 size_t len, jsmntok_t *tokens, size_t num_tokens) { 4203 jsmntok_t *token; 4204 int start; 4205 4206 start = parser->pos; 4207 4208 for (; parser->pos < len && js[parser->pos] != '\0'; parser->pos++) { 4209 switch (js[parser->pos]) { 4210 #ifndef JSMN_STRICT 4211 /* In strict mode primitive must be followed by "," or "}" or "]" */ 4212 case ':': 4213 #endif 4214 case '\t' : case '\r' : case '\n' : case ' ' : 4215 case ',' : case ']' : case '}' : 4216 goto found; 4217 } 4218 if (js[parser->pos] < 32 || js[parser->pos] >= 127) { 4219 parser->pos = start; 4220 return JSMN_ERROR_INVAL; 4221 } 4222 } 4223 #ifdef JSMN_STRICT 4224 /* In strict mode primitive must be followed by a comma/object/array */ 4225 parser->pos = start; 4226 return JSMN_ERROR_PART; 4227 #endif 4228 4229 found: 4230 if (tokens == NULL) { 4231 parser->pos--; 4232 return 0; 4233 } 4234 token = jsmn_alloc_token(parser, tokens, num_tokens); 4235 if (token == NULL) { 4236 parser->pos = start; 4237 return JSMN_ERROR_NOMEM; 4238 } 4239 jsmn_fill_token(token, JSMN_PRIMITIVE, start, parser->pos); 4240 #ifdef JSMN_PARENT_LINKS 4241 token->parent = parser->toksuper; 4242 #endif 4243 parser->pos--; 4244 return 0; 4245 } 4246 4247 /** 4248 * Fills next token with JSON string. 4249 */ 4250 static int jsmn_parse_string(jsmn_parser *parser, const char *js, 4251 size_t len, jsmntok_t *tokens, size_t num_tokens) { 4252 jsmntok_t *token; 4253 4254 int start = parser->pos; 4255 4256 parser->pos++; 4257 4258 /* Skip starting quote */ 4259 for (; parser->pos < len && js[parser->pos] != '\0'; parser->pos++) { 4260 char c = js[parser->pos]; 4261 4262 /* Quote: end of string */ 4263 if (c == '\"') { 4264 if (tokens == NULL) { 4265 return 0; 4266 } 4267 token = jsmn_alloc_token(parser, tokens, num_tokens); 4268 if (token == NULL) { 4269 parser->pos = start; 4270 return JSMN_ERROR_NOMEM; 4271 } 4272 jsmn_fill_token(token, JSMN_STRING, start+1, parser->pos); 4273 #ifdef JSMN_PARENT_LINKS 4274 token->parent = parser->toksuper; 4275 #endif 4276 return 0; 4277 } 4278 4279 /* Backslash: Quoted symbol expected */ 4280 if (c == '\\' && parser->pos + 1 < len) { 4281 int i; 4282 parser->pos++; 4283 switch (js[parser->pos]) { 4284 /* Allowed escaped symbols */ 4285 case '\"': case '/' : case '\\' : case 'b' : 4286 case 'f' : case 'r' : case 'n' : case 't' : 4287 break; 4288 /* Allows escaped symbol \uXXXX */ 4289 case 'u': 4290 parser->pos++; 4291 for(i = 0; i < 4 && parser->pos < len && js[parser->pos] != '\0'; i++) { 4292 /* If it isn't a hex character we have an error */ 4293 if(!((js[parser->pos] >= 48 && js[parser->pos] <= 57) || /* 0-9 */ 4294 (js[parser->pos] >= 65 && js[parser->pos] <= 70) || /* A-F */ 4295 (js[parser->pos] >= 97 && js[parser->pos] <= 102))) { /* a-f */ 4296 parser->pos = start; 4297 return JSMN_ERROR_INVAL; 4298 } 4299 parser->pos++; 4300 } 4301 parser->pos--; 4302 break; 4303 /* Unexpected symbol */ 4304 default: 4305 parser->pos = start; 4306 return JSMN_ERROR_INVAL; 4307 } 4308 } 4309 } 4310 parser->pos = start; 4311 return JSMN_ERROR_PART; 4312 } 4313 4314 /** 4315 * Parse JSON string and fill tokens. 4316 */ 4317 static int jsmn_parse(jsmn_parser *parser, const char *js, size_t len, 4318 jsmntok_t *tokens, size_t num_tokens) { 4319 int r; 4320 int i; 4321 jsmntok_t *token; 4322 int count = parser->toknext; 4323 4324 for (; parser->pos < len && js[parser->pos] != '\0'; parser->pos++) { 4325 char c; 4326 jsmntype_t type; 4327 4328 c = js[parser->pos]; 4329 switch (c) { 4330 case '{': case '[': 4331 count++; 4332 if (tokens == NULL) { 4333 break; 4334 } 4335 token = jsmn_alloc_token(parser, tokens, num_tokens); 4336 if (token == NULL) 4337 return JSMN_ERROR_NOMEM; 4338 if (parser->toksuper != -1) { 4339 tokens[parser->toksuper].size++; 4340 #ifdef JSMN_PARENT_LINKS 4341 token->parent = parser->toksuper; 4342 #endif 4343 } 4344 token->type = (c == '{' ? JSMN_OBJECT : JSMN_ARRAY); 4345 token->start = parser->pos; 4346 parser->toksuper = parser->toknext - 1; 4347 break; 4348 case '}': case ']': 4349 if (tokens == NULL) 4350 break; 4351 type = (c == '}' ? JSMN_OBJECT : JSMN_ARRAY); 4352 #ifdef JSMN_PARENT_LINKS 4353 if (parser->toknext < 1) { 4354 return JSMN_ERROR_INVAL; 4355 } 4356 token = &tokens[parser->toknext - 1]; 4357 for (;;) { 4358 if (token->start != -1 && token->end == -1) { 4359 if (token->type != type) { 4360 return JSMN_ERROR_INVAL; 4361 } 4362 token->end = parser->pos + 1; 4363 parser->toksuper = token->parent; 4364 break; 4365 } 4366 if (token->parent == -1) { 4367 if(token->type != type || parser->toksuper == -1) { 4368 return JSMN_ERROR_INVAL; 4369 } 4370 break; 4371 } 4372 token = &tokens[token->parent]; 4373 } 4374 #else 4375 for (i = parser->toknext - 1; i >= 0; i--) { 4376 token = &tokens[i]; 4377 if (token->start != -1 && token->end == -1) { 4378 if (token->type != type) { 4379 return JSMN_ERROR_INVAL; 4380 } 4381 parser->toksuper = -1; 4382 token->end = parser->pos + 1; 4383 break; 4384 } 4385 } 4386 /* Error if unmatched closing bracket */ 4387 if (i == -1) return JSMN_ERROR_INVAL; 4388 for (; i >= 0; i--) { 4389 token = &tokens[i]; 4390 if (token->start != -1 && token->end == -1) { 4391 parser->toksuper = i; 4392 break; 4393 } 4394 } 4395 #endif 4396 break; 4397 case '\"': 4398 r = jsmn_parse_string(parser, js, len, tokens, num_tokens); 4399 if (r < 0) return r; 4400 count++; 4401 if (parser->toksuper != -1 && tokens != NULL) 4402 tokens[parser->toksuper].size++; 4403 break; 4404 case '\t' : case '\r' : case '\n' : case ' ': 4405 break; 4406 case ':': 4407 parser->toksuper = parser->toknext - 1; 4408 break; 4409 case ',': 4410 if (tokens != NULL && parser->toksuper != -1 && 4411 tokens[parser->toksuper].type != JSMN_ARRAY && 4412 tokens[parser->toksuper].type != JSMN_OBJECT) { 4413 #ifdef JSMN_PARENT_LINKS 4414 parser->toksuper = tokens[parser->toksuper].parent; 4415 #else 4416 for (i = parser->toknext - 1; i >= 0; i--) { 4417 if (tokens[i].type == JSMN_ARRAY || tokens[i].type == JSMN_OBJECT) { 4418 if (tokens[i].start != -1 && tokens[i].end == -1) { 4419 parser->toksuper = i; 4420 break; 4421 } 4422 } 4423 } 4424 #endif 4425 } 4426 break; 4427 #ifdef JSMN_STRICT 4428 /* In strict mode primitives are: numbers and booleans */ 4429 case '-': case '0': case '1' : case '2': case '3' : case '4': 4430 case '5': case '6': case '7' : case '8': case '9': 4431 case 't': case 'f': case 'n' : 4432 /* And they must not be keys of the object */ 4433 if (tokens != NULL && parser->toksuper != -1) { 4434 jsmntok_t *t = &tokens[parser->toksuper]; 4435 if (t->type == JSMN_OBJECT || 4436 (t->type == JSMN_STRING && t->size != 0)) { 4437 return JSMN_ERROR_INVAL; 4438 } 4439 } 4440 #else 4441 /* In non-strict mode every unquoted value is a primitive */ 4442 default: 4443 #endif 4444 r = jsmn_parse_primitive(parser, js, len, tokens, num_tokens); 4445 if (r < 0) return r; 4446 count++; 4447 if (parser->toksuper != -1 && tokens != NULL) 4448 tokens[parser->toksuper].size++; 4449 break; 4450 4451 #ifdef JSMN_STRICT 4452 /* Unexpected char in strict mode */ 4453 default: 4454 return JSMN_ERROR_INVAL; 4455 #endif 4456 } 4457 } 4458 4459 if (tokens != NULL) { 4460 for (i = parser->toknext - 1; i >= 0; i--) { 4461 /* Unmatched opened object or array */ 4462 if (tokens[i].start != -1 && tokens[i].end == -1) { 4463 return JSMN_ERROR_PART; 4464 } 4465 } 4466 } 4467 4468 return count; 4469 } 4470 4471 /** 4472 * Creates a new parser based over a given buffer with an array of tokens 4473 * available. 4474 */ 4475 static void jsmn_init(jsmn_parser *parser) { 4476 parser->pos = 0; 4477 parser->toknext = 0; 4478 parser->toksuper = -1; 4479 } 4480 /* 4481 * -- jsmn.c end -- 4482 */ 4483 4484 #endif /* #ifdef CGLTF_IMPLEMENTATION */ 4485 4486 /* cgltf is distributed under MIT license: 4487 * 4488 * Copyright (c) 2018 Johannes Kuhlmann 4489 4490 * Permission is hereby granted, free of charge, to any person obtaining a copy 4491 * of this software and associated documentation files (the "Software"), to deal 4492 * in the Software without restriction, including without limitation the rights 4493 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 4494 * copies of the Software, and to permit persons to whom the Software is 4495 * furnished to do so, subject to the following conditions: 4496 4497 * The above copyright notice and this permission notice shall be included in all 4498 * copies or substantial portions of the Software. 4499 4500 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 4501 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 4502 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 4503 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 4504 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 4505 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 4506 * SOFTWARE. 4507 */