naev 0.11.5
cgltf.h
1
92#ifndef CGLTF_H_INCLUDED__
93#define CGLTF_H_INCLUDED__
94
95#include <stddef.h>
96
97#ifdef __cplusplus
98extern "C" {
99#endif
100
101typedef size_t cgltf_size;
102typedef long long int cgltf_ssize;
103typedef float cgltf_float;
104typedef int cgltf_int;
105typedef unsigned int cgltf_uint;
106typedef int cgltf_bool;
107
108typedef 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
116typedef 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
132{
133 void* (*alloc_func)(void* user, cgltf_size size);
134 void (*free_func) (void* user, void* ptr);
135 void* user_data;
137
138typedef 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;
144
145typedef struct cgltf_options
146{
147 cgltf_file_type type; /* invalid == auto detect */
148 cgltf_size json_token_count; /* 0 == auto */
152
153typedef 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
161typedef 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
175typedef 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
187typedef 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
200typedef 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
212typedef 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
220typedef 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
229typedef 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
236typedef 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
243typedef 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
251typedef 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
258typedef struct cgltf_extras {
259 cgltf_size start_offset;
260 cgltf_size end_offset;
262
263typedef struct cgltf_extension {
264 char* name;
265 char* data;
267
268typedef 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;
279
280typedef 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
288typedef 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
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;
306
307typedef 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;
322
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;
341
342typedef 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;
358 cgltf_extras extras;
359 cgltf_size extensions_count;
360 cgltf_extension* extensions;
362
363typedef struct cgltf_attribute
364{
365 char* name;
366 cgltf_attribute_type type;
367 cgltf_int index;
368 cgltf_accessor* data;
370
371typedef 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;
381
382typedef 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;
393
394typedef 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;
405
407{
408 cgltf_float offset[2];
409 cgltf_float rotation;
410 cgltf_float scale[2];
411 cgltf_bool has_texcoord;
412 cgltf_int texcoord;
414
415typedef 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;
426
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;
438
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;
448
449typedef 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;
458
459typedef struct cgltf_transmission
460{
461 cgltf_texture_view transmission_texture;
462 cgltf_float transmission_factor;
464
465typedef struct cgltf_ior
466{
467 cgltf_float ior;
468} cgltf_ior;
469
470typedef 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;
477
478typedef 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;
485
486typedef 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;
493
495{
496 cgltf_float emissive_strength;
498
499typedef 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;
508
509typedef 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;
544
546{
547 cgltf_size variant;
548 cgltf_material* material;
549 cgltf_extras extras;
551
552typedef struct cgltf_morph_target {
553 cgltf_attribute* attributes;
554 cgltf_size attributes_count;
556
558 cgltf_buffer_view* buffer_view;
559 cgltf_attribute* attributes;
560 cgltf_size attributes_count;
562
564 cgltf_buffer_view* buffer_view;
565 cgltf_attribute* attributes;
566 cgltf_size attributes_count;
568
569typedef 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;
585
586typedef 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
599typedef struct cgltf_node cgltf_node;
600
601typedef 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
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;
621
623 cgltf_float xmag;
624 cgltf_float ymag;
625 cgltf_float zfar;
626 cgltf_float znear;
627 cgltf_extras extras;
629
630typedef 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;
641
642typedef 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;
652
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
679typedef 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;
687
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;
696
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;
705
706typedef 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;
716
718{
719 char* name;
720 cgltf_extras extras;
722
723typedef 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;
732
733typedef 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
806} cgltf_data;
807
808cgltf_result cgltf_parse(
809 const cgltf_options* options,
810 const void* data,
811 cgltf_size size,
812 cgltf_data** out_data);
813
814cgltf_result cgltf_parse_file(
815 const cgltf_options* options,
816 const char* path,
817 cgltf_data** out_data);
818
819cgltf_result cgltf_load_buffers(
820 const cgltf_options* options,
821 cgltf_data* data,
822 const char* gltf_path);
823
824cgltf_result cgltf_load_buffer_base64(const cgltf_options* options, cgltf_size size, const char* base64, void** out_data);
825
826cgltf_size cgltf_decode_string(char* string);
827cgltf_size cgltf_decode_uri(char* uri);
828
829cgltf_result cgltf_validate(cgltf_data* data);
830
831void cgltf_free(cgltf_data* data);
832
833void cgltf_node_transform_local(const cgltf_node* node, cgltf_float* out_matrix);
834void cgltf_node_transform_world(const cgltf_node* node, cgltf_float* out_matrix);
835
836cgltf_bool cgltf_accessor_read_float(const cgltf_accessor* accessor, cgltf_size index, cgltf_float* out, cgltf_size element_size);
837cgltf_bool cgltf_accessor_read_uint(const cgltf_accessor* accessor, cgltf_size index, cgltf_uint* out, cgltf_size element_size);
838cgltf_size cgltf_accessor_read_index(const cgltf_accessor* accessor, cgltf_size index);
839
840cgltf_size cgltf_num_components(cgltf_type type);
841
842cgltf_size cgltf_accessor_unpack_floats(const cgltf_accessor* accessor, cgltf_float* out, cgltf_size float_count);
843
844cgltf_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 */
891typedef enum {
892 JSMN_UNDEFINED = 0,
893 JSMN_OBJECT = 1,
894 JSMN_ARRAY = 2,
895 JSMN_STRING = 3,
896 JSMN_PRIMITIVE = 4
897} jsmntype_t;
898enum 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};
906typedef 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;
915typedef 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;
920static void jsmn_init(jsmn_parser *parser);
921static 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
927static const cgltf_size GlbHeaderSize = 12;
928static const cgltf_size GlbChunkHeaderSize = 8;
929static const uint32_t GlbVersion = 2;
930static const uint32_t GlbMagic = 0x46546C67;
931static const uint32_t GlbMagicJsonChunk = 0x4E4F534A;
932static 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
953static void* cgltf_default_alloc(void* user, cgltf_size size)
954{
955 (void)user;
956 return CGLTF_MALLOC(size);
957}
958
959static void cgltf_default_free(void* user, void* ptr)
960{
961 (void)user;
962 CGLTF_FREE(ptr);
963}
964
965static 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
980static 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
1043static 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
1050static cgltf_result cgltf_parse_json(cgltf_options* options, const uint8_t* json_chunk, cgltf_size size, cgltf_data** out_data);
1051
1052cgltf_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
1184cgltf_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
1215static 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
1234static 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
1261cgltf_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
1308static 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
1317cgltf_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
1388cgltf_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
1419cgltf_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
1489static cgltf_size cgltf_calc_size(cgltf_type type, cgltf_component_type component_type);
1490
1491static 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
1535cgltf_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
1720cgltf_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
1748void 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
1758void 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
2045void 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
2090void 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
2125static 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
2146static 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
2163static 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
2191static cgltf_size cgltf_component_size(cgltf_component_type component_type);
2192
2193static 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
2249const 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
2262cgltf_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
2282cgltf_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
2340static 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
2364static 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
2388cgltf_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
2408cgltf_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
2439static 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
2447static 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
2457static 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
2467static 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
2477static 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
2483static 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
2513static 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
2521static 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
2538static 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
2557static 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
2579static 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
2599static 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
2649static 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
2686static 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
2695static 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
2729static 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
2766static 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
2797static 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
2828static 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
2908static 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
2953static 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
3069static 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
3165static 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
3184static 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
3207static 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
3338static 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
3461static 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
3507static 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
3604static 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
3661static 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
3707static 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
3755static 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
3788static 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
3834static 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
3868static 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
3912static 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
3954static 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
3987static 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
4048static 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
4099static 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
4168static 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
4276static 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
4461static 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
4480static 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
4499static 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
4518static 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
4537static 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
4556static 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
4650static 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
4769static 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
4788static 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
4836static 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
4855static 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
4920static 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
4939static 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
5099static 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
5118static 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
5228static 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
5247static 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
5426static 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
5445static 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
5496static 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
5515static 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
5578static 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
5669static 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
5740static 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
5759static 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
5792static 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
5811static 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
5865cgltf_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
5887static 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
5905static 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
5919static int cgltf_fixup_pointers(cgltf_data* out_data);
5920
5921static 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
6112cgltf_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
6191static 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
6404static 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
6422static 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
6433static 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
6461found:
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
6482static 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
6549static 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
6707static 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 */
static const double c[]
Definition rng.c:264