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