cgltf.h (199324B)
1 /** 2 * cgltf - a single-file glTF 2.0 parser written in C99. 3 * 4 * Version: 1.14 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 as well as file operation callbacks. 28 * Should be zero-initialized 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 * This is useful when decoding data URIs in images. 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_unpack_floats` reads in the data from an accessor, applies sparse data (if any), 62 * and converts them to floating point. Assumes that `cgltf_load_buffers` has already been called. 63 * By passing null for the output pointer, users can find out how many floats are required in the 64 * output buffer. 65 * 66 * `cgltf_accessor_unpack_indices` reads in the index data from an accessor. Assumes that 67 * `cgltf_load_buffers` has already been called. By passing null for the output pointer, users can 68 * find out how many indices are required in the output buffer. Returns 0 if the accessor is 69 * sparse or if the output component size is less than the accessor's component size. 70 * 71 * `cgltf_num_components` is a tiny utility that tells you the dimensionality of 72 * a certain accessor type. This can be used before `cgltf_accessor_unpack_floats` to help allocate 73 * the necessary amount of memory. `cgltf_component_size` and `cgltf_calc_size` exist for 74 * similar purposes. 75 * 76 * `cgltf_accessor_read_float` reads a certain element from a non-sparse accessor and converts it to 77 * floating point, assuming that `cgltf_load_buffers` has already been called. The passed-in element 78 * size is the number of floats in the output buffer, which should be in the range [1, 16]. Returns 79 * false if the passed-in element_size is too small, or if the accessor is sparse. 80 * 81 * `cgltf_accessor_read_uint` is similar to its floating-point counterpart, but limited to reading 82 * vector types and does not support matrix types. The passed-in element size is the number of uints 83 * in the output buffer, which should be in the range [1, 4]. Returns false if the passed-in 84 * element_size is too small, or if the accessor is sparse. 85 * 86 * `cgltf_accessor_read_index` is similar to its floating-point counterpart, but it returns size_t 87 * and only works with single-component data types. 88 * 89 * `cgltf_copy_extras_json` allows users to retrieve the "extras" data that can be attached to many 90 * glTF objects (which can be arbitrary JSON data). This is a legacy function, consider using 91 * cgltf_extras::data directly instead. You can parse this data using your own JSON parser 92 * or, if you've included the cgltf implementation using the integrated JSMN JSON parser. 93 */ 94 #ifndef CGLTF_H_INCLUDED__ 95 #define CGLTF_H_INCLUDED__ 96 97 #include <stddef.h> 98 #include <stdint.h> /* For uint8_t, uint32_t */ 99 100 #ifdef __cplusplus 101 extern "C" { 102 #endif 103 104 typedef size_t cgltf_size; 105 typedef long long int cgltf_ssize; 106 typedef float cgltf_float; 107 typedef int cgltf_int; 108 typedef unsigned int cgltf_uint; 109 typedef int cgltf_bool; 110 111 typedef enum cgltf_file_type 112 { 113 cgltf_file_type_invalid, 114 cgltf_file_type_gltf, 115 cgltf_file_type_glb, 116 cgltf_file_type_max_enum 117 } cgltf_file_type; 118 119 typedef enum cgltf_result 120 { 121 cgltf_result_success, 122 cgltf_result_data_too_short, 123 cgltf_result_unknown_format, 124 cgltf_result_invalid_json, 125 cgltf_result_invalid_gltf, 126 cgltf_result_invalid_options, 127 cgltf_result_file_not_found, 128 cgltf_result_io_error, 129 cgltf_result_out_of_memory, 130 cgltf_result_legacy_gltf, 131 cgltf_result_max_enum 132 } cgltf_result; 133 134 typedef struct cgltf_memory_options 135 { 136 void* (*alloc_func)(void* user, cgltf_size size); 137 void (*free_func) (void* user, void* ptr); 138 void* user_data; 139 } cgltf_memory_options; 140 141 typedef struct cgltf_file_options 142 { 143 cgltf_result(*read)(const struct cgltf_memory_options* memory_options, const struct cgltf_file_options* file_options, const char* path, cgltf_size* size, void** data); 144 void (*release)(const struct cgltf_memory_options* memory_options, const struct cgltf_file_options* file_options, void* data); 145 void* user_data; 146 } cgltf_file_options; 147 148 typedef struct cgltf_options 149 { 150 cgltf_file_type type; /* invalid == auto detect */ 151 cgltf_size json_token_count; /* 0 == auto */ 152 cgltf_memory_options memory; 153 cgltf_file_options file; 154 } cgltf_options; 155 156 typedef enum cgltf_buffer_view_type 157 { 158 cgltf_buffer_view_type_invalid, 159 cgltf_buffer_view_type_indices, 160 cgltf_buffer_view_type_vertices, 161 cgltf_buffer_view_type_max_enum 162 } cgltf_buffer_view_type; 163 164 typedef enum cgltf_attribute_type 165 { 166 cgltf_attribute_type_invalid, 167 cgltf_attribute_type_position, 168 cgltf_attribute_type_normal, 169 cgltf_attribute_type_tangent, 170 cgltf_attribute_type_texcoord, 171 cgltf_attribute_type_color, 172 cgltf_attribute_type_joints, 173 cgltf_attribute_type_weights, 174 cgltf_attribute_type_custom, 175 cgltf_attribute_type_max_enum 176 } cgltf_attribute_type; 177 178 typedef enum cgltf_component_type 179 { 180 cgltf_component_type_invalid, 181 cgltf_component_type_r_8, /* BYTE */ 182 cgltf_component_type_r_8u, /* UNSIGNED_BYTE */ 183 cgltf_component_type_r_16, /* SHORT */ 184 cgltf_component_type_r_16u, /* UNSIGNED_SHORT */ 185 cgltf_component_type_r_32u, /* UNSIGNED_INT */ 186 cgltf_component_type_r_32f, /* FLOAT */ 187 cgltf_component_type_max_enum 188 } cgltf_component_type; 189 190 typedef enum cgltf_type 191 { 192 cgltf_type_invalid, 193 cgltf_type_scalar, 194 cgltf_type_vec2, 195 cgltf_type_vec3, 196 cgltf_type_vec4, 197 cgltf_type_mat2, 198 cgltf_type_mat3, 199 cgltf_type_mat4, 200 cgltf_type_max_enum 201 } cgltf_type; 202 203 typedef enum cgltf_primitive_type 204 { 205 cgltf_primitive_type_invalid, 206 cgltf_primitive_type_points, 207 cgltf_primitive_type_lines, 208 cgltf_primitive_type_line_loop, 209 cgltf_primitive_type_line_strip, 210 cgltf_primitive_type_triangles, 211 cgltf_primitive_type_triangle_strip, 212 cgltf_primitive_type_triangle_fan, 213 cgltf_primitive_type_max_enum 214 } cgltf_primitive_type; 215 216 typedef enum cgltf_alpha_mode 217 { 218 cgltf_alpha_mode_opaque, 219 cgltf_alpha_mode_mask, 220 cgltf_alpha_mode_blend, 221 cgltf_alpha_mode_max_enum 222 } cgltf_alpha_mode; 223 224 typedef enum cgltf_animation_path_type { 225 cgltf_animation_path_type_invalid, 226 cgltf_animation_path_type_translation, 227 cgltf_animation_path_type_rotation, 228 cgltf_animation_path_type_scale, 229 cgltf_animation_path_type_weights, 230 cgltf_animation_path_type_max_enum 231 } cgltf_animation_path_type; 232 233 typedef enum cgltf_interpolation_type { 234 cgltf_interpolation_type_linear, 235 cgltf_interpolation_type_step, 236 cgltf_interpolation_type_cubic_spline, 237 cgltf_interpolation_type_max_enum 238 } cgltf_interpolation_type; 239 240 typedef enum cgltf_camera_type { 241 cgltf_camera_type_invalid, 242 cgltf_camera_type_perspective, 243 cgltf_camera_type_orthographic, 244 cgltf_camera_type_max_enum 245 } cgltf_camera_type; 246 247 typedef enum cgltf_light_type { 248 cgltf_light_type_invalid, 249 cgltf_light_type_directional, 250 cgltf_light_type_point, 251 cgltf_light_type_spot, 252 cgltf_light_type_max_enum 253 } cgltf_light_type; 254 255 typedef enum cgltf_data_free_method { 256 cgltf_data_free_method_none, 257 cgltf_data_free_method_file_release, 258 cgltf_data_free_method_memory_free, 259 cgltf_data_free_method_max_enum 260 } cgltf_data_free_method; 261 262 typedef struct cgltf_extras { 263 cgltf_size start_offset; /* this field is deprecated and will be removed in the future; use data instead */ 264 cgltf_size end_offset; /* this field is deprecated and will be removed in the future; use data instead */ 265 266 char* data; 267 } cgltf_extras; 268 269 typedef struct cgltf_extension { 270 char* name; 271 char* data; 272 } cgltf_extension; 273 274 typedef struct cgltf_buffer 275 { 276 char* name; 277 cgltf_size size; 278 char* uri; 279 void* data; /* loaded by cgltf_load_buffers */ 280 cgltf_data_free_method data_free_method; 281 cgltf_extras extras; 282 cgltf_size extensions_count; 283 cgltf_extension* extensions; 284 } cgltf_buffer; 285 286 typedef enum cgltf_meshopt_compression_mode { 287 cgltf_meshopt_compression_mode_invalid, 288 cgltf_meshopt_compression_mode_attributes, 289 cgltf_meshopt_compression_mode_triangles, 290 cgltf_meshopt_compression_mode_indices, 291 cgltf_meshopt_compression_mode_max_enum 292 } cgltf_meshopt_compression_mode; 293 294 typedef enum cgltf_meshopt_compression_filter { 295 cgltf_meshopt_compression_filter_none, 296 cgltf_meshopt_compression_filter_octahedral, 297 cgltf_meshopt_compression_filter_quaternion, 298 cgltf_meshopt_compression_filter_exponential, 299 cgltf_meshopt_compression_filter_max_enum 300 } cgltf_meshopt_compression_filter; 301 302 typedef struct cgltf_meshopt_compression 303 { 304 cgltf_buffer* buffer; 305 cgltf_size offset; 306 cgltf_size size; 307 cgltf_size stride; 308 cgltf_size count; 309 cgltf_meshopt_compression_mode mode; 310 cgltf_meshopt_compression_filter filter; 311 } cgltf_meshopt_compression; 312 313 typedef struct cgltf_buffer_view 314 { 315 char *name; 316 cgltf_buffer* buffer; 317 cgltf_size offset; 318 cgltf_size size; 319 cgltf_size stride; /* 0 == automatically determined by accessor */ 320 cgltf_buffer_view_type type; 321 void* data; /* overrides buffer->data if present, filled by extensions */ 322 cgltf_bool has_meshopt_compression; 323 cgltf_meshopt_compression meshopt_compression; 324 cgltf_extras extras; 325 cgltf_size extensions_count; 326 cgltf_extension* extensions; 327 } cgltf_buffer_view; 328 329 typedef struct cgltf_accessor_sparse 330 { 331 cgltf_size count; 332 cgltf_buffer_view* indices_buffer_view; 333 cgltf_size indices_byte_offset; 334 cgltf_component_type indices_component_type; 335 cgltf_buffer_view* values_buffer_view; 336 cgltf_size values_byte_offset; 337 } cgltf_accessor_sparse; 338 339 typedef struct cgltf_accessor 340 { 341 char* name; 342 cgltf_component_type component_type; 343 cgltf_bool normalized; 344 cgltf_type type; 345 cgltf_size offset; 346 cgltf_size count; 347 cgltf_size stride; 348 cgltf_buffer_view* buffer_view; 349 cgltf_bool has_min; 350 cgltf_float min[16]; 351 cgltf_bool has_max; 352 cgltf_float max[16]; 353 cgltf_bool is_sparse; 354 cgltf_accessor_sparse sparse; 355 cgltf_extras extras; 356 cgltf_size extensions_count; 357 cgltf_extension* extensions; 358 } cgltf_accessor; 359 360 typedef struct cgltf_attribute 361 { 362 char* name; 363 cgltf_attribute_type type; 364 cgltf_int index; 365 cgltf_accessor* data; 366 } cgltf_attribute; 367 368 typedef struct cgltf_image 369 { 370 char* name; 371 char* uri; 372 cgltf_buffer_view* buffer_view; 373 char* mime_type; 374 cgltf_extras extras; 375 cgltf_size extensions_count; 376 cgltf_extension* extensions; 377 } cgltf_image; 378 379 typedef struct cgltf_sampler 380 { 381 char* name; 382 cgltf_int mag_filter; 383 cgltf_int min_filter; 384 cgltf_int wrap_s; 385 cgltf_int wrap_t; 386 cgltf_extras extras; 387 cgltf_size extensions_count; 388 cgltf_extension* extensions; 389 } cgltf_sampler; 390 391 typedef struct cgltf_texture 392 { 393 char* name; 394 cgltf_image* image; 395 cgltf_sampler* sampler; 396 cgltf_bool has_basisu; 397 cgltf_image* basisu_image; 398 cgltf_bool has_webp; 399 cgltf_image* webp_image; 400 cgltf_extras extras; 401 cgltf_size extensions_count; 402 cgltf_extension* extensions; 403 } cgltf_texture; 404 405 typedef struct cgltf_texture_transform 406 { 407 cgltf_float offset[2]; 408 cgltf_float rotation; 409 cgltf_float scale[2]; 410 cgltf_bool has_texcoord; 411 cgltf_int texcoord; 412 } cgltf_texture_transform; 413 414 typedef struct cgltf_texture_view 415 { 416 cgltf_texture* texture; 417 cgltf_int texcoord; 418 cgltf_float scale; /* equivalent to strength for occlusion_texture */ 419 cgltf_bool has_transform; 420 cgltf_texture_transform transform; 421 } cgltf_texture_view; 422 423 typedef struct cgltf_pbr_metallic_roughness 424 { 425 cgltf_texture_view base_color_texture; 426 cgltf_texture_view metallic_roughness_texture; 427 428 cgltf_float base_color_factor[4]; 429 cgltf_float metallic_factor; 430 cgltf_float roughness_factor; 431 } cgltf_pbr_metallic_roughness; 432 433 typedef struct cgltf_pbr_specular_glossiness 434 { 435 cgltf_texture_view diffuse_texture; 436 cgltf_texture_view specular_glossiness_texture; 437 438 cgltf_float diffuse_factor[4]; 439 cgltf_float specular_factor[3]; 440 cgltf_float glossiness_factor; 441 } cgltf_pbr_specular_glossiness; 442 443 typedef struct cgltf_clearcoat 444 { 445 cgltf_texture_view clearcoat_texture; 446 cgltf_texture_view clearcoat_roughness_texture; 447 cgltf_texture_view clearcoat_normal_texture; 448 449 cgltf_float clearcoat_factor; 450 cgltf_float clearcoat_roughness_factor; 451 } cgltf_clearcoat; 452 453 typedef struct cgltf_transmission 454 { 455 cgltf_texture_view transmission_texture; 456 cgltf_float transmission_factor; 457 } cgltf_transmission; 458 459 typedef struct cgltf_ior 460 { 461 cgltf_float ior; 462 } cgltf_ior; 463 464 typedef struct cgltf_specular 465 { 466 cgltf_texture_view specular_texture; 467 cgltf_texture_view specular_color_texture; 468 cgltf_float specular_color_factor[3]; 469 cgltf_float specular_factor; 470 } cgltf_specular; 471 472 typedef struct cgltf_volume 473 { 474 cgltf_texture_view thickness_texture; 475 cgltf_float thickness_factor; 476 cgltf_float attenuation_color[3]; 477 cgltf_float attenuation_distance; 478 } cgltf_volume; 479 480 typedef struct cgltf_sheen 481 { 482 cgltf_texture_view sheen_color_texture; 483 cgltf_float sheen_color_factor[3]; 484 cgltf_texture_view sheen_roughness_texture; 485 cgltf_float sheen_roughness_factor; 486 } cgltf_sheen; 487 488 typedef struct cgltf_emissive_strength 489 { 490 cgltf_float emissive_strength; 491 } cgltf_emissive_strength; 492 493 typedef struct cgltf_iridescence 494 { 495 cgltf_float iridescence_factor; 496 cgltf_texture_view iridescence_texture; 497 cgltf_float iridescence_ior; 498 cgltf_float iridescence_thickness_min; 499 cgltf_float iridescence_thickness_max; 500 cgltf_texture_view iridescence_thickness_texture; 501 } cgltf_iridescence; 502 503 typedef struct cgltf_anisotropy 504 { 505 cgltf_float anisotropy_strength; 506 cgltf_float anisotropy_rotation; 507 cgltf_texture_view anisotropy_texture; 508 } cgltf_anisotropy; 509 510 typedef struct cgltf_dispersion 511 { 512 cgltf_float dispersion; 513 } cgltf_dispersion; 514 515 typedef struct cgltf_material 516 { 517 char* name; 518 cgltf_bool has_pbr_metallic_roughness; 519 cgltf_bool has_pbr_specular_glossiness; 520 cgltf_bool has_clearcoat; 521 cgltf_bool has_transmission; 522 cgltf_bool has_volume; 523 cgltf_bool has_ior; 524 cgltf_bool has_specular; 525 cgltf_bool has_sheen; 526 cgltf_bool has_emissive_strength; 527 cgltf_bool has_iridescence; 528 cgltf_bool has_anisotropy; 529 cgltf_bool has_dispersion; 530 cgltf_pbr_metallic_roughness pbr_metallic_roughness; 531 cgltf_pbr_specular_glossiness pbr_specular_glossiness; 532 cgltf_clearcoat clearcoat; 533 cgltf_ior ior; 534 cgltf_specular specular; 535 cgltf_sheen sheen; 536 cgltf_transmission transmission; 537 cgltf_volume volume; 538 cgltf_emissive_strength emissive_strength; 539 cgltf_iridescence iridescence; 540 cgltf_anisotropy anisotropy; 541 cgltf_dispersion dispersion; 542 cgltf_texture_view normal_texture; 543 cgltf_texture_view occlusion_texture; 544 cgltf_texture_view emissive_texture; 545 cgltf_float emissive_factor[3]; 546 cgltf_alpha_mode alpha_mode; 547 cgltf_float alpha_cutoff; 548 cgltf_bool double_sided; 549 cgltf_bool unlit; 550 cgltf_extras extras; 551 cgltf_size extensions_count; 552 cgltf_extension* extensions; 553 } cgltf_material; 554 555 typedef struct cgltf_material_mapping 556 { 557 cgltf_size variant; 558 cgltf_material* material; 559 cgltf_extras extras; 560 } cgltf_material_mapping; 561 562 typedef struct cgltf_morph_target { 563 cgltf_attribute* attributes; 564 cgltf_size attributes_count; 565 } cgltf_morph_target; 566 567 typedef struct cgltf_draco_mesh_compression { 568 cgltf_buffer_view* buffer_view; 569 cgltf_attribute* attributes; 570 cgltf_size attributes_count; 571 } cgltf_draco_mesh_compression; 572 573 typedef struct cgltf_mesh_gpu_instancing { 574 cgltf_attribute* attributes; 575 cgltf_size attributes_count; 576 } cgltf_mesh_gpu_instancing; 577 578 typedef struct cgltf_primitive { 579 cgltf_primitive_type type; 580 cgltf_accessor* indices; 581 cgltf_material* material; 582 cgltf_attribute* attributes; 583 cgltf_size attributes_count; 584 cgltf_morph_target* targets; 585 cgltf_size targets_count; 586 cgltf_extras extras; 587 cgltf_bool has_draco_mesh_compression; 588 cgltf_draco_mesh_compression draco_mesh_compression; 589 cgltf_material_mapping* mappings; 590 cgltf_size mappings_count; 591 cgltf_size extensions_count; 592 cgltf_extension* extensions; 593 } cgltf_primitive; 594 595 typedef struct cgltf_mesh { 596 char* name; 597 cgltf_primitive* primitives; 598 cgltf_size primitives_count; 599 cgltf_float* weights; 600 cgltf_size weights_count; 601 char** target_names; 602 cgltf_size target_names_count; 603 cgltf_extras extras; 604 cgltf_size extensions_count; 605 cgltf_extension* extensions; 606 } cgltf_mesh; 607 608 typedef struct cgltf_node cgltf_node; 609 610 typedef struct cgltf_skin { 611 char* name; 612 cgltf_node** joints; 613 cgltf_size joints_count; 614 cgltf_node* skeleton; 615 cgltf_accessor* inverse_bind_matrices; 616 cgltf_extras extras; 617 cgltf_size extensions_count; 618 cgltf_extension* extensions; 619 } cgltf_skin; 620 621 typedef struct cgltf_camera_perspective { 622 cgltf_bool has_aspect_ratio; 623 cgltf_float aspect_ratio; 624 cgltf_float yfov; 625 cgltf_bool has_zfar; 626 cgltf_float zfar; 627 cgltf_float znear; 628 cgltf_extras extras; 629 } cgltf_camera_perspective; 630 631 typedef struct cgltf_camera_orthographic { 632 cgltf_float xmag; 633 cgltf_float ymag; 634 cgltf_float zfar; 635 cgltf_float znear; 636 cgltf_extras extras; 637 } cgltf_camera_orthographic; 638 639 typedef struct cgltf_camera { 640 char* name; 641 cgltf_camera_type type; 642 union { 643 cgltf_camera_perspective perspective; 644 cgltf_camera_orthographic orthographic; 645 } data; 646 cgltf_extras extras; 647 cgltf_size extensions_count; 648 cgltf_extension* extensions; 649 } cgltf_camera; 650 651 typedef struct cgltf_light { 652 char* name; 653 cgltf_float color[3]; 654 cgltf_float intensity; 655 cgltf_light_type type; 656 cgltf_float range; 657 cgltf_float spot_inner_cone_angle; 658 cgltf_float spot_outer_cone_angle; 659 cgltf_extras extras; 660 } cgltf_light; 661 662 struct cgltf_node { 663 char* name; 664 cgltf_node* parent; 665 cgltf_node** children; 666 cgltf_size children_count; 667 cgltf_skin* skin; 668 cgltf_mesh* mesh; 669 cgltf_camera* camera; 670 cgltf_light* light; 671 cgltf_float* weights; 672 cgltf_size weights_count; 673 cgltf_bool has_translation; 674 cgltf_bool has_rotation; 675 cgltf_bool has_scale; 676 cgltf_bool has_matrix; 677 cgltf_float translation[3]; 678 cgltf_float rotation[4]; 679 cgltf_float scale[3]; 680 cgltf_float matrix[16]; 681 cgltf_extras extras; 682 cgltf_bool has_mesh_gpu_instancing; 683 cgltf_mesh_gpu_instancing mesh_gpu_instancing; 684 cgltf_size extensions_count; 685 cgltf_extension* extensions; 686 }; 687 688 typedef struct cgltf_scene { 689 char* name; 690 cgltf_node** nodes; 691 cgltf_size nodes_count; 692 cgltf_extras extras; 693 cgltf_size extensions_count; 694 cgltf_extension* extensions; 695 } cgltf_scene; 696 697 typedef struct cgltf_animation_sampler { 698 cgltf_accessor* input; 699 cgltf_accessor* output; 700 cgltf_interpolation_type interpolation; 701 cgltf_extras extras; 702 cgltf_size extensions_count; 703 cgltf_extension* extensions; 704 } cgltf_animation_sampler; 705 706 typedef struct cgltf_animation_channel { 707 cgltf_animation_sampler* sampler; 708 cgltf_node* target_node; 709 cgltf_animation_path_type target_path; 710 cgltf_extras extras; 711 cgltf_size extensions_count; 712 cgltf_extension* extensions; 713 } cgltf_animation_channel; 714 715 typedef struct cgltf_animation { 716 char* name; 717 cgltf_animation_sampler* samplers; 718 cgltf_size samplers_count; 719 cgltf_animation_channel* channels; 720 cgltf_size channels_count; 721 cgltf_extras extras; 722 cgltf_size extensions_count; 723 cgltf_extension* extensions; 724 } cgltf_animation; 725 726 typedef struct cgltf_material_variant 727 { 728 char* name; 729 cgltf_extras extras; 730 } cgltf_material_variant; 731 732 typedef struct cgltf_asset { 733 char* copyright; 734 char* generator; 735 char* version; 736 char* min_version; 737 cgltf_extras extras; 738 cgltf_size extensions_count; 739 cgltf_extension* extensions; 740 } cgltf_asset; 741 742 typedef struct cgltf_data 743 { 744 cgltf_file_type file_type; 745 void* file_data; 746 747 cgltf_asset asset; 748 749 cgltf_mesh* meshes; 750 cgltf_size meshes_count; 751 752 cgltf_material* materials; 753 cgltf_size materials_count; 754 755 cgltf_accessor* accessors; 756 cgltf_size accessors_count; 757 758 cgltf_buffer_view* buffer_views; 759 cgltf_size buffer_views_count; 760 761 cgltf_buffer* buffers; 762 cgltf_size buffers_count; 763 764 cgltf_image* images; 765 cgltf_size images_count; 766 767 cgltf_texture* textures; 768 cgltf_size textures_count; 769 770 cgltf_sampler* samplers; 771 cgltf_size samplers_count; 772 773 cgltf_skin* skins; 774 cgltf_size skins_count; 775 776 cgltf_camera* cameras; 777 cgltf_size cameras_count; 778 779 cgltf_light* lights; 780 cgltf_size lights_count; 781 782 cgltf_node* nodes; 783 cgltf_size nodes_count; 784 785 cgltf_scene* scenes; 786 cgltf_size scenes_count; 787 788 cgltf_scene* scene; 789 790 cgltf_animation* animations; 791 cgltf_size animations_count; 792 793 cgltf_material_variant* variants; 794 cgltf_size variants_count; 795 796 cgltf_extras extras; 797 798 cgltf_size data_extensions_count; 799 cgltf_extension* data_extensions; 800 801 char** extensions_used; 802 cgltf_size extensions_used_count; 803 804 char** extensions_required; 805 cgltf_size extensions_required_count; 806 807 const char* json; 808 cgltf_size json_size; 809 810 const void* bin; 811 cgltf_size bin_size; 812 813 cgltf_memory_options memory; 814 cgltf_file_options file; 815 } cgltf_data; 816 817 cgltf_result cgltf_parse( 818 const cgltf_options* options, 819 const void* data, 820 cgltf_size size, 821 cgltf_data** out_data); 822 823 cgltf_result cgltf_parse_file( 824 const cgltf_options* options, 825 const char* path, 826 cgltf_data** out_data); 827 828 cgltf_result cgltf_load_buffers( 829 const cgltf_options* options, 830 cgltf_data* data, 831 const char* gltf_path); 832 833 cgltf_result cgltf_load_buffer_base64(const cgltf_options* options, cgltf_size size, const char* base64, void** out_data); 834 835 cgltf_size cgltf_decode_string(char* string); 836 cgltf_size cgltf_decode_uri(char* uri); 837 838 cgltf_result cgltf_validate(cgltf_data* data); 839 840 void cgltf_free(cgltf_data* data); 841 842 void cgltf_node_transform_local(const cgltf_node* node, cgltf_float* out_matrix); 843 void cgltf_node_transform_world(const cgltf_node* node, cgltf_float* out_matrix); 844 845 const uint8_t* cgltf_buffer_view_data(const cgltf_buffer_view* view); 846 847 cgltf_bool cgltf_accessor_read_float(const cgltf_accessor* accessor, cgltf_size index, cgltf_float* out, cgltf_size element_size); 848 cgltf_bool cgltf_accessor_read_uint(const cgltf_accessor* accessor, cgltf_size index, cgltf_uint* out, cgltf_size element_size); 849 cgltf_size cgltf_accessor_read_index(const cgltf_accessor* accessor, cgltf_size index); 850 851 cgltf_size cgltf_num_components(cgltf_type type); 852 cgltf_size cgltf_component_size(cgltf_component_type component_type); 853 cgltf_size cgltf_calc_size(cgltf_type type, cgltf_component_type component_type); 854 855 cgltf_size cgltf_accessor_unpack_floats(const cgltf_accessor* accessor, cgltf_float* out, cgltf_size float_count); 856 cgltf_size cgltf_accessor_unpack_indices(const cgltf_accessor* accessor, void* out, cgltf_size out_component_size, cgltf_size index_count); 857 858 /* this function is deprecated and will be removed in the future; use cgltf_extras::data instead */ 859 cgltf_result cgltf_copy_extras_json(const cgltf_data* data, const cgltf_extras* extras, char* dest, cgltf_size* dest_size); 860 861 cgltf_size cgltf_mesh_index(const cgltf_data* data, const cgltf_mesh* object); 862 cgltf_size cgltf_material_index(const cgltf_data* data, const cgltf_material* object); 863 cgltf_size cgltf_accessor_index(const cgltf_data* data, const cgltf_accessor* object); 864 cgltf_size cgltf_buffer_view_index(const cgltf_data* data, const cgltf_buffer_view* object); 865 cgltf_size cgltf_buffer_index(const cgltf_data* data, const cgltf_buffer* object); 866 cgltf_size cgltf_image_index(const cgltf_data* data, const cgltf_image* object); 867 cgltf_size cgltf_texture_index(const cgltf_data* data, const cgltf_texture* object); 868 cgltf_size cgltf_sampler_index(const cgltf_data* data, const cgltf_sampler* object); 869 cgltf_size cgltf_skin_index(const cgltf_data* data, const cgltf_skin* object); 870 cgltf_size cgltf_camera_index(const cgltf_data* data, const cgltf_camera* object); 871 cgltf_size cgltf_light_index(const cgltf_data* data, const cgltf_light* object); 872 cgltf_size cgltf_node_index(const cgltf_data* data, const cgltf_node* object); 873 cgltf_size cgltf_scene_index(const cgltf_data* data, const cgltf_scene* object); 874 cgltf_size cgltf_animation_index(const cgltf_data* data, const cgltf_animation* object); 875 cgltf_size cgltf_animation_sampler_index(const cgltf_animation* animation, const cgltf_animation_sampler* object); 876 cgltf_size cgltf_animation_channel_index(const cgltf_animation* animation, const cgltf_animation_channel* object); 877 878 #ifdef __cplusplus 879 } 880 #endif 881 882 #endif /* #ifndef CGLTF_H_INCLUDED__ */ 883 884 /* 885 * 886 * Stop now, if you are only interested in the API. 887 * Below, you find the implementation. 888 * 889 */ 890 891 #if defined(__INTELLISENSE__) || defined(__JETBRAINS_IDE__) 892 /* This makes MSVC/CLion intellisense work. */ 893 #define CGLTF_IMPLEMENTATION 894 #endif 895 896 #ifdef CGLTF_IMPLEMENTATION 897 898 #include <assert.h> /* For assert */ 899 #include <string.h> /* For strncpy */ 900 #include <stdio.h> /* For fopen */ 901 #include <limits.h> /* For UINT_MAX etc */ 902 #include <float.h> /* For FLT_MAX */ 903 904 #if !defined(CGLTF_MALLOC) || !defined(CGLTF_FREE) || !defined(CGLTF_ATOI) || !defined(CGLTF_ATOF) || !defined(CGLTF_ATOLL) 905 #include <stdlib.h> /* For malloc, free, atoi, atof */ 906 #endif 907 908 /* JSMN_PARENT_LINKS is necessary to make parsing large structures linear in input size */ 909 #define JSMN_PARENT_LINKS 910 911 /* JSMN_STRICT is necessary to reject invalid JSON documents */ 912 #define JSMN_STRICT 913 914 /* 915 * -- jsmn.h start -- 916 * Source: https://github.com/zserge/jsmn 917 * License: MIT 918 */ 919 typedef enum { 920 JSMN_UNDEFINED = 0, 921 JSMN_OBJECT = 1, 922 JSMN_ARRAY = 2, 923 JSMN_STRING = 3, 924 JSMN_PRIMITIVE = 4 925 } jsmntype_t; 926 enum jsmnerr { 927 /* Not enough tokens were provided */ 928 JSMN_ERROR_NOMEM = -1, 929 /* Invalid character inside JSON string */ 930 JSMN_ERROR_INVAL = -2, 931 /* The string is not a full JSON packet, more bytes expected */ 932 JSMN_ERROR_PART = -3 933 }; 934 typedef struct { 935 jsmntype_t type; 936 ptrdiff_t start; 937 ptrdiff_t end; 938 int size; 939 #ifdef JSMN_PARENT_LINKS 940 int parent; 941 #endif 942 } jsmntok_t; 943 typedef struct { 944 size_t pos; /* offset in the JSON string */ 945 unsigned int toknext; /* next token to allocate */ 946 int toksuper; /* superior token node, e.g parent object or array */ 947 } jsmn_parser; 948 static void jsmn_init(jsmn_parser *parser); 949 static int jsmn_parse(jsmn_parser *parser, const char *js, size_t len, jsmntok_t *tokens, size_t num_tokens); 950 /* 951 * -- jsmn.h end -- 952 */ 953 954 955 #ifndef CGLTF_CONSTS 956 #define GlbHeaderSize 12 957 #define GlbChunkHeaderSize 8 958 static const uint32_t GlbVersion = 2; 959 static const uint32_t GlbMagic = 0x46546C67; 960 static const uint32_t GlbMagicJsonChunk = 0x4E4F534A; 961 static const uint32_t GlbMagicBinChunk = 0x004E4942; 962 #define CGLTF_CONSTS 963 #endif 964 965 #ifndef CGLTF_MALLOC 966 #define CGLTF_MALLOC(size) malloc(size) 967 #endif 968 #ifndef CGLTF_FREE 969 #define CGLTF_FREE(ptr) free(ptr) 970 #endif 971 #ifndef CGLTF_ATOI 972 #define CGLTF_ATOI(str) atoi(str) 973 #endif 974 #ifndef CGLTF_ATOF 975 #define CGLTF_ATOF(str) atof(str) 976 #endif 977 #ifndef CGLTF_ATOLL 978 #define CGLTF_ATOLL(str) atoll(str) 979 #endif 980 #ifndef CGLTF_VALIDATE_ENABLE_ASSERTS 981 #define CGLTF_VALIDATE_ENABLE_ASSERTS 0 982 #endif 983 984 static void* cgltf_default_alloc(void* user, cgltf_size size) 985 { 986 (void)user; 987 return CGLTF_MALLOC(size); 988 } 989 990 static void cgltf_default_free(void* user, void* ptr) 991 { 992 (void)user; 993 CGLTF_FREE(ptr); 994 } 995 996 static void* cgltf_calloc(cgltf_options* options, size_t element_size, cgltf_size count) 997 { 998 if (SIZE_MAX / element_size < count) 999 { 1000 return NULL; 1001 } 1002 void* result = options->memory.alloc_func(options->memory.user_data, element_size * count); 1003 if (!result) 1004 { 1005 return NULL; 1006 } 1007 memset(result, 0, element_size * count); 1008 return result; 1009 } 1010 1011 static cgltf_result cgltf_default_file_read(const struct cgltf_memory_options* memory_options, const struct cgltf_file_options* file_options, const char* path, cgltf_size* size, void** data) 1012 { 1013 (void)file_options; 1014 void* (*memory_alloc)(void*, cgltf_size) = memory_options->alloc_func ? memory_options->alloc_func : &cgltf_default_alloc; 1015 void (*memory_free)(void*, void*) = memory_options->free_func ? memory_options->free_func : &cgltf_default_free; 1016 1017 FILE* file = fopen(path, "rb"); 1018 if (!file) 1019 { 1020 return cgltf_result_file_not_found; 1021 } 1022 1023 cgltf_size file_size = size ? *size : 0; 1024 1025 if (file_size == 0) 1026 { 1027 fseek(file, 0, SEEK_END); 1028 1029 #ifdef _MSC_VER 1030 __int64 length = _ftelli64(file); 1031 #else 1032 long length = ftell(file); 1033 #endif 1034 1035 if (length < 0) 1036 { 1037 fclose(file); 1038 return cgltf_result_io_error; 1039 } 1040 1041 fseek(file, 0, SEEK_SET); 1042 file_size = (cgltf_size)length; 1043 } 1044 1045 char* file_data = (char*)memory_alloc(memory_options->user_data, file_size); 1046 if (!file_data) 1047 { 1048 fclose(file); 1049 return cgltf_result_out_of_memory; 1050 } 1051 1052 cgltf_size read_size = fread(file_data, 1, file_size, file); 1053 1054 fclose(file); 1055 1056 if (read_size != file_size) 1057 { 1058 memory_free(memory_options->user_data, file_data); 1059 return cgltf_result_io_error; 1060 } 1061 1062 if (size) 1063 { 1064 *size = file_size; 1065 } 1066 if (data) 1067 { 1068 *data = file_data; 1069 } 1070 1071 return cgltf_result_success; 1072 } 1073 1074 static void cgltf_default_file_release(const struct cgltf_memory_options* memory_options, const struct cgltf_file_options* file_options, void* data) 1075 { 1076 (void)file_options; 1077 void (*memfree)(void*, void*) = memory_options->free_func ? memory_options->free_func : &cgltf_default_free; 1078 memfree(memory_options->user_data, data); 1079 } 1080 1081 static cgltf_result cgltf_parse_json(cgltf_options* options, const uint8_t* json_chunk, cgltf_size size, cgltf_data** out_data); 1082 1083 cgltf_result cgltf_parse(const cgltf_options* options, const void* data, cgltf_size size, cgltf_data** out_data) 1084 { 1085 if (size < GlbHeaderSize) 1086 { 1087 return cgltf_result_data_too_short; 1088 } 1089 1090 if (options == NULL) 1091 { 1092 return cgltf_result_invalid_options; 1093 } 1094 1095 cgltf_options fixed_options = *options; 1096 if (fixed_options.memory.alloc_func == NULL) 1097 { 1098 fixed_options.memory.alloc_func = &cgltf_default_alloc; 1099 } 1100 if (fixed_options.memory.free_func == NULL) 1101 { 1102 fixed_options.memory.free_func = &cgltf_default_free; 1103 } 1104 1105 uint32_t tmp; 1106 // Magic 1107 memcpy(&tmp, data, 4); 1108 if (tmp != GlbMagic) 1109 { 1110 if (fixed_options.type == cgltf_file_type_invalid) 1111 { 1112 fixed_options.type = cgltf_file_type_gltf; 1113 } 1114 else if (fixed_options.type == cgltf_file_type_glb) 1115 { 1116 return cgltf_result_unknown_format; 1117 } 1118 } 1119 1120 if (fixed_options.type == cgltf_file_type_gltf) 1121 { 1122 cgltf_result json_result = cgltf_parse_json(&fixed_options, (const uint8_t*)data, size, out_data); 1123 if (json_result != cgltf_result_success) 1124 { 1125 return json_result; 1126 } 1127 1128 (*out_data)->file_type = cgltf_file_type_gltf; 1129 1130 return cgltf_result_success; 1131 } 1132 1133 const uint8_t* ptr = (const uint8_t*)data; 1134 // Version 1135 memcpy(&tmp, ptr + 4, 4); 1136 uint32_t version = tmp; 1137 if (version != GlbVersion) 1138 { 1139 return version < GlbVersion ? cgltf_result_legacy_gltf : cgltf_result_unknown_format; 1140 } 1141 1142 // Total length 1143 memcpy(&tmp, ptr + 8, 4); 1144 if (tmp > size) 1145 { 1146 return cgltf_result_data_too_short; 1147 } 1148 1149 const uint8_t* json_chunk = ptr + GlbHeaderSize; 1150 1151 if (GlbHeaderSize + GlbChunkHeaderSize > size) 1152 { 1153 return cgltf_result_data_too_short; 1154 } 1155 1156 // JSON chunk: length 1157 uint32_t json_length; 1158 memcpy(&json_length, json_chunk, 4); 1159 if (json_length > size - GlbHeaderSize - GlbChunkHeaderSize) 1160 { 1161 return cgltf_result_data_too_short; 1162 } 1163 1164 // JSON chunk: magic 1165 memcpy(&tmp, json_chunk + 4, 4); 1166 if (tmp != GlbMagicJsonChunk) 1167 { 1168 return cgltf_result_unknown_format; 1169 } 1170 1171 json_chunk += GlbChunkHeaderSize; 1172 1173 const void* bin = NULL; 1174 cgltf_size bin_size = 0; 1175 1176 if (GlbChunkHeaderSize <= size - GlbHeaderSize - GlbChunkHeaderSize - json_length) 1177 { 1178 // We can read another chunk 1179 const uint8_t* bin_chunk = json_chunk + json_length; 1180 1181 // Bin chunk: length 1182 uint32_t bin_length; 1183 memcpy(&bin_length, bin_chunk, 4); 1184 if (bin_length > size - GlbHeaderSize - GlbChunkHeaderSize - json_length - GlbChunkHeaderSize) 1185 { 1186 return cgltf_result_data_too_short; 1187 } 1188 1189 // Bin chunk: magic 1190 memcpy(&tmp, bin_chunk + 4, 4); 1191 if (tmp != GlbMagicBinChunk) 1192 { 1193 return cgltf_result_unknown_format; 1194 } 1195 1196 bin_chunk += GlbChunkHeaderSize; 1197 1198 bin = bin_chunk; 1199 bin_size = bin_length; 1200 } 1201 1202 cgltf_result json_result = cgltf_parse_json(&fixed_options, json_chunk, json_length, out_data); 1203 if (json_result != cgltf_result_success) 1204 { 1205 return json_result; 1206 } 1207 1208 (*out_data)->file_type = cgltf_file_type_glb; 1209 (*out_data)->bin = bin; 1210 (*out_data)->bin_size = bin_size; 1211 1212 return cgltf_result_success; 1213 } 1214 1215 cgltf_result cgltf_parse_file(const cgltf_options* options, const char* path, cgltf_data** out_data) 1216 { 1217 if (options == NULL) 1218 { 1219 return cgltf_result_invalid_options; 1220 } 1221 1222 cgltf_result (*file_read)(const struct cgltf_memory_options*, const struct cgltf_file_options*, const char*, cgltf_size*, void**) = options->file.read ? options->file.read : &cgltf_default_file_read; 1223 void (*file_release)(const struct cgltf_memory_options*, const struct cgltf_file_options*, void* data) = options->file.release ? options->file.release : cgltf_default_file_release; 1224 1225 void* file_data = NULL; 1226 cgltf_size file_size = 0; 1227 cgltf_result result = file_read(&options->memory, &options->file, path, &file_size, &file_data); 1228 if (result != cgltf_result_success) 1229 { 1230 return result; 1231 } 1232 1233 result = cgltf_parse(options, file_data, file_size, out_data); 1234 1235 if (result != cgltf_result_success) 1236 { 1237 file_release(&options->memory, &options->file, file_data); 1238 return result; 1239 } 1240 1241 (*out_data)->file_data = file_data; 1242 1243 return cgltf_result_success; 1244 } 1245 1246 static void cgltf_combine_paths(char* path, const char* base, const char* uri) 1247 { 1248 const char* s0 = strrchr(base, '/'); 1249 const char* s1 = strrchr(base, '\\'); 1250 const char* slash = s0 ? (s1 && s1 > s0 ? s1 : s0) : s1; 1251 1252 if (slash) 1253 { 1254 size_t prefix = slash - base + 1; 1255 1256 strncpy(path, base, prefix); 1257 strcpy(path + prefix, uri); 1258 } 1259 else 1260 { 1261 strcpy(path, uri); 1262 } 1263 } 1264 1265 static cgltf_result cgltf_load_buffer_file(const cgltf_options* options, cgltf_size size, const char* uri, const char* gltf_path, void** out_data) 1266 { 1267 void* (*memory_alloc)(void*, cgltf_size) = options->memory.alloc_func ? options->memory.alloc_func : &cgltf_default_alloc; 1268 void (*memory_free)(void*, void*) = options->memory.free_func ? options->memory.free_func : &cgltf_default_free; 1269 cgltf_result (*file_read)(const struct cgltf_memory_options*, const struct cgltf_file_options*, const char*, cgltf_size*, void**) = options->file.read ? options->file.read : &cgltf_default_file_read; 1270 1271 char* path = (char*)memory_alloc(options->memory.user_data, strlen(uri) + strlen(gltf_path) + 1); 1272 if (!path) 1273 { 1274 return cgltf_result_out_of_memory; 1275 } 1276 1277 cgltf_combine_paths(path, gltf_path, uri); 1278 1279 // after combining, the tail of the resulting path is a uri; decode_uri converts it into path 1280 cgltf_decode_uri(path + strlen(path) - strlen(uri)); 1281 1282 void* file_data = NULL; 1283 cgltf_result result = file_read(&options->memory, &options->file, path, &size, &file_data); 1284 1285 memory_free(options->memory.user_data, path); 1286 1287 *out_data = (result == cgltf_result_success) ? file_data : NULL; 1288 1289 return result; 1290 } 1291 1292 cgltf_result cgltf_load_buffer_base64(const cgltf_options* options, cgltf_size size, const char* base64, void** out_data) 1293 { 1294 void* (*memory_alloc)(void*, cgltf_size) = options->memory.alloc_func ? options->memory.alloc_func : &cgltf_default_alloc; 1295 void (*memory_free)(void*, void*) = options->memory.free_func ? options->memory.free_func : &cgltf_default_free; 1296 1297 unsigned char* data = (unsigned char*)memory_alloc(options->memory.user_data, size); 1298 if (!data) 1299 { 1300 return cgltf_result_out_of_memory; 1301 } 1302 1303 unsigned int buffer = 0; 1304 unsigned int buffer_bits = 0; 1305 1306 for (cgltf_size i = 0; i < size; ++i) 1307 { 1308 while (buffer_bits < 8) 1309 { 1310 char ch = *base64++; 1311 1312 int index = 1313 (unsigned)(ch - 'A') < 26 ? (ch - 'A') : 1314 (unsigned)(ch - 'a') < 26 ? (ch - 'a') + 26 : 1315 (unsigned)(ch - '0') < 10 ? (ch - '0') + 52 : 1316 ch == '+' ? 62 : 1317 ch == '/' ? 63 : 1318 -1; 1319 1320 if (index < 0) 1321 { 1322 memory_free(options->memory.user_data, data); 1323 return cgltf_result_io_error; 1324 } 1325 1326 buffer = (buffer << 6) | index; 1327 buffer_bits += 6; 1328 } 1329 1330 data[i] = (unsigned char)(buffer >> (buffer_bits - 8)); 1331 buffer_bits -= 8; 1332 } 1333 1334 *out_data = data; 1335 1336 return cgltf_result_success; 1337 } 1338 1339 static int cgltf_unhex(char ch) 1340 { 1341 return 1342 (unsigned)(ch - '0') < 10 ? (ch - '0') : 1343 (unsigned)(ch - 'A') < 6 ? (ch - 'A') + 10 : 1344 (unsigned)(ch - 'a') < 6 ? (ch - 'a') + 10 : 1345 -1; 1346 } 1347 1348 cgltf_size cgltf_decode_string(char* string) 1349 { 1350 char* read = string + strcspn(string, "\\"); 1351 if (*read == 0) 1352 { 1353 return read - string; 1354 } 1355 char* write = string; 1356 char* last = string; 1357 1358 for (;;) 1359 { 1360 // Copy characters since last escaped sequence 1361 cgltf_size written = read - last; 1362 memmove(write, last, written); 1363 write += written; 1364 1365 if (*read++ == 0) 1366 { 1367 break; 1368 } 1369 1370 // jsmn already checked that all escape sequences are valid 1371 switch (*read++) 1372 { 1373 case '\"': *write++ = '\"'; break; 1374 case '/': *write++ = '/'; break; 1375 case '\\': *write++ = '\\'; break; 1376 case 'b': *write++ = '\b'; break; 1377 case 'f': *write++ = '\f'; break; 1378 case 'r': *write++ = '\r'; break; 1379 case 'n': *write++ = '\n'; break; 1380 case 't': *write++ = '\t'; break; 1381 case 'u': 1382 { 1383 // UCS-2 codepoint \uXXXX to UTF-8 1384 int character = 0; 1385 for (cgltf_size i = 0; i < 4; ++i) 1386 { 1387 character = (character << 4) + cgltf_unhex(*read++); 1388 } 1389 1390 if (character <= 0x7F) 1391 { 1392 *write++ = character & 0xFF; 1393 } 1394 else if (character <= 0x7FF) 1395 { 1396 *write++ = 0xC0 | ((character >> 6) & 0xFF); 1397 *write++ = 0x80 | (character & 0x3F); 1398 } 1399 else 1400 { 1401 *write++ = 0xE0 | ((character >> 12) & 0xFF); 1402 *write++ = 0x80 | ((character >> 6) & 0x3F); 1403 *write++ = 0x80 | (character & 0x3F); 1404 } 1405 break; 1406 } 1407 default: 1408 break; 1409 } 1410 1411 last = read; 1412 read += strcspn(read, "\\"); 1413 } 1414 1415 *write = 0; 1416 return write - string; 1417 } 1418 1419 cgltf_size cgltf_decode_uri(char* uri) 1420 { 1421 char* write = uri; 1422 char* i = uri; 1423 1424 while (*i) 1425 { 1426 if (*i == '%') 1427 { 1428 int ch1 = cgltf_unhex(i[1]); 1429 1430 if (ch1 >= 0) 1431 { 1432 int ch2 = cgltf_unhex(i[2]); 1433 1434 if (ch2 >= 0) 1435 { 1436 *write++ = (char)(ch1 * 16 + ch2); 1437 i += 3; 1438 continue; 1439 } 1440 } 1441 } 1442 1443 *write++ = *i++; 1444 } 1445 1446 *write = 0; 1447 return write - uri; 1448 } 1449 1450 cgltf_result cgltf_load_buffers(const cgltf_options* options, cgltf_data* data, const char* gltf_path) 1451 { 1452 if (options == NULL) 1453 { 1454 return cgltf_result_invalid_options; 1455 } 1456 1457 if (data->buffers_count && data->buffers[0].data == NULL && data->buffers[0].uri == NULL && data->bin) 1458 { 1459 if (data->bin_size < data->buffers[0].size) 1460 { 1461 return cgltf_result_data_too_short; 1462 } 1463 1464 data->buffers[0].data = (void*)data->bin; 1465 data->buffers[0].data_free_method = cgltf_data_free_method_none; 1466 } 1467 1468 for (cgltf_size i = 0; i < data->buffers_count; ++i) 1469 { 1470 if (data->buffers[i].data) 1471 { 1472 continue; 1473 } 1474 1475 const char* uri = data->buffers[i].uri; 1476 1477 if (uri == NULL) 1478 { 1479 continue; 1480 } 1481 1482 if (strncmp(uri, "data:", 5) == 0) 1483 { 1484 const char* comma = strchr(uri, ','); 1485 1486 if (comma && comma - uri >= 7 && strncmp(comma - 7, ";base64", 7) == 0) 1487 { 1488 cgltf_result res = cgltf_load_buffer_base64(options, data->buffers[i].size, comma + 1, &data->buffers[i].data); 1489 data->buffers[i].data_free_method = cgltf_data_free_method_memory_free; 1490 1491 if (res != cgltf_result_success) 1492 { 1493 return res; 1494 } 1495 } 1496 else 1497 { 1498 return cgltf_result_unknown_format; 1499 } 1500 } 1501 else if (strstr(uri, "://") == NULL && gltf_path) 1502 { 1503 cgltf_result res = cgltf_load_buffer_file(options, data->buffers[i].size, uri, gltf_path, &data->buffers[i].data); 1504 data->buffers[i].data_free_method = cgltf_data_free_method_file_release; 1505 1506 if (res != cgltf_result_success) 1507 { 1508 return res; 1509 } 1510 } 1511 else 1512 { 1513 return cgltf_result_unknown_format; 1514 } 1515 } 1516 1517 return cgltf_result_success; 1518 } 1519 1520 static cgltf_size cgltf_calc_index_bound(cgltf_buffer_view* buffer_view, cgltf_size offset, cgltf_component_type component_type, cgltf_size count) 1521 { 1522 char* data = (char*)buffer_view->buffer->data + offset + buffer_view->offset; 1523 cgltf_size bound = 0; 1524 1525 switch (component_type) 1526 { 1527 case cgltf_component_type_r_8u: 1528 for (size_t i = 0; i < count; ++i) 1529 { 1530 cgltf_size v = ((unsigned char*)data)[i]; 1531 bound = bound > v ? bound : v; 1532 } 1533 break; 1534 1535 case cgltf_component_type_r_16u: 1536 for (size_t i = 0; i < count; ++i) 1537 { 1538 cgltf_size v = ((unsigned short*)data)[i]; 1539 bound = bound > v ? bound : v; 1540 } 1541 break; 1542 1543 case cgltf_component_type_r_32u: 1544 for (size_t i = 0; i < count; ++i) 1545 { 1546 cgltf_size v = ((unsigned int*)data)[i]; 1547 bound = bound > v ? bound : v; 1548 } 1549 break; 1550 1551 default: 1552 ; 1553 } 1554 1555 return bound; 1556 } 1557 1558 #if CGLTF_VALIDATE_ENABLE_ASSERTS 1559 #define CGLTF_ASSERT_IF(cond, result) assert(!(cond)); if (cond) return result; 1560 #else 1561 #define CGLTF_ASSERT_IF(cond, result) if (cond) return result; 1562 #endif 1563 1564 cgltf_result cgltf_validate(cgltf_data* data) 1565 { 1566 for (cgltf_size i = 0; i < data->accessors_count; ++i) 1567 { 1568 cgltf_accessor* accessor = &data->accessors[i]; 1569 1570 CGLTF_ASSERT_IF(data->accessors[i].component_type == cgltf_component_type_invalid, cgltf_result_invalid_gltf); 1571 CGLTF_ASSERT_IF(data->accessors[i].type == cgltf_type_invalid, cgltf_result_invalid_gltf); 1572 1573 cgltf_size element_size = cgltf_calc_size(accessor->type, accessor->component_type); 1574 1575 if (accessor->buffer_view) 1576 { 1577 cgltf_size req_size = accessor->offset + accessor->stride * (accessor->count - 1) + element_size; 1578 1579 CGLTF_ASSERT_IF(accessor->buffer_view->size < req_size, cgltf_result_data_too_short); 1580 } 1581 1582 if (accessor->is_sparse) 1583 { 1584 cgltf_accessor_sparse* sparse = &accessor->sparse; 1585 1586 cgltf_size indices_component_size = cgltf_component_size(sparse->indices_component_type); 1587 cgltf_size indices_req_size = sparse->indices_byte_offset + indices_component_size * sparse->count; 1588 cgltf_size values_req_size = sparse->values_byte_offset + element_size * sparse->count; 1589 1590 CGLTF_ASSERT_IF(sparse->indices_buffer_view->size < indices_req_size || 1591 sparse->values_buffer_view->size < values_req_size, cgltf_result_data_too_short); 1592 1593 CGLTF_ASSERT_IF(sparse->indices_component_type != cgltf_component_type_r_8u && 1594 sparse->indices_component_type != cgltf_component_type_r_16u && 1595 sparse->indices_component_type != cgltf_component_type_r_32u, cgltf_result_invalid_gltf); 1596 1597 if (sparse->indices_buffer_view->buffer->data) 1598 { 1599 cgltf_size index_bound = cgltf_calc_index_bound(sparse->indices_buffer_view, sparse->indices_byte_offset, sparse->indices_component_type, sparse->count); 1600 1601 CGLTF_ASSERT_IF(index_bound >= accessor->count, cgltf_result_data_too_short); 1602 } 1603 } 1604 } 1605 1606 for (cgltf_size i = 0; i < data->buffer_views_count; ++i) 1607 { 1608 cgltf_size req_size = data->buffer_views[i].offset + data->buffer_views[i].size; 1609 1610 CGLTF_ASSERT_IF(data->buffer_views[i].buffer && data->buffer_views[i].buffer->size < req_size, cgltf_result_data_too_short); 1611 1612 if (data->buffer_views[i].has_meshopt_compression) 1613 { 1614 cgltf_meshopt_compression* mc = &data->buffer_views[i].meshopt_compression; 1615 1616 CGLTF_ASSERT_IF(mc->buffer == NULL || mc->buffer->size < mc->offset + mc->size, cgltf_result_data_too_short); 1617 1618 CGLTF_ASSERT_IF(data->buffer_views[i].stride && mc->stride != data->buffer_views[i].stride, cgltf_result_invalid_gltf); 1619 1620 CGLTF_ASSERT_IF(data->buffer_views[i].size != mc->stride * mc->count, cgltf_result_invalid_gltf); 1621 1622 CGLTF_ASSERT_IF(mc->mode == cgltf_meshopt_compression_mode_invalid, cgltf_result_invalid_gltf); 1623 1624 CGLTF_ASSERT_IF(mc->mode == cgltf_meshopt_compression_mode_attributes && !(mc->stride % 4 == 0 && mc->stride <= 256), cgltf_result_invalid_gltf); 1625 1626 CGLTF_ASSERT_IF(mc->mode == cgltf_meshopt_compression_mode_triangles && mc->count % 3 != 0, cgltf_result_invalid_gltf); 1627 1628 CGLTF_ASSERT_IF((mc->mode == cgltf_meshopt_compression_mode_triangles || mc->mode == cgltf_meshopt_compression_mode_indices) && mc->stride != 2 && mc->stride != 4, cgltf_result_invalid_gltf); 1629 1630 CGLTF_ASSERT_IF((mc->mode == cgltf_meshopt_compression_mode_triangles || mc->mode == cgltf_meshopt_compression_mode_indices) && mc->filter != cgltf_meshopt_compression_filter_none, cgltf_result_invalid_gltf); 1631 1632 CGLTF_ASSERT_IF(mc->filter == cgltf_meshopt_compression_filter_octahedral && mc->stride != 4 && mc->stride != 8, cgltf_result_invalid_gltf); 1633 1634 CGLTF_ASSERT_IF(mc->filter == cgltf_meshopt_compression_filter_quaternion && mc->stride != 8, cgltf_result_invalid_gltf); 1635 } 1636 } 1637 1638 for (cgltf_size i = 0; i < data->meshes_count; ++i) 1639 { 1640 if (data->meshes[i].weights) 1641 { 1642 CGLTF_ASSERT_IF(data->meshes[i].primitives_count && data->meshes[i].primitives[0].targets_count != data->meshes[i].weights_count, cgltf_result_invalid_gltf); 1643 } 1644 1645 if (data->meshes[i].target_names) 1646 { 1647 CGLTF_ASSERT_IF(data->meshes[i].primitives_count && data->meshes[i].primitives[0].targets_count != data->meshes[i].target_names_count, cgltf_result_invalid_gltf); 1648 } 1649 1650 for (cgltf_size j = 0; j < data->meshes[i].primitives_count; ++j) 1651 { 1652 CGLTF_ASSERT_IF(data->meshes[i].primitives[j].type == cgltf_primitive_type_invalid, cgltf_result_invalid_gltf); 1653 CGLTF_ASSERT_IF(data->meshes[i].primitives[j].targets_count != data->meshes[i].primitives[0].targets_count, cgltf_result_invalid_gltf); 1654 1655 CGLTF_ASSERT_IF(data->meshes[i].primitives[j].attributes_count == 0, cgltf_result_invalid_gltf); 1656 1657 cgltf_accessor* first = data->meshes[i].primitives[j].attributes[0].data; 1658 1659 CGLTF_ASSERT_IF(first->count == 0, cgltf_result_invalid_gltf); 1660 1661 for (cgltf_size k = 0; k < data->meshes[i].primitives[j].attributes_count; ++k) 1662 { 1663 CGLTF_ASSERT_IF(data->meshes[i].primitives[j].attributes[k].data->count != first->count, cgltf_result_invalid_gltf); 1664 } 1665 1666 for (cgltf_size k = 0; k < data->meshes[i].primitives[j].targets_count; ++k) 1667 { 1668 for (cgltf_size m = 0; m < data->meshes[i].primitives[j].targets[k].attributes_count; ++m) 1669 { 1670 CGLTF_ASSERT_IF(data->meshes[i].primitives[j].targets[k].attributes[m].data->count != first->count, cgltf_result_invalid_gltf); 1671 } 1672 } 1673 1674 cgltf_accessor* indices = data->meshes[i].primitives[j].indices; 1675 1676 CGLTF_ASSERT_IF(indices && 1677 indices->component_type != cgltf_component_type_r_8u && 1678 indices->component_type != cgltf_component_type_r_16u && 1679 indices->component_type != cgltf_component_type_r_32u, cgltf_result_invalid_gltf); 1680 1681 CGLTF_ASSERT_IF(indices && indices->type != cgltf_type_scalar, cgltf_result_invalid_gltf); 1682 CGLTF_ASSERT_IF(indices && indices->stride != cgltf_component_size(indices->component_type), cgltf_result_invalid_gltf); 1683 1684 if (indices && indices->buffer_view && indices->buffer_view->buffer->data) 1685 { 1686 cgltf_size index_bound = cgltf_calc_index_bound(indices->buffer_view, indices->offset, indices->component_type, indices->count); 1687 1688 CGLTF_ASSERT_IF(index_bound >= first->count, cgltf_result_data_too_short); 1689 } 1690 1691 for (cgltf_size k = 0; k < data->meshes[i].primitives[j].mappings_count; ++k) 1692 { 1693 CGLTF_ASSERT_IF(data->meshes[i].primitives[j].mappings[k].variant >= data->variants_count, cgltf_result_invalid_gltf); 1694 } 1695 } 1696 } 1697 1698 for (cgltf_size i = 0; i < data->nodes_count; ++i) 1699 { 1700 if (data->nodes[i].weights && data->nodes[i].mesh) 1701 { 1702 CGLTF_ASSERT_IF(data->nodes[i].mesh->primitives_count && data->nodes[i].mesh->primitives[0].targets_count != data->nodes[i].weights_count, cgltf_result_invalid_gltf); 1703 } 1704 1705 if (data->nodes[i].has_mesh_gpu_instancing) 1706 { 1707 CGLTF_ASSERT_IF(data->nodes[i].mesh == NULL, cgltf_result_invalid_gltf); 1708 CGLTF_ASSERT_IF(data->nodes[i].mesh_gpu_instancing.attributes_count == 0, cgltf_result_invalid_gltf); 1709 1710 cgltf_accessor* first = data->nodes[i].mesh_gpu_instancing.attributes[0].data; 1711 1712 for (cgltf_size k = 0; k < data->nodes[i].mesh_gpu_instancing.attributes_count; ++k) 1713 { 1714 CGLTF_ASSERT_IF(data->nodes[i].mesh_gpu_instancing.attributes[k].data->count != first->count, cgltf_result_invalid_gltf); 1715 } 1716 } 1717 } 1718 1719 for (cgltf_size i = 0; i < data->nodes_count; ++i) 1720 { 1721 cgltf_node* p1 = data->nodes[i].parent; 1722 cgltf_node* p2 = p1 ? p1->parent : NULL; 1723 1724 while (p1 && p2) 1725 { 1726 CGLTF_ASSERT_IF(p1 == p2, cgltf_result_invalid_gltf); 1727 1728 p1 = p1->parent; 1729 p2 = p2->parent ? p2->parent->parent : NULL; 1730 } 1731 } 1732 1733 for (cgltf_size i = 0; i < data->scenes_count; ++i) 1734 { 1735 for (cgltf_size j = 0; j < data->scenes[i].nodes_count; ++j) 1736 { 1737 CGLTF_ASSERT_IF(data->scenes[i].nodes[j]->parent, cgltf_result_invalid_gltf); 1738 } 1739 } 1740 1741 for (cgltf_size i = 0; i < data->animations_count; ++i) 1742 { 1743 for (cgltf_size j = 0; j < data->animations[i].channels_count; ++j) 1744 { 1745 cgltf_animation_channel* channel = &data->animations[i].channels[j]; 1746 1747 if (!channel->target_node) 1748 { 1749 continue; 1750 } 1751 1752 cgltf_size components = 1; 1753 1754 if (channel->target_path == cgltf_animation_path_type_weights) 1755 { 1756 CGLTF_ASSERT_IF(!channel->target_node->mesh || !channel->target_node->mesh->primitives_count, cgltf_result_invalid_gltf); 1757 1758 components = channel->target_node->mesh->primitives[0].targets_count; 1759 } 1760 1761 cgltf_size values = channel->sampler->interpolation == cgltf_interpolation_type_cubic_spline ? 3 : 1; 1762 1763 CGLTF_ASSERT_IF(channel->sampler->input->count * components * values != channel->sampler->output->count, cgltf_result_invalid_gltf); 1764 } 1765 } 1766 1767 for (cgltf_size i = 0; i < data->variants_count; ++i) 1768 { 1769 CGLTF_ASSERT_IF(!data->variants[i].name, cgltf_result_invalid_gltf); 1770 } 1771 1772 return cgltf_result_success; 1773 } 1774 1775 cgltf_result cgltf_copy_extras_json(const cgltf_data* data, const cgltf_extras* extras, char* dest, cgltf_size* dest_size) 1776 { 1777 cgltf_size json_size = extras->end_offset - extras->start_offset; 1778 1779 if (!dest) 1780 { 1781 if (dest_size) 1782 { 1783 *dest_size = json_size + 1; 1784 return cgltf_result_success; 1785 } 1786 return cgltf_result_invalid_options; 1787 } 1788 1789 if (*dest_size + 1 < json_size) 1790 { 1791 strncpy(dest, data->json + extras->start_offset, *dest_size - 1); 1792 dest[*dest_size - 1] = 0; 1793 } 1794 else 1795 { 1796 strncpy(dest, data->json + extras->start_offset, json_size); 1797 dest[json_size] = 0; 1798 } 1799 1800 return cgltf_result_success; 1801 } 1802 1803 static void cgltf_free_extras(cgltf_data* data, cgltf_extras* extras) 1804 { 1805 data->memory.free_func(data->memory.user_data, extras->data); 1806 } 1807 1808 static void cgltf_free_extensions(cgltf_data* data, cgltf_extension* extensions, cgltf_size extensions_count) 1809 { 1810 for (cgltf_size i = 0; i < extensions_count; ++i) 1811 { 1812 data->memory.free_func(data->memory.user_data, extensions[i].name); 1813 data->memory.free_func(data->memory.user_data, extensions[i].data); 1814 } 1815 data->memory.free_func(data->memory.user_data, extensions); 1816 } 1817 1818 void cgltf_free(cgltf_data* data) 1819 { 1820 if (!data) 1821 { 1822 return; 1823 } 1824 1825 void (*file_release)(const struct cgltf_memory_options*, const struct cgltf_file_options*, void* data) = data->file.release ? data->file.release : cgltf_default_file_release; 1826 1827 data->memory.free_func(data->memory.user_data, data->asset.copyright); 1828 data->memory.free_func(data->memory.user_data, data->asset.generator); 1829 data->memory.free_func(data->memory.user_data, data->asset.version); 1830 data->memory.free_func(data->memory.user_data, data->asset.min_version); 1831 1832 cgltf_free_extensions(data, data->asset.extensions, data->asset.extensions_count); 1833 cgltf_free_extras(data, &data->asset.extras); 1834 1835 for (cgltf_size i = 0; i < data->accessors_count; ++i) 1836 { 1837 data->memory.free_func(data->memory.user_data, data->accessors[i].name); 1838 1839 cgltf_free_extensions(data, data->accessors[i].extensions, data->accessors[i].extensions_count); 1840 cgltf_free_extras(data, &data->accessors[i].extras); 1841 } 1842 data->memory.free_func(data->memory.user_data, data->accessors); 1843 1844 for (cgltf_size i = 0; i < data->buffer_views_count; ++i) 1845 { 1846 data->memory.free_func(data->memory.user_data, data->buffer_views[i].name); 1847 data->memory.free_func(data->memory.user_data, data->buffer_views[i].data); 1848 1849 cgltf_free_extensions(data, data->buffer_views[i].extensions, data->buffer_views[i].extensions_count); 1850 cgltf_free_extras(data, &data->buffer_views[i].extras); 1851 } 1852 data->memory.free_func(data->memory.user_data, data->buffer_views); 1853 1854 for (cgltf_size i = 0; i < data->buffers_count; ++i) 1855 { 1856 data->memory.free_func(data->memory.user_data, data->buffers[i].name); 1857 1858 if (data->buffers[i].data_free_method == cgltf_data_free_method_file_release) 1859 { 1860 file_release(&data->memory, &data->file, data->buffers[i].data); 1861 } 1862 else if (data->buffers[i].data_free_method == cgltf_data_free_method_memory_free) 1863 { 1864 data->memory.free_func(data->memory.user_data, data->buffers[i].data); 1865 } 1866 1867 data->memory.free_func(data->memory.user_data, data->buffers[i].uri); 1868 1869 cgltf_free_extensions(data, data->buffers[i].extensions, data->buffers[i].extensions_count); 1870 cgltf_free_extras(data, &data->buffers[i].extras); 1871 } 1872 data->memory.free_func(data->memory.user_data, data->buffers); 1873 1874 for (cgltf_size i = 0; i < data->meshes_count; ++i) 1875 { 1876 data->memory.free_func(data->memory.user_data, data->meshes[i].name); 1877 1878 for (cgltf_size j = 0; j < data->meshes[i].primitives_count; ++j) 1879 { 1880 for (cgltf_size k = 0; k < data->meshes[i].primitives[j].attributes_count; ++k) 1881 { 1882 data->memory.free_func(data->memory.user_data, data->meshes[i].primitives[j].attributes[k].name); 1883 } 1884 1885 data->memory.free_func(data->memory.user_data, data->meshes[i].primitives[j].attributes); 1886 1887 for (cgltf_size k = 0; k < data->meshes[i].primitives[j].targets_count; ++k) 1888 { 1889 for (cgltf_size m = 0; m < data->meshes[i].primitives[j].targets[k].attributes_count; ++m) 1890 { 1891 data->memory.free_func(data->memory.user_data, data->meshes[i].primitives[j].targets[k].attributes[m].name); 1892 } 1893 1894 data->memory.free_func(data->memory.user_data, data->meshes[i].primitives[j].targets[k].attributes); 1895 } 1896 1897 data->memory.free_func(data->memory.user_data, data->meshes[i].primitives[j].targets); 1898 1899 if (data->meshes[i].primitives[j].has_draco_mesh_compression) 1900 { 1901 for (cgltf_size k = 0; k < data->meshes[i].primitives[j].draco_mesh_compression.attributes_count; ++k) 1902 { 1903 data->memory.free_func(data->memory.user_data, data->meshes[i].primitives[j].draco_mesh_compression.attributes[k].name); 1904 } 1905 1906 data->memory.free_func(data->memory.user_data, data->meshes[i].primitives[j].draco_mesh_compression.attributes); 1907 } 1908 1909 for (cgltf_size k = 0; k < data->meshes[i].primitives[j].mappings_count; ++k) 1910 { 1911 cgltf_free_extras(data, &data->meshes[i].primitives[j].mappings[k].extras); 1912 } 1913 1914 data->memory.free_func(data->memory.user_data, data->meshes[i].primitives[j].mappings); 1915 1916 cgltf_free_extensions(data, data->meshes[i].primitives[j].extensions, data->meshes[i].primitives[j].extensions_count); 1917 cgltf_free_extras(data, &data->meshes[i].primitives[j].extras); 1918 } 1919 1920 data->memory.free_func(data->memory.user_data, data->meshes[i].primitives); 1921 data->memory.free_func(data->memory.user_data, data->meshes[i].weights); 1922 1923 for (cgltf_size j = 0; j < data->meshes[i].target_names_count; ++j) 1924 { 1925 data->memory.free_func(data->memory.user_data, data->meshes[i].target_names[j]); 1926 } 1927 1928 cgltf_free_extensions(data, data->meshes[i].extensions, data->meshes[i].extensions_count); 1929 cgltf_free_extras(data, &data->meshes[i].extras); 1930 1931 data->memory.free_func(data->memory.user_data, data->meshes[i].target_names); 1932 } 1933 1934 data->memory.free_func(data->memory.user_data, data->meshes); 1935 1936 for (cgltf_size i = 0; i < data->materials_count; ++i) 1937 { 1938 data->memory.free_func(data->memory.user_data, data->materials[i].name); 1939 1940 cgltf_free_extensions(data, data->materials[i].extensions, data->materials[i].extensions_count); 1941 cgltf_free_extras(data, &data->materials[i].extras); 1942 } 1943 1944 data->memory.free_func(data->memory.user_data, data->materials); 1945 1946 for (cgltf_size i = 0; i < data->images_count; ++i) 1947 { 1948 data->memory.free_func(data->memory.user_data, data->images[i].name); 1949 data->memory.free_func(data->memory.user_data, data->images[i].uri); 1950 data->memory.free_func(data->memory.user_data, data->images[i].mime_type); 1951 1952 cgltf_free_extensions(data, data->images[i].extensions, data->images[i].extensions_count); 1953 cgltf_free_extras(data, &data->images[i].extras); 1954 } 1955 1956 data->memory.free_func(data->memory.user_data, data->images); 1957 1958 for (cgltf_size i = 0; i < data->textures_count; ++i) 1959 { 1960 data->memory.free_func(data->memory.user_data, data->textures[i].name); 1961 1962 cgltf_free_extensions(data, data->textures[i].extensions, data->textures[i].extensions_count); 1963 cgltf_free_extras(data, &data->textures[i].extras); 1964 } 1965 1966 data->memory.free_func(data->memory.user_data, data->textures); 1967 1968 for (cgltf_size i = 0; i < data->samplers_count; ++i) 1969 { 1970 data->memory.free_func(data->memory.user_data, data->samplers[i].name); 1971 1972 cgltf_free_extensions(data, data->samplers[i].extensions, data->samplers[i].extensions_count); 1973 cgltf_free_extras(data, &data->samplers[i].extras); 1974 } 1975 1976 data->memory.free_func(data->memory.user_data, data->samplers); 1977 1978 for (cgltf_size i = 0; i < data->skins_count; ++i) 1979 { 1980 data->memory.free_func(data->memory.user_data, data->skins[i].name); 1981 data->memory.free_func(data->memory.user_data, data->skins[i].joints); 1982 1983 cgltf_free_extensions(data, data->skins[i].extensions, data->skins[i].extensions_count); 1984 cgltf_free_extras(data, &data->skins[i].extras); 1985 } 1986 1987 data->memory.free_func(data->memory.user_data, data->skins); 1988 1989 for (cgltf_size i = 0; i < data->cameras_count; ++i) 1990 { 1991 data->memory.free_func(data->memory.user_data, data->cameras[i].name); 1992 1993 if (data->cameras[i].type == cgltf_camera_type_perspective) 1994 { 1995 cgltf_free_extras(data, &data->cameras[i].data.perspective.extras); 1996 } 1997 else if (data->cameras[i].type == cgltf_camera_type_orthographic) 1998 { 1999 cgltf_free_extras(data, &data->cameras[i].data.orthographic.extras); 2000 } 2001 2002 cgltf_free_extensions(data, data->cameras[i].extensions, data->cameras[i].extensions_count); 2003 cgltf_free_extras(data, &data->cameras[i].extras); 2004 } 2005 2006 data->memory.free_func(data->memory.user_data, data->cameras); 2007 2008 for (cgltf_size i = 0; i < data->lights_count; ++i) 2009 { 2010 data->memory.free_func(data->memory.user_data, data->lights[i].name); 2011 2012 cgltf_free_extras(data, &data->lights[i].extras); 2013 } 2014 2015 data->memory.free_func(data->memory.user_data, data->lights); 2016 2017 for (cgltf_size i = 0; i < data->nodes_count; ++i) 2018 { 2019 data->memory.free_func(data->memory.user_data, data->nodes[i].name); 2020 data->memory.free_func(data->memory.user_data, data->nodes[i].children); 2021 data->memory.free_func(data->memory.user_data, data->nodes[i].weights); 2022 2023 if (data->nodes[i].has_mesh_gpu_instancing) 2024 { 2025 for (cgltf_size j = 0; j < data->nodes[i].mesh_gpu_instancing.attributes_count; ++j) 2026 { 2027 data->memory.free_func(data->memory.user_data, data->nodes[i].mesh_gpu_instancing.attributes[j].name); 2028 } 2029 2030 data->memory.free_func(data->memory.user_data, data->nodes[i].mesh_gpu_instancing.attributes); 2031 } 2032 2033 cgltf_free_extensions(data, data->nodes[i].extensions, data->nodes[i].extensions_count); 2034 cgltf_free_extras(data, &data->nodes[i].extras); 2035 } 2036 2037 data->memory.free_func(data->memory.user_data, data->nodes); 2038 2039 for (cgltf_size i = 0; i < data->scenes_count; ++i) 2040 { 2041 data->memory.free_func(data->memory.user_data, data->scenes[i].name); 2042 data->memory.free_func(data->memory.user_data, data->scenes[i].nodes); 2043 2044 cgltf_free_extensions(data, data->scenes[i].extensions, data->scenes[i].extensions_count); 2045 cgltf_free_extras(data, &data->scenes[i].extras); 2046 } 2047 2048 data->memory.free_func(data->memory.user_data, data->scenes); 2049 2050 for (cgltf_size i = 0; i < data->animations_count; ++i) 2051 { 2052 data->memory.free_func(data->memory.user_data, data->animations[i].name); 2053 for (cgltf_size j = 0; j < data->animations[i].samplers_count; ++j) 2054 { 2055 cgltf_free_extensions(data, data->animations[i].samplers[j].extensions, data->animations[i].samplers[j].extensions_count); 2056 cgltf_free_extras(data, &data->animations[i].samplers[j].extras); 2057 } 2058 data->memory.free_func(data->memory.user_data, data->animations[i].samplers); 2059 2060 for (cgltf_size j = 0; j < data->animations[i].channels_count; ++j) 2061 { 2062 cgltf_free_extensions(data, data->animations[i].channels[j].extensions, data->animations[i].channels[j].extensions_count); 2063 cgltf_free_extras(data, &data->animations[i].channels[j].extras); 2064 } 2065 data->memory.free_func(data->memory.user_data, data->animations[i].channels); 2066 2067 cgltf_free_extensions(data, data->animations[i].extensions, data->animations[i].extensions_count); 2068 cgltf_free_extras(data, &data->animations[i].extras); 2069 } 2070 2071 data->memory.free_func(data->memory.user_data, data->animations); 2072 2073 for (cgltf_size i = 0; i < data->variants_count; ++i) 2074 { 2075 data->memory.free_func(data->memory.user_data, data->variants[i].name); 2076 2077 cgltf_free_extras(data, &data->variants[i].extras); 2078 } 2079 2080 data->memory.free_func(data->memory.user_data, data->variants); 2081 2082 cgltf_free_extensions(data, data->data_extensions, data->data_extensions_count); 2083 cgltf_free_extras(data, &data->extras); 2084 2085 for (cgltf_size i = 0; i < data->extensions_used_count; ++i) 2086 { 2087 data->memory.free_func(data->memory.user_data, data->extensions_used[i]); 2088 } 2089 2090 data->memory.free_func(data->memory.user_data, data->extensions_used); 2091 2092 for (cgltf_size i = 0; i < data->extensions_required_count; ++i) 2093 { 2094 data->memory.free_func(data->memory.user_data, data->extensions_required[i]); 2095 } 2096 2097 data->memory.free_func(data->memory.user_data, data->extensions_required); 2098 2099 file_release(&data->memory, &data->file, data->file_data); 2100 2101 data->memory.free_func(data->memory.user_data, data); 2102 } 2103 2104 void cgltf_node_transform_local(const cgltf_node* node, cgltf_float* out_matrix) 2105 { 2106 cgltf_float* lm = out_matrix; 2107 2108 if (node->has_matrix) 2109 { 2110 memcpy(lm, node->matrix, sizeof(float) * 16); 2111 } 2112 else 2113 { 2114 float tx = node->translation[0]; 2115 float ty = node->translation[1]; 2116 float tz = node->translation[2]; 2117 2118 float qx = node->rotation[0]; 2119 float qy = node->rotation[1]; 2120 float qz = node->rotation[2]; 2121 float qw = node->rotation[3]; 2122 2123 float sx = node->scale[0]; 2124 float sy = node->scale[1]; 2125 float sz = node->scale[2]; 2126 2127 lm[0] = (1 - 2 * qy*qy - 2 * qz*qz) * sx; 2128 lm[1] = (2 * qx*qy + 2 * qz*qw) * sx; 2129 lm[2] = (2 * qx*qz - 2 * qy*qw) * sx; 2130 lm[3] = 0.f; 2131 2132 lm[4] = (2 * qx*qy - 2 * qz*qw) * sy; 2133 lm[5] = (1 - 2 * qx*qx - 2 * qz*qz) * sy; 2134 lm[6] = (2 * qy*qz + 2 * qx*qw) * sy; 2135 lm[7] = 0.f; 2136 2137 lm[8] = (2 * qx*qz + 2 * qy*qw) * sz; 2138 lm[9] = (2 * qy*qz - 2 * qx*qw) * sz; 2139 lm[10] = (1 - 2 * qx*qx - 2 * qy*qy) * sz; 2140 lm[11] = 0.f; 2141 2142 lm[12] = tx; 2143 lm[13] = ty; 2144 lm[14] = tz; 2145 lm[15] = 1.f; 2146 } 2147 } 2148 2149 void cgltf_node_transform_world(const cgltf_node* node, cgltf_float* out_matrix) 2150 { 2151 cgltf_float* lm = out_matrix; 2152 cgltf_node_transform_local(node, lm); 2153 2154 const cgltf_node* parent = node->parent; 2155 2156 while (parent) 2157 { 2158 float pm[16]; 2159 cgltf_node_transform_local(parent, pm); 2160 2161 for (int i = 0; i < 4; ++i) 2162 { 2163 float l0 = lm[i * 4 + 0]; 2164 float l1 = lm[i * 4 + 1]; 2165 float l2 = lm[i * 4 + 2]; 2166 2167 float r0 = l0 * pm[0] + l1 * pm[4] + l2 * pm[8]; 2168 float r1 = l0 * pm[1] + l1 * pm[5] + l2 * pm[9]; 2169 float r2 = l0 * pm[2] + l1 * pm[6] + l2 * pm[10]; 2170 2171 lm[i * 4 + 0] = r0; 2172 lm[i * 4 + 1] = r1; 2173 lm[i * 4 + 2] = r2; 2174 } 2175 2176 lm[12] += pm[12]; 2177 lm[13] += pm[13]; 2178 lm[14] += pm[14]; 2179 2180 parent = parent->parent; 2181 } 2182 } 2183 2184 static cgltf_ssize cgltf_component_read_integer(const void* in, cgltf_component_type component_type) 2185 { 2186 switch (component_type) 2187 { 2188 case cgltf_component_type_r_16: 2189 return *((const int16_t*) in); 2190 case cgltf_component_type_r_16u: 2191 return *((const uint16_t*) in); 2192 case cgltf_component_type_r_32u: 2193 return *((const uint32_t*) in); 2194 case cgltf_component_type_r_8: 2195 return *((const int8_t*) in); 2196 case cgltf_component_type_r_8u: 2197 return *((const uint8_t*) in); 2198 default: 2199 return 0; 2200 } 2201 } 2202 2203 static cgltf_size cgltf_component_read_index(const void* in, cgltf_component_type component_type) 2204 { 2205 switch (component_type) 2206 { 2207 case cgltf_component_type_r_16u: 2208 return *((const uint16_t*) in); 2209 case cgltf_component_type_r_32u: 2210 return *((const uint32_t*) in); 2211 case cgltf_component_type_r_8u: 2212 return *((const uint8_t*) in); 2213 default: 2214 return 0; 2215 } 2216 } 2217 2218 static cgltf_float cgltf_component_read_float(const void* in, cgltf_component_type component_type, cgltf_bool normalized) 2219 { 2220 if (component_type == cgltf_component_type_r_32f) 2221 { 2222 return *((const float*) in); 2223 } 2224 2225 if (normalized) 2226 { 2227 switch (component_type) 2228 { 2229 // note: glTF spec doesn't currently define normalized conversions for 32-bit integers 2230 case cgltf_component_type_r_16: 2231 return *((const int16_t*) in) / (cgltf_float)32767; 2232 case cgltf_component_type_r_16u: 2233 return *((const uint16_t*) in) / (cgltf_float)65535; 2234 case cgltf_component_type_r_8: 2235 return *((const int8_t*) in) / (cgltf_float)127; 2236 case cgltf_component_type_r_8u: 2237 return *((const uint8_t*) in) / (cgltf_float)255; 2238 default: 2239 return 0; 2240 } 2241 } 2242 2243 return (cgltf_float)cgltf_component_read_integer(in, component_type); 2244 } 2245 2246 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) 2247 { 2248 cgltf_size num_components = cgltf_num_components(type); 2249 2250 if (element_size < num_components) { 2251 return 0; 2252 } 2253 2254 // There are three special cases for component extraction, see #data-alignment in the 2.0 spec. 2255 2256 cgltf_size component_size = cgltf_component_size(component_type); 2257 2258 if (type == cgltf_type_mat2 && component_size == 1) 2259 { 2260 out[0] = cgltf_component_read_float(element, component_type, normalized); 2261 out[1] = cgltf_component_read_float(element + 1, component_type, normalized); 2262 out[2] = cgltf_component_read_float(element + 4, component_type, normalized); 2263 out[3] = cgltf_component_read_float(element + 5, component_type, normalized); 2264 return 1; 2265 } 2266 2267 if (type == cgltf_type_mat3 && component_size == 1) 2268 { 2269 out[0] = cgltf_component_read_float(element, component_type, normalized); 2270 out[1] = cgltf_component_read_float(element + 1, component_type, normalized); 2271 out[2] = cgltf_component_read_float(element + 2, component_type, normalized); 2272 out[3] = cgltf_component_read_float(element + 4, component_type, normalized); 2273 out[4] = cgltf_component_read_float(element + 5, component_type, normalized); 2274 out[5] = cgltf_component_read_float(element + 6, component_type, normalized); 2275 out[6] = cgltf_component_read_float(element + 8, component_type, normalized); 2276 out[7] = cgltf_component_read_float(element + 9, component_type, normalized); 2277 out[8] = cgltf_component_read_float(element + 10, component_type, normalized); 2278 return 1; 2279 } 2280 2281 if (type == cgltf_type_mat3 && component_size == 2) 2282 { 2283 out[0] = cgltf_component_read_float(element, component_type, normalized); 2284 out[1] = cgltf_component_read_float(element + 2, component_type, normalized); 2285 out[2] = cgltf_component_read_float(element + 4, component_type, normalized); 2286 out[3] = cgltf_component_read_float(element + 8, component_type, normalized); 2287 out[4] = cgltf_component_read_float(element + 10, component_type, normalized); 2288 out[5] = cgltf_component_read_float(element + 12, component_type, normalized); 2289 out[6] = cgltf_component_read_float(element + 16, component_type, normalized); 2290 out[7] = cgltf_component_read_float(element + 18, component_type, normalized); 2291 out[8] = cgltf_component_read_float(element + 20, component_type, normalized); 2292 return 1; 2293 } 2294 2295 for (cgltf_size i = 0; i < num_components; ++i) 2296 { 2297 out[i] = cgltf_component_read_float(element + component_size * i, component_type, normalized); 2298 } 2299 return 1; 2300 } 2301 2302 const uint8_t* cgltf_buffer_view_data(const cgltf_buffer_view* view) 2303 { 2304 if (view->data) 2305 return (const uint8_t*)view->data; 2306 2307 if (!view->buffer->data) 2308 return NULL; 2309 2310 const uint8_t* result = (const uint8_t*)view->buffer->data; 2311 result += view->offset; 2312 return result; 2313 } 2314 2315 cgltf_bool cgltf_accessor_read_float(const cgltf_accessor* accessor, cgltf_size index, cgltf_float* out, cgltf_size element_size) 2316 { 2317 if (accessor->is_sparse) 2318 { 2319 return 0; 2320 } 2321 if (accessor->buffer_view == NULL) 2322 { 2323 memset(out, 0, element_size * sizeof(cgltf_float)); 2324 return 1; 2325 } 2326 const uint8_t* element = cgltf_buffer_view_data(accessor->buffer_view); 2327 if (element == NULL) 2328 { 2329 return 0; 2330 } 2331 element += accessor->offset + accessor->stride * index; 2332 return cgltf_element_read_float(element, accessor->type, accessor->component_type, accessor->normalized, out, element_size); 2333 } 2334 2335 cgltf_size cgltf_accessor_unpack_floats(const cgltf_accessor* accessor, cgltf_float* out, cgltf_size float_count) 2336 { 2337 cgltf_size floats_per_element = cgltf_num_components(accessor->type); 2338 cgltf_size available_floats = accessor->count * floats_per_element; 2339 if (out == NULL) 2340 { 2341 return available_floats; 2342 } 2343 2344 float_count = available_floats < float_count ? available_floats : float_count; 2345 cgltf_size element_count = float_count / floats_per_element; 2346 2347 // First pass: convert each element in the base accessor. 2348 if (accessor->buffer_view == NULL) 2349 { 2350 memset(out, 0, element_count * floats_per_element * sizeof(cgltf_float)); 2351 } 2352 else 2353 { 2354 const uint8_t* element = cgltf_buffer_view_data(accessor->buffer_view); 2355 if (element == NULL) 2356 { 2357 return 0; 2358 } 2359 element += accessor->offset; 2360 2361 if (accessor->component_type == cgltf_component_type_r_32f && accessor->stride == floats_per_element * sizeof(cgltf_float)) 2362 { 2363 memcpy(out, element, element_count * floats_per_element * sizeof(cgltf_float)); 2364 } 2365 else 2366 { 2367 cgltf_float* dest = out; 2368 2369 for (cgltf_size index = 0; index < element_count; index++, dest += floats_per_element, element += accessor->stride) 2370 { 2371 if (!cgltf_element_read_float(element, accessor->type, accessor->component_type, accessor->normalized, dest, floats_per_element)) 2372 { 2373 return 0; 2374 } 2375 } 2376 } 2377 } 2378 2379 // Second pass: write out each element in the sparse accessor. 2380 if (accessor->is_sparse) 2381 { 2382 const cgltf_accessor_sparse* sparse = &accessor->sparse; 2383 2384 const uint8_t* index_data = cgltf_buffer_view_data(sparse->indices_buffer_view); 2385 const uint8_t* reader_head = cgltf_buffer_view_data(sparse->values_buffer_view); 2386 2387 if (index_data == NULL || reader_head == NULL) 2388 { 2389 return 0; 2390 } 2391 2392 index_data += sparse->indices_byte_offset; 2393 reader_head += sparse->values_byte_offset; 2394 2395 cgltf_size index_stride = cgltf_component_size(sparse->indices_component_type); 2396 for (cgltf_size reader_index = 0; reader_index < sparse->count; reader_index++, index_data += index_stride, reader_head += accessor->stride) 2397 { 2398 size_t writer_index = cgltf_component_read_index(index_data, sparse->indices_component_type); 2399 float* writer_head = out + writer_index * floats_per_element; 2400 2401 if (!cgltf_element_read_float(reader_head, accessor->type, accessor->component_type, accessor->normalized, writer_head, floats_per_element)) 2402 { 2403 return 0; 2404 } 2405 } 2406 } 2407 2408 return element_count * floats_per_element; 2409 } 2410 2411 static cgltf_uint cgltf_component_read_uint(const void* in, cgltf_component_type component_type) 2412 { 2413 switch (component_type) 2414 { 2415 case cgltf_component_type_r_8: 2416 return *((const int8_t*) in); 2417 2418 case cgltf_component_type_r_8u: 2419 return *((const uint8_t*) in); 2420 2421 case cgltf_component_type_r_16: 2422 return *((const int16_t*) in); 2423 2424 case cgltf_component_type_r_16u: 2425 return *((const uint16_t*) in); 2426 2427 case cgltf_component_type_r_32u: 2428 return *((const uint32_t*) in); 2429 2430 default: 2431 return 0; 2432 } 2433 } 2434 2435 static cgltf_bool cgltf_element_read_uint(const uint8_t* element, cgltf_type type, cgltf_component_type component_type, cgltf_uint* out, cgltf_size element_size) 2436 { 2437 cgltf_size num_components = cgltf_num_components(type); 2438 2439 if (element_size < num_components) 2440 { 2441 return 0; 2442 } 2443 2444 // Reading integer matrices is not a valid use case 2445 if (type == cgltf_type_mat2 || type == cgltf_type_mat3 || type == cgltf_type_mat4) 2446 { 2447 return 0; 2448 } 2449 2450 cgltf_size component_size = cgltf_component_size(component_type); 2451 2452 for (cgltf_size i = 0; i < num_components; ++i) 2453 { 2454 out[i] = cgltf_component_read_uint(element + component_size * i, component_type); 2455 } 2456 return 1; 2457 } 2458 2459 cgltf_bool cgltf_accessor_read_uint(const cgltf_accessor* accessor, cgltf_size index, cgltf_uint* out, cgltf_size element_size) 2460 { 2461 if (accessor->is_sparse) 2462 { 2463 return 0; 2464 } 2465 if (accessor->buffer_view == NULL) 2466 { 2467 memset(out, 0, element_size * sizeof( cgltf_uint )); 2468 return 1; 2469 } 2470 const uint8_t* element = cgltf_buffer_view_data(accessor->buffer_view); 2471 if (element == NULL) 2472 { 2473 return 0; 2474 } 2475 element += accessor->offset + accessor->stride * index; 2476 return cgltf_element_read_uint(element, accessor->type, accessor->component_type, out, element_size); 2477 } 2478 2479 cgltf_size cgltf_accessor_read_index(const cgltf_accessor* accessor, cgltf_size index) 2480 { 2481 if (accessor->is_sparse) 2482 { 2483 return 0; // This is an error case, but we can't communicate the error with existing interface. 2484 } 2485 if (accessor->buffer_view == NULL) 2486 { 2487 return 0; 2488 } 2489 const uint8_t* element = cgltf_buffer_view_data(accessor->buffer_view); 2490 if (element == NULL) 2491 { 2492 return 0; // This is an error case, but we can't communicate the error with existing interface. 2493 } 2494 element += accessor->offset + accessor->stride * index; 2495 return cgltf_component_read_index(element, accessor->component_type); 2496 } 2497 2498 cgltf_size cgltf_mesh_index(const cgltf_data* data, const cgltf_mesh* object) 2499 { 2500 assert(object && (cgltf_size)(object - data->meshes) < data->meshes_count); 2501 return (cgltf_size)(object - data->meshes); 2502 } 2503 2504 cgltf_size cgltf_material_index(const cgltf_data* data, const cgltf_material* object) 2505 { 2506 assert(object && (cgltf_size)(object - data->materials) < data->materials_count); 2507 return (cgltf_size)(object - data->materials); 2508 } 2509 2510 cgltf_size cgltf_accessor_index(const cgltf_data* data, const cgltf_accessor* object) 2511 { 2512 assert(object && (cgltf_size)(object - data->accessors) < data->accessors_count); 2513 return (cgltf_size)(object - data->accessors); 2514 } 2515 2516 cgltf_size cgltf_buffer_view_index(const cgltf_data* data, const cgltf_buffer_view* object) 2517 { 2518 assert(object && (cgltf_size)(object - data->buffer_views) < data->buffer_views_count); 2519 return (cgltf_size)(object - data->buffer_views); 2520 } 2521 2522 cgltf_size cgltf_buffer_index(const cgltf_data* data, const cgltf_buffer* object) 2523 { 2524 assert(object && (cgltf_size)(object - data->buffers) < data->buffers_count); 2525 return (cgltf_size)(object - data->buffers); 2526 } 2527 2528 cgltf_size cgltf_image_index(const cgltf_data* data, const cgltf_image* object) 2529 { 2530 assert(object && (cgltf_size)(object - data->images) < data->images_count); 2531 return (cgltf_size)(object - data->images); 2532 } 2533 2534 cgltf_size cgltf_texture_index(const cgltf_data* data, const cgltf_texture* object) 2535 { 2536 assert(object && (cgltf_size)(object - data->textures) < data->textures_count); 2537 return (cgltf_size)(object - data->textures); 2538 } 2539 2540 cgltf_size cgltf_sampler_index(const cgltf_data* data, const cgltf_sampler* object) 2541 { 2542 assert(object && (cgltf_size)(object - data->samplers) < data->samplers_count); 2543 return (cgltf_size)(object - data->samplers); 2544 } 2545 2546 cgltf_size cgltf_skin_index(const cgltf_data* data, const cgltf_skin* object) 2547 { 2548 assert(object && (cgltf_size)(object - data->skins) < data->skins_count); 2549 return (cgltf_size)(object - data->skins); 2550 } 2551 2552 cgltf_size cgltf_camera_index(const cgltf_data* data, const cgltf_camera* object) 2553 { 2554 assert(object && (cgltf_size)(object - data->cameras) < data->cameras_count); 2555 return (cgltf_size)(object - data->cameras); 2556 } 2557 2558 cgltf_size cgltf_light_index(const cgltf_data* data, const cgltf_light* object) 2559 { 2560 assert(object && (cgltf_size)(object - data->lights) < data->lights_count); 2561 return (cgltf_size)(object - data->lights); 2562 } 2563 2564 cgltf_size cgltf_node_index(const cgltf_data* data, const cgltf_node* object) 2565 { 2566 assert(object && (cgltf_size)(object - data->nodes) < data->nodes_count); 2567 return (cgltf_size)(object - data->nodes); 2568 } 2569 2570 cgltf_size cgltf_scene_index(const cgltf_data* data, const cgltf_scene* object) 2571 { 2572 assert(object && (cgltf_size)(object - data->scenes) < data->scenes_count); 2573 return (cgltf_size)(object - data->scenes); 2574 } 2575 2576 cgltf_size cgltf_animation_index(const cgltf_data* data, const cgltf_animation* object) 2577 { 2578 assert(object && (cgltf_size)(object - data->animations) < data->animations_count); 2579 return (cgltf_size)(object - data->animations); 2580 } 2581 2582 cgltf_size cgltf_animation_sampler_index(const cgltf_animation* animation, const cgltf_animation_sampler* object) 2583 { 2584 assert(object && (cgltf_size)(object - animation->samplers) < animation->samplers_count); 2585 return (cgltf_size)(object - animation->samplers); 2586 } 2587 2588 cgltf_size cgltf_animation_channel_index(const cgltf_animation* animation, const cgltf_animation_channel* object) 2589 { 2590 assert(object && (cgltf_size)(object - animation->channels) < animation->channels_count); 2591 return (cgltf_size)(object - animation->channels); 2592 } 2593 2594 cgltf_size cgltf_accessor_unpack_indices(const cgltf_accessor* accessor, void* out, cgltf_size out_component_size, cgltf_size index_count) 2595 { 2596 if (out == NULL) 2597 { 2598 return accessor->count; 2599 } 2600 2601 index_count = accessor->count < index_count ? accessor->count : index_count; 2602 cgltf_size index_component_size = cgltf_component_size(accessor->component_type); 2603 2604 if (accessor->is_sparse) 2605 { 2606 return 0; 2607 } 2608 if (accessor->buffer_view == NULL) 2609 { 2610 return 0; 2611 } 2612 if (index_component_size > out_component_size) 2613 { 2614 return 0; 2615 } 2616 const uint8_t* element = cgltf_buffer_view_data(accessor->buffer_view); 2617 if (element == NULL) 2618 { 2619 return 0; 2620 } 2621 element += accessor->offset; 2622 2623 if (index_component_size == out_component_size && accessor->stride == out_component_size) 2624 { 2625 memcpy(out, element, index_count * index_component_size); 2626 return index_count; 2627 } 2628 2629 // The component size of the output array is larger than the component size of the index data, so index data will be padded. 2630 switch (out_component_size) 2631 { 2632 case 2: 2633 for (cgltf_size index = 0; index < index_count; index++, element += accessor->stride) 2634 { 2635 ((uint16_t*)out)[index] = (uint16_t)cgltf_component_read_index(element, accessor->component_type); 2636 } 2637 break; 2638 case 4: 2639 for (cgltf_size index = 0; index < index_count; index++, element += accessor->stride) 2640 { 2641 ((uint32_t*)out)[index] = (uint32_t)cgltf_component_read_index(element, accessor->component_type); 2642 } 2643 break; 2644 default: 2645 break; 2646 } 2647 2648 return index_count; 2649 } 2650 2651 #define CGLTF_ERROR_JSON -1 2652 #define CGLTF_ERROR_NOMEM -2 2653 #define CGLTF_ERROR_LEGACY -3 2654 2655 #define CGLTF_CHECK_TOKTYPE(tok_, type_) if ((tok_).type != (type_)) { return CGLTF_ERROR_JSON; } 2656 #define CGLTF_CHECK_TOKTYPE_RET(tok_, type_, ret_) if ((tok_).type != (type_)) { return ret_; } 2657 #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 */ 2658 2659 #define CGLTF_PTRINDEX(type, idx) (type*)((cgltf_size)idx + 1) 2660 #define CGLTF_PTRFIXUP(var, data, size) if (var) { if ((cgltf_size)var > size) { return CGLTF_ERROR_JSON; } var = &data[(cgltf_size)var-1]; } 2661 #define CGLTF_PTRFIXUP_REQ(var, data, size) if (!var || (cgltf_size)var > size) { return CGLTF_ERROR_JSON; } var = &data[(cgltf_size)var-1]; 2662 2663 static int cgltf_json_strcmp(jsmntok_t const* tok, const uint8_t* json_chunk, const char* str) 2664 { 2665 CGLTF_CHECK_TOKTYPE(*tok, JSMN_STRING); 2666 size_t const str_len = strlen(str); 2667 size_t const name_length = (size_t)(tok->end - tok->start); 2668 return (str_len == name_length) ? strncmp((const char*)json_chunk + tok->start, str, str_len) : 128; 2669 } 2670 2671 static int cgltf_json_to_int(jsmntok_t const* tok, const uint8_t* json_chunk) 2672 { 2673 CGLTF_CHECK_TOKTYPE(*tok, JSMN_PRIMITIVE); 2674 char tmp[128]; 2675 int size = (size_t)(tok->end - tok->start) < sizeof(tmp) ? (int)(tok->end - tok->start) : (int)(sizeof(tmp) - 1); 2676 strncpy(tmp, (const char*)json_chunk + tok->start, size); 2677 tmp[size] = 0; 2678 return CGLTF_ATOI(tmp); 2679 } 2680 2681 static cgltf_size cgltf_json_to_size(jsmntok_t const* tok, const uint8_t* json_chunk) 2682 { 2683 CGLTF_CHECK_TOKTYPE_RET(*tok, JSMN_PRIMITIVE, 0); 2684 char tmp[128]; 2685 int size = (size_t)(tok->end - tok->start) < sizeof(tmp) ? (int)(tok->end - tok->start) : (int)(sizeof(tmp) - 1); 2686 strncpy(tmp, (const char*)json_chunk + tok->start, size); 2687 tmp[size] = 0; 2688 long long res = CGLTF_ATOLL(tmp); 2689 return res < 0 ? 0 : (cgltf_size)res; 2690 } 2691 2692 static cgltf_float cgltf_json_to_float(jsmntok_t const* tok, const uint8_t* json_chunk) 2693 { 2694 CGLTF_CHECK_TOKTYPE(*tok, JSMN_PRIMITIVE); 2695 char tmp[128]; 2696 int size = (size_t)(tok->end - tok->start) < sizeof(tmp) ? (int)(tok->end - tok->start) : (int)(sizeof(tmp) - 1); 2697 strncpy(tmp, (const char*)json_chunk + tok->start, size); 2698 tmp[size] = 0; 2699 return (cgltf_float)CGLTF_ATOF(tmp); 2700 } 2701 2702 static cgltf_bool cgltf_json_to_bool(jsmntok_t const* tok, const uint8_t* json_chunk) 2703 { 2704 int size = (int)(tok->end - tok->start); 2705 return size == 4 && memcmp(json_chunk + tok->start, "true", 4) == 0; 2706 } 2707 2708 static int cgltf_skip_json(jsmntok_t const* tokens, int i) 2709 { 2710 int end = i + 1; 2711 2712 while (i < end) 2713 { 2714 switch (tokens[i].type) 2715 { 2716 case JSMN_OBJECT: 2717 end += tokens[i].size * 2; 2718 break; 2719 2720 case JSMN_ARRAY: 2721 end += tokens[i].size; 2722 break; 2723 2724 case JSMN_PRIMITIVE: 2725 case JSMN_STRING: 2726 break; 2727 2728 default: 2729 return -1; 2730 } 2731 2732 i++; 2733 } 2734 2735 return i; 2736 } 2737 2738 static void cgltf_fill_float_array(float* out_array, int size, float value) 2739 { 2740 for (int j = 0; j < size; ++j) 2741 { 2742 out_array[j] = value; 2743 } 2744 } 2745 2746 static int cgltf_parse_json_float_array(jsmntok_t const* tokens, int i, const uint8_t* json_chunk, float* out_array, int size) 2747 { 2748 CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_ARRAY); 2749 if (tokens[i].size != size) 2750 { 2751 return CGLTF_ERROR_JSON; 2752 } 2753 ++i; 2754 for (int j = 0; j < size; ++j) 2755 { 2756 CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_PRIMITIVE); 2757 out_array[j] = cgltf_json_to_float(tokens + i, json_chunk); 2758 ++i; 2759 } 2760 return i; 2761 } 2762 2763 static int cgltf_parse_json_string(cgltf_options* options, jsmntok_t const* tokens, int i, const uint8_t* json_chunk, char** out_string) 2764 { 2765 CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_STRING); 2766 if (*out_string) 2767 { 2768 return CGLTF_ERROR_JSON; 2769 } 2770 int size = (int)(tokens[i].end - tokens[i].start); 2771 char* result = (char*)options->memory.alloc_func(options->memory.user_data, size + 1); 2772 if (!result) 2773 { 2774 return CGLTF_ERROR_NOMEM; 2775 } 2776 strncpy(result, (const char*)json_chunk + tokens[i].start, size); 2777 result[size] = 0; 2778 *out_string = result; 2779 return i + 1; 2780 } 2781 2782 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) 2783 { 2784 (void)json_chunk; 2785 if (tokens[i].type != JSMN_ARRAY) 2786 { 2787 return tokens[i].type == JSMN_OBJECT ? CGLTF_ERROR_LEGACY : CGLTF_ERROR_JSON; 2788 } 2789 if (*out_array) 2790 { 2791 return CGLTF_ERROR_JSON; 2792 } 2793 int size = tokens[i].size; 2794 void* result = cgltf_calloc(options, element_size, size); 2795 if (!result) 2796 { 2797 return CGLTF_ERROR_NOMEM; 2798 } 2799 *out_array = result; 2800 *out_size = size; 2801 return i + 1; 2802 } 2803 2804 static int cgltf_parse_json_string_array(cgltf_options* options, jsmntok_t const* tokens, int i, const uint8_t* json_chunk, char*** out_array, cgltf_size* out_size) 2805 { 2806 CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_ARRAY); 2807 i = cgltf_parse_json_array(options, tokens, i, json_chunk, sizeof(char*), (void**)out_array, out_size); 2808 if (i < 0) 2809 { 2810 return i; 2811 } 2812 2813 for (cgltf_size j = 0; j < *out_size; ++j) 2814 { 2815 i = cgltf_parse_json_string(options, tokens, i, json_chunk, j + (*out_array)); 2816 if (i < 0) 2817 { 2818 return i; 2819 } 2820 } 2821 return i; 2822 } 2823 2824 static void cgltf_parse_attribute_type(const char* name, cgltf_attribute_type* out_type, int* out_index) 2825 { 2826 if (*name == '_') 2827 { 2828 *out_type = cgltf_attribute_type_custom; 2829 return; 2830 } 2831 2832 const char* us = strchr(name, '_'); 2833 size_t len = us ? (size_t)(us - name) : strlen(name); 2834 2835 if (len == 8 && strncmp(name, "POSITION", 8) == 0) 2836 { 2837 *out_type = cgltf_attribute_type_position; 2838 } 2839 else if (len == 6 && strncmp(name, "NORMAL", 6) == 0) 2840 { 2841 *out_type = cgltf_attribute_type_normal; 2842 } 2843 else if (len == 7 && strncmp(name, "TANGENT", 7) == 0) 2844 { 2845 *out_type = cgltf_attribute_type_tangent; 2846 } 2847 else if (len == 8 && strncmp(name, "TEXCOORD", 8) == 0) 2848 { 2849 *out_type = cgltf_attribute_type_texcoord; 2850 } 2851 else if (len == 5 && strncmp(name, "COLOR", 5) == 0) 2852 { 2853 *out_type = cgltf_attribute_type_color; 2854 } 2855 else if (len == 6 && strncmp(name, "JOINTS", 6) == 0) 2856 { 2857 *out_type = cgltf_attribute_type_joints; 2858 } 2859 else if (len == 7 && strncmp(name, "WEIGHTS", 7) == 0) 2860 { 2861 *out_type = cgltf_attribute_type_weights; 2862 } 2863 else 2864 { 2865 *out_type = cgltf_attribute_type_invalid; 2866 } 2867 2868 if (us && *out_type != cgltf_attribute_type_invalid) 2869 { 2870 *out_index = CGLTF_ATOI(us + 1); 2871 if (*out_index < 0) 2872 { 2873 *out_type = cgltf_attribute_type_invalid; 2874 *out_index = 0; 2875 } 2876 } 2877 } 2878 2879 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) 2880 { 2881 CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT); 2882 2883 if (*out_attributes) 2884 { 2885 return CGLTF_ERROR_JSON; 2886 } 2887 2888 *out_attributes_count = tokens[i].size; 2889 *out_attributes = (cgltf_attribute*)cgltf_calloc(options, sizeof(cgltf_attribute), *out_attributes_count); 2890 ++i; 2891 2892 if (!*out_attributes) 2893 { 2894 return CGLTF_ERROR_NOMEM; 2895 } 2896 2897 for (cgltf_size j = 0; j < *out_attributes_count; ++j) 2898 { 2899 CGLTF_CHECK_KEY(tokens[i]); 2900 2901 i = cgltf_parse_json_string(options, tokens, i, json_chunk, &(*out_attributes)[j].name); 2902 if (i < 0) 2903 { 2904 return CGLTF_ERROR_JSON; 2905 } 2906 2907 cgltf_parse_attribute_type((*out_attributes)[j].name, &(*out_attributes)[j].type, &(*out_attributes)[j].index); 2908 2909 (*out_attributes)[j].data = CGLTF_PTRINDEX(cgltf_accessor, cgltf_json_to_int(tokens + i, json_chunk)); 2910 ++i; 2911 } 2912 2913 return i; 2914 } 2915 2916 static int cgltf_parse_json_extras(cgltf_options* options, jsmntok_t const* tokens, int i, const uint8_t* json_chunk, cgltf_extras* out_extras) 2917 { 2918 if (out_extras->data) 2919 { 2920 return CGLTF_ERROR_JSON; 2921 } 2922 2923 /* fill deprecated fields for now, this will be removed in the future */ 2924 out_extras->start_offset = tokens[i].start; 2925 out_extras->end_offset = tokens[i].end; 2926 2927 size_t start = tokens[i].start; 2928 size_t size = tokens[i].end - start; 2929 out_extras->data = (char*)options->memory.alloc_func(options->memory.user_data, size + 1); 2930 if (!out_extras->data) 2931 { 2932 return CGLTF_ERROR_NOMEM; 2933 } 2934 strncpy(out_extras->data, (const char*)json_chunk + start, size); 2935 out_extras->data[size] = '\0'; 2936 2937 i = cgltf_skip_json(tokens, i); 2938 return i; 2939 } 2940 2941 static int cgltf_parse_json_unprocessed_extension(cgltf_options* options, jsmntok_t const* tokens, int i, const uint8_t* json_chunk, cgltf_extension* out_extension) 2942 { 2943 CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_STRING); 2944 CGLTF_CHECK_TOKTYPE(tokens[i+1], JSMN_OBJECT); 2945 if (out_extension->name) 2946 { 2947 return CGLTF_ERROR_JSON; 2948 } 2949 2950 cgltf_size name_length = tokens[i].end - tokens[i].start; 2951 out_extension->name = (char*)options->memory.alloc_func(options->memory.user_data, name_length + 1); 2952 if (!out_extension->name) 2953 { 2954 return CGLTF_ERROR_NOMEM; 2955 } 2956 strncpy(out_extension->name, (const char*)json_chunk + tokens[i].start, name_length); 2957 out_extension->name[name_length] = 0; 2958 i++; 2959 2960 size_t start = tokens[i].start; 2961 size_t size = tokens[i].end - start; 2962 out_extension->data = (char*)options->memory.alloc_func(options->memory.user_data, size + 1); 2963 if (!out_extension->data) 2964 { 2965 return CGLTF_ERROR_NOMEM; 2966 } 2967 strncpy(out_extension->data, (const char*)json_chunk + start, size); 2968 out_extension->data[size] = '\0'; 2969 2970 i = cgltf_skip_json(tokens, i); 2971 2972 return i; 2973 } 2974 2975 static int cgltf_parse_json_unprocessed_extensions(cgltf_options* options, jsmntok_t const* tokens, int i, const uint8_t* json_chunk, cgltf_size* out_extensions_count, cgltf_extension** out_extensions) 2976 { 2977 ++i; 2978 2979 CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT); 2980 if(*out_extensions) 2981 { 2982 return CGLTF_ERROR_JSON; 2983 } 2984 2985 int extensions_size = tokens[i].size; 2986 *out_extensions_count = 0; 2987 *out_extensions = (cgltf_extension*)cgltf_calloc(options, sizeof(cgltf_extension), extensions_size); 2988 2989 if (!*out_extensions) 2990 { 2991 return CGLTF_ERROR_NOMEM; 2992 } 2993 2994 ++i; 2995 2996 for (int j = 0; j < extensions_size; ++j) 2997 { 2998 CGLTF_CHECK_KEY(tokens[i]); 2999 3000 cgltf_size extension_index = (*out_extensions_count)++; 3001 cgltf_extension* extension = &((*out_extensions)[extension_index]); 3002 i = cgltf_parse_json_unprocessed_extension(options, tokens, i, json_chunk, extension); 3003 3004 if (i < 0) 3005 { 3006 return i; 3007 } 3008 } 3009 return i; 3010 } 3011 3012 static int cgltf_parse_json_draco_mesh_compression(cgltf_options* options, jsmntok_t const* tokens, int i, const uint8_t* json_chunk, cgltf_draco_mesh_compression* out_draco_mesh_compression) 3013 { 3014 CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT); 3015 3016 int size = tokens[i].size; 3017 ++i; 3018 3019 for (int j = 0; j < size; ++j) 3020 { 3021 CGLTF_CHECK_KEY(tokens[i]); 3022 3023 if (cgltf_json_strcmp(tokens + i, json_chunk, "attributes") == 0) 3024 { 3025 i = cgltf_parse_json_attribute_list(options, tokens, i + 1, json_chunk, &out_draco_mesh_compression->attributes, &out_draco_mesh_compression->attributes_count); 3026 } 3027 else if (cgltf_json_strcmp(tokens + i, json_chunk, "bufferView") == 0) 3028 { 3029 ++i; 3030 out_draco_mesh_compression->buffer_view = CGLTF_PTRINDEX(cgltf_buffer_view, cgltf_json_to_int(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 return i; 3045 } 3046 3047 static int cgltf_parse_json_mesh_gpu_instancing(cgltf_options* options, jsmntok_t const* tokens, int i, const uint8_t* json_chunk, cgltf_mesh_gpu_instancing* out_mesh_gpu_instancing) 3048 { 3049 CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT); 3050 3051 int size = tokens[i].size; 3052 ++i; 3053 3054 for (int j = 0; j < size; ++j) 3055 { 3056 CGLTF_CHECK_KEY(tokens[i]); 3057 3058 if (cgltf_json_strcmp(tokens + i, json_chunk, "attributes") == 0) 3059 { 3060 i = cgltf_parse_json_attribute_list(options, tokens, i + 1, json_chunk, &out_mesh_gpu_instancing->attributes, &out_mesh_gpu_instancing->attributes_count); 3061 } 3062 else 3063 { 3064 i = cgltf_skip_json(tokens, i+1); 3065 } 3066 3067 if (i < 0) 3068 { 3069 return i; 3070 } 3071 } 3072 3073 return i; 3074 } 3075 3076 static int cgltf_parse_json_material_mapping_data(cgltf_options* options, jsmntok_t const* tokens, int i, const uint8_t* json_chunk, cgltf_material_mapping* out_mappings, cgltf_size* offset) 3077 { 3078 (void)options; 3079 CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_ARRAY); 3080 3081 int size = tokens[i].size; 3082 ++i; 3083 3084 for (int j = 0; j < size; ++j) 3085 { 3086 CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT); 3087 3088 int obj_size = tokens[i].size; 3089 ++i; 3090 3091 int material = -1; 3092 int variants_tok = -1; 3093 int extras_tok = -1; 3094 3095 for (int k = 0; k < obj_size; ++k) 3096 { 3097 CGLTF_CHECK_KEY(tokens[i]); 3098 3099 if (cgltf_json_strcmp(tokens + i, json_chunk, "material") == 0) 3100 { 3101 ++i; 3102 material = cgltf_json_to_int(tokens + i, json_chunk); 3103 ++i; 3104 } 3105 else if (cgltf_json_strcmp(tokens + i, json_chunk, "variants") == 0) 3106 { 3107 variants_tok = i+1; 3108 CGLTF_CHECK_TOKTYPE(tokens[variants_tok], JSMN_ARRAY); 3109 3110 i = cgltf_skip_json(tokens, i+1); 3111 } 3112 else if (cgltf_json_strcmp(tokens + i, json_chunk, "extras") == 0) 3113 { 3114 extras_tok = i + 1; 3115 i = cgltf_skip_json(tokens, extras_tok); 3116 } 3117 else 3118 { 3119 i = cgltf_skip_json(tokens, i+1); 3120 } 3121 3122 if (i < 0) 3123 { 3124 return i; 3125 } 3126 } 3127 3128 if (material < 0 || variants_tok < 0) 3129 { 3130 return CGLTF_ERROR_JSON; 3131 } 3132 3133 if (out_mappings) 3134 { 3135 for (int k = 0; k < tokens[variants_tok].size; ++k) 3136 { 3137 int variant = cgltf_json_to_int(&tokens[variants_tok + 1 + k], json_chunk); 3138 if (variant < 0) 3139 return variant; 3140 3141 out_mappings[*offset].material = CGLTF_PTRINDEX(cgltf_material, material); 3142 out_mappings[*offset].variant = variant; 3143 3144 if (extras_tok >= 0) 3145 { 3146 int e = cgltf_parse_json_extras(options, tokens, extras_tok, json_chunk, &out_mappings[*offset].extras); 3147 if (e < 0) 3148 return e; 3149 } 3150 3151 (*offset)++; 3152 } 3153 } 3154 else 3155 { 3156 (*offset) += tokens[variants_tok].size; 3157 } 3158 } 3159 3160 return i; 3161 } 3162 3163 static int cgltf_parse_json_material_mappings(cgltf_options* options, jsmntok_t const* tokens, int i, const uint8_t* json_chunk, cgltf_primitive* out_prim) 3164 { 3165 CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT); 3166 3167 int size = tokens[i].size; 3168 ++i; 3169 3170 for (int j = 0; j < size; ++j) 3171 { 3172 CGLTF_CHECK_KEY(tokens[i]); 3173 3174 if (cgltf_json_strcmp(tokens + i, json_chunk, "mappings") == 0) 3175 { 3176 if (out_prim->mappings) 3177 { 3178 return CGLTF_ERROR_JSON; 3179 } 3180 3181 cgltf_size mappings_offset = 0; 3182 int k = cgltf_parse_json_material_mapping_data(options, tokens, i + 1, json_chunk, NULL, &mappings_offset); 3183 if (k < 0) 3184 { 3185 return k; 3186 } 3187 3188 out_prim->mappings_count = mappings_offset; 3189 out_prim->mappings = (cgltf_material_mapping*)cgltf_calloc(options, sizeof(cgltf_material_mapping), out_prim->mappings_count); 3190 3191 mappings_offset = 0; 3192 i = cgltf_parse_json_material_mapping_data(options, tokens, i + 1, json_chunk, out_prim->mappings, &mappings_offset); 3193 } 3194 else 3195 { 3196 i = cgltf_skip_json(tokens, i+1); 3197 } 3198 3199 if (i < 0) 3200 { 3201 return i; 3202 } 3203 } 3204 3205 return i; 3206 } 3207 3208 static cgltf_primitive_type cgltf_json_to_primitive_type(jsmntok_t const* tok, const uint8_t* json_chunk) 3209 { 3210 int type = cgltf_json_to_int(tok, json_chunk); 3211 3212 switch (type) 3213 { 3214 case 0: 3215 return cgltf_primitive_type_points; 3216 case 1: 3217 return cgltf_primitive_type_lines; 3218 case 2: 3219 return cgltf_primitive_type_line_loop; 3220 case 3: 3221 return cgltf_primitive_type_line_strip; 3222 case 4: 3223 return cgltf_primitive_type_triangles; 3224 case 5: 3225 return cgltf_primitive_type_triangle_strip; 3226 case 6: 3227 return cgltf_primitive_type_triangle_fan; 3228 default: 3229 return cgltf_primitive_type_invalid; 3230 } 3231 } 3232 3233 static int cgltf_parse_json_primitive(cgltf_options* options, jsmntok_t const* tokens, int i, const uint8_t* json_chunk, cgltf_primitive* out_prim) 3234 { 3235 CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT); 3236 3237 out_prim->type = cgltf_primitive_type_triangles; 3238 3239 int size = tokens[i].size; 3240 ++i; 3241 3242 for (int j = 0; j < size; ++j) 3243 { 3244 CGLTF_CHECK_KEY(tokens[i]); 3245 3246 if (cgltf_json_strcmp(tokens+i, json_chunk, "mode") == 0) 3247 { 3248 ++i; 3249 out_prim->type = cgltf_json_to_primitive_type(tokens+i, json_chunk); 3250 ++i; 3251 } 3252 else if (cgltf_json_strcmp(tokens+i, json_chunk, "indices") == 0) 3253 { 3254 ++i; 3255 out_prim->indices = CGLTF_PTRINDEX(cgltf_accessor, cgltf_json_to_int(tokens + i, json_chunk)); 3256 ++i; 3257 } 3258 else if (cgltf_json_strcmp(tokens+i, json_chunk, "material") == 0) 3259 { 3260 ++i; 3261 out_prim->material = CGLTF_PTRINDEX(cgltf_material, cgltf_json_to_int(tokens + i, json_chunk)); 3262 ++i; 3263 } 3264 else if (cgltf_json_strcmp(tokens+i, json_chunk, "attributes") == 0) 3265 { 3266 i = cgltf_parse_json_attribute_list(options, tokens, i + 1, json_chunk, &out_prim->attributes, &out_prim->attributes_count); 3267 } 3268 else if (cgltf_json_strcmp(tokens+i, json_chunk, "targets") == 0) 3269 { 3270 i = cgltf_parse_json_array(options, tokens, i + 1, json_chunk, sizeof(cgltf_morph_target), (void**)&out_prim->targets, &out_prim->targets_count); 3271 if (i < 0) 3272 { 3273 return i; 3274 } 3275 3276 for (cgltf_size k = 0; k < out_prim->targets_count; ++k) 3277 { 3278 i = cgltf_parse_json_attribute_list(options, tokens, i, json_chunk, &out_prim->targets[k].attributes, &out_prim->targets[k].attributes_count); 3279 if (i < 0) 3280 { 3281 return i; 3282 } 3283 } 3284 } 3285 else if (cgltf_json_strcmp(tokens + i, json_chunk, "extras") == 0) 3286 { 3287 i = cgltf_parse_json_extras(options, tokens, i + 1, json_chunk, &out_prim->extras); 3288 } 3289 else if (cgltf_json_strcmp(tokens + i, json_chunk, "extensions") == 0) 3290 { 3291 ++i; 3292 3293 CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT); 3294 if(out_prim->extensions) 3295 { 3296 return CGLTF_ERROR_JSON; 3297 } 3298 3299 int extensions_size = tokens[i].size; 3300 out_prim->extensions_count = 0; 3301 out_prim->extensions = (cgltf_extension*)cgltf_calloc(options, sizeof(cgltf_extension), extensions_size); 3302 3303 if (!out_prim->extensions) 3304 { 3305 return CGLTF_ERROR_NOMEM; 3306 } 3307 3308 ++i; 3309 for (int k = 0; k < extensions_size; ++k) 3310 { 3311 CGLTF_CHECK_KEY(tokens[i]); 3312 3313 if (cgltf_json_strcmp(tokens+i, json_chunk, "KHR_draco_mesh_compression") == 0) 3314 { 3315 out_prim->has_draco_mesh_compression = 1; 3316 i = cgltf_parse_json_draco_mesh_compression(options, tokens, i + 1, json_chunk, &out_prim->draco_mesh_compression); 3317 } 3318 else if (cgltf_json_strcmp(tokens+i, json_chunk, "KHR_materials_variants") == 0) 3319 { 3320 i = cgltf_parse_json_material_mappings(options, tokens, i + 1, json_chunk, out_prim); 3321 } 3322 else 3323 { 3324 i = cgltf_parse_json_unprocessed_extension(options, tokens, i, json_chunk, &(out_prim->extensions[out_prim->extensions_count++])); 3325 } 3326 3327 if (i < 0) 3328 { 3329 return i; 3330 } 3331 } 3332 } 3333 else 3334 { 3335 i = cgltf_skip_json(tokens, i+1); 3336 } 3337 3338 if (i < 0) 3339 { 3340 return i; 3341 } 3342 } 3343 3344 return i; 3345 } 3346 3347 static int cgltf_parse_json_mesh(cgltf_options* options, jsmntok_t const* tokens, int i, const uint8_t* json_chunk, cgltf_mesh* out_mesh) 3348 { 3349 CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT); 3350 3351 int size = tokens[i].size; 3352 ++i; 3353 3354 for (int j = 0; j < size; ++j) 3355 { 3356 CGLTF_CHECK_KEY(tokens[i]); 3357 3358 if (cgltf_json_strcmp(tokens+i, json_chunk, "name") == 0) 3359 { 3360 i = cgltf_parse_json_string(options, tokens, i + 1, json_chunk, &out_mesh->name); 3361 } 3362 else if (cgltf_json_strcmp(tokens+i, json_chunk, "primitives") == 0) 3363 { 3364 i = cgltf_parse_json_array(options, tokens, i + 1, json_chunk, sizeof(cgltf_primitive), (void**)&out_mesh->primitives, &out_mesh->primitives_count); 3365 if (i < 0) 3366 { 3367 return i; 3368 } 3369 3370 for (cgltf_size prim_index = 0; prim_index < out_mesh->primitives_count; ++prim_index) 3371 { 3372 i = cgltf_parse_json_primitive(options, tokens, i, json_chunk, &out_mesh->primitives[prim_index]); 3373 if (i < 0) 3374 { 3375 return i; 3376 } 3377 } 3378 } 3379 else if (cgltf_json_strcmp(tokens + i, json_chunk, "weights") == 0) 3380 { 3381 i = cgltf_parse_json_array(options, tokens, i + 1, json_chunk, sizeof(cgltf_float), (void**)&out_mesh->weights, &out_mesh->weights_count); 3382 if (i < 0) 3383 { 3384 return i; 3385 } 3386 3387 i = cgltf_parse_json_float_array(tokens, i - 1, json_chunk, out_mesh->weights, (int)out_mesh->weights_count); 3388 } 3389 else if (cgltf_json_strcmp(tokens + i, json_chunk, "extras") == 0) 3390 { 3391 ++i; 3392 3393 out_mesh->extras.start_offset = tokens[i].start; 3394 out_mesh->extras.end_offset = tokens[i].end; 3395 3396 if (tokens[i].type == JSMN_OBJECT) 3397 { 3398 int extras_size = tokens[i].size; 3399 ++i; 3400 3401 for (int k = 0; k < extras_size; ++k) 3402 { 3403 CGLTF_CHECK_KEY(tokens[i]); 3404 3405 if (cgltf_json_strcmp(tokens+i, json_chunk, "targetNames") == 0 && tokens[i+1].type == JSMN_ARRAY) 3406 { 3407 i = cgltf_parse_json_string_array(options, tokens, i + 1, json_chunk, &out_mesh->target_names, &out_mesh->target_names_count); 3408 } 3409 else 3410 { 3411 i = cgltf_skip_json(tokens, i+1); 3412 } 3413 3414 if (i < 0) 3415 { 3416 return i; 3417 } 3418 } 3419 } 3420 else 3421 { 3422 i = cgltf_skip_json(tokens, i); 3423 } 3424 } 3425 else if (cgltf_json_strcmp(tokens + i, json_chunk, "extensions") == 0) 3426 { 3427 i = cgltf_parse_json_unprocessed_extensions(options, tokens, i, json_chunk, &out_mesh->extensions_count, &out_mesh->extensions); 3428 } 3429 else 3430 { 3431 i = cgltf_skip_json(tokens, i+1); 3432 } 3433 3434 if (i < 0) 3435 { 3436 return i; 3437 } 3438 } 3439 3440 return i; 3441 } 3442 3443 static int cgltf_parse_json_meshes(cgltf_options* options, jsmntok_t const* tokens, int i, const uint8_t* json_chunk, cgltf_data* out_data) 3444 { 3445 i = cgltf_parse_json_array(options, tokens, i, json_chunk, sizeof(cgltf_mesh), (void**)&out_data->meshes, &out_data->meshes_count); 3446 if (i < 0) 3447 { 3448 return i; 3449 } 3450 3451 for (cgltf_size j = 0; j < out_data->meshes_count; ++j) 3452 { 3453 i = cgltf_parse_json_mesh(options, tokens, i, json_chunk, &out_data->meshes[j]); 3454 if (i < 0) 3455 { 3456 return i; 3457 } 3458 } 3459 return i; 3460 } 3461 3462 static cgltf_component_type cgltf_json_to_component_type(jsmntok_t const* tok, const uint8_t* json_chunk) 3463 { 3464 int type = cgltf_json_to_int(tok, json_chunk); 3465 3466 switch (type) 3467 { 3468 case 5120: 3469 return cgltf_component_type_r_8; 3470 case 5121: 3471 return cgltf_component_type_r_8u; 3472 case 5122: 3473 return cgltf_component_type_r_16; 3474 case 5123: 3475 return cgltf_component_type_r_16u; 3476 case 5125: 3477 return cgltf_component_type_r_32u; 3478 case 5126: 3479 return cgltf_component_type_r_32f; 3480 default: 3481 return cgltf_component_type_invalid; 3482 } 3483 } 3484 3485 static int cgltf_parse_json_accessor_sparse(jsmntok_t const* tokens, int i, const uint8_t* json_chunk, cgltf_accessor_sparse* out_sparse) 3486 { 3487 CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT); 3488 3489 int size = tokens[i].size; 3490 ++i; 3491 3492 for (int j = 0; j < size; ++j) 3493 { 3494 CGLTF_CHECK_KEY(tokens[i]); 3495 3496 if (cgltf_json_strcmp(tokens+i, json_chunk, "count") == 0) 3497 { 3498 ++i; 3499 out_sparse->count = cgltf_json_to_size(tokens + i, json_chunk); 3500 ++i; 3501 } 3502 else if (cgltf_json_strcmp(tokens+i, json_chunk, "indices") == 0) 3503 { 3504 ++i; 3505 CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT); 3506 3507 int indices_size = tokens[i].size; 3508 ++i; 3509 3510 for (int k = 0; k < indices_size; ++k) 3511 { 3512 CGLTF_CHECK_KEY(tokens[i]); 3513 3514 if (cgltf_json_strcmp(tokens+i, json_chunk, "bufferView") == 0) 3515 { 3516 ++i; 3517 out_sparse->indices_buffer_view = CGLTF_PTRINDEX(cgltf_buffer_view, cgltf_json_to_int(tokens + i, json_chunk)); 3518 ++i; 3519 } 3520 else if (cgltf_json_strcmp(tokens+i, json_chunk, "byteOffset") == 0) 3521 { 3522 ++i; 3523 out_sparse->indices_byte_offset = cgltf_json_to_size(tokens + i, json_chunk); 3524 ++i; 3525 } 3526 else if (cgltf_json_strcmp(tokens+i, json_chunk, "componentType") == 0) 3527 { 3528 ++i; 3529 out_sparse->indices_component_type = cgltf_json_to_component_type(tokens + i, json_chunk); 3530 ++i; 3531 } 3532 else 3533 { 3534 i = cgltf_skip_json(tokens, i+1); 3535 } 3536 3537 if (i < 0) 3538 { 3539 return i; 3540 } 3541 } 3542 } 3543 else if (cgltf_json_strcmp(tokens+i, json_chunk, "values") == 0) 3544 { 3545 ++i; 3546 CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT); 3547 3548 int values_size = tokens[i].size; 3549 ++i; 3550 3551 for (int k = 0; k < values_size; ++k) 3552 { 3553 CGLTF_CHECK_KEY(tokens[i]); 3554 3555 if (cgltf_json_strcmp(tokens+i, json_chunk, "bufferView") == 0) 3556 { 3557 ++i; 3558 out_sparse->values_buffer_view = CGLTF_PTRINDEX(cgltf_buffer_view, cgltf_json_to_int(tokens + i, json_chunk)); 3559 ++i; 3560 } 3561 else if (cgltf_json_strcmp(tokens+i, json_chunk, "byteOffset") == 0) 3562 { 3563 ++i; 3564 out_sparse->values_byte_offset = cgltf_json_to_size(tokens + i, json_chunk); 3565 ++i; 3566 } 3567 else 3568 { 3569 i = cgltf_skip_json(tokens, i+1); 3570 } 3571 3572 if (i < 0) 3573 { 3574 return i; 3575 } 3576 } 3577 } 3578 else 3579 { 3580 i = cgltf_skip_json(tokens, i+1); 3581 } 3582 3583 if (i < 0) 3584 { 3585 return i; 3586 } 3587 } 3588 3589 return i; 3590 } 3591 3592 static int cgltf_parse_json_accessor(cgltf_options* options, jsmntok_t const* tokens, int i, const uint8_t* json_chunk, cgltf_accessor* out_accessor) 3593 { 3594 CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT); 3595 3596 int size = tokens[i].size; 3597 ++i; 3598 3599 for (int j = 0; j < size; ++j) 3600 { 3601 CGLTF_CHECK_KEY(tokens[i]); 3602 3603 if (cgltf_json_strcmp(tokens + i, json_chunk, "name") == 0) 3604 { 3605 i = cgltf_parse_json_string(options, tokens, i + 1, json_chunk, &out_accessor->name); 3606 } 3607 else if (cgltf_json_strcmp(tokens+i, json_chunk, "bufferView") == 0) 3608 { 3609 ++i; 3610 out_accessor->buffer_view = CGLTF_PTRINDEX(cgltf_buffer_view, cgltf_json_to_int(tokens + i, json_chunk)); 3611 ++i; 3612 } 3613 else if (cgltf_json_strcmp(tokens+i, json_chunk, "byteOffset") == 0) 3614 { 3615 ++i; 3616 out_accessor->offset = 3617 cgltf_json_to_size(tokens+i, json_chunk); 3618 ++i; 3619 } 3620 else if (cgltf_json_strcmp(tokens+i, json_chunk, "componentType") == 0) 3621 { 3622 ++i; 3623 out_accessor->component_type = cgltf_json_to_component_type(tokens + i, json_chunk); 3624 ++i; 3625 } 3626 else if (cgltf_json_strcmp(tokens+i, json_chunk, "normalized") == 0) 3627 { 3628 ++i; 3629 out_accessor->normalized = cgltf_json_to_bool(tokens+i, json_chunk); 3630 ++i; 3631 } 3632 else if (cgltf_json_strcmp(tokens+i, json_chunk, "count") == 0) 3633 { 3634 ++i; 3635 out_accessor->count = cgltf_json_to_size(tokens+i, json_chunk); 3636 ++i; 3637 } 3638 else if (cgltf_json_strcmp(tokens+i, json_chunk, "type") == 0) 3639 { 3640 ++i; 3641 if (cgltf_json_strcmp(tokens+i, json_chunk, "SCALAR") == 0) 3642 { 3643 out_accessor->type = cgltf_type_scalar; 3644 } 3645 else if (cgltf_json_strcmp(tokens+i, json_chunk, "VEC2") == 0) 3646 { 3647 out_accessor->type = cgltf_type_vec2; 3648 } 3649 else if (cgltf_json_strcmp(tokens+i, json_chunk, "VEC3") == 0) 3650 { 3651 out_accessor->type = cgltf_type_vec3; 3652 } 3653 else if (cgltf_json_strcmp(tokens+i, json_chunk, "VEC4") == 0) 3654 { 3655 out_accessor->type = cgltf_type_vec4; 3656 } 3657 else if (cgltf_json_strcmp(tokens+i, json_chunk, "MAT2") == 0) 3658 { 3659 out_accessor->type = cgltf_type_mat2; 3660 } 3661 else if (cgltf_json_strcmp(tokens+i, json_chunk, "MAT3") == 0) 3662 { 3663 out_accessor->type = cgltf_type_mat3; 3664 } 3665 else if (cgltf_json_strcmp(tokens+i, json_chunk, "MAT4") == 0) 3666 { 3667 out_accessor->type = cgltf_type_mat4; 3668 } 3669 ++i; 3670 } 3671 else if (cgltf_json_strcmp(tokens + i, json_chunk, "min") == 0) 3672 { 3673 ++i; 3674 out_accessor->has_min = 1; 3675 // note: we can't parse the precise number of elements since type may not have been computed yet 3676 int min_size = tokens[i].size > 16 ? 16 : tokens[i].size; 3677 i = cgltf_parse_json_float_array(tokens, i, json_chunk, out_accessor->min, min_size); 3678 } 3679 else if (cgltf_json_strcmp(tokens + i, json_chunk, "max") == 0) 3680 { 3681 ++i; 3682 out_accessor->has_max = 1; 3683 // note: we can't parse the precise number of elements since type may not have been computed yet 3684 int max_size = tokens[i].size > 16 ? 16 : tokens[i].size; 3685 i = cgltf_parse_json_float_array(tokens, i, json_chunk, out_accessor->max, max_size); 3686 } 3687 else if (cgltf_json_strcmp(tokens + i, json_chunk, "sparse") == 0) 3688 { 3689 out_accessor->is_sparse = 1; 3690 i = cgltf_parse_json_accessor_sparse(tokens, i + 1, json_chunk, &out_accessor->sparse); 3691 } 3692 else if (cgltf_json_strcmp(tokens + i, json_chunk, "extras") == 0) 3693 { 3694 i = cgltf_parse_json_extras(options, tokens, i + 1, json_chunk, &out_accessor->extras); 3695 } 3696 else if (cgltf_json_strcmp(tokens + i, json_chunk, "extensions") == 0) 3697 { 3698 i = cgltf_parse_json_unprocessed_extensions(options, tokens, i, json_chunk, &out_accessor->extensions_count, &out_accessor->extensions); 3699 } 3700 else 3701 { 3702 i = cgltf_skip_json(tokens, i+1); 3703 } 3704 3705 if (i < 0) 3706 { 3707 return i; 3708 } 3709 } 3710 3711 return i; 3712 } 3713 3714 static int cgltf_parse_json_texture_transform(jsmntok_t const* tokens, int i, const uint8_t* json_chunk, cgltf_texture_transform* out_texture_transform) 3715 { 3716 CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT); 3717 3718 int size = tokens[i].size; 3719 ++i; 3720 3721 for (int j = 0; j < size; ++j) 3722 { 3723 CGLTF_CHECK_KEY(tokens[i]); 3724 3725 if (cgltf_json_strcmp(tokens + i, json_chunk, "offset") == 0) 3726 { 3727 i = cgltf_parse_json_float_array(tokens, i + 1, json_chunk, out_texture_transform->offset, 2); 3728 } 3729 else if (cgltf_json_strcmp(tokens + i, json_chunk, "rotation") == 0) 3730 { 3731 ++i; 3732 out_texture_transform->rotation = cgltf_json_to_float(tokens + i, json_chunk); 3733 ++i; 3734 } 3735 else if (cgltf_json_strcmp(tokens + i, json_chunk, "scale") == 0) 3736 { 3737 i = cgltf_parse_json_float_array(tokens, i + 1, json_chunk, out_texture_transform->scale, 2); 3738 } 3739 else if (cgltf_json_strcmp(tokens + i, json_chunk, "texCoord") == 0) 3740 { 3741 ++i; 3742 out_texture_transform->has_texcoord = 1; 3743 out_texture_transform->texcoord = cgltf_json_to_int(tokens + i, json_chunk); 3744 ++i; 3745 } 3746 else 3747 { 3748 i = cgltf_skip_json(tokens, i + 1); 3749 } 3750 3751 if (i < 0) 3752 { 3753 return i; 3754 } 3755 } 3756 3757 return i; 3758 } 3759 3760 static int cgltf_parse_json_texture_view(cgltf_options* options, jsmntok_t const* tokens, int i, const uint8_t* json_chunk, cgltf_texture_view* out_texture_view) 3761 { 3762 (void)options; 3763 3764 CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT); 3765 3766 out_texture_view->scale = 1.0f; 3767 cgltf_fill_float_array(out_texture_view->transform.scale, 2, 1.0f); 3768 3769 int size = tokens[i].size; 3770 ++i; 3771 3772 for (int j = 0; j < size; ++j) 3773 { 3774 CGLTF_CHECK_KEY(tokens[i]); 3775 3776 if (cgltf_json_strcmp(tokens + i, json_chunk, "index") == 0) 3777 { 3778 ++i; 3779 out_texture_view->texture = CGLTF_PTRINDEX(cgltf_texture, cgltf_json_to_int(tokens + i, json_chunk)); 3780 ++i; 3781 } 3782 else if (cgltf_json_strcmp(tokens + i, json_chunk, "texCoord") == 0) 3783 { 3784 ++i; 3785 out_texture_view->texcoord = cgltf_json_to_int(tokens + i, json_chunk); 3786 ++i; 3787 } 3788 else if (cgltf_json_strcmp(tokens + i, json_chunk, "scale") == 0) 3789 { 3790 ++i; 3791 out_texture_view->scale = cgltf_json_to_float(tokens + i, json_chunk); 3792 ++i; 3793 } 3794 else if (cgltf_json_strcmp(tokens + i, json_chunk, "strength") == 0) 3795 { 3796 ++i; 3797 out_texture_view->scale = cgltf_json_to_float(tokens + i, json_chunk); 3798 ++i; 3799 } 3800 else if (cgltf_json_strcmp(tokens + i, json_chunk, "extensions") == 0) 3801 { 3802 ++i; 3803 3804 CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT); 3805 int extensions_size = tokens[i].size; 3806 3807 ++i; 3808 3809 for (int k = 0; k < extensions_size; ++k) 3810 { 3811 CGLTF_CHECK_KEY(tokens[i]); 3812 3813 if (cgltf_json_strcmp(tokens+i, json_chunk, "KHR_texture_transform") == 0) 3814 { 3815 out_texture_view->has_transform = 1; 3816 i = cgltf_parse_json_texture_transform(tokens, i + 1, json_chunk, &out_texture_view->transform); 3817 } 3818 else 3819 { 3820 i = cgltf_skip_json(tokens, i + 1); 3821 } 3822 3823 if (i < 0) 3824 { 3825 return i; 3826 } 3827 } 3828 } 3829 else 3830 { 3831 i = cgltf_skip_json(tokens, i + 1); 3832 } 3833 3834 if (i < 0) 3835 { 3836 return i; 3837 } 3838 } 3839 3840 return i; 3841 } 3842 3843 static int cgltf_parse_json_pbr_metallic_roughness(cgltf_options* options, jsmntok_t const* tokens, int i, const uint8_t* json_chunk, cgltf_pbr_metallic_roughness* out_pbr) 3844 { 3845 CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT); 3846 3847 int size = tokens[i].size; 3848 ++i; 3849 3850 for (int j = 0; j < size; ++j) 3851 { 3852 CGLTF_CHECK_KEY(tokens[i]); 3853 3854 if (cgltf_json_strcmp(tokens+i, json_chunk, "metallicFactor") == 0) 3855 { 3856 ++i; 3857 out_pbr->metallic_factor = 3858 cgltf_json_to_float(tokens + i, json_chunk); 3859 ++i; 3860 } 3861 else if (cgltf_json_strcmp(tokens+i, json_chunk, "roughnessFactor") == 0) 3862 { 3863 ++i; 3864 out_pbr->roughness_factor = 3865 cgltf_json_to_float(tokens+i, json_chunk); 3866 ++i; 3867 } 3868 else if (cgltf_json_strcmp(tokens+i, json_chunk, "baseColorFactor") == 0) 3869 { 3870 i = cgltf_parse_json_float_array(tokens, i + 1, json_chunk, out_pbr->base_color_factor, 4); 3871 } 3872 else if (cgltf_json_strcmp(tokens+i, json_chunk, "baseColorTexture") == 0) 3873 { 3874 i = cgltf_parse_json_texture_view(options, tokens, i + 1, json_chunk, &out_pbr->base_color_texture); 3875 } 3876 else if (cgltf_json_strcmp(tokens + i, json_chunk, "metallicRoughnessTexture") == 0) 3877 { 3878 i = cgltf_parse_json_texture_view(options, tokens, i + 1, json_chunk, &out_pbr->metallic_roughness_texture); 3879 } 3880 else 3881 { 3882 i = cgltf_skip_json(tokens, i+1); 3883 } 3884 3885 if (i < 0) 3886 { 3887 return i; 3888 } 3889 } 3890 3891 return i; 3892 } 3893 3894 static int cgltf_parse_json_pbr_specular_glossiness(cgltf_options* options, jsmntok_t const* tokens, int i, const uint8_t* json_chunk, cgltf_pbr_specular_glossiness* out_pbr) 3895 { 3896 CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT); 3897 int size = tokens[i].size; 3898 ++i; 3899 3900 for (int j = 0; j < size; ++j) 3901 { 3902 CGLTF_CHECK_KEY(tokens[i]); 3903 3904 if (cgltf_json_strcmp(tokens+i, json_chunk, "diffuseFactor") == 0) 3905 { 3906 i = cgltf_parse_json_float_array(tokens, i + 1, json_chunk, out_pbr->diffuse_factor, 4); 3907 } 3908 else if (cgltf_json_strcmp(tokens+i, json_chunk, "specularFactor") == 0) 3909 { 3910 i = cgltf_parse_json_float_array(tokens, i + 1, json_chunk, out_pbr->specular_factor, 3); 3911 } 3912 else if (cgltf_json_strcmp(tokens+i, json_chunk, "glossinessFactor") == 0) 3913 { 3914 ++i; 3915 out_pbr->glossiness_factor = cgltf_json_to_float(tokens + i, json_chunk); 3916 ++i; 3917 } 3918 else if (cgltf_json_strcmp(tokens+i, json_chunk, "diffuseTexture") == 0) 3919 { 3920 i = cgltf_parse_json_texture_view(options, tokens, i + 1, json_chunk, &out_pbr->diffuse_texture); 3921 } 3922 else if (cgltf_json_strcmp(tokens+i, json_chunk, "specularGlossinessTexture") == 0) 3923 { 3924 i = cgltf_parse_json_texture_view(options, tokens, i + 1, json_chunk, &out_pbr->specular_glossiness_texture); 3925 } 3926 else 3927 { 3928 i = cgltf_skip_json(tokens, i+1); 3929 } 3930 3931 if (i < 0) 3932 { 3933 return i; 3934 } 3935 } 3936 3937 return i; 3938 } 3939 3940 static int cgltf_parse_json_clearcoat(cgltf_options* options, jsmntok_t const* tokens, int i, const uint8_t* json_chunk, cgltf_clearcoat* out_clearcoat) 3941 { 3942 CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT); 3943 int size = tokens[i].size; 3944 ++i; 3945 3946 for (int j = 0; j < size; ++j) 3947 { 3948 CGLTF_CHECK_KEY(tokens[i]); 3949 3950 if (cgltf_json_strcmp(tokens+i, json_chunk, "clearcoatFactor") == 0) 3951 { 3952 ++i; 3953 out_clearcoat->clearcoat_factor = cgltf_json_to_float(tokens + i, json_chunk); 3954 ++i; 3955 } 3956 else if (cgltf_json_strcmp(tokens+i, json_chunk, "clearcoatRoughnessFactor") == 0) 3957 { 3958 ++i; 3959 out_clearcoat->clearcoat_roughness_factor = cgltf_json_to_float(tokens + i, json_chunk); 3960 ++i; 3961 } 3962 else if (cgltf_json_strcmp(tokens+i, json_chunk, "clearcoatTexture") == 0) 3963 { 3964 i = cgltf_parse_json_texture_view(options, tokens, i + 1, json_chunk, &out_clearcoat->clearcoat_texture); 3965 } 3966 else if (cgltf_json_strcmp(tokens+i, json_chunk, "clearcoatRoughnessTexture") == 0) 3967 { 3968 i = cgltf_parse_json_texture_view(options, tokens, i + 1, json_chunk, &out_clearcoat->clearcoat_roughness_texture); 3969 } 3970 else if (cgltf_json_strcmp(tokens+i, json_chunk, "clearcoatNormalTexture") == 0) 3971 { 3972 i = cgltf_parse_json_texture_view(options, tokens, i + 1, json_chunk, &out_clearcoat->clearcoat_normal_texture); 3973 } 3974 else 3975 { 3976 i = cgltf_skip_json(tokens, i+1); 3977 } 3978 3979 if (i < 0) 3980 { 3981 return i; 3982 } 3983 } 3984 3985 return i; 3986 } 3987 3988 static int cgltf_parse_json_ior(jsmntok_t const* tokens, int i, const uint8_t* json_chunk, cgltf_ior* out_ior) 3989 { 3990 CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT); 3991 int size = tokens[i].size; 3992 ++i; 3993 3994 // Default values 3995 out_ior->ior = 1.5f; 3996 3997 for (int j = 0; j < size; ++j) 3998 { 3999 CGLTF_CHECK_KEY(tokens[i]); 4000 4001 if (cgltf_json_strcmp(tokens+i, json_chunk, "ior") == 0) 4002 { 4003 ++i; 4004 out_ior->ior = cgltf_json_to_float(tokens + i, json_chunk); 4005 ++i; 4006 } 4007 else 4008 { 4009 i = cgltf_skip_json(tokens, i+1); 4010 } 4011 4012 if (i < 0) 4013 { 4014 return i; 4015 } 4016 } 4017 4018 return i; 4019 } 4020 4021 static int cgltf_parse_json_specular(cgltf_options* options, jsmntok_t const* tokens, int i, const uint8_t* json_chunk, cgltf_specular* out_specular) 4022 { 4023 CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT); 4024 int size = tokens[i].size; 4025 ++i; 4026 4027 // Default values 4028 out_specular->specular_factor = 1.0f; 4029 cgltf_fill_float_array(out_specular->specular_color_factor, 3, 1.0f); 4030 4031 for (int j = 0; j < size; ++j) 4032 { 4033 CGLTF_CHECK_KEY(tokens[i]); 4034 4035 if (cgltf_json_strcmp(tokens+i, json_chunk, "specularFactor") == 0) 4036 { 4037 ++i; 4038 out_specular->specular_factor = cgltf_json_to_float(tokens + i, json_chunk); 4039 ++i; 4040 } 4041 else if (cgltf_json_strcmp(tokens+i, json_chunk, "specularColorFactor") == 0) 4042 { 4043 i = cgltf_parse_json_float_array(tokens, i + 1, json_chunk, out_specular->specular_color_factor, 3); 4044 } 4045 else if (cgltf_json_strcmp(tokens+i, json_chunk, "specularTexture") == 0) 4046 { 4047 i = cgltf_parse_json_texture_view(options, tokens, i + 1, json_chunk, &out_specular->specular_texture); 4048 } 4049 else if (cgltf_json_strcmp(tokens + i, json_chunk, "specularColorTexture") == 0) 4050 { 4051 i = cgltf_parse_json_texture_view(options, tokens, i + 1, json_chunk, &out_specular->specular_color_texture); 4052 } 4053 else 4054 { 4055 i = cgltf_skip_json(tokens, i+1); 4056 } 4057 4058 if (i < 0) 4059 { 4060 return i; 4061 } 4062 } 4063 4064 return i; 4065 } 4066 4067 static int cgltf_parse_json_transmission(cgltf_options* options, jsmntok_t const* tokens, int i, const uint8_t* json_chunk, cgltf_transmission* out_transmission) 4068 { 4069 CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT); 4070 int size = tokens[i].size; 4071 ++i; 4072 4073 for (int j = 0; j < size; ++j) 4074 { 4075 CGLTF_CHECK_KEY(tokens[i]); 4076 4077 if (cgltf_json_strcmp(tokens+i, json_chunk, "transmissionFactor") == 0) 4078 { 4079 ++i; 4080 out_transmission->transmission_factor = cgltf_json_to_float(tokens + i, json_chunk); 4081 ++i; 4082 } 4083 else if (cgltf_json_strcmp(tokens+i, json_chunk, "transmissionTexture") == 0) 4084 { 4085 i = cgltf_parse_json_texture_view(options, tokens, i + 1, json_chunk, &out_transmission->transmission_texture); 4086 } 4087 else 4088 { 4089 i = cgltf_skip_json(tokens, i+1); 4090 } 4091 4092 if (i < 0) 4093 { 4094 return i; 4095 } 4096 } 4097 4098 return i; 4099 } 4100 4101 static int cgltf_parse_json_volume(cgltf_options* options, jsmntok_t const* tokens, int i, const uint8_t* json_chunk, cgltf_volume* out_volume) 4102 { 4103 CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT); 4104 int size = tokens[i].size; 4105 ++i; 4106 4107 for (int j = 0; j < size; ++j) 4108 { 4109 CGLTF_CHECK_KEY(tokens[i]); 4110 4111 if (cgltf_json_strcmp(tokens + i, json_chunk, "thicknessFactor") == 0) 4112 { 4113 ++i; 4114 out_volume->thickness_factor = cgltf_json_to_float(tokens + i, json_chunk); 4115 ++i; 4116 } 4117 else if (cgltf_json_strcmp(tokens + i, json_chunk, "thicknessTexture") == 0) 4118 { 4119 i = cgltf_parse_json_texture_view(options, tokens, i + 1, json_chunk, &out_volume->thickness_texture); 4120 } 4121 else if (cgltf_json_strcmp(tokens + i, json_chunk, "attenuationColor") == 0) 4122 { 4123 i = cgltf_parse_json_float_array(tokens, i + 1, json_chunk, out_volume->attenuation_color, 3); 4124 } 4125 else if (cgltf_json_strcmp(tokens + i, json_chunk, "attenuationDistance") == 0) 4126 { 4127 ++i; 4128 out_volume->attenuation_distance = cgltf_json_to_float(tokens + i, json_chunk); 4129 ++i; 4130 } 4131 else 4132 { 4133 i = cgltf_skip_json(tokens, i + 1); 4134 } 4135 4136 if (i < 0) 4137 { 4138 return i; 4139 } 4140 } 4141 4142 return i; 4143 } 4144 4145 static int cgltf_parse_json_sheen(cgltf_options* options, jsmntok_t const* tokens, int i, const uint8_t* json_chunk, cgltf_sheen* out_sheen) 4146 { 4147 CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT); 4148 int size = tokens[i].size; 4149 ++i; 4150 4151 for (int j = 0; j < size; ++j) 4152 { 4153 CGLTF_CHECK_KEY(tokens[i]); 4154 4155 if (cgltf_json_strcmp(tokens+i, json_chunk, "sheenColorFactor") == 0) 4156 { 4157 i = cgltf_parse_json_float_array(tokens, i + 1, json_chunk, out_sheen->sheen_color_factor, 3); 4158 } 4159 else if (cgltf_json_strcmp(tokens+i, json_chunk, "sheenColorTexture") == 0) 4160 { 4161 i = cgltf_parse_json_texture_view(options, tokens, i + 1, json_chunk, &out_sheen->sheen_color_texture); 4162 } 4163 else if (cgltf_json_strcmp(tokens+i, json_chunk, "sheenRoughnessFactor") == 0) 4164 { 4165 ++i; 4166 out_sheen->sheen_roughness_factor = cgltf_json_to_float(tokens + i, json_chunk); 4167 ++i; 4168 } 4169 else if (cgltf_json_strcmp(tokens+i, json_chunk, "sheenRoughnessTexture") == 0) 4170 { 4171 i = cgltf_parse_json_texture_view(options, tokens, i + 1, json_chunk, &out_sheen->sheen_roughness_texture); 4172 } 4173 else 4174 { 4175 i = cgltf_skip_json(tokens, i+1); 4176 } 4177 4178 if (i < 0) 4179 { 4180 return i; 4181 } 4182 } 4183 4184 return i; 4185 } 4186 4187 static int cgltf_parse_json_emissive_strength(jsmntok_t const* tokens, int i, const uint8_t* json_chunk, cgltf_emissive_strength* out_emissive_strength) 4188 { 4189 CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT); 4190 int size = tokens[i].size; 4191 ++i; 4192 4193 // Default 4194 out_emissive_strength->emissive_strength = 1.f; 4195 4196 for (int j = 0; j < size; ++j) 4197 { 4198 CGLTF_CHECK_KEY(tokens[i]); 4199 4200 if (cgltf_json_strcmp(tokens + i, json_chunk, "emissiveStrength") == 0) 4201 { 4202 ++i; 4203 out_emissive_strength->emissive_strength = cgltf_json_to_float(tokens + i, json_chunk); 4204 ++i; 4205 } 4206 else 4207 { 4208 i = cgltf_skip_json(tokens, i + 1); 4209 } 4210 4211 if (i < 0) 4212 { 4213 return i; 4214 } 4215 } 4216 4217 return i; 4218 } 4219 4220 static int cgltf_parse_json_iridescence(cgltf_options* options, jsmntok_t const* tokens, int i, const uint8_t* json_chunk, cgltf_iridescence* out_iridescence) 4221 { 4222 CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT); 4223 int size = tokens[i].size; 4224 ++i; 4225 4226 // Default 4227 out_iridescence->iridescence_ior = 1.3f; 4228 out_iridescence->iridescence_thickness_min = 100.f; 4229 out_iridescence->iridescence_thickness_max = 400.f; 4230 4231 for (int j = 0; j < size; ++j) 4232 { 4233 CGLTF_CHECK_KEY(tokens[i]); 4234 4235 if (cgltf_json_strcmp(tokens + i, json_chunk, "iridescenceFactor") == 0) 4236 { 4237 ++i; 4238 out_iridescence->iridescence_factor = cgltf_json_to_float(tokens + i, json_chunk); 4239 ++i; 4240 } 4241 else if (cgltf_json_strcmp(tokens + i, json_chunk, "iridescenceTexture") == 0) 4242 { 4243 i = cgltf_parse_json_texture_view(options, tokens, i + 1, json_chunk, &out_iridescence->iridescence_texture); 4244 } 4245 else if (cgltf_json_strcmp(tokens + i, json_chunk, "iridescenceIor") == 0) 4246 { 4247 ++i; 4248 out_iridescence->iridescence_ior = cgltf_json_to_float(tokens + i, json_chunk); 4249 ++i; 4250 } 4251 else if (cgltf_json_strcmp(tokens + i, json_chunk, "iridescenceThicknessMinimum") == 0) 4252 { 4253 ++i; 4254 out_iridescence->iridescence_thickness_min = cgltf_json_to_float(tokens + i, json_chunk); 4255 ++i; 4256 } 4257 else if (cgltf_json_strcmp(tokens + i, json_chunk, "iridescenceThicknessMaximum") == 0) 4258 { 4259 ++i; 4260 out_iridescence->iridescence_thickness_max = cgltf_json_to_float(tokens + i, json_chunk); 4261 ++i; 4262 } 4263 else if (cgltf_json_strcmp(tokens + i, json_chunk, "iridescenceThicknessTexture") == 0) 4264 { 4265 i = cgltf_parse_json_texture_view(options, tokens, i + 1, json_chunk, &out_iridescence->iridescence_thickness_texture); 4266 } 4267 else 4268 { 4269 i = cgltf_skip_json(tokens, i + 1); 4270 } 4271 4272 if (i < 0) 4273 { 4274 return i; 4275 } 4276 } 4277 4278 return i; 4279 } 4280 4281 static int cgltf_parse_json_anisotropy(cgltf_options* options, jsmntok_t const* tokens, int i, const uint8_t* json_chunk, cgltf_anisotropy* out_anisotropy) 4282 { 4283 CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT); 4284 int size = tokens[i].size; 4285 ++i; 4286 4287 4288 for (int j = 0; j < size; ++j) 4289 { 4290 CGLTF_CHECK_KEY(tokens[i]); 4291 4292 if (cgltf_json_strcmp(tokens + i, json_chunk, "anisotropyStrength") == 0) 4293 { 4294 ++i; 4295 out_anisotropy->anisotropy_strength = cgltf_json_to_float(tokens + i, json_chunk); 4296 ++i; 4297 } 4298 else if (cgltf_json_strcmp(tokens + i, json_chunk, "anisotropyRotation") == 0) 4299 { 4300 ++i; 4301 out_anisotropy->anisotropy_rotation = cgltf_json_to_float(tokens + i, json_chunk); 4302 ++i; 4303 } 4304 else if (cgltf_json_strcmp(tokens + i, json_chunk, "anisotropyTexture") == 0) 4305 { 4306 i = cgltf_parse_json_texture_view(options, tokens, i + 1, json_chunk, &out_anisotropy->anisotropy_texture); 4307 } 4308 else 4309 { 4310 i = cgltf_skip_json(tokens, i + 1); 4311 } 4312 4313 if (i < 0) 4314 { 4315 return i; 4316 } 4317 } 4318 4319 return i; 4320 } 4321 4322 static int cgltf_parse_json_dispersion(jsmntok_t const* tokens, int i, const uint8_t* json_chunk, cgltf_dispersion* out_dispersion) 4323 { 4324 CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT); 4325 int size = tokens[i].size; 4326 ++i; 4327 4328 4329 for (int j = 0; j < size; ++j) 4330 { 4331 CGLTF_CHECK_KEY(tokens[i]); 4332 4333 if (cgltf_json_strcmp(tokens + i, json_chunk, "dispersion") == 0) 4334 { 4335 ++i; 4336 out_dispersion->dispersion = cgltf_json_to_float(tokens + i, json_chunk); 4337 ++i; 4338 } 4339 else 4340 { 4341 i = cgltf_skip_json(tokens, i + 1); 4342 } 4343 4344 if (i < 0) 4345 { 4346 return i; 4347 } 4348 } 4349 4350 return i; 4351 } 4352 4353 static int cgltf_parse_json_image(cgltf_options* options, jsmntok_t const* tokens, int i, const uint8_t* json_chunk, cgltf_image* out_image) 4354 { 4355 CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT); 4356 4357 int size = tokens[i].size; 4358 ++i; 4359 4360 for (int j = 0; j < size; ++j) 4361 { 4362 CGLTF_CHECK_KEY(tokens[i]); 4363 4364 if (cgltf_json_strcmp(tokens + i, json_chunk, "uri") == 0) 4365 { 4366 i = cgltf_parse_json_string(options, tokens, i + 1, json_chunk, &out_image->uri); 4367 } 4368 else if (cgltf_json_strcmp(tokens+i, json_chunk, "bufferView") == 0) 4369 { 4370 ++i; 4371 out_image->buffer_view = CGLTF_PTRINDEX(cgltf_buffer_view, cgltf_json_to_int(tokens + i, json_chunk)); 4372 ++i; 4373 } 4374 else if (cgltf_json_strcmp(tokens + i, json_chunk, "mimeType") == 0) 4375 { 4376 i = cgltf_parse_json_string(options, tokens, i + 1, json_chunk, &out_image->mime_type); 4377 } 4378 else if (cgltf_json_strcmp(tokens + i, json_chunk, "name") == 0) 4379 { 4380 i = cgltf_parse_json_string(options, tokens, i + 1, json_chunk, &out_image->name); 4381 } 4382 else if (cgltf_json_strcmp(tokens + i, json_chunk, "extras") == 0) 4383 { 4384 i = cgltf_parse_json_extras(options, tokens, i + 1, json_chunk, &out_image->extras); 4385 } 4386 else if (cgltf_json_strcmp(tokens + i, json_chunk, "extensions") == 0) 4387 { 4388 i = cgltf_parse_json_unprocessed_extensions(options, tokens, i, json_chunk, &out_image->extensions_count, &out_image->extensions); 4389 } 4390 else 4391 { 4392 i = cgltf_skip_json(tokens, i + 1); 4393 } 4394 4395 if (i < 0) 4396 { 4397 return i; 4398 } 4399 } 4400 4401 return i; 4402 } 4403 4404 static int cgltf_parse_json_sampler(cgltf_options* options, jsmntok_t const* tokens, int i, const uint8_t* json_chunk, cgltf_sampler* out_sampler) 4405 { 4406 (void)options; 4407 CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT); 4408 4409 out_sampler->wrap_s = 10497; 4410 out_sampler->wrap_t = 10497; 4411 4412 int size = tokens[i].size; 4413 ++i; 4414 4415 for (int j = 0; j < size; ++j) 4416 { 4417 CGLTF_CHECK_KEY(tokens[i]); 4418 4419 if (cgltf_json_strcmp(tokens + i, json_chunk, "name") == 0) 4420 { 4421 i = cgltf_parse_json_string(options, tokens, i + 1, json_chunk, &out_sampler->name); 4422 } 4423 else if (cgltf_json_strcmp(tokens + i, json_chunk, "magFilter") == 0) 4424 { 4425 ++i; 4426 out_sampler->mag_filter 4427 = cgltf_json_to_int(tokens + i, json_chunk); 4428 ++i; 4429 } 4430 else if (cgltf_json_strcmp(tokens + i, json_chunk, "minFilter") == 0) 4431 { 4432 ++i; 4433 out_sampler->min_filter 4434 = cgltf_json_to_int(tokens + i, json_chunk); 4435 ++i; 4436 } 4437 else if (cgltf_json_strcmp(tokens + i, json_chunk, "wrapS") == 0) 4438 { 4439 ++i; 4440 out_sampler->wrap_s 4441 = cgltf_json_to_int(tokens + i, json_chunk); 4442 ++i; 4443 } 4444 else if (cgltf_json_strcmp(tokens + i, json_chunk, "wrapT") == 0) 4445 { 4446 ++i; 4447 out_sampler->wrap_t 4448 = cgltf_json_to_int(tokens + i, json_chunk); 4449 ++i; 4450 } 4451 else if (cgltf_json_strcmp(tokens + i, json_chunk, "extras") == 0) 4452 { 4453 i = cgltf_parse_json_extras(options, tokens, i + 1, json_chunk, &out_sampler->extras); 4454 } 4455 else if (cgltf_json_strcmp(tokens + i, json_chunk, "extensions") == 0) 4456 { 4457 i = cgltf_parse_json_unprocessed_extensions(options, tokens, i, json_chunk, &out_sampler->extensions_count, &out_sampler->extensions); 4458 } 4459 else 4460 { 4461 i = cgltf_skip_json(tokens, i + 1); 4462 } 4463 4464 if (i < 0) 4465 { 4466 return i; 4467 } 4468 } 4469 4470 return i; 4471 } 4472 4473 static int cgltf_parse_json_texture(cgltf_options* options, jsmntok_t const* tokens, int i, const uint8_t* json_chunk, cgltf_texture* out_texture) 4474 { 4475 CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT); 4476 4477 int size = tokens[i].size; 4478 ++i; 4479 4480 for (int j = 0; j < size; ++j) 4481 { 4482 CGLTF_CHECK_KEY(tokens[i]); 4483 4484 if (cgltf_json_strcmp(tokens+i, json_chunk, "name") == 0) 4485 { 4486 i = cgltf_parse_json_string(options, tokens, i + 1, json_chunk, &out_texture->name); 4487 } 4488 else if (cgltf_json_strcmp(tokens + i, json_chunk, "sampler") == 0) 4489 { 4490 ++i; 4491 out_texture->sampler = CGLTF_PTRINDEX(cgltf_sampler, cgltf_json_to_int(tokens + i, json_chunk)); 4492 ++i; 4493 } 4494 else if (cgltf_json_strcmp(tokens + i, json_chunk, "source") == 0) 4495 { 4496 ++i; 4497 out_texture->image = CGLTF_PTRINDEX(cgltf_image, cgltf_json_to_int(tokens + i, json_chunk)); 4498 ++i; 4499 } 4500 else if (cgltf_json_strcmp(tokens + i, json_chunk, "extras") == 0) 4501 { 4502 i = cgltf_parse_json_extras(options, tokens, i + 1, json_chunk, &out_texture->extras); 4503 } 4504 else if (cgltf_json_strcmp(tokens + i, json_chunk, "extensions") == 0) 4505 { 4506 ++i; 4507 4508 CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT); 4509 if (out_texture->extensions) 4510 { 4511 return CGLTF_ERROR_JSON; 4512 } 4513 4514 int extensions_size = tokens[i].size; 4515 ++i; 4516 out_texture->extensions = (cgltf_extension*)cgltf_calloc(options, sizeof(cgltf_extension), extensions_size); 4517 out_texture->extensions_count = 0; 4518 4519 if (!out_texture->extensions) 4520 { 4521 return CGLTF_ERROR_NOMEM; 4522 } 4523 4524 for (int k = 0; k < extensions_size; ++k) 4525 { 4526 CGLTF_CHECK_KEY(tokens[i]); 4527 4528 if (cgltf_json_strcmp(tokens + i, json_chunk, "KHR_texture_basisu") == 0) 4529 { 4530 out_texture->has_basisu = 1; 4531 ++i; 4532 CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT); 4533 int num_properties = tokens[i].size; 4534 ++i; 4535 4536 for (int t = 0; t < num_properties; ++t) 4537 { 4538 CGLTF_CHECK_KEY(tokens[i]); 4539 4540 if (cgltf_json_strcmp(tokens + i, json_chunk, "source") == 0) 4541 { 4542 ++i; 4543 out_texture->basisu_image = CGLTF_PTRINDEX(cgltf_image, cgltf_json_to_int(tokens + i, json_chunk)); 4544 ++i; 4545 } 4546 else 4547 { 4548 i = cgltf_skip_json(tokens, i + 1); 4549 } 4550 if (i < 0) 4551 { 4552 return i; 4553 } 4554 } 4555 } 4556 else if (cgltf_json_strcmp(tokens + i, json_chunk, "EXT_texture_webp") == 0) 4557 { 4558 out_texture->has_webp = 1; 4559 ++i; 4560 CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT); 4561 int num_properties = tokens[i].size; 4562 ++i; 4563 4564 for (int t = 0; t < num_properties; ++t) 4565 { 4566 CGLTF_CHECK_KEY(tokens[i]); 4567 4568 if (cgltf_json_strcmp(tokens + i, json_chunk, "source") == 0) 4569 { 4570 ++i; 4571 out_texture->webp_image = CGLTF_PTRINDEX(cgltf_image, cgltf_json_to_int(tokens + i, json_chunk)); 4572 ++i; 4573 } 4574 else 4575 { 4576 i = cgltf_skip_json(tokens, i + 1); 4577 } 4578 if (i < 0) 4579 { 4580 return i; 4581 } 4582 } 4583 } 4584 else 4585 { 4586 i = cgltf_parse_json_unprocessed_extension(options, tokens, i, json_chunk, &(out_texture->extensions[out_texture->extensions_count++])); 4587 } 4588 4589 if (i < 0) 4590 { 4591 return i; 4592 } 4593 } 4594 } 4595 else 4596 { 4597 i = cgltf_skip_json(tokens, i + 1); 4598 } 4599 4600 if (i < 0) 4601 { 4602 return i; 4603 } 4604 } 4605 4606 return i; 4607 } 4608 4609 static int cgltf_parse_json_material(cgltf_options* options, jsmntok_t const* tokens, int i, const uint8_t* json_chunk, cgltf_material* out_material) 4610 { 4611 CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT); 4612 4613 cgltf_fill_float_array(out_material->pbr_metallic_roughness.base_color_factor, 4, 1.0f); 4614 out_material->pbr_metallic_roughness.metallic_factor = 1.0f; 4615 out_material->pbr_metallic_roughness.roughness_factor = 1.0f; 4616 4617 cgltf_fill_float_array(out_material->pbr_specular_glossiness.diffuse_factor, 4, 1.0f); 4618 cgltf_fill_float_array(out_material->pbr_specular_glossiness.specular_factor, 3, 1.0f); 4619 out_material->pbr_specular_glossiness.glossiness_factor = 1.0f; 4620 4621 cgltf_fill_float_array(out_material->volume.attenuation_color, 3, 1.0f); 4622 out_material->volume.attenuation_distance = FLT_MAX; 4623 4624 out_material->alpha_cutoff = 0.5f; 4625 4626 int size = tokens[i].size; 4627 ++i; 4628 4629 for (int j = 0; j < size; ++j) 4630 { 4631 CGLTF_CHECK_KEY(tokens[i]); 4632 4633 if (cgltf_json_strcmp(tokens+i, json_chunk, "name") == 0) 4634 { 4635 i = cgltf_parse_json_string(options, tokens, i + 1, json_chunk, &out_material->name); 4636 } 4637 else if (cgltf_json_strcmp(tokens+i, json_chunk, "pbrMetallicRoughness") == 0) 4638 { 4639 out_material->has_pbr_metallic_roughness = 1; 4640 i = cgltf_parse_json_pbr_metallic_roughness(options, tokens, i + 1, json_chunk, &out_material->pbr_metallic_roughness); 4641 } 4642 else if (cgltf_json_strcmp(tokens+i, json_chunk, "emissiveFactor") == 0) 4643 { 4644 i = cgltf_parse_json_float_array(tokens, i + 1, json_chunk, out_material->emissive_factor, 3); 4645 } 4646 else if (cgltf_json_strcmp(tokens + i, json_chunk, "normalTexture") == 0) 4647 { 4648 i = cgltf_parse_json_texture_view(options, tokens, i + 1, json_chunk, 4649 &out_material->normal_texture); 4650 } 4651 else if (cgltf_json_strcmp(tokens + i, json_chunk, "occlusionTexture") == 0) 4652 { 4653 i = cgltf_parse_json_texture_view(options, tokens, i + 1, json_chunk, 4654 &out_material->occlusion_texture); 4655 } 4656 else if (cgltf_json_strcmp(tokens + i, json_chunk, "emissiveTexture") == 0) 4657 { 4658 i = cgltf_parse_json_texture_view(options, tokens, i + 1, json_chunk, 4659 &out_material->emissive_texture); 4660 } 4661 else if (cgltf_json_strcmp(tokens + i, json_chunk, "alphaMode") == 0) 4662 { 4663 ++i; 4664 if (cgltf_json_strcmp(tokens + i, json_chunk, "OPAQUE") == 0) 4665 { 4666 out_material->alpha_mode = cgltf_alpha_mode_opaque; 4667 } 4668 else if (cgltf_json_strcmp(tokens + i, json_chunk, "MASK") == 0) 4669 { 4670 out_material->alpha_mode = cgltf_alpha_mode_mask; 4671 } 4672 else if (cgltf_json_strcmp(tokens + i, json_chunk, "BLEND") == 0) 4673 { 4674 out_material->alpha_mode = cgltf_alpha_mode_blend; 4675 } 4676 ++i; 4677 } 4678 else if (cgltf_json_strcmp(tokens + i, json_chunk, "alphaCutoff") == 0) 4679 { 4680 ++i; 4681 out_material->alpha_cutoff = cgltf_json_to_float(tokens + i, json_chunk); 4682 ++i; 4683 } 4684 else if (cgltf_json_strcmp(tokens + i, json_chunk, "doubleSided") == 0) 4685 { 4686 ++i; 4687 out_material->double_sided = 4688 cgltf_json_to_bool(tokens + i, json_chunk); 4689 ++i; 4690 } 4691 else if (cgltf_json_strcmp(tokens + i, json_chunk, "extras") == 0) 4692 { 4693 i = cgltf_parse_json_extras(options, tokens, i + 1, json_chunk, &out_material->extras); 4694 } 4695 else if (cgltf_json_strcmp(tokens + i, json_chunk, "extensions") == 0) 4696 { 4697 ++i; 4698 4699 CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT); 4700 if(out_material->extensions) 4701 { 4702 return CGLTF_ERROR_JSON; 4703 } 4704 4705 int extensions_size = tokens[i].size; 4706 ++i; 4707 out_material->extensions = (cgltf_extension*)cgltf_calloc(options, sizeof(cgltf_extension), extensions_size); 4708 out_material->extensions_count= 0; 4709 4710 if (!out_material->extensions) 4711 { 4712 return CGLTF_ERROR_NOMEM; 4713 } 4714 4715 for (int k = 0; k < extensions_size; ++k) 4716 { 4717 CGLTF_CHECK_KEY(tokens[i]); 4718 4719 if (cgltf_json_strcmp(tokens+i, json_chunk, "KHR_materials_pbrSpecularGlossiness") == 0) 4720 { 4721 out_material->has_pbr_specular_glossiness = 1; 4722 i = cgltf_parse_json_pbr_specular_glossiness(options, tokens, i + 1, json_chunk, &out_material->pbr_specular_glossiness); 4723 } 4724 else if (cgltf_json_strcmp(tokens+i, json_chunk, "KHR_materials_unlit") == 0) 4725 { 4726 out_material->unlit = 1; 4727 i = cgltf_skip_json(tokens, i+1); 4728 } 4729 else if (cgltf_json_strcmp(tokens+i, json_chunk, "KHR_materials_clearcoat") == 0) 4730 { 4731 out_material->has_clearcoat = 1; 4732 i = cgltf_parse_json_clearcoat(options, tokens, i + 1, json_chunk, &out_material->clearcoat); 4733 } 4734 else if (cgltf_json_strcmp(tokens+i, json_chunk, "KHR_materials_ior") == 0) 4735 { 4736 out_material->has_ior = 1; 4737 i = cgltf_parse_json_ior(tokens, i + 1, json_chunk, &out_material->ior); 4738 } 4739 else if (cgltf_json_strcmp(tokens+i, json_chunk, "KHR_materials_specular") == 0) 4740 { 4741 out_material->has_specular = 1; 4742 i = cgltf_parse_json_specular(options, tokens, i + 1, json_chunk, &out_material->specular); 4743 } 4744 else if (cgltf_json_strcmp(tokens+i, json_chunk, "KHR_materials_transmission") == 0) 4745 { 4746 out_material->has_transmission = 1; 4747 i = cgltf_parse_json_transmission(options, tokens, i + 1, json_chunk, &out_material->transmission); 4748 } 4749 else if (cgltf_json_strcmp(tokens + i, json_chunk, "KHR_materials_volume") == 0) 4750 { 4751 out_material->has_volume = 1; 4752 i = cgltf_parse_json_volume(options, tokens, i + 1, json_chunk, &out_material->volume); 4753 } 4754 else if (cgltf_json_strcmp(tokens+i, json_chunk, "KHR_materials_sheen") == 0) 4755 { 4756 out_material->has_sheen = 1; 4757 i = cgltf_parse_json_sheen(options, tokens, i + 1, json_chunk, &out_material->sheen); 4758 } 4759 else if (cgltf_json_strcmp(tokens + i, json_chunk, "KHR_materials_emissive_strength") == 0) 4760 { 4761 out_material->has_emissive_strength = 1; 4762 i = cgltf_parse_json_emissive_strength(tokens, i + 1, json_chunk, &out_material->emissive_strength); 4763 } 4764 else if (cgltf_json_strcmp(tokens + i, json_chunk, "KHR_materials_iridescence") == 0) 4765 { 4766 out_material->has_iridescence = 1; 4767 i = cgltf_parse_json_iridescence(options, tokens, i + 1, json_chunk, &out_material->iridescence); 4768 } 4769 else if (cgltf_json_strcmp(tokens + i, json_chunk, "KHR_materials_anisotropy") == 0) 4770 { 4771 out_material->has_anisotropy = 1; 4772 i = cgltf_parse_json_anisotropy(options, tokens, i + 1, json_chunk, &out_material->anisotropy); 4773 } 4774 else if (cgltf_json_strcmp(tokens + i, json_chunk, "KHR_materials_dispersion") == 0) 4775 { 4776 out_material->has_dispersion = 1; 4777 i = cgltf_parse_json_dispersion(tokens, i + 1, json_chunk, &out_material->dispersion); 4778 } 4779 else 4780 { 4781 i = cgltf_parse_json_unprocessed_extension(options, tokens, i, json_chunk, &(out_material->extensions[out_material->extensions_count++])); 4782 } 4783 4784 if (i < 0) 4785 { 4786 return i; 4787 } 4788 } 4789 } 4790 else 4791 { 4792 i = cgltf_skip_json(tokens, i+1); 4793 } 4794 4795 if (i < 0) 4796 { 4797 return i; 4798 } 4799 } 4800 4801 return i; 4802 } 4803 4804 static int cgltf_parse_json_accessors(cgltf_options* options, jsmntok_t const* tokens, int i, const uint8_t* json_chunk, cgltf_data* out_data) 4805 { 4806 i = cgltf_parse_json_array(options, tokens, i, json_chunk, sizeof(cgltf_accessor), (void**)&out_data->accessors, &out_data->accessors_count); 4807 if (i < 0) 4808 { 4809 return i; 4810 } 4811 4812 for (cgltf_size j = 0; j < out_data->accessors_count; ++j) 4813 { 4814 i = cgltf_parse_json_accessor(options, tokens, i, json_chunk, &out_data->accessors[j]); 4815 if (i < 0) 4816 { 4817 return i; 4818 } 4819 } 4820 return i; 4821 } 4822 4823 static int cgltf_parse_json_materials(cgltf_options* options, jsmntok_t const* tokens, int i, const uint8_t* json_chunk, cgltf_data* out_data) 4824 { 4825 i = cgltf_parse_json_array(options, tokens, i, json_chunk, sizeof(cgltf_material), (void**)&out_data->materials, &out_data->materials_count); 4826 if (i < 0) 4827 { 4828 return i; 4829 } 4830 4831 for (cgltf_size j = 0; j < out_data->materials_count; ++j) 4832 { 4833 i = cgltf_parse_json_material(options, tokens, i, json_chunk, &out_data->materials[j]); 4834 if (i < 0) 4835 { 4836 return i; 4837 } 4838 } 4839 return i; 4840 } 4841 4842 static int cgltf_parse_json_images(cgltf_options* options, jsmntok_t const* tokens, int i, const uint8_t* json_chunk, cgltf_data* out_data) 4843 { 4844 i = cgltf_parse_json_array(options, tokens, i, json_chunk, sizeof(cgltf_image), (void**)&out_data->images, &out_data->images_count); 4845 if (i < 0) 4846 { 4847 return i; 4848 } 4849 4850 for (cgltf_size j = 0; j < out_data->images_count; ++j) 4851 { 4852 i = cgltf_parse_json_image(options, tokens, i, json_chunk, &out_data->images[j]); 4853 if (i < 0) 4854 { 4855 return i; 4856 } 4857 } 4858 return i; 4859 } 4860 4861 static int cgltf_parse_json_textures(cgltf_options* options, jsmntok_t const* tokens, int i, const uint8_t* json_chunk, cgltf_data* out_data) 4862 { 4863 i = cgltf_parse_json_array(options, tokens, i, json_chunk, sizeof(cgltf_texture), (void**)&out_data->textures, &out_data->textures_count); 4864 if (i < 0) 4865 { 4866 return i; 4867 } 4868 4869 for (cgltf_size j = 0; j < out_data->textures_count; ++j) 4870 { 4871 i = cgltf_parse_json_texture(options, tokens, i, json_chunk, &out_data->textures[j]); 4872 if (i < 0) 4873 { 4874 return i; 4875 } 4876 } 4877 return i; 4878 } 4879 4880 static int cgltf_parse_json_samplers(cgltf_options* options, jsmntok_t const* tokens, int i, const uint8_t* json_chunk, cgltf_data* out_data) 4881 { 4882 i = cgltf_parse_json_array(options, tokens, i, json_chunk, sizeof(cgltf_sampler), (void**)&out_data->samplers, &out_data->samplers_count); 4883 if (i < 0) 4884 { 4885 return i; 4886 } 4887 4888 for (cgltf_size j = 0; j < out_data->samplers_count; ++j) 4889 { 4890 i = cgltf_parse_json_sampler(options, tokens, i, json_chunk, &out_data->samplers[j]); 4891 if (i < 0) 4892 { 4893 return i; 4894 } 4895 } 4896 return i; 4897 } 4898 4899 static int cgltf_parse_json_meshopt_compression(cgltf_options* options, jsmntok_t const* tokens, int i, const uint8_t* json_chunk, cgltf_meshopt_compression* out_meshopt_compression) 4900 { 4901 (void)options; 4902 CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT); 4903 4904 int size = tokens[i].size; 4905 ++i; 4906 4907 for (int j = 0; j < size; ++j) 4908 { 4909 CGLTF_CHECK_KEY(tokens[i]); 4910 4911 if (cgltf_json_strcmp(tokens+i, json_chunk, "buffer") == 0) 4912 { 4913 ++i; 4914 out_meshopt_compression->buffer = CGLTF_PTRINDEX(cgltf_buffer, cgltf_json_to_int(tokens + i, json_chunk)); 4915 ++i; 4916 } 4917 else if (cgltf_json_strcmp(tokens+i, json_chunk, "byteOffset") == 0) 4918 { 4919 ++i; 4920 out_meshopt_compression->offset = cgltf_json_to_size(tokens+i, json_chunk); 4921 ++i; 4922 } 4923 else if (cgltf_json_strcmp(tokens+i, json_chunk, "byteLength") == 0) 4924 { 4925 ++i; 4926 out_meshopt_compression->size = cgltf_json_to_size(tokens+i, json_chunk); 4927 ++i; 4928 } 4929 else if (cgltf_json_strcmp(tokens+i, json_chunk, "byteStride") == 0) 4930 { 4931 ++i; 4932 out_meshopt_compression->stride = cgltf_json_to_size(tokens+i, json_chunk); 4933 ++i; 4934 } 4935 else if (cgltf_json_strcmp(tokens+i, json_chunk, "count") == 0) 4936 { 4937 ++i; 4938 out_meshopt_compression->count = cgltf_json_to_size(tokens+i, json_chunk); 4939 ++i; 4940 } 4941 else if (cgltf_json_strcmp(tokens+i, json_chunk, "mode") == 0) 4942 { 4943 ++i; 4944 if (cgltf_json_strcmp(tokens+i, json_chunk, "ATTRIBUTES") == 0) 4945 { 4946 out_meshopt_compression->mode = cgltf_meshopt_compression_mode_attributes; 4947 } 4948 else if (cgltf_json_strcmp(tokens+i, json_chunk, "TRIANGLES") == 0) 4949 { 4950 out_meshopt_compression->mode = cgltf_meshopt_compression_mode_triangles; 4951 } 4952 else if (cgltf_json_strcmp(tokens+i, json_chunk, "INDICES") == 0) 4953 { 4954 out_meshopt_compression->mode = cgltf_meshopt_compression_mode_indices; 4955 } 4956 ++i; 4957 } 4958 else if (cgltf_json_strcmp(tokens+i, json_chunk, "filter") == 0) 4959 { 4960 ++i; 4961 if (cgltf_json_strcmp(tokens+i, json_chunk, "NONE") == 0) 4962 { 4963 out_meshopt_compression->filter = cgltf_meshopt_compression_filter_none; 4964 } 4965 else if (cgltf_json_strcmp(tokens+i, json_chunk, "OCTAHEDRAL") == 0) 4966 { 4967 out_meshopt_compression->filter = cgltf_meshopt_compression_filter_octahedral; 4968 } 4969 else if (cgltf_json_strcmp(tokens+i, json_chunk, "QUATERNION") == 0) 4970 { 4971 out_meshopt_compression->filter = cgltf_meshopt_compression_filter_quaternion; 4972 } 4973 else if (cgltf_json_strcmp(tokens+i, json_chunk, "EXPONENTIAL") == 0) 4974 { 4975 out_meshopt_compression->filter = cgltf_meshopt_compression_filter_exponential; 4976 } 4977 ++i; 4978 } 4979 else 4980 { 4981 i = cgltf_skip_json(tokens, i+1); 4982 } 4983 4984 if (i < 0) 4985 { 4986 return i; 4987 } 4988 } 4989 4990 return i; 4991 } 4992 4993 static int cgltf_parse_json_buffer_view(cgltf_options* options, jsmntok_t const* tokens, int i, const uint8_t* json_chunk, cgltf_buffer_view* out_buffer_view) 4994 { 4995 CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT); 4996 4997 int size = tokens[i].size; 4998 ++i; 4999 5000 for (int j = 0; j < size; ++j) 5001 { 5002 CGLTF_CHECK_KEY(tokens[i]); 5003 5004 if (cgltf_json_strcmp(tokens + i, json_chunk, "name") == 0) 5005 { 5006 i = cgltf_parse_json_string(options, tokens, i + 1, json_chunk, &out_buffer_view->name); 5007 } 5008 else if (cgltf_json_strcmp(tokens+i, json_chunk, "buffer") == 0) 5009 { 5010 ++i; 5011 out_buffer_view->buffer = CGLTF_PTRINDEX(cgltf_buffer, cgltf_json_to_int(tokens + i, json_chunk)); 5012 ++i; 5013 } 5014 else if (cgltf_json_strcmp(tokens+i, json_chunk, "byteOffset") == 0) 5015 { 5016 ++i; 5017 out_buffer_view->offset = 5018 cgltf_json_to_size(tokens+i, json_chunk); 5019 ++i; 5020 } 5021 else if (cgltf_json_strcmp(tokens+i, json_chunk, "byteLength") == 0) 5022 { 5023 ++i; 5024 out_buffer_view->size = 5025 cgltf_json_to_size(tokens+i, json_chunk); 5026 ++i; 5027 } 5028 else if (cgltf_json_strcmp(tokens+i, json_chunk, "byteStride") == 0) 5029 { 5030 ++i; 5031 out_buffer_view->stride = 5032 cgltf_json_to_size(tokens+i, json_chunk); 5033 ++i; 5034 } 5035 else if (cgltf_json_strcmp(tokens+i, json_chunk, "target") == 0) 5036 { 5037 ++i; 5038 int type = cgltf_json_to_int(tokens+i, json_chunk); 5039 switch (type) 5040 { 5041 case 34962: 5042 type = cgltf_buffer_view_type_vertices; 5043 break; 5044 case 34963: 5045 type = cgltf_buffer_view_type_indices; 5046 break; 5047 default: 5048 type = cgltf_buffer_view_type_invalid; 5049 break; 5050 } 5051 out_buffer_view->type = (cgltf_buffer_view_type)type; 5052 ++i; 5053 } 5054 else if (cgltf_json_strcmp(tokens + i, json_chunk, "extras") == 0) 5055 { 5056 i = cgltf_parse_json_extras(options, tokens, i + 1, json_chunk, &out_buffer_view->extras); 5057 } 5058 else if (cgltf_json_strcmp(tokens + i, json_chunk, "extensions") == 0) 5059 { 5060 ++i; 5061 5062 CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT); 5063 if(out_buffer_view->extensions) 5064 { 5065 return CGLTF_ERROR_JSON; 5066 } 5067 5068 int extensions_size = tokens[i].size; 5069 out_buffer_view->extensions_count = 0; 5070 out_buffer_view->extensions = (cgltf_extension*)cgltf_calloc(options, sizeof(cgltf_extension), extensions_size); 5071 5072 if (!out_buffer_view->extensions) 5073 { 5074 return CGLTF_ERROR_NOMEM; 5075 } 5076 5077 ++i; 5078 for (int k = 0; k < extensions_size; ++k) 5079 { 5080 CGLTF_CHECK_KEY(tokens[i]); 5081 5082 if (cgltf_json_strcmp(tokens+i, json_chunk, "EXT_meshopt_compression") == 0) 5083 { 5084 out_buffer_view->has_meshopt_compression = 1; 5085 i = cgltf_parse_json_meshopt_compression(options, tokens, i + 1, json_chunk, &out_buffer_view->meshopt_compression); 5086 } 5087 else 5088 { 5089 i = cgltf_parse_json_unprocessed_extension(options, tokens, i, json_chunk, &(out_buffer_view->extensions[out_buffer_view->extensions_count++])); 5090 } 5091 5092 if (i < 0) 5093 { 5094 return i; 5095 } 5096 } 5097 } 5098 else 5099 { 5100 i = cgltf_skip_json(tokens, i+1); 5101 } 5102 5103 if (i < 0) 5104 { 5105 return i; 5106 } 5107 } 5108 5109 return i; 5110 } 5111 5112 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) 5113 { 5114 i = cgltf_parse_json_array(options, tokens, i, json_chunk, sizeof(cgltf_buffer_view), (void**)&out_data->buffer_views, &out_data->buffer_views_count); 5115 if (i < 0) 5116 { 5117 return i; 5118 } 5119 5120 for (cgltf_size j = 0; j < out_data->buffer_views_count; ++j) 5121 { 5122 i = cgltf_parse_json_buffer_view(options, tokens, i, json_chunk, &out_data->buffer_views[j]); 5123 if (i < 0) 5124 { 5125 return i; 5126 } 5127 } 5128 return i; 5129 } 5130 5131 static int cgltf_parse_json_buffer(cgltf_options* options, jsmntok_t const* tokens, int i, const uint8_t* json_chunk, cgltf_buffer* out_buffer) 5132 { 5133 CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT); 5134 5135 int size = tokens[i].size; 5136 ++i; 5137 5138 for (int j = 0; j < size; ++j) 5139 { 5140 CGLTF_CHECK_KEY(tokens[i]); 5141 5142 if (cgltf_json_strcmp(tokens + i, json_chunk, "name") == 0) 5143 { 5144 i = cgltf_parse_json_string(options, tokens, i + 1, json_chunk, &out_buffer->name); 5145 } 5146 else if (cgltf_json_strcmp(tokens+i, json_chunk, "byteLength") == 0) 5147 { 5148 ++i; 5149 out_buffer->size = 5150 cgltf_json_to_size(tokens+i, json_chunk); 5151 ++i; 5152 } 5153 else if (cgltf_json_strcmp(tokens+i, json_chunk, "uri") == 0) 5154 { 5155 i = cgltf_parse_json_string(options, tokens, i + 1, json_chunk, &out_buffer->uri); 5156 } 5157 else if (cgltf_json_strcmp(tokens + i, json_chunk, "extras") == 0) 5158 { 5159 i = cgltf_parse_json_extras(options, tokens, i + 1, json_chunk, &out_buffer->extras); 5160 } 5161 else if (cgltf_json_strcmp(tokens + i, json_chunk, "extensions") == 0) 5162 { 5163 i = cgltf_parse_json_unprocessed_extensions(options, tokens, i, json_chunk, &out_buffer->extensions_count, &out_buffer->extensions); 5164 } 5165 else 5166 { 5167 i = cgltf_skip_json(tokens, i+1); 5168 } 5169 5170 if (i < 0) 5171 { 5172 return i; 5173 } 5174 } 5175 5176 return i; 5177 } 5178 5179 static int cgltf_parse_json_buffers(cgltf_options* options, jsmntok_t const* tokens, int i, const uint8_t* json_chunk, cgltf_data* out_data) 5180 { 5181 i = cgltf_parse_json_array(options, tokens, i, json_chunk, sizeof(cgltf_buffer), (void**)&out_data->buffers, &out_data->buffers_count); 5182 if (i < 0) 5183 { 5184 return i; 5185 } 5186 5187 for (cgltf_size j = 0; j < out_data->buffers_count; ++j) 5188 { 5189 i = cgltf_parse_json_buffer(options, tokens, i, json_chunk, &out_data->buffers[j]); 5190 if (i < 0) 5191 { 5192 return i; 5193 } 5194 } 5195 return i; 5196 } 5197 5198 static int cgltf_parse_json_skin(cgltf_options* options, jsmntok_t const* tokens, int i, const uint8_t* json_chunk, cgltf_skin* out_skin) 5199 { 5200 CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT); 5201 5202 int size = tokens[i].size; 5203 ++i; 5204 5205 for (int j = 0; j < size; ++j) 5206 { 5207 CGLTF_CHECK_KEY(tokens[i]); 5208 5209 if (cgltf_json_strcmp(tokens+i, json_chunk, "name") == 0) 5210 { 5211 i = cgltf_parse_json_string(options, tokens, i + 1, json_chunk, &out_skin->name); 5212 } 5213 else if (cgltf_json_strcmp(tokens+i, json_chunk, "joints") == 0) 5214 { 5215 i = cgltf_parse_json_array(options, tokens, i + 1, json_chunk, sizeof(cgltf_node*), (void**)&out_skin->joints, &out_skin->joints_count); 5216 if (i < 0) 5217 { 5218 return i; 5219 } 5220 5221 for (cgltf_size k = 0; k < out_skin->joints_count; ++k) 5222 { 5223 out_skin->joints[k] = CGLTF_PTRINDEX(cgltf_node, cgltf_json_to_int(tokens + i, json_chunk)); 5224 ++i; 5225 } 5226 } 5227 else if (cgltf_json_strcmp(tokens+i, json_chunk, "skeleton") == 0) 5228 { 5229 ++i; 5230 CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_PRIMITIVE); 5231 out_skin->skeleton = CGLTF_PTRINDEX(cgltf_node, cgltf_json_to_int(tokens + i, json_chunk)); 5232 ++i; 5233 } 5234 else if (cgltf_json_strcmp(tokens+i, json_chunk, "inverseBindMatrices") == 0) 5235 { 5236 ++i; 5237 CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_PRIMITIVE); 5238 out_skin->inverse_bind_matrices = CGLTF_PTRINDEX(cgltf_accessor, cgltf_json_to_int(tokens + i, json_chunk)); 5239 ++i; 5240 } 5241 else if (cgltf_json_strcmp(tokens + i, json_chunk, "extras") == 0) 5242 { 5243 i = cgltf_parse_json_extras(options, tokens, i + 1, json_chunk, &out_skin->extras); 5244 } 5245 else if (cgltf_json_strcmp(tokens + i, json_chunk, "extensions") == 0) 5246 { 5247 i = cgltf_parse_json_unprocessed_extensions(options, tokens, i, json_chunk, &out_skin->extensions_count, &out_skin->extensions); 5248 } 5249 else 5250 { 5251 i = cgltf_skip_json(tokens, i+1); 5252 } 5253 5254 if (i < 0) 5255 { 5256 return i; 5257 } 5258 } 5259 5260 return i; 5261 } 5262 5263 static int cgltf_parse_json_skins(cgltf_options* options, jsmntok_t const* tokens, int i, const uint8_t* json_chunk, cgltf_data* out_data) 5264 { 5265 i = cgltf_parse_json_array(options, tokens, i, json_chunk, sizeof(cgltf_skin), (void**)&out_data->skins, &out_data->skins_count); 5266 if (i < 0) 5267 { 5268 return i; 5269 } 5270 5271 for (cgltf_size j = 0; j < out_data->skins_count; ++j) 5272 { 5273 i = cgltf_parse_json_skin(options, tokens, i, json_chunk, &out_data->skins[j]); 5274 if (i < 0) 5275 { 5276 return i; 5277 } 5278 } 5279 return i; 5280 } 5281 5282 static int cgltf_parse_json_camera(cgltf_options* options, jsmntok_t const* tokens, int i, const uint8_t* json_chunk, cgltf_camera* out_camera) 5283 { 5284 CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT); 5285 5286 int size = tokens[i].size; 5287 ++i; 5288 5289 for (int j = 0; j < size; ++j) 5290 { 5291 CGLTF_CHECK_KEY(tokens[i]); 5292 5293 if (cgltf_json_strcmp(tokens+i, json_chunk, "name") == 0) 5294 { 5295 i = cgltf_parse_json_string(options, tokens, i + 1, json_chunk, &out_camera->name); 5296 } 5297 else if (cgltf_json_strcmp(tokens+i, json_chunk, "perspective") == 0) 5298 { 5299 ++i; 5300 5301 CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT); 5302 5303 int data_size = tokens[i].size; 5304 ++i; 5305 5306 if (out_camera->type != cgltf_camera_type_invalid) 5307 { 5308 return CGLTF_ERROR_JSON; 5309 } 5310 5311 out_camera->type = cgltf_camera_type_perspective; 5312 5313 for (int k = 0; k < data_size; ++k) 5314 { 5315 CGLTF_CHECK_KEY(tokens[i]); 5316 5317 if (cgltf_json_strcmp(tokens+i, json_chunk, "aspectRatio") == 0) 5318 { 5319 ++i; 5320 out_camera->data.perspective.has_aspect_ratio = 1; 5321 out_camera->data.perspective.aspect_ratio = cgltf_json_to_float(tokens + i, json_chunk); 5322 ++i; 5323 } 5324 else if (cgltf_json_strcmp(tokens+i, json_chunk, "yfov") == 0) 5325 { 5326 ++i; 5327 out_camera->data.perspective.yfov = cgltf_json_to_float(tokens + i, json_chunk); 5328 ++i; 5329 } 5330 else if (cgltf_json_strcmp(tokens+i, json_chunk, "zfar") == 0) 5331 { 5332 ++i; 5333 out_camera->data.perspective.has_zfar = 1; 5334 out_camera->data.perspective.zfar = cgltf_json_to_float(tokens + i, json_chunk); 5335 ++i; 5336 } 5337 else if (cgltf_json_strcmp(tokens+i, json_chunk, "znear") == 0) 5338 { 5339 ++i; 5340 out_camera->data.perspective.znear = cgltf_json_to_float(tokens + i, json_chunk); 5341 ++i; 5342 } 5343 else if (cgltf_json_strcmp(tokens + i, json_chunk, "extras") == 0) 5344 { 5345 i = cgltf_parse_json_extras(options, tokens, i + 1, json_chunk, &out_camera->data.perspective.extras); 5346 } 5347 else 5348 { 5349 i = cgltf_skip_json(tokens, i+1); 5350 } 5351 5352 if (i < 0) 5353 { 5354 return i; 5355 } 5356 } 5357 } 5358 else if (cgltf_json_strcmp(tokens+i, json_chunk, "orthographic") == 0) 5359 { 5360 ++i; 5361 5362 CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT); 5363 5364 int data_size = tokens[i].size; 5365 ++i; 5366 5367 if (out_camera->type != cgltf_camera_type_invalid) 5368 { 5369 return CGLTF_ERROR_JSON; 5370 } 5371 5372 out_camera->type = cgltf_camera_type_orthographic; 5373 5374 for (int k = 0; k < data_size; ++k) 5375 { 5376 CGLTF_CHECK_KEY(tokens[i]); 5377 5378 if (cgltf_json_strcmp(tokens+i, json_chunk, "xmag") == 0) 5379 { 5380 ++i; 5381 out_camera->data.orthographic.xmag = cgltf_json_to_float(tokens + i, json_chunk); 5382 ++i; 5383 } 5384 else if (cgltf_json_strcmp(tokens+i, json_chunk, "ymag") == 0) 5385 { 5386 ++i; 5387 out_camera->data.orthographic.ymag = cgltf_json_to_float(tokens + i, json_chunk); 5388 ++i; 5389 } 5390 else if (cgltf_json_strcmp(tokens+i, json_chunk, "zfar") == 0) 5391 { 5392 ++i; 5393 out_camera->data.orthographic.zfar = cgltf_json_to_float(tokens + i, json_chunk); 5394 ++i; 5395 } 5396 else if (cgltf_json_strcmp(tokens+i, json_chunk, "znear") == 0) 5397 { 5398 ++i; 5399 out_camera->data.orthographic.znear = cgltf_json_to_float(tokens + i, json_chunk); 5400 ++i; 5401 } 5402 else if (cgltf_json_strcmp(tokens + i, json_chunk, "extras") == 0) 5403 { 5404 i = cgltf_parse_json_extras(options, tokens, i + 1, json_chunk, &out_camera->data.orthographic.extras); 5405 } 5406 else 5407 { 5408 i = cgltf_skip_json(tokens, i+1); 5409 } 5410 5411 if (i < 0) 5412 { 5413 return i; 5414 } 5415 } 5416 } 5417 else if (cgltf_json_strcmp(tokens + i, json_chunk, "extras") == 0) 5418 { 5419 i = cgltf_parse_json_extras(options, tokens, i + 1, json_chunk, &out_camera->extras); 5420 } 5421 else if (cgltf_json_strcmp(tokens + i, json_chunk, "extensions") == 0) 5422 { 5423 i = cgltf_parse_json_unprocessed_extensions(options, tokens, i, json_chunk, &out_camera->extensions_count, &out_camera->extensions); 5424 } 5425 else 5426 { 5427 i = cgltf_skip_json(tokens, i+1); 5428 } 5429 5430 if (i < 0) 5431 { 5432 return i; 5433 } 5434 } 5435 5436 return i; 5437 } 5438 5439 static int cgltf_parse_json_cameras(cgltf_options* options, jsmntok_t const* tokens, int i, const uint8_t* json_chunk, cgltf_data* out_data) 5440 { 5441 i = cgltf_parse_json_array(options, tokens, i, json_chunk, sizeof(cgltf_camera), (void**)&out_data->cameras, &out_data->cameras_count); 5442 if (i < 0) 5443 { 5444 return i; 5445 } 5446 5447 for (cgltf_size j = 0; j < out_data->cameras_count; ++j) 5448 { 5449 i = cgltf_parse_json_camera(options, tokens, i, json_chunk, &out_data->cameras[j]); 5450 if (i < 0) 5451 { 5452 return i; 5453 } 5454 } 5455 return i; 5456 } 5457 5458 static int cgltf_parse_json_light(cgltf_options* options, jsmntok_t const* tokens, int i, const uint8_t* json_chunk, cgltf_light* out_light) 5459 { 5460 CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT); 5461 5462 out_light->color[0] = 1.f; 5463 out_light->color[1] = 1.f; 5464 out_light->color[2] = 1.f; 5465 out_light->intensity = 1.f; 5466 5467 out_light->spot_inner_cone_angle = 0.f; 5468 out_light->spot_outer_cone_angle = 3.1415926535f / 4.0f; 5469 5470 int size = tokens[i].size; 5471 ++i; 5472 5473 for (int j = 0; j < size; ++j) 5474 { 5475 CGLTF_CHECK_KEY(tokens[i]); 5476 5477 if (cgltf_json_strcmp(tokens+i, json_chunk, "name") == 0) 5478 { 5479 i = cgltf_parse_json_string(options, tokens, i + 1, json_chunk, &out_light->name); 5480 } 5481 else if (cgltf_json_strcmp(tokens + i, json_chunk, "color") == 0) 5482 { 5483 i = cgltf_parse_json_float_array(tokens, i + 1, json_chunk, out_light->color, 3); 5484 } 5485 else if (cgltf_json_strcmp(tokens + i, json_chunk, "intensity") == 0) 5486 { 5487 ++i; 5488 out_light->intensity = cgltf_json_to_float(tokens + i, json_chunk); 5489 ++i; 5490 } 5491 else if (cgltf_json_strcmp(tokens+i, json_chunk, "type") == 0) 5492 { 5493 ++i; 5494 if (cgltf_json_strcmp(tokens + i, json_chunk, "directional") == 0) 5495 { 5496 out_light->type = cgltf_light_type_directional; 5497 } 5498 else if (cgltf_json_strcmp(tokens + i, json_chunk, "point") == 0) 5499 { 5500 out_light->type = cgltf_light_type_point; 5501 } 5502 else if (cgltf_json_strcmp(tokens + i, json_chunk, "spot") == 0) 5503 { 5504 out_light->type = cgltf_light_type_spot; 5505 } 5506 ++i; 5507 } 5508 else if (cgltf_json_strcmp(tokens + i, json_chunk, "range") == 0) 5509 { 5510 ++i; 5511 out_light->range = cgltf_json_to_float(tokens + i, json_chunk); 5512 ++i; 5513 } 5514 else if (cgltf_json_strcmp(tokens+i, json_chunk, "spot") == 0) 5515 { 5516 ++i; 5517 5518 CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT); 5519 5520 int data_size = tokens[i].size; 5521 ++i; 5522 5523 for (int k = 0; k < data_size; ++k) 5524 { 5525 CGLTF_CHECK_KEY(tokens[i]); 5526 5527 if (cgltf_json_strcmp(tokens+i, json_chunk, "innerConeAngle") == 0) 5528 { 5529 ++i; 5530 out_light->spot_inner_cone_angle = cgltf_json_to_float(tokens + i, json_chunk); 5531 ++i; 5532 } 5533 else if (cgltf_json_strcmp(tokens+i, json_chunk, "outerConeAngle") == 0) 5534 { 5535 ++i; 5536 out_light->spot_outer_cone_angle = cgltf_json_to_float(tokens + i, json_chunk); 5537 ++i; 5538 } 5539 else 5540 { 5541 i = cgltf_skip_json(tokens, i+1); 5542 } 5543 5544 if (i < 0) 5545 { 5546 return i; 5547 } 5548 } 5549 } 5550 else if (cgltf_json_strcmp(tokens + i, json_chunk, "extras") == 0) 5551 { 5552 i = cgltf_parse_json_extras(options, tokens, i + 1, json_chunk, &out_light->extras); 5553 } 5554 else 5555 { 5556 i = cgltf_skip_json(tokens, i+1); 5557 } 5558 5559 if (i < 0) 5560 { 5561 return i; 5562 } 5563 } 5564 5565 return i; 5566 } 5567 5568 static int cgltf_parse_json_lights(cgltf_options* options, jsmntok_t const* tokens, int i, const uint8_t* json_chunk, cgltf_data* out_data) 5569 { 5570 i = cgltf_parse_json_array(options, tokens, i, json_chunk, sizeof(cgltf_light), (void**)&out_data->lights, &out_data->lights_count); 5571 if (i < 0) 5572 { 5573 return i; 5574 } 5575 5576 for (cgltf_size j = 0; j < out_data->lights_count; ++j) 5577 { 5578 i = cgltf_parse_json_light(options, tokens, i, json_chunk, &out_data->lights[j]); 5579 if (i < 0) 5580 { 5581 return i; 5582 } 5583 } 5584 return i; 5585 } 5586 5587 static int cgltf_parse_json_node(cgltf_options* options, jsmntok_t const* tokens, int i, const uint8_t* json_chunk, cgltf_node* out_node) 5588 { 5589 CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT); 5590 5591 out_node->rotation[3] = 1.0f; 5592 out_node->scale[0] = 1.0f; 5593 out_node->scale[1] = 1.0f; 5594 out_node->scale[2] = 1.0f; 5595 out_node->matrix[0] = 1.0f; 5596 out_node->matrix[5] = 1.0f; 5597 out_node->matrix[10] = 1.0f; 5598 out_node->matrix[15] = 1.0f; 5599 5600 int size = tokens[i].size; 5601 ++i; 5602 5603 for (int j = 0; j < size; ++j) 5604 { 5605 CGLTF_CHECK_KEY(tokens[i]); 5606 5607 if (cgltf_json_strcmp(tokens+i, json_chunk, "name") == 0) 5608 { 5609 i = cgltf_parse_json_string(options, tokens, i + 1, json_chunk, &out_node->name); 5610 } 5611 else if (cgltf_json_strcmp(tokens+i, json_chunk, "children") == 0) 5612 { 5613 i = cgltf_parse_json_array(options, tokens, i + 1, json_chunk, sizeof(cgltf_node*), (void**)&out_node->children, &out_node->children_count); 5614 if (i < 0) 5615 { 5616 return i; 5617 } 5618 5619 for (cgltf_size k = 0; k < out_node->children_count; ++k) 5620 { 5621 out_node->children[k] = CGLTF_PTRINDEX(cgltf_node, cgltf_json_to_int(tokens + i, json_chunk)); 5622 ++i; 5623 } 5624 } 5625 else if (cgltf_json_strcmp(tokens+i, json_chunk, "mesh") == 0) 5626 { 5627 ++i; 5628 CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_PRIMITIVE); 5629 out_node->mesh = CGLTF_PTRINDEX(cgltf_mesh, cgltf_json_to_int(tokens + i, json_chunk)); 5630 ++i; 5631 } 5632 else if (cgltf_json_strcmp(tokens+i, json_chunk, "skin") == 0) 5633 { 5634 ++i; 5635 CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_PRIMITIVE); 5636 out_node->skin = CGLTF_PTRINDEX(cgltf_skin, cgltf_json_to_int(tokens + i, json_chunk)); 5637 ++i; 5638 } 5639 else if (cgltf_json_strcmp(tokens+i, json_chunk, "camera") == 0) 5640 { 5641 ++i; 5642 CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_PRIMITIVE); 5643 out_node->camera = CGLTF_PTRINDEX(cgltf_camera, cgltf_json_to_int(tokens + i, json_chunk)); 5644 ++i; 5645 } 5646 else if (cgltf_json_strcmp(tokens+i, json_chunk, "translation") == 0) 5647 { 5648 out_node->has_translation = 1; 5649 i = cgltf_parse_json_float_array(tokens, i + 1, json_chunk, out_node->translation, 3); 5650 } 5651 else if (cgltf_json_strcmp(tokens+i, json_chunk, "rotation") == 0) 5652 { 5653 out_node->has_rotation = 1; 5654 i = cgltf_parse_json_float_array(tokens, i + 1, json_chunk, out_node->rotation, 4); 5655 } 5656 else if (cgltf_json_strcmp(tokens+i, json_chunk, "scale") == 0) 5657 { 5658 out_node->has_scale = 1; 5659 i = cgltf_parse_json_float_array(tokens, i + 1, json_chunk, out_node->scale, 3); 5660 } 5661 else if (cgltf_json_strcmp(tokens+i, json_chunk, "matrix") == 0) 5662 { 5663 out_node->has_matrix = 1; 5664 i = cgltf_parse_json_float_array(tokens, i + 1, json_chunk, out_node->matrix, 16); 5665 } 5666 else if (cgltf_json_strcmp(tokens + i, json_chunk, "weights") == 0) 5667 { 5668 i = cgltf_parse_json_array(options, tokens, i + 1, json_chunk, sizeof(cgltf_float), (void**)&out_node->weights, &out_node->weights_count); 5669 if (i < 0) 5670 { 5671 return i; 5672 } 5673 5674 i = cgltf_parse_json_float_array(tokens, i - 1, json_chunk, out_node->weights, (int)out_node->weights_count); 5675 } 5676 else if (cgltf_json_strcmp(tokens + i, json_chunk, "extras") == 0) 5677 { 5678 i = cgltf_parse_json_extras(options, tokens, i + 1, json_chunk, &out_node->extras); 5679 } 5680 else if (cgltf_json_strcmp(tokens + i, json_chunk, "extensions") == 0) 5681 { 5682 ++i; 5683 5684 CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT); 5685 if(out_node->extensions) 5686 { 5687 return CGLTF_ERROR_JSON; 5688 } 5689 5690 int extensions_size = tokens[i].size; 5691 out_node->extensions_count= 0; 5692 out_node->extensions = (cgltf_extension*)cgltf_calloc(options, sizeof(cgltf_extension), extensions_size); 5693 5694 if (!out_node->extensions) 5695 { 5696 return CGLTF_ERROR_NOMEM; 5697 } 5698 5699 ++i; 5700 5701 for (int k = 0; k < extensions_size; ++k) 5702 { 5703 CGLTF_CHECK_KEY(tokens[i]); 5704 5705 if (cgltf_json_strcmp(tokens+i, json_chunk, "KHR_lights_punctual") == 0) 5706 { 5707 ++i; 5708 5709 CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT); 5710 5711 int data_size = tokens[i].size; 5712 ++i; 5713 5714 for (int m = 0; m < data_size; ++m) 5715 { 5716 CGLTF_CHECK_KEY(tokens[i]); 5717 5718 if (cgltf_json_strcmp(tokens + i, json_chunk, "light") == 0) 5719 { 5720 ++i; 5721 CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_PRIMITIVE); 5722 out_node->light = CGLTF_PTRINDEX(cgltf_light, cgltf_json_to_int(tokens + i, json_chunk)); 5723 ++i; 5724 } 5725 else 5726 { 5727 i = cgltf_skip_json(tokens, i + 1); 5728 } 5729 5730 if (i < 0) 5731 { 5732 return i; 5733 } 5734 } 5735 } 5736 else if (cgltf_json_strcmp(tokens + i, json_chunk, "EXT_mesh_gpu_instancing") == 0) 5737 { 5738 out_node->has_mesh_gpu_instancing = 1; 5739 i = cgltf_parse_json_mesh_gpu_instancing(options, tokens, i + 1, json_chunk, &out_node->mesh_gpu_instancing); 5740 } 5741 else 5742 { 5743 i = cgltf_parse_json_unprocessed_extension(options, tokens, i, json_chunk, &(out_node->extensions[out_node->extensions_count++])); 5744 } 5745 5746 if (i < 0) 5747 { 5748 return i; 5749 } 5750 } 5751 } 5752 else 5753 { 5754 i = cgltf_skip_json(tokens, i+1); 5755 } 5756 5757 if (i < 0) 5758 { 5759 return i; 5760 } 5761 } 5762 5763 return i; 5764 } 5765 5766 static int cgltf_parse_json_nodes(cgltf_options* options, jsmntok_t const* tokens, int i, const uint8_t* json_chunk, cgltf_data* out_data) 5767 { 5768 i = cgltf_parse_json_array(options, tokens, i, json_chunk, sizeof(cgltf_node), (void**)&out_data->nodes, &out_data->nodes_count); 5769 if (i < 0) 5770 { 5771 return i; 5772 } 5773 5774 for (cgltf_size j = 0; j < out_data->nodes_count; ++j) 5775 { 5776 i = cgltf_parse_json_node(options, tokens, i, json_chunk, &out_data->nodes[j]); 5777 if (i < 0) 5778 { 5779 return i; 5780 } 5781 } 5782 return i; 5783 } 5784 5785 static int cgltf_parse_json_scene(cgltf_options* options, jsmntok_t const* tokens, int i, const uint8_t* json_chunk, cgltf_scene* out_scene) 5786 { 5787 CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT); 5788 5789 int size = tokens[i].size; 5790 ++i; 5791 5792 for (int j = 0; j < size; ++j) 5793 { 5794 CGLTF_CHECK_KEY(tokens[i]); 5795 5796 if (cgltf_json_strcmp(tokens+i, json_chunk, "name") == 0) 5797 { 5798 i = cgltf_parse_json_string(options, tokens, i + 1, json_chunk, &out_scene->name); 5799 } 5800 else if (cgltf_json_strcmp(tokens+i, json_chunk, "nodes") == 0) 5801 { 5802 i = cgltf_parse_json_array(options, tokens, i + 1, json_chunk, sizeof(cgltf_node*), (void**)&out_scene->nodes, &out_scene->nodes_count); 5803 if (i < 0) 5804 { 5805 return i; 5806 } 5807 5808 for (cgltf_size k = 0; k < out_scene->nodes_count; ++k) 5809 { 5810 out_scene->nodes[k] = CGLTF_PTRINDEX(cgltf_node, cgltf_json_to_int(tokens + i, json_chunk)); 5811 ++i; 5812 } 5813 } 5814 else if (cgltf_json_strcmp(tokens + i, json_chunk, "extras") == 0) 5815 { 5816 i = cgltf_parse_json_extras(options, tokens, i + 1, json_chunk, &out_scene->extras); 5817 } 5818 else if (cgltf_json_strcmp(tokens + i, json_chunk, "extensions") == 0) 5819 { 5820 i = cgltf_parse_json_unprocessed_extensions(options, tokens, i, json_chunk, &out_scene->extensions_count, &out_scene->extensions); 5821 } 5822 else 5823 { 5824 i = cgltf_skip_json(tokens, i+1); 5825 } 5826 5827 if (i < 0) 5828 { 5829 return i; 5830 } 5831 } 5832 5833 return i; 5834 } 5835 5836 static int cgltf_parse_json_scenes(cgltf_options* options, jsmntok_t const* tokens, int i, const uint8_t* json_chunk, cgltf_data* out_data) 5837 { 5838 i = cgltf_parse_json_array(options, tokens, i, json_chunk, sizeof(cgltf_scene), (void**)&out_data->scenes, &out_data->scenes_count); 5839 if (i < 0) 5840 { 5841 return i; 5842 } 5843 5844 for (cgltf_size j = 0; j < out_data->scenes_count; ++j) 5845 { 5846 i = cgltf_parse_json_scene(options, tokens, i, json_chunk, &out_data->scenes[j]); 5847 if (i < 0) 5848 { 5849 return i; 5850 } 5851 } 5852 return i; 5853 } 5854 5855 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) 5856 { 5857 (void)options; 5858 CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT); 5859 5860 int size = tokens[i].size; 5861 ++i; 5862 5863 for (int j = 0; j < size; ++j) 5864 { 5865 CGLTF_CHECK_KEY(tokens[i]); 5866 5867 if (cgltf_json_strcmp(tokens+i, json_chunk, "input") == 0) 5868 { 5869 ++i; 5870 out_sampler->input = CGLTF_PTRINDEX(cgltf_accessor, cgltf_json_to_int(tokens + i, json_chunk)); 5871 ++i; 5872 } 5873 else if (cgltf_json_strcmp(tokens+i, json_chunk, "output") == 0) 5874 { 5875 ++i; 5876 out_sampler->output = CGLTF_PTRINDEX(cgltf_accessor, cgltf_json_to_int(tokens + i, json_chunk)); 5877 ++i; 5878 } 5879 else if (cgltf_json_strcmp(tokens+i, json_chunk, "interpolation") == 0) 5880 { 5881 ++i; 5882 if (cgltf_json_strcmp(tokens + i, json_chunk, "LINEAR") == 0) 5883 { 5884 out_sampler->interpolation = cgltf_interpolation_type_linear; 5885 } 5886 else if (cgltf_json_strcmp(tokens + i, json_chunk, "STEP") == 0) 5887 { 5888 out_sampler->interpolation = cgltf_interpolation_type_step; 5889 } 5890 else if (cgltf_json_strcmp(tokens + i, json_chunk, "CUBICSPLINE") == 0) 5891 { 5892 out_sampler->interpolation = cgltf_interpolation_type_cubic_spline; 5893 } 5894 ++i; 5895 } 5896 else if (cgltf_json_strcmp(tokens + i, json_chunk, "extras") == 0) 5897 { 5898 i = cgltf_parse_json_extras(options, tokens, i + 1, json_chunk, &out_sampler->extras); 5899 } 5900 else if (cgltf_json_strcmp(tokens + i, json_chunk, "extensions") == 0) 5901 { 5902 i = cgltf_parse_json_unprocessed_extensions(options, tokens, i, json_chunk, &out_sampler->extensions_count, &out_sampler->extensions); 5903 } 5904 else 5905 { 5906 i = cgltf_skip_json(tokens, i+1); 5907 } 5908 5909 if (i < 0) 5910 { 5911 return i; 5912 } 5913 } 5914 5915 return i; 5916 } 5917 5918 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) 5919 { 5920 (void)options; 5921 CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT); 5922 5923 int size = tokens[i].size; 5924 ++i; 5925 5926 for (int j = 0; j < size; ++j) 5927 { 5928 CGLTF_CHECK_KEY(tokens[i]); 5929 5930 if (cgltf_json_strcmp(tokens+i, json_chunk, "sampler") == 0) 5931 { 5932 ++i; 5933 out_channel->sampler = CGLTF_PTRINDEX(cgltf_animation_sampler, cgltf_json_to_int(tokens + i, json_chunk)); 5934 ++i; 5935 } 5936 else if (cgltf_json_strcmp(tokens+i, json_chunk, "target") == 0) 5937 { 5938 ++i; 5939 5940 CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT); 5941 5942 int target_size = tokens[i].size; 5943 ++i; 5944 5945 for (int k = 0; k < target_size; ++k) 5946 { 5947 CGLTF_CHECK_KEY(tokens[i]); 5948 5949 if (cgltf_json_strcmp(tokens+i, json_chunk, "node") == 0) 5950 { 5951 ++i; 5952 out_channel->target_node = CGLTF_PTRINDEX(cgltf_node, cgltf_json_to_int(tokens + i, json_chunk)); 5953 ++i; 5954 } 5955 else if (cgltf_json_strcmp(tokens+i, json_chunk, "path") == 0) 5956 { 5957 ++i; 5958 if (cgltf_json_strcmp(tokens+i, json_chunk, "translation") == 0) 5959 { 5960 out_channel->target_path = cgltf_animation_path_type_translation; 5961 } 5962 else if (cgltf_json_strcmp(tokens+i, json_chunk, "rotation") == 0) 5963 { 5964 out_channel->target_path = cgltf_animation_path_type_rotation; 5965 } 5966 else if (cgltf_json_strcmp(tokens+i, json_chunk, "scale") == 0) 5967 { 5968 out_channel->target_path = cgltf_animation_path_type_scale; 5969 } 5970 else if (cgltf_json_strcmp(tokens+i, json_chunk, "weights") == 0) 5971 { 5972 out_channel->target_path = cgltf_animation_path_type_weights; 5973 } 5974 ++i; 5975 } 5976 else if (cgltf_json_strcmp(tokens + i, json_chunk, "extras") == 0) 5977 { 5978 i = cgltf_parse_json_extras(options, tokens, i + 1, json_chunk, &out_channel->extras); 5979 } 5980 else if (cgltf_json_strcmp(tokens + i, json_chunk, "extensions") == 0) 5981 { 5982 i = cgltf_parse_json_unprocessed_extensions(options, tokens, i, json_chunk, &out_channel->extensions_count, &out_channel->extensions); 5983 } 5984 else 5985 { 5986 i = cgltf_skip_json(tokens, i+1); 5987 } 5988 5989 if (i < 0) 5990 { 5991 return i; 5992 } 5993 } 5994 } 5995 else 5996 { 5997 i = cgltf_skip_json(tokens, i+1); 5998 } 5999 6000 if (i < 0) 6001 { 6002 return i; 6003 } 6004 } 6005 6006 return i; 6007 } 6008 6009 static int cgltf_parse_json_animation(cgltf_options* options, jsmntok_t const* tokens, int i, const uint8_t* json_chunk, cgltf_animation* out_animation) 6010 { 6011 CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT); 6012 6013 int size = tokens[i].size; 6014 ++i; 6015 6016 for (int j = 0; j < size; ++j) 6017 { 6018 CGLTF_CHECK_KEY(tokens[i]); 6019 6020 if (cgltf_json_strcmp(tokens+i, json_chunk, "name") == 0) 6021 { 6022 i = cgltf_parse_json_string(options, tokens, i + 1, json_chunk, &out_animation->name); 6023 } 6024 else if (cgltf_json_strcmp(tokens+i, json_chunk, "samplers") == 0) 6025 { 6026 i = cgltf_parse_json_array(options, tokens, i + 1, json_chunk, sizeof(cgltf_animation_sampler), (void**)&out_animation->samplers, &out_animation->samplers_count); 6027 if (i < 0) 6028 { 6029 return i; 6030 } 6031 6032 for (cgltf_size k = 0; k < out_animation->samplers_count; ++k) 6033 { 6034 i = cgltf_parse_json_animation_sampler(options, tokens, i, json_chunk, &out_animation->samplers[k]); 6035 if (i < 0) 6036 { 6037 return i; 6038 } 6039 } 6040 } 6041 else if (cgltf_json_strcmp(tokens+i, json_chunk, "channels") == 0) 6042 { 6043 i = cgltf_parse_json_array(options, tokens, i + 1, json_chunk, sizeof(cgltf_animation_channel), (void**)&out_animation->channels, &out_animation->channels_count); 6044 if (i < 0) 6045 { 6046 return i; 6047 } 6048 6049 for (cgltf_size k = 0; k < out_animation->channels_count; ++k) 6050 { 6051 i = cgltf_parse_json_animation_channel(options, tokens, i, json_chunk, &out_animation->channels[k]); 6052 if (i < 0) 6053 { 6054 return i; 6055 } 6056 } 6057 } 6058 else if (cgltf_json_strcmp(tokens + i, json_chunk, "extras") == 0) 6059 { 6060 i = cgltf_parse_json_extras(options, tokens, i + 1, json_chunk, &out_animation->extras); 6061 } 6062 else if (cgltf_json_strcmp(tokens + i, json_chunk, "extensions") == 0) 6063 { 6064 i = cgltf_parse_json_unprocessed_extensions(options, tokens, i, json_chunk, &out_animation->extensions_count, &out_animation->extensions); 6065 } 6066 else 6067 { 6068 i = cgltf_skip_json(tokens, i+1); 6069 } 6070 6071 if (i < 0) 6072 { 6073 return i; 6074 } 6075 } 6076 6077 return i; 6078 } 6079 6080 static int cgltf_parse_json_animations(cgltf_options* options, jsmntok_t const* tokens, int i, const uint8_t* json_chunk, cgltf_data* out_data) 6081 { 6082 i = cgltf_parse_json_array(options, tokens, i, json_chunk, sizeof(cgltf_animation), (void**)&out_data->animations, &out_data->animations_count); 6083 if (i < 0) 6084 { 6085 return i; 6086 } 6087 6088 for (cgltf_size j = 0; j < out_data->animations_count; ++j) 6089 { 6090 i = cgltf_parse_json_animation(options, tokens, i, json_chunk, &out_data->animations[j]); 6091 if (i < 0) 6092 { 6093 return i; 6094 } 6095 } 6096 return i; 6097 } 6098 6099 static int cgltf_parse_json_variant(cgltf_options* options, jsmntok_t const* tokens, int i, const uint8_t* json_chunk, cgltf_material_variant* out_variant) 6100 { 6101 CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT); 6102 6103 int size = tokens[i].size; 6104 ++i; 6105 6106 for (int j = 0; j < size; ++j) 6107 { 6108 CGLTF_CHECK_KEY(tokens[i]); 6109 6110 if (cgltf_json_strcmp(tokens+i, json_chunk, "name") == 0) 6111 { 6112 i = cgltf_parse_json_string(options, tokens, i + 1, json_chunk, &out_variant->name); 6113 } 6114 else if (cgltf_json_strcmp(tokens + i, json_chunk, "extras") == 0) 6115 { 6116 i = cgltf_parse_json_extras(options, tokens, i + 1, json_chunk, &out_variant->extras); 6117 } 6118 else 6119 { 6120 i = cgltf_skip_json(tokens, i+1); 6121 } 6122 6123 if (i < 0) 6124 { 6125 return i; 6126 } 6127 } 6128 6129 return i; 6130 } 6131 6132 static int cgltf_parse_json_variants(cgltf_options* options, jsmntok_t const* tokens, int i, const uint8_t* json_chunk, cgltf_data* out_data) 6133 { 6134 i = cgltf_parse_json_array(options, tokens, i, json_chunk, sizeof(cgltf_material_variant), (void**)&out_data->variants, &out_data->variants_count); 6135 if (i < 0) 6136 { 6137 return i; 6138 } 6139 6140 for (cgltf_size j = 0; j < out_data->variants_count; ++j) 6141 { 6142 i = cgltf_parse_json_variant(options, tokens, i, json_chunk, &out_data->variants[j]); 6143 if (i < 0) 6144 { 6145 return i; 6146 } 6147 } 6148 return i; 6149 } 6150 6151 static int cgltf_parse_json_asset(cgltf_options* options, jsmntok_t const* tokens, int i, const uint8_t* json_chunk, cgltf_asset* out_asset) 6152 { 6153 CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT); 6154 6155 int size = tokens[i].size; 6156 ++i; 6157 6158 for (int j = 0; j < size; ++j) 6159 { 6160 CGLTF_CHECK_KEY(tokens[i]); 6161 6162 if (cgltf_json_strcmp(tokens+i, json_chunk, "copyright") == 0) 6163 { 6164 i = cgltf_parse_json_string(options, tokens, i + 1, json_chunk, &out_asset->copyright); 6165 } 6166 else if (cgltf_json_strcmp(tokens+i, json_chunk, "generator") == 0) 6167 { 6168 i = cgltf_parse_json_string(options, tokens, i + 1, json_chunk, &out_asset->generator); 6169 } 6170 else if (cgltf_json_strcmp(tokens+i, json_chunk, "version") == 0) 6171 { 6172 i = cgltf_parse_json_string(options, tokens, i + 1, json_chunk, &out_asset->version); 6173 } 6174 else if (cgltf_json_strcmp(tokens+i, json_chunk, "minVersion") == 0) 6175 { 6176 i = cgltf_parse_json_string(options, tokens, i + 1, json_chunk, &out_asset->min_version); 6177 } 6178 else if (cgltf_json_strcmp(tokens + i, json_chunk, "extras") == 0) 6179 { 6180 i = cgltf_parse_json_extras(options, tokens, i + 1, json_chunk, &out_asset->extras); 6181 } 6182 else if (cgltf_json_strcmp(tokens + i, json_chunk, "extensions") == 0) 6183 { 6184 i = cgltf_parse_json_unprocessed_extensions(options, tokens, i, json_chunk, &out_asset->extensions_count, &out_asset->extensions); 6185 } 6186 else 6187 { 6188 i = cgltf_skip_json(tokens, i+1); 6189 } 6190 6191 if (i < 0) 6192 { 6193 return i; 6194 } 6195 } 6196 6197 if (out_asset->version && CGLTF_ATOF(out_asset->version) < 2) 6198 { 6199 return CGLTF_ERROR_LEGACY; 6200 } 6201 6202 return i; 6203 } 6204 6205 cgltf_size cgltf_num_components(cgltf_type type) { 6206 switch (type) 6207 { 6208 case cgltf_type_vec2: 6209 return 2; 6210 case cgltf_type_vec3: 6211 return 3; 6212 case cgltf_type_vec4: 6213 return 4; 6214 case cgltf_type_mat2: 6215 return 4; 6216 case cgltf_type_mat3: 6217 return 9; 6218 case cgltf_type_mat4: 6219 return 16; 6220 case cgltf_type_invalid: 6221 case cgltf_type_scalar: 6222 default: 6223 return 1; 6224 } 6225 } 6226 6227 cgltf_size cgltf_component_size(cgltf_component_type component_type) { 6228 switch (component_type) 6229 { 6230 case cgltf_component_type_r_8: 6231 case cgltf_component_type_r_8u: 6232 return 1; 6233 case cgltf_component_type_r_16: 6234 case cgltf_component_type_r_16u: 6235 return 2; 6236 case cgltf_component_type_r_32u: 6237 case cgltf_component_type_r_32f: 6238 return 4; 6239 case cgltf_component_type_invalid: 6240 default: 6241 return 0; 6242 } 6243 } 6244 6245 cgltf_size cgltf_calc_size(cgltf_type type, cgltf_component_type component_type) 6246 { 6247 cgltf_size component_size = cgltf_component_size(component_type); 6248 if (type == cgltf_type_mat2 && component_size == 1) 6249 { 6250 return 8 * component_size; 6251 } 6252 else if (type == cgltf_type_mat3 && (component_size == 1 || component_size == 2)) 6253 { 6254 return 12 * component_size; 6255 } 6256 return component_size * cgltf_num_components(type); 6257 } 6258 6259 static int cgltf_fixup_pointers(cgltf_data* out_data); 6260 6261 static int cgltf_parse_json_root(cgltf_options* options, jsmntok_t const* tokens, int i, const uint8_t* json_chunk, cgltf_data* out_data) 6262 { 6263 CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT); 6264 6265 int size = tokens[i].size; 6266 ++i; 6267 6268 for (int j = 0; j < size; ++j) 6269 { 6270 CGLTF_CHECK_KEY(tokens[i]); 6271 6272 if (cgltf_json_strcmp(tokens + i, json_chunk, "asset") == 0) 6273 { 6274 i = cgltf_parse_json_asset(options, tokens, i + 1, json_chunk, &out_data->asset); 6275 } 6276 else if (cgltf_json_strcmp(tokens + i, json_chunk, "meshes") == 0) 6277 { 6278 i = cgltf_parse_json_meshes(options, tokens, i + 1, json_chunk, out_data); 6279 } 6280 else if (cgltf_json_strcmp(tokens + i, json_chunk, "accessors") == 0) 6281 { 6282 i = cgltf_parse_json_accessors(options, tokens, i + 1, json_chunk, out_data); 6283 } 6284 else if (cgltf_json_strcmp(tokens + i, json_chunk, "bufferViews") == 0) 6285 { 6286 i = cgltf_parse_json_buffer_views(options, tokens, i + 1, json_chunk, out_data); 6287 } 6288 else if (cgltf_json_strcmp(tokens + i, json_chunk, "buffers") == 0) 6289 { 6290 i = cgltf_parse_json_buffers(options, tokens, i + 1, json_chunk, out_data); 6291 } 6292 else if (cgltf_json_strcmp(tokens + i, json_chunk, "materials") == 0) 6293 { 6294 i = cgltf_parse_json_materials(options, tokens, i + 1, json_chunk, out_data); 6295 } 6296 else if (cgltf_json_strcmp(tokens + i, json_chunk, "images") == 0) 6297 { 6298 i = cgltf_parse_json_images(options, tokens, i + 1, json_chunk, out_data); 6299 } 6300 else if (cgltf_json_strcmp(tokens + i, json_chunk, "textures") == 0) 6301 { 6302 i = cgltf_parse_json_textures(options, tokens, i + 1, json_chunk, out_data); 6303 } 6304 else if (cgltf_json_strcmp(tokens + i, json_chunk, "samplers") == 0) 6305 { 6306 i = cgltf_parse_json_samplers(options, tokens, i + 1, json_chunk, out_data); 6307 } 6308 else if (cgltf_json_strcmp(tokens + i, json_chunk, "skins") == 0) 6309 { 6310 i = cgltf_parse_json_skins(options, tokens, i + 1, json_chunk, out_data); 6311 } 6312 else if (cgltf_json_strcmp(tokens + i, json_chunk, "cameras") == 0) 6313 { 6314 i = cgltf_parse_json_cameras(options, tokens, i + 1, json_chunk, out_data); 6315 } 6316 else if (cgltf_json_strcmp(tokens + i, json_chunk, "nodes") == 0) 6317 { 6318 i = cgltf_parse_json_nodes(options, tokens, i + 1, json_chunk, out_data); 6319 } 6320 else if (cgltf_json_strcmp(tokens + i, json_chunk, "scenes") == 0) 6321 { 6322 i = cgltf_parse_json_scenes(options, tokens, i + 1, json_chunk, out_data); 6323 } 6324 else if (cgltf_json_strcmp(tokens + i, json_chunk, "scene") == 0) 6325 { 6326 ++i; 6327 out_data->scene = CGLTF_PTRINDEX(cgltf_scene, cgltf_json_to_int(tokens + i, json_chunk)); 6328 ++i; 6329 } 6330 else if (cgltf_json_strcmp(tokens + i, json_chunk, "animations") == 0) 6331 { 6332 i = cgltf_parse_json_animations(options, tokens, i + 1, json_chunk, out_data); 6333 } 6334 else if (cgltf_json_strcmp(tokens+i, json_chunk, "extras") == 0) 6335 { 6336 i = cgltf_parse_json_extras(options, tokens, i + 1, json_chunk, &out_data->extras); 6337 } 6338 else if (cgltf_json_strcmp(tokens + i, json_chunk, "extensions") == 0) 6339 { 6340 ++i; 6341 6342 CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT); 6343 if(out_data->data_extensions) 6344 { 6345 return CGLTF_ERROR_JSON; 6346 } 6347 6348 int extensions_size = tokens[i].size; 6349 out_data->data_extensions_count = 0; 6350 out_data->data_extensions = (cgltf_extension*)cgltf_calloc(options, sizeof(cgltf_extension), extensions_size); 6351 6352 if (!out_data->data_extensions) 6353 { 6354 return CGLTF_ERROR_NOMEM; 6355 } 6356 6357 ++i; 6358 6359 for (int k = 0; k < extensions_size; ++k) 6360 { 6361 CGLTF_CHECK_KEY(tokens[i]); 6362 6363 if (cgltf_json_strcmp(tokens+i, json_chunk, "KHR_lights_punctual") == 0) 6364 { 6365 ++i; 6366 6367 CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT); 6368 6369 int data_size = tokens[i].size; 6370 ++i; 6371 6372 for (int m = 0; m < data_size; ++m) 6373 { 6374 CGLTF_CHECK_KEY(tokens[i]); 6375 6376 if (cgltf_json_strcmp(tokens + i, json_chunk, "lights") == 0) 6377 { 6378 i = cgltf_parse_json_lights(options, tokens, i + 1, json_chunk, out_data); 6379 } 6380 else 6381 { 6382 i = cgltf_skip_json(tokens, i + 1); 6383 } 6384 6385 if (i < 0) 6386 { 6387 return i; 6388 } 6389 } 6390 } 6391 else if (cgltf_json_strcmp(tokens+i, json_chunk, "KHR_materials_variants") == 0) 6392 { 6393 ++i; 6394 6395 CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT); 6396 6397 int data_size = tokens[i].size; 6398 ++i; 6399 6400 for (int m = 0; m < data_size; ++m) 6401 { 6402 CGLTF_CHECK_KEY(tokens[i]); 6403 6404 if (cgltf_json_strcmp(tokens + i, json_chunk, "variants") == 0) 6405 { 6406 i = cgltf_parse_json_variants(options, tokens, i + 1, json_chunk, out_data); 6407 } 6408 else 6409 { 6410 i = cgltf_skip_json(tokens, i + 1); 6411 } 6412 6413 if (i < 0) 6414 { 6415 return i; 6416 } 6417 } 6418 } 6419 else 6420 { 6421 i = cgltf_parse_json_unprocessed_extension(options, tokens, i, json_chunk, &(out_data->data_extensions[out_data->data_extensions_count++])); 6422 } 6423 6424 if (i < 0) 6425 { 6426 return i; 6427 } 6428 } 6429 } 6430 else if (cgltf_json_strcmp(tokens + i, json_chunk, "extensionsUsed") == 0) 6431 { 6432 i = cgltf_parse_json_string_array(options, tokens, i + 1, json_chunk, &out_data->extensions_used, &out_data->extensions_used_count); 6433 } 6434 else if (cgltf_json_strcmp(tokens + i, json_chunk, "extensionsRequired") == 0) 6435 { 6436 i = cgltf_parse_json_string_array(options, tokens, i + 1, json_chunk, &out_data->extensions_required, &out_data->extensions_required_count); 6437 } 6438 else 6439 { 6440 i = cgltf_skip_json(tokens, i + 1); 6441 } 6442 6443 if (i < 0) 6444 { 6445 return i; 6446 } 6447 } 6448 6449 return i; 6450 } 6451 6452 cgltf_result cgltf_parse_json(cgltf_options* options, const uint8_t* json_chunk, cgltf_size size, cgltf_data** out_data) 6453 { 6454 jsmn_parser parser = { 0, 0, 0 }; 6455 6456 if (options->json_token_count == 0) 6457 { 6458 int token_count = jsmn_parse(&parser, (const char*)json_chunk, size, NULL, 0); 6459 6460 if (token_count <= 0) 6461 { 6462 return cgltf_result_invalid_json; 6463 } 6464 6465 options->json_token_count = token_count; 6466 } 6467 6468 jsmntok_t* tokens = (jsmntok_t*)options->memory.alloc_func(options->memory.user_data, sizeof(jsmntok_t) * (options->json_token_count + 1)); 6469 6470 if (!tokens) 6471 { 6472 return cgltf_result_out_of_memory; 6473 } 6474 6475 jsmn_init(&parser); 6476 6477 int token_count = jsmn_parse(&parser, (const char*)json_chunk, size, tokens, options->json_token_count); 6478 6479 if (token_count <= 0) 6480 { 6481 options->memory.free_func(options->memory.user_data, tokens); 6482 return cgltf_result_invalid_json; 6483 } 6484 6485 // this makes sure that we always have an UNDEFINED token at the end of the stream 6486 // for invalid JSON inputs this makes sure we don't perform out of bound reads of token data 6487 tokens[token_count].type = JSMN_UNDEFINED; 6488 6489 cgltf_data* data = (cgltf_data*)options->memory.alloc_func(options->memory.user_data, sizeof(cgltf_data)); 6490 6491 if (!data) 6492 { 6493 options->memory.free_func(options->memory.user_data, tokens); 6494 return cgltf_result_out_of_memory; 6495 } 6496 6497 memset(data, 0, sizeof(cgltf_data)); 6498 data->memory = options->memory; 6499 data->file = options->file; 6500 6501 int i = cgltf_parse_json_root(options, tokens, 0, json_chunk, data); 6502 6503 options->memory.free_func(options->memory.user_data, tokens); 6504 6505 if (i < 0) 6506 { 6507 cgltf_free(data); 6508 6509 switch (i) 6510 { 6511 case CGLTF_ERROR_NOMEM: return cgltf_result_out_of_memory; 6512 case CGLTF_ERROR_LEGACY: return cgltf_result_legacy_gltf; 6513 default: return cgltf_result_invalid_gltf; 6514 } 6515 } 6516 6517 if (cgltf_fixup_pointers(data) < 0) 6518 { 6519 cgltf_free(data); 6520 return cgltf_result_invalid_gltf; 6521 } 6522 6523 data->json = (const char*)json_chunk; 6524 data->json_size = size; 6525 6526 *out_data = data; 6527 6528 return cgltf_result_success; 6529 } 6530 6531 static int cgltf_fixup_pointers(cgltf_data* data) 6532 { 6533 for (cgltf_size i = 0; i < data->meshes_count; ++i) 6534 { 6535 for (cgltf_size j = 0; j < data->meshes[i].primitives_count; ++j) 6536 { 6537 CGLTF_PTRFIXUP(data->meshes[i].primitives[j].indices, data->accessors, data->accessors_count); 6538 CGLTF_PTRFIXUP(data->meshes[i].primitives[j].material, data->materials, data->materials_count); 6539 6540 for (cgltf_size k = 0; k < data->meshes[i].primitives[j].attributes_count; ++k) 6541 { 6542 CGLTF_PTRFIXUP_REQ(data->meshes[i].primitives[j].attributes[k].data, data->accessors, data->accessors_count); 6543 } 6544 6545 for (cgltf_size k = 0; k < data->meshes[i].primitives[j].targets_count; ++k) 6546 { 6547 for (cgltf_size m = 0; m < data->meshes[i].primitives[j].targets[k].attributes_count; ++m) 6548 { 6549 CGLTF_PTRFIXUP_REQ(data->meshes[i].primitives[j].targets[k].attributes[m].data, data->accessors, data->accessors_count); 6550 } 6551 } 6552 6553 if (data->meshes[i].primitives[j].has_draco_mesh_compression) 6554 { 6555 CGLTF_PTRFIXUP_REQ(data->meshes[i].primitives[j].draco_mesh_compression.buffer_view, data->buffer_views, data->buffer_views_count); 6556 for (cgltf_size m = 0; m < data->meshes[i].primitives[j].draco_mesh_compression.attributes_count; ++m) 6557 { 6558 CGLTF_PTRFIXUP_REQ(data->meshes[i].primitives[j].draco_mesh_compression.attributes[m].data, data->accessors, data->accessors_count); 6559 } 6560 } 6561 6562 for (cgltf_size k = 0; k < data->meshes[i].primitives[j].mappings_count; ++k) 6563 { 6564 CGLTF_PTRFIXUP_REQ(data->meshes[i].primitives[j].mappings[k].material, data->materials, data->materials_count); 6565 } 6566 } 6567 } 6568 6569 for (cgltf_size i = 0; i < data->accessors_count; ++i) 6570 { 6571 CGLTF_PTRFIXUP(data->accessors[i].buffer_view, data->buffer_views, data->buffer_views_count); 6572 6573 if (data->accessors[i].is_sparse) 6574 { 6575 CGLTF_PTRFIXUP_REQ(data->accessors[i].sparse.indices_buffer_view, data->buffer_views, data->buffer_views_count); 6576 CGLTF_PTRFIXUP_REQ(data->accessors[i].sparse.values_buffer_view, data->buffer_views, data->buffer_views_count); 6577 } 6578 6579 if (data->accessors[i].buffer_view) 6580 { 6581 data->accessors[i].stride = data->accessors[i].buffer_view->stride; 6582 } 6583 6584 if (data->accessors[i].stride == 0) 6585 { 6586 data->accessors[i].stride = cgltf_calc_size(data->accessors[i].type, data->accessors[i].component_type); 6587 } 6588 } 6589 6590 for (cgltf_size i = 0; i < data->textures_count; ++i) 6591 { 6592 CGLTF_PTRFIXUP(data->textures[i].image, data->images, data->images_count); 6593 CGLTF_PTRFIXUP(data->textures[i].basisu_image, data->images, data->images_count); 6594 CGLTF_PTRFIXUP(data->textures[i].webp_image, data->images, data->images_count); 6595 CGLTF_PTRFIXUP(data->textures[i].sampler, data->samplers, data->samplers_count); 6596 } 6597 6598 for (cgltf_size i = 0; i < data->images_count; ++i) 6599 { 6600 CGLTF_PTRFIXUP(data->images[i].buffer_view, data->buffer_views, data->buffer_views_count); 6601 } 6602 6603 for (cgltf_size i = 0; i < data->materials_count; ++i) 6604 { 6605 CGLTF_PTRFIXUP(data->materials[i].normal_texture.texture, data->textures, data->textures_count); 6606 CGLTF_PTRFIXUP(data->materials[i].emissive_texture.texture, data->textures, data->textures_count); 6607 CGLTF_PTRFIXUP(data->materials[i].occlusion_texture.texture, data->textures, data->textures_count); 6608 6609 CGLTF_PTRFIXUP(data->materials[i].pbr_metallic_roughness.base_color_texture.texture, data->textures, data->textures_count); 6610 CGLTF_PTRFIXUP(data->materials[i].pbr_metallic_roughness.metallic_roughness_texture.texture, data->textures, data->textures_count); 6611 6612 CGLTF_PTRFIXUP(data->materials[i].pbr_specular_glossiness.diffuse_texture.texture, data->textures, data->textures_count); 6613 CGLTF_PTRFIXUP(data->materials[i].pbr_specular_glossiness.specular_glossiness_texture.texture, data->textures, data->textures_count); 6614 6615 CGLTF_PTRFIXUP(data->materials[i].clearcoat.clearcoat_texture.texture, data->textures, data->textures_count); 6616 CGLTF_PTRFIXUP(data->materials[i].clearcoat.clearcoat_roughness_texture.texture, data->textures, data->textures_count); 6617 CGLTF_PTRFIXUP(data->materials[i].clearcoat.clearcoat_normal_texture.texture, data->textures, data->textures_count); 6618 6619 CGLTF_PTRFIXUP(data->materials[i].specular.specular_texture.texture, data->textures, data->textures_count); 6620 CGLTF_PTRFIXUP(data->materials[i].specular.specular_color_texture.texture, data->textures, data->textures_count); 6621 6622 CGLTF_PTRFIXUP(data->materials[i].transmission.transmission_texture.texture, data->textures, data->textures_count); 6623 6624 CGLTF_PTRFIXUP(data->materials[i].volume.thickness_texture.texture, data->textures, data->textures_count); 6625 6626 CGLTF_PTRFIXUP(data->materials[i].sheen.sheen_color_texture.texture, data->textures, data->textures_count); 6627 CGLTF_PTRFIXUP(data->materials[i].sheen.sheen_roughness_texture.texture, data->textures, data->textures_count); 6628 6629 CGLTF_PTRFIXUP(data->materials[i].iridescence.iridescence_texture.texture, data->textures, data->textures_count); 6630 CGLTF_PTRFIXUP(data->materials[i].iridescence.iridescence_thickness_texture.texture, data->textures, data->textures_count); 6631 6632 CGLTF_PTRFIXUP(data->materials[i].anisotropy.anisotropy_texture.texture, data->textures, data->textures_count); 6633 } 6634 6635 for (cgltf_size i = 0; i < data->buffer_views_count; ++i) 6636 { 6637 CGLTF_PTRFIXUP_REQ(data->buffer_views[i].buffer, data->buffers, data->buffers_count); 6638 6639 if (data->buffer_views[i].has_meshopt_compression) 6640 { 6641 CGLTF_PTRFIXUP_REQ(data->buffer_views[i].meshopt_compression.buffer, data->buffers, data->buffers_count); 6642 } 6643 } 6644 6645 for (cgltf_size i = 0; i < data->skins_count; ++i) 6646 { 6647 for (cgltf_size j = 0; j < data->skins[i].joints_count; ++j) 6648 { 6649 CGLTF_PTRFIXUP_REQ(data->skins[i].joints[j], data->nodes, data->nodes_count); 6650 } 6651 6652 CGLTF_PTRFIXUP(data->skins[i].skeleton, data->nodes, data->nodes_count); 6653 CGLTF_PTRFIXUP(data->skins[i].inverse_bind_matrices, data->accessors, data->accessors_count); 6654 } 6655 6656 for (cgltf_size i = 0; i < data->nodes_count; ++i) 6657 { 6658 for (cgltf_size j = 0; j < data->nodes[i].children_count; ++j) 6659 { 6660 CGLTF_PTRFIXUP_REQ(data->nodes[i].children[j], data->nodes, data->nodes_count); 6661 6662 if (data->nodes[i].children[j]->parent) 6663 { 6664 return CGLTF_ERROR_JSON; 6665 } 6666 6667 data->nodes[i].children[j]->parent = &data->nodes[i]; 6668 } 6669 6670 CGLTF_PTRFIXUP(data->nodes[i].mesh, data->meshes, data->meshes_count); 6671 CGLTF_PTRFIXUP(data->nodes[i].skin, data->skins, data->skins_count); 6672 CGLTF_PTRFIXUP(data->nodes[i].camera, data->cameras, data->cameras_count); 6673 CGLTF_PTRFIXUP(data->nodes[i].light, data->lights, data->lights_count); 6674 6675 if (data->nodes[i].has_mesh_gpu_instancing) 6676 { 6677 for (cgltf_size m = 0; m < data->nodes[i].mesh_gpu_instancing.attributes_count; ++m) 6678 { 6679 CGLTF_PTRFIXUP_REQ(data->nodes[i].mesh_gpu_instancing.attributes[m].data, data->accessors, data->accessors_count); 6680 } 6681 } 6682 } 6683 6684 for (cgltf_size i = 0; i < data->scenes_count; ++i) 6685 { 6686 for (cgltf_size j = 0; j < data->scenes[i].nodes_count; ++j) 6687 { 6688 CGLTF_PTRFIXUP_REQ(data->scenes[i].nodes[j], data->nodes, data->nodes_count); 6689 6690 if (data->scenes[i].nodes[j]->parent) 6691 { 6692 return CGLTF_ERROR_JSON; 6693 } 6694 } 6695 } 6696 6697 CGLTF_PTRFIXUP(data->scene, data->scenes, data->scenes_count); 6698 6699 for (cgltf_size i = 0; i < data->animations_count; ++i) 6700 { 6701 for (cgltf_size j = 0; j < data->animations[i].samplers_count; ++j) 6702 { 6703 CGLTF_PTRFIXUP_REQ(data->animations[i].samplers[j].input, data->accessors, data->accessors_count); 6704 CGLTF_PTRFIXUP_REQ(data->animations[i].samplers[j].output, data->accessors, data->accessors_count); 6705 } 6706 6707 for (cgltf_size j = 0; j < data->animations[i].channels_count; ++j) 6708 { 6709 CGLTF_PTRFIXUP_REQ(data->animations[i].channels[j].sampler, data->animations[i].samplers, data->animations[i].samplers_count); 6710 CGLTF_PTRFIXUP(data->animations[i].channels[j].target_node, data->nodes, data->nodes_count); 6711 } 6712 } 6713 6714 return 0; 6715 } 6716 6717 /* 6718 * -- jsmn.c start -- 6719 * Source: https://github.com/zserge/jsmn 6720 * License: MIT 6721 * 6722 * Copyright (c) 2010 Serge A. Zaitsev 6723 6724 * Permission is hereby granted, free of charge, to any person obtaining a copy 6725 * of this software and associated documentation files (the "Software"), to deal 6726 * in the Software without restriction, including without limitation the rights 6727 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 6728 * copies of the Software, and to permit persons to whom the Software is 6729 * furnished to do so, subject to the following conditions: 6730 6731 * The above copyright notice and this permission notice shall be included in 6732 * all copies or substantial portions of the Software. 6733 6734 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 6735 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 6736 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 6737 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 6738 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 6739 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 6740 * THE SOFTWARE. 6741 */ 6742 6743 /** 6744 * Allocates a fresh unused token from the token pull. 6745 */ 6746 static jsmntok_t *jsmn_alloc_token(jsmn_parser *parser, 6747 jsmntok_t *tokens, size_t num_tokens) { 6748 jsmntok_t *tok; 6749 if (parser->toknext >= num_tokens) { 6750 return NULL; 6751 } 6752 tok = &tokens[parser->toknext++]; 6753 tok->start = tok->end = -1; 6754 tok->size = 0; 6755 #ifdef JSMN_PARENT_LINKS 6756 tok->parent = -1; 6757 #endif 6758 return tok; 6759 } 6760 6761 /** 6762 * Fills token type and boundaries. 6763 */ 6764 static void jsmn_fill_token(jsmntok_t *token, jsmntype_t type, 6765 ptrdiff_t start, ptrdiff_t end) { 6766 token->type = type; 6767 token->start = start; 6768 token->end = end; 6769 token->size = 0; 6770 } 6771 6772 /** 6773 * Fills next available token with JSON primitive. 6774 */ 6775 static int jsmn_parse_primitive(jsmn_parser *parser, const char *js, 6776 size_t len, jsmntok_t *tokens, size_t num_tokens) { 6777 jsmntok_t *token; 6778 ptrdiff_t start; 6779 6780 start = parser->pos; 6781 6782 for (; parser->pos < len && js[parser->pos] != '\0'; parser->pos++) { 6783 switch (js[parser->pos]) { 6784 #ifndef JSMN_STRICT 6785 /* In strict mode primitive must be followed by "," or "}" or "]" */ 6786 case ':': 6787 #endif 6788 case '\t' : case '\r' : case '\n' : case ' ' : 6789 case ',' : case ']' : case '}' : 6790 goto found; 6791 } 6792 if (js[parser->pos] < 32 || js[parser->pos] >= 127) { 6793 parser->pos = start; 6794 return JSMN_ERROR_INVAL; 6795 } 6796 } 6797 #ifdef JSMN_STRICT 6798 /* In strict mode primitive must be followed by a comma/object/array */ 6799 parser->pos = start; 6800 return JSMN_ERROR_PART; 6801 #endif 6802 6803 found: 6804 if (tokens == NULL) { 6805 parser->pos--; 6806 return 0; 6807 } 6808 token = jsmn_alloc_token(parser, tokens, num_tokens); 6809 if (token == NULL) { 6810 parser->pos = start; 6811 return JSMN_ERROR_NOMEM; 6812 } 6813 jsmn_fill_token(token, JSMN_PRIMITIVE, start, parser->pos); 6814 #ifdef JSMN_PARENT_LINKS 6815 token->parent = parser->toksuper; 6816 #endif 6817 parser->pos--; 6818 return 0; 6819 } 6820 6821 /** 6822 * Fills next token with JSON string. 6823 */ 6824 static int jsmn_parse_string(jsmn_parser *parser, const char *js, 6825 size_t len, jsmntok_t *tokens, size_t num_tokens) { 6826 jsmntok_t *token; 6827 6828 ptrdiff_t start = parser->pos; 6829 6830 parser->pos++; 6831 6832 /* Skip starting quote */ 6833 for (; parser->pos < len && js[parser->pos] != '\0'; parser->pos++) { 6834 char c = js[parser->pos]; 6835 6836 /* Quote: end of string */ 6837 if (c == '\"') { 6838 if (tokens == NULL) { 6839 return 0; 6840 } 6841 token = jsmn_alloc_token(parser, tokens, num_tokens); 6842 if (token == NULL) { 6843 parser->pos = start; 6844 return JSMN_ERROR_NOMEM; 6845 } 6846 jsmn_fill_token(token, JSMN_STRING, start+1, parser->pos); 6847 #ifdef JSMN_PARENT_LINKS 6848 token->parent = parser->toksuper; 6849 #endif 6850 return 0; 6851 } 6852 6853 /* Backslash: Quoted symbol expected */ 6854 if (c == '\\' && parser->pos + 1 < len) { 6855 int i; 6856 parser->pos++; 6857 switch (js[parser->pos]) { 6858 /* Allowed escaped symbols */ 6859 case '\"': case '/' : case '\\' : case 'b' : 6860 case 'f' : case 'r' : case 'n' : case 't' : 6861 break; 6862 /* Allows escaped symbol \uXXXX */ 6863 case 'u': 6864 parser->pos++; 6865 for(i = 0; i < 4 && parser->pos < len && js[parser->pos] != '\0'; i++) { 6866 /* If it isn't a hex character we have an error */ 6867 if(!((js[parser->pos] >= 48 && js[parser->pos] <= 57) || /* 0-9 */ 6868 (js[parser->pos] >= 65 && js[parser->pos] <= 70) || /* A-F */ 6869 (js[parser->pos] >= 97 && js[parser->pos] <= 102))) { /* a-f */ 6870 parser->pos = start; 6871 return JSMN_ERROR_INVAL; 6872 } 6873 parser->pos++; 6874 } 6875 parser->pos--; 6876 break; 6877 /* Unexpected symbol */ 6878 default: 6879 parser->pos = start; 6880 return JSMN_ERROR_INVAL; 6881 } 6882 } 6883 } 6884 parser->pos = start; 6885 return JSMN_ERROR_PART; 6886 } 6887 6888 /** 6889 * Parse JSON string and fill tokens. 6890 */ 6891 static int jsmn_parse(jsmn_parser *parser, const char *js, size_t len, 6892 jsmntok_t *tokens, size_t num_tokens) { 6893 int r; 6894 int i; 6895 jsmntok_t *token; 6896 int count = parser->toknext; 6897 6898 for (; parser->pos < len && js[parser->pos] != '\0'; parser->pos++) { 6899 char c; 6900 jsmntype_t type; 6901 6902 c = js[parser->pos]; 6903 switch (c) { 6904 case '{': case '[': 6905 count++; 6906 if (tokens == NULL) { 6907 break; 6908 } 6909 token = jsmn_alloc_token(parser, tokens, num_tokens); 6910 if (token == NULL) 6911 return JSMN_ERROR_NOMEM; 6912 if (parser->toksuper != -1) { 6913 tokens[parser->toksuper].size++; 6914 #ifdef JSMN_PARENT_LINKS 6915 token->parent = parser->toksuper; 6916 #endif 6917 } 6918 token->type = (c == '{' ? JSMN_OBJECT : JSMN_ARRAY); 6919 token->start = parser->pos; 6920 parser->toksuper = parser->toknext - 1; 6921 break; 6922 case '}': case ']': 6923 if (tokens == NULL) 6924 break; 6925 type = (c == '}' ? JSMN_OBJECT : JSMN_ARRAY); 6926 #ifdef JSMN_PARENT_LINKS 6927 if (parser->toknext < 1) { 6928 return JSMN_ERROR_INVAL; 6929 } 6930 token = &tokens[parser->toknext - 1]; 6931 for (;;) { 6932 if (token->start != -1 && token->end == -1) { 6933 if (token->type != type) { 6934 return JSMN_ERROR_INVAL; 6935 } 6936 token->end = parser->pos + 1; 6937 parser->toksuper = token->parent; 6938 break; 6939 } 6940 if (token->parent == -1) { 6941 if(token->type != type || parser->toksuper == -1) { 6942 return JSMN_ERROR_INVAL; 6943 } 6944 break; 6945 } 6946 token = &tokens[token->parent]; 6947 } 6948 #else 6949 for (i = parser->toknext - 1; i >= 0; i--) { 6950 token = &tokens[i]; 6951 if (token->start != -1 && token->end == -1) { 6952 if (token->type != type) { 6953 return JSMN_ERROR_INVAL; 6954 } 6955 parser->toksuper = -1; 6956 token->end = parser->pos + 1; 6957 break; 6958 } 6959 } 6960 /* Error if unmatched closing bracket */ 6961 if (i == -1) return JSMN_ERROR_INVAL; 6962 for (; i >= 0; i--) { 6963 token = &tokens[i]; 6964 if (token->start != -1 && token->end == -1) { 6965 parser->toksuper = i; 6966 break; 6967 } 6968 } 6969 #endif 6970 break; 6971 case '\"': 6972 r = jsmn_parse_string(parser, js, len, tokens, num_tokens); 6973 if (r < 0) return r; 6974 count++; 6975 if (parser->toksuper != -1 && tokens != NULL) 6976 tokens[parser->toksuper].size++; 6977 break; 6978 case '\t' : case '\r' : case '\n' : case ' ': 6979 break; 6980 case ':': 6981 parser->toksuper = parser->toknext - 1; 6982 break; 6983 case ',': 6984 if (tokens != NULL && parser->toksuper != -1 && 6985 tokens[parser->toksuper].type != JSMN_ARRAY && 6986 tokens[parser->toksuper].type != JSMN_OBJECT) { 6987 #ifdef JSMN_PARENT_LINKS 6988 parser->toksuper = tokens[parser->toksuper].parent; 6989 #else 6990 for (i = parser->toknext - 1; i >= 0; i--) { 6991 if (tokens[i].type == JSMN_ARRAY || tokens[i].type == JSMN_OBJECT) { 6992 if (tokens[i].start != -1 && tokens[i].end == -1) { 6993 parser->toksuper = i; 6994 break; 6995 } 6996 } 6997 } 6998 #endif 6999 } 7000 break; 7001 #ifdef JSMN_STRICT 7002 /* In strict mode primitives are: numbers and booleans */ 7003 case '-': case '0': case '1' : case '2': case '3' : case '4': 7004 case '5': case '6': case '7' : case '8': case '9': 7005 case 't': case 'f': case 'n' : 7006 /* And they must not be keys of the object */ 7007 if (tokens != NULL && parser->toksuper != -1) { 7008 jsmntok_t *t = &tokens[parser->toksuper]; 7009 if (t->type == JSMN_OBJECT || 7010 (t->type == JSMN_STRING && t->size != 0)) { 7011 return JSMN_ERROR_INVAL; 7012 } 7013 } 7014 #else 7015 /* In non-strict mode every unquoted value is a primitive */ 7016 default: 7017 #endif 7018 r = jsmn_parse_primitive(parser, js, len, tokens, num_tokens); 7019 if (r < 0) return r; 7020 count++; 7021 if (parser->toksuper != -1 && tokens != NULL) 7022 tokens[parser->toksuper].size++; 7023 break; 7024 7025 #ifdef JSMN_STRICT 7026 /* Unexpected char in strict mode */ 7027 default: 7028 return JSMN_ERROR_INVAL; 7029 #endif 7030 } 7031 } 7032 7033 if (tokens != NULL) { 7034 for (i = parser->toknext - 1; i >= 0; i--) { 7035 /* Unmatched opened object or array */ 7036 if (tokens[i].start != -1 && tokens[i].end == -1) { 7037 return JSMN_ERROR_PART; 7038 } 7039 } 7040 } 7041 7042 return count; 7043 } 7044 7045 /** 7046 * Creates a new parser based over a given buffer with an array of tokens 7047 * available. 7048 */ 7049 static void jsmn_init(jsmn_parser *parser) { 7050 parser->pos = 0; 7051 parser->toknext = 0; 7052 parser->toksuper = -1; 7053 } 7054 /* 7055 * -- jsmn.c end -- 7056 */ 7057 7058 #endif /* #ifdef CGLTF_IMPLEMENTATION */ 7059 7060 /* cgltf is distributed under MIT license: 7061 * 7062 * Copyright (c) 2018-2021 Johannes Kuhlmann 7063 7064 * Permission is hereby granted, free of charge, to any person obtaining a copy 7065 * of this software and associated documentation files (the "Software"), to deal 7066 * in the Software without restriction, including without limitation the rights 7067 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7068 * copies of the Software, and to permit persons to whom the Software is 7069 * furnished to do so, subject to the following conditions: 7070 7071 * The above copyright notice and this permission notice shall be included in all 7072 * copies or substantial portions of the Software. 7073 7074 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 7075 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 7076 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 7077 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 7078 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 7079 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 7080 * SOFTWARE. 7081 */