diff options
| author | Ray <[email protected]> | 2019-08-07 00:33:57 +0200 |
|---|---|---|
| committer | Ray <[email protected]> | 2019-08-07 00:33:57 +0200 |
| commit | 3d46297cc150803a55e27f446b2d4708ff0b04bd (patch) | |
| tree | ed441cacca41738d27371e2d49c11be250ba2462 /src/external/cgltf.h | |
| parent | 439e73a8ece912f2a7df5f4c0ed7fc6fb7673672 (diff) | |
| download | raylib-3d46297cc150803a55e27f446b2d4708ff0b04bd.tar.gz raylib-3d46297cc150803a55e27f446b2d4708ff0b04bd.zip | |
Update external libraries
Diffstat (limited to 'src/external/cgltf.h')
| -rw-r--r-- | src/external/cgltf.h | 598 |
1 files changed, 497 insertions, 101 deletions
diff --git a/src/external/cgltf.h b/src/external/cgltf.h index 85d5c985..7f3f77f7 100644 --- a/src/external/cgltf.h +++ b/src/external/cgltf.h @@ -1,7 +1,7 @@ /** * cgltf - a single-file glTF 2.0 parser written in C99. * - * Version: 1.0 + * Version: 1.2 * * Website: https://github.com/jkuhlmann/cgltf * @@ -35,8 +35,15 @@ * variable. * * `cgltf_result cgltf_load_buffers(const cgltf_options*, cgltf_data*, - * const char*)` can be optionally called to open and read buffer - * files using the `FILE*` APIs. + * const char* gltf_path)` can be optionally called to open and read buffer + * files using the `FILE*` APIs. The `gltf_path` argument is the path to + * the original glTF file, which allows the parser to resolve the path to + * buffer files. + * + * `cgltf_result cgltf_load_buffer_base64(const cgltf_options* options, + * cgltf_size size, const char* base64, void** out_data)` decodes + * base64-encoded data content. Used internally by `cgltf_load_buffers()` + * and may be useful if you're not dealing with normal files. * * `cgltf_result cgltf_parse_file(const cgltf_options* options, const * char* path, cgltf_data** out_data)` can be used to open the given @@ -44,6 +51,29 @@ * * `cgltf_result cgltf_validate(cgltf_data*)` can be used to do additional * checks to make sure the parsed glTF data is valid. + * + * `cgltf_node_transform_local` converts the translation / rotation / scale properties of a node + * into a mat4. + * + * `cgltf_node_transform_world` calls `cgltf_node_transform_local` on every ancestor in order + * to compute the root-to-node transformation. + * + * `cgltf_accessor_read_float` reads a certain element from an accessor and converts it to + * floating point, assuming that `cgltf_load_buffers` has already been called. The passed-in element + * size is the number of floats in the output buffer, which should be in the range [1, 16]. Returns + * false if the passed-in element_size is too small, or if the accessor is sparse. + * + * `cgltf_accessor_read_index` is similar to its floating-point counterpart, but it returns size_t + * and only works with single-component data types. + * + * `cgltf_result cgltf_copy_extras_json(const cgltf_data*, const cgltf_extras*, + * char* dest, cgltf_size* dest_size)` allows to retrieve the "extras" data that + * can be attached to many glTF objects (which can be arbitrary JSON data). The + * `cgltf_extras` struct stores the offsets of the start and end of the extras JSON data + * as it appears in the complete glTF JSON data. This function copies the extras data + * into the provided buffer. If `dest` is NULL, the length of the data is written into + * `dest_size`. You can then parse this data using your own JSON parser + * or, if you've included the cgltf implementation using the integrated JSMN JSON parser. */ #ifndef CGLTF_H_INCLUDED__ #define CGLTF_H_INCLUDED__ @@ -175,11 +205,17 @@ typedef enum cgltf_light_type { cgltf_light_type_spot, } cgltf_light_type; +typedef struct cgltf_extras { + cgltf_size start_offset; + cgltf_size end_offset; +} cgltf_extras; + typedef struct cgltf_buffer { cgltf_size size; char* uri; void* data; /* loaded by cgltf_load_buffers */ + cgltf_extras extras; } cgltf_buffer; typedef struct cgltf_buffer_view @@ -189,6 +225,7 @@ typedef struct cgltf_buffer_view cgltf_size size; cgltf_size stride; /* 0 == automatically determined by accessor */ cgltf_buffer_view_type type; + cgltf_extras extras; } cgltf_buffer_view; typedef struct cgltf_accessor_sparse @@ -199,6 +236,9 @@ typedef struct cgltf_accessor_sparse cgltf_component_type indices_component_type; cgltf_buffer_view* values_buffer_view; cgltf_size values_byte_offset; + cgltf_extras extras; + cgltf_extras indices_extras; + cgltf_extras values_extras; } cgltf_accessor_sparse; typedef struct cgltf_accessor @@ -216,6 +256,7 @@ typedef struct cgltf_accessor cgltf_float max[16]; cgltf_bool is_sparse; cgltf_accessor_sparse sparse; + cgltf_extras extras; } cgltf_accessor; typedef struct cgltf_attribute @@ -232,6 +273,7 @@ typedef struct cgltf_image char* uri; cgltf_buffer_view* buffer_view; char* mime_type; + cgltf_extras extras; } cgltf_image; typedef struct cgltf_sampler @@ -240,6 +282,7 @@ typedef struct cgltf_sampler cgltf_int min_filter; cgltf_int wrap_s; cgltf_int wrap_t; + cgltf_extras extras; } cgltf_sampler; typedef struct cgltf_texture @@ -247,6 +290,7 @@ typedef struct cgltf_texture char* name; cgltf_image* image; cgltf_sampler* sampler; + cgltf_extras extras; } cgltf_texture; typedef struct cgltf_texture_transform @@ -264,6 +308,7 @@ typedef struct cgltf_texture_view cgltf_float scale; /* equivalent to strength for occlusion_texture */ cgltf_bool has_transform; cgltf_texture_transform transform; + cgltf_extras extras; } cgltf_texture_view; typedef struct cgltf_pbr_metallic_roughness @@ -274,6 +319,8 @@ typedef struct cgltf_pbr_metallic_roughness cgltf_float base_color_factor[4]; cgltf_float metallic_factor; cgltf_float roughness_factor; + + cgltf_extras extras; } cgltf_pbr_metallic_roughness; typedef struct cgltf_pbr_specular_glossiness @@ -301,6 +348,7 @@ typedef struct cgltf_material cgltf_float alpha_cutoff; cgltf_bool double_sided; cgltf_bool unlit; + cgltf_extras extras; } cgltf_material; typedef struct cgltf_morph_target { @@ -316,6 +364,7 @@ typedef struct cgltf_primitive { cgltf_size attributes_count; cgltf_morph_target* targets; cgltf_size targets_count; + cgltf_extras extras; } cgltf_primitive; typedef struct cgltf_mesh { @@ -324,6 +373,7 @@ typedef struct cgltf_mesh { cgltf_size primitives_count; cgltf_float* weights; cgltf_size weights_count; + cgltf_extras extras; } cgltf_mesh; typedef struct cgltf_node cgltf_node; @@ -334,6 +384,7 @@ typedef struct cgltf_skin { cgltf_size joints_count; cgltf_node* skeleton; cgltf_accessor* inverse_bind_matrices; + cgltf_extras extras; } cgltf_skin; typedef struct cgltf_camera_perspective { @@ -341,6 +392,7 @@ typedef struct cgltf_camera_perspective { cgltf_float yfov; cgltf_float zfar; cgltf_float znear; + cgltf_extras extras; } cgltf_camera_perspective; typedef struct cgltf_camera_orthographic { @@ -348,6 +400,7 @@ typedef struct cgltf_camera_orthographic { cgltf_float ymag; cgltf_float zfar; cgltf_float znear; + cgltf_extras extras; } cgltf_camera_orthographic; typedef struct cgltf_camera { @@ -357,6 +410,7 @@ typedef struct cgltf_camera { cgltf_camera_perspective perspective; cgltf_camera_orthographic orthographic; }; + cgltf_extras extras; } cgltf_camera; typedef struct cgltf_light { @@ -388,24 +442,28 @@ struct cgltf_node { cgltf_float rotation[4]; cgltf_float scale[3]; cgltf_float matrix[16]; + cgltf_extras extras; }; typedef struct cgltf_scene { char* name; cgltf_node** nodes; cgltf_size nodes_count; + cgltf_extras extras; } cgltf_scene; typedef struct cgltf_animation_sampler { cgltf_accessor* input; cgltf_accessor* output; cgltf_interpolation_type interpolation; + cgltf_extras extras; } cgltf_animation_sampler; typedef struct cgltf_animation_channel { cgltf_animation_sampler* sampler; cgltf_node* target_node; cgltf_animation_path_type target_path; + cgltf_extras extras; } cgltf_animation_channel; typedef struct cgltf_animation { @@ -414,6 +472,7 @@ typedef struct cgltf_animation { cgltf_size samplers_count; cgltf_animation_channel* channels; cgltf_size channels_count; + cgltf_extras extras; } cgltf_animation; typedef struct cgltf_asset { @@ -421,6 +480,7 @@ typedef struct cgltf_asset { char* generator; char* version; char* min_version; + cgltf_extras extras; } cgltf_asset; typedef struct cgltf_data @@ -474,6 +534,17 @@ typedef struct cgltf_data cgltf_animation* animations; cgltf_size animations_count; + cgltf_extras extras; + + char** extensions_used; + cgltf_size extensions_used_count; + + char** extensions_required; + cgltf_size extensions_required_count; + + const char* json; + cgltf_size json_size; + const void* bin; cgltf_size bin_size; @@ -495,7 +566,10 @@ cgltf_result cgltf_parse_file( cgltf_result cgltf_load_buffers( const cgltf_options* options, cgltf_data* data, - const char* base_path); + const char* gltf_path); + + +cgltf_result cgltf_load_buffer_base64(const cgltf_options* options, cgltf_size size, const char* base64, void** out_data); cgltf_result cgltf_validate( cgltf_data* data); @@ -505,6 +579,11 @@ void cgltf_free(cgltf_data* data); void cgltf_node_transform_local(const cgltf_node* node, cgltf_float* out_matrix); void cgltf_node_transform_world(const cgltf_node* node, cgltf_float* out_matrix); +cgltf_bool cgltf_accessor_read_float(const cgltf_accessor* accessor, cgltf_size index, cgltf_float* out, cgltf_size element_size); +cgltf_size cgltf_accessor_read_index(const cgltf_accessor* accessor, cgltf_size index); + +cgltf_result cgltf_copy_extras_json(const cgltf_data* data, const cgltf_extras* extras, char* dest, cgltf_size* dest_size); + #ifdef __cplusplus } #endif @@ -528,7 +607,14 @@ void cgltf_node_transform_world(const cgltf_node* node, cgltf_float* out_matrix) #include <stdint.h> /* For uint8_t, uint32_t */ #include <string.h> /* For strncpy */ #include <stdlib.h> /* For malloc, free */ -#include <stdio.h> /* For fopen */ +#include <stdio.h> /* For fopen */ +#include <limits.h> /* For UINT_MAX etc */ + +/* JSMN_PARENT_LINKS is necessary to make parsing large structures linear in input size */ +#define JSMN_PARENT_LINKS + +/* JSMN_STRICT is necessary to reject invalid JSON documents */ +#define JSMN_STRICT /* * -- jsmn.h start -- @@ -580,11 +666,13 @@ static const uint32_t GlbMagicBinChunk = 0x004E4942; static void* cgltf_default_alloc(void* user, cgltf_size size) { + (void)user; return malloc(size); } static void cgltf_default_free(void* user, void* ptr) { + (void)user; free(ptr); } @@ -810,22 +898,22 @@ static void cgltf_combine_paths(char* path, const char* base, const char* uri) } else { - strcpy(path, base); + strcpy(path, uri); } } -static cgltf_result cgltf_load_buffer_file(const cgltf_options* options, cgltf_size size, const char* uri, const char* base_path, void** out_data) +static cgltf_result cgltf_load_buffer_file(const cgltf_options* options, cgltf_size size, const char* uri, const char* gltf_path, void** out_data) { void* (*memory_alloc)(void*, cgltf_size) = options->memory_alloc ? options->memory_alloc : &cgltf_default_alloc; void (*memory_free)(void*, void*) = options->memory_free ? options->memory_free : &cgltf_default_free; - char* path = (char*)memory_alloc(options->memory_user_data, strlen(uri) + strlen(base_path) + 1); + char* path = (char*)memory_alloc(options->memory_user_data, strlen(uri) + strlen(gltf_path) + 1); if (!path) { return cgltf_result_out_of_memory; } - cgltf_combine_paths(path, base_path, uri); + cgltf_combine_paths(path, gltf_path, uri); FILE* file = fopen(path, "rb"); @@ -858,7 +946,7 @@ static cgltf_result cgltf_load_buffer_file(const cgltf_options* options, cgltf_s return cgltf_result_success; } -static cgltf_result cgltf_load_buffer_base64(const cgltf_options* options, cgltf_size size, const char* base64, void** out_data) +cgltf_result cgltf_load_buffer_base64(const cgltf_options* options, cgltf_size size, const char* base64, void** out_data) { void* (*memory_alloc)(void*, cgltf_size) = options->memory_alloc ? options->memory_alloc : &cgltf_default_alloc; void (*memory_free)(void*, void*) = options->memory_free ? options->memory_free : &cgltf_default_free; @@ -905,7 +993,7 @@ static cgltf_result cgltf_load_buffer_base64(const cgltf_options* options, cgltf return cgltf_result_success; } -cgltf_result cgltf_load_buffers(const cgltf_options* options, cgltf_data* data, const char* base_path) +cgltf_result cgltf_load_buffers(const cgltf_options* options, cgltf_data* data, const char* gltf_path) { if (options == NULL) { @@ -954,9 +1042,9 @@ cgltf_result cgltf_load_buffers(const cgltf_options* options, cgltf_data* data, return cgltf_result_unknown_format; } } - else if (strstr(uri, "://") == NULL) + else if (strstr(uri, "://") == NULL && gltf_path) { - cgltf_result res = cgltf_load_buffer_file(options, data->buffers[i].size, uri, base_path, &data->buffers[i].data); + cgltf_result res = cgltf_load_buffer_file(options, data->buffers[i].size, uri, gltf_path, &data->buffers[i].data); if (res != cgltf_result_success) { @@ -1150,6 +1238,34 @@ cgltf_result cgltf_validate(cgltf_data* data) return cgltf_result_success; } +cgltf_result cgltf_copy_extras_json(const cgltf_data* data, const cgltf_extras* extras, char* dest, cgltf_size* dest_size) +{ + cgltf_size json_size = extras->end_offset - extras->start_offset; + + if (!dest) + { + if (dest_size) + { + *dest_size = json_size + 1; + return cgltf_result_success; + } + return cgltf_result_invalid_options; + } + + if (*dest_size + 1 < json_size) + { + strncpy(dest, data->json + extras->start_offset, *dest_size - 1); + dest[*dest_size - 1] = 0; + } + else + { + strncpy(dest, data->json + extras->start_offset, json_size); + dest[json_size] = 0; + } + + return cgltf_result_success; +} + void cgltf_free(cgltf_data* data) { if (!data) @@ -1282,6 +1398,20 @@ void cgltf_free(cgltf_data* data) data->memory_free(data->memory_user_data, data->animations); + for (cgltf_size i = 0; i < data->extensions_used_count; ++i) + { + data->memory_free(data->memory_user_data, data->extensions_used[i]); + } + + data->memory_free(data->memory_user_data, data->extensions_used); + + for (cgltf_size i = 0; i < data->extensions_required_count; ++i) + { + data->memory_free(data->memory_user_data, data->extensions_required[i]); + } + + data->memory_free(data->memory_user_data, data->extensions_required); + data->memory_free(data->memory_user_data, data->file_data); data->memory_free(data->memory_user_data, data); @@ -1367,6 +1497,142 @@ void cgltf_node_transform_world(const cgltf_node* node, cgltf_float* out_matrix) } } +static cgltf_size cgltf_component_read_index(const void* in, cgltf_component_type component_type) +{ + switch (component_type) + { + case cgltf_component_type_r_16: + return *((const int16_t*) in); + case cgltf_component_type_r_16u: + return *((const uint16_t*) in); + case cgltf_component_type_r_32u: + return *((const uint32_t*) in); + case cgltf_component_type_r_32f: + return (cgltf_size)*((const float*) in); + case cgltf_component_type_r_8: + return *((const int8_t*) in); + case cgltf_component_type_r_8u: + case cgltf_component_type_invalid: + default: + return *((const uint8_t*) in); + } +} + +static cgltf_float cgltf_component_read_float(const void* in, cgltf_component_type component_type, cgltf_bool normalized) +{ + if (component_type == cgltf_component_type_r_32f) + { + return *((const float*) in); + } + + if (normalized) + { + switch (component_type) + { + case cgltf_component_type_r_32u: + return *((const uint32_t*) in) / (float) UINT_MAX; + case cgltf_component_type_r_16: + return *((const int16_t*) in) / (float) SHRT_MAX; + case cgltf_component_type_r_16u: + return *((const uint16_t*) in) / (float) USHRT_MAX; + case cgltf_component_type_r_8: + return *((const int8_t*) in) / (float) SCHAR_MAX; + case cgltf_component_type_r_8u: + case cgltf_component_type_invalid: + default: + return *((const uint8_t*) in) / (float) CHAR_MAX; + } + } + + return (cgltf_float)cgltf_component_read_index(in, component_type); +} + +static cgltf_size cgltf_num_components(cgltf_type type); +static cgltf_size cgltf_component_size(cgltf_component_type component_type); + +static cgltf_bool cgltf_element_read_float(const uint8_t* element, cgltf_type type, cgltf_component_type component_type, cgltf_bool normalized, cgltf_float* out, cgltf_size element_size) +{ + cgltf_size num_components = cgltf_num_components(type); + + if (element_size < num_components) { + return 0; + } + + // There are three special cases for component extraction, see #data-alignment in the 2.0 spec. + + cgltf_size component_size = cgltf_component_size(component_type); + + if (type == cgltf_type_mat2 && component_size == 1) + { + out[0] = cgltf_component_read_float(element, component_type, normalized); + out[1] = cgltf_component_read_float(element + 1, component_type, normalized); + out[2] = cgltf_component_read_float(element + 4, component_type, normalized); + out[3] = cgltf_component_read_float(element + 5, component_type, normalized); + return 1; + } + + if (type == cgltf_type_mat3 && component_size == 1) + { + out[0] = cgltf_component_read_float(element, component_type, normalized); + out[1] = cgltf_component_read_float(element + 1, component_type, normalized); + out[2] = cgltf_component_read_float(element + 2, component_type, normalized); + out[3] = cgltf_component_read_float(element + 4, component_type, normalized); + out[4] = cgltf_component_read_float(element + 5, component_type, normalized); + out[5] = cgltf_component_read_float(element + 6, component_type, normalized); + out[6] = cgltf_component_read_float(element + 8, component_type, normalized); + out[7] = cgltf_component_read_float(element + 9, component_type, normalized); + out[8] = cgltf_component_read_float(element + 10, component_type, normalized); + return 1; + } + + if (type == cgltf_type_mat3 && component_size == 2) + { + out[0] = cgltf_component_read_float(element, component_type, normalized); + out[1] = cgltf_component_read_float(element + 2, component_type, normalized); + out[2] = cgltf_component_read_float(element + 4, component_type, normalized); + out[3] = cgltf_component_read_float(element + 8, component_type, normalized); + out[4] = cgltf_component_read_float(element + 10, component_type, normalized); + out[5] = cgltf_component_read_float(element + 12, component_type, normalized); + out[6] = cgltf_component_read_float(element + 16, component_type, normalized); + out[7] = cgltf_component_read_float(element + 18, component_type, normalized); + out[8] = cgltf_component_read_float(element + 20, component_type, normalized); + return 1; + } + + for (cgltf_size i = 0; i < num_components; ++i) + { + out[i] = cgltf_component_read_float(element + component_size * i, component_type, normalized); + } + return 1; +} + + +cgltf_bool cgltf_accessor_read_float(const cgltf_accessor* accessor, cgltf_size index, cgltf_float* out, cgltf_size element_size) +{ + if (accessor->is_sparse || accessor->buffer_view == NULL) + { + return 0; + } + + cgltf_size offset = accessor->offset + accessor->buffer_view->offset; + const uint8_t* element = (const uint8_t*) accessor->buffer_view->buffer->data; + element += offset + accessor->stride * index; + return cgltf_element_read_float(element, accessor->type, accessor->component_type, accessor->normalized, out, element_size); +} + +cgltf_size cgltf_accessor_read_index(const cgltf_accessor* accessor, cgltf_size index) +{ + if (accessor->buffer_view) + { + cgltf_size offset = accessor->offset + accessor->buffer_view->offset; + const uint8_t* element = (const uint8_t*) accessor->buffer_view->buffer->data; + element += offset + accessor->stride * index; + return cgltf_component_read_index(element, accessor->component_type); + } + + return 0; +} + #define CGLTF_ERROR_JSON -1 #define CGLTF_ERROR_NOMEM -2 @@ -1413,39 +1679,31 @@ static cgltf_bool cgltf_json_to_bool(jsmntok_t const* tok, const uint8_t* json_c static int cgltf_skip_json(jsmntok_t const* tokens, int i) { - if (tokens[i].type == JSMN_ARRAY) - { - int size = tokens[i].size; - ++i; - for (int j = 0; j < size; ++j) - { - i = cgltf_skip_json(tokens, i); - if (i < 0) - { - return i; - } - } - } - else if (tokens[i].type == JSMN_OBJECT) + int end = i + 1; + + while (i < end) { - int size = tokens[i].size; - ++i; - for (int j = 0; j < size; ++j) + switch (tokens[i].type) { - CGLTF_CHECK_KEY(tokens[i]); - ++i; - i = cgltf_skip_json(tokens, i); - if (i < 0) - { - return i; - } + case JSMN_OBJECT: + end += tokens[i].size * 2; + break; + + case JSMN_ARRAY: + end += tokens[i].size; + break; + + case JSMN_PRIMITIVE: + case JSMN_STRING: + break; + + default: + return -1; } + + i++; } - else if (tokens[i].type == JSMN_PRIMITIVE - || tokens[i].type == JSMN_STRING) - { - return i + 1; - } + return i; } @@ -1495,6 +1753,7 @@ static int cgltf_parse_json_string(cgltf_options* options, jsmntok_t const* toke static int cgltf_parse_json_array(cgltf_options* options, jsmntok_t const* tokens, int i, const uint8_t* json_chunk, size_t element_size, void** out_array, cgltf_size* out_size) { + (void)json_chunk; CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_ARRAY); if (*out_array) { @@ -1511,6 +1770,26 @@ static int cgltf_parse_json_array(cgltf_options* options, jsmntok_t const* token return i + 1; } +static int cgltf_parse_json_string_array(cgltf_options* options, jsmntok_t const* tokens, int i, const uint8_t* json_chunk, char*** out_array, cgltf_size* out_size) +{ + CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_ARRAY); + i = cgltf_parse_json_array(options, tokens, i, json_chunk, sizeof(char*), (void**)out_array, out_size); + if (i < 0) + { + return i; + } + + for (cgltf_size j = 0; j < *out_size; ++j) + { + i = cgltf_parse_json_string(options, tokens, i, json_chunk, j + (*out_array)); + if (i < 0) + { + return i; + } + } + return i; +} + static void cgltf_parse_attribute_type(const char* name, cgltf_attribute_type* out_type, int* out_index) { const char* us = strchr(name, '_'); @@ -1592,6 +1871,15 @@ static int cgltf_parse_json_attribute_list(cgltf_options* options, jsmntok_t con return i; } +static int cgltf_parse_json_extras(jsmntok_t const* tokens, int i, const uint8_t* json_chunk, cgltf_extras* out_extras) +{ + (void)json_chunk; + out_extras->start_offset = tokens[i].start; + out_extras->end_offset = tokens[i].end; + i = cgltf_skip_json(tokens, i); + return i; +} + static int cgltf_parse_json_primitive(cgltf_options* options, jsmntok_t const* tokens, int i, const uint8_t* json_chunk, cgltf_primitive* out_prim) { CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT); @@ -1637,15 +1925,19 @@ static int cgltf_parse_json_primitive(cgltf_options* options, jsmntok_t const* t return i; } - for (cgltf_size j = 0; j < out_prim->targets_count; ++j) + for (cgltf_size k = 0; k < out_prim->targets_count; ++k) { - i = cgltf_parse_json_attribute_list(options, tokens, i, json_chunk, &out_prim->targets[j].attributes, &out_prim->targets[j].attributes_count); + i = cgltf_parse_json_attribute_list(options, tokens, i, json_chunk, &out_prim->targets[k].attributes, &out_prim->targets[k].attributes_count); if (i < 0) { return i; } } } + else if (cgltf_json_strcmp(tokens + i, json_chunk, "extras") == 0) + { + i = cgltf_parse_json_extras(tokens, i + 1, json_chunk, &out_prim->extras); + } else { i = cgltf_skip_json(tokens, i+1); @@ -1702,6 +1994,10 @@ static int cgltf_parse_json_mesh(cgltf_options* options, jsmntok_t const* tokens i = cgltf_parse_json_float_array(tokens, i - 1, json_chunk, out_mesh->weights, (int)out_mesh->weights_count); } + else if (cgltf_json_strcmp(tokens + i, json_chunk, "extras") == 0) + { + i = cgltf_parse_json_extras(tokens, i + 1, json_chunk, &out_mesh->extras); + } else { i = cgltf_skip_json(tokens, i+1); @@ -1805,6 +2101,10 @@ static int cgltf_parse_json_accessor_sparse(jsmntok_t const* tokens, int i, cons out_sparse->indices_component_type = cgltf_json_to_component_type(tokens + i, json_chunk); ++i; } + else if (cgltf_json_strcmp(tokens + i, json_chunk, "extras") == 0) + { + i = cgltf_parse_json_extras(tokens, i + 1, json_chunk, &out_sparse->indices_extras); + } else { i = cgltf_skip_json(tokens, i+1); @@ -1840,6 +2140,10 @@ static int cgltf_parse_json_accessor_sparse(jsmntok_t const* tokens, int i, cons out_sparse->values_byte_offset = cgltf_json_to_int(tokens + i, json_chunk); ++i; } + else if (cgltf_json_strcmp(tokens + i, json_chunk, "extras") == 0) + { + i = cgltf_parse_json_extras(tokens, i + 1, json_chunk, &out_sparse->values_extras); + } else { i = cgltf_skip_json(tokens, i+1); @@ -1851,6 +2155,10 @@ static int cgltf_parse_json_accessor_sparse(jsmntok_t const* tokens, int i, cons } } } + else if (cgltf_json_strcmp(tokens + i, json_chunk, "extras") == 0) + { + i = cgltf_parse_json_extras(tokens, i + 1, json_chunk, &out_sparse->extras); + } else { i = cgltf_skip_json(tokens, i+1); @@ -1962,6 +2270,10 @@ static int cgltf_parse_json_accessor(jsmntok_t const* tokens, int i, const uint8 out_accessor->is_sparse = 1; i = cgltf_parse_json_accessor_sparse(tokens, i + 1, json_chunk, &out_accessor->sparse); } + else if (cgltf_json_strcmp(tokens + i, json_chunk, "extras") == 0) + { + i = cgltf_parse_json_extras(tokens, i + 1, json_chunk, &out_accessor->extras); + } else { i = cgltf_skip_json(tokens, i+1); @@ -2059,6 +2371,10 @@ static int cgltf_parse_json_texture_view(jsmntok_t const* tokens, int i, const u out_texture_view->scale = cgltf_json_to_float(tokens + i, json_chunk); ++i; } + else if (cgltf_json_strcmp(tokens + i, json_chunk, "extras") == 0) + { + i = cgltf_parse_json_extras(tokens, i + 1, json_chunk, &out_texture_view->extras); + } else if (cgltf_json_strcmp(tokens + i, json_chunk, "extensions") == 0) { ++i; @@ -2070,6 +2386,8 @@ static int cgltf_parse_json_texture_view(jsmntok_t const* tokens, int i, const u for (int k = 0; k < extensions_size; ++k) { + CGLTF_CHECK_KEY(tokens[i]); + if (cgltf_json_strcmp(tokens+i, json_chunk, "KHR_texture_transform") == 0) { out_texture_view->has_transform = 1; @@ -2079,6 +2397,11 @@ static int cgltf_parse_json_texture_view(jsmntok_t const* tokens, int i, const u { i = cgltf_skip_json(tokens, i+1); } + + if (i < 0) + { + return i; + } } } else @@ -2134,6 +2457,10 @@ static int cgltf_parse_json_pbr_metallic_roughness(jsmntok_t const* tokens, int i = cgltf_parse_json_texture_view(tokens, i + 1, json_chunk, &out_pbr->metallic_roughness_texture); } + else if (cgltf_json_strcmp(tokens + i, json_chunk, "extras") == 0) + { + i = cgltf_parse_json_extras(tokens, i + 1, json_chunk, &out_pbr->extras); + } else { i = cgltf_skip_json(tokens, i+1); @@ -2161,18 +2488,10 @@ static int cgltf_parse_json_pbr_specular_glossiness(jsmntok_t const* tokens, int if (cgltf_json_strcmp(tokens+i, json_chunk, "diffuseFactor") == 0) { i = cgltf_parse_json_float_array(tokens, i + 1, json_chunk, out_pbr->diffuse_factor, 4); - if (i < 0) - { - return i; - } } else if (cgltf_json_strcmp(tokens+i, json_chunk, "specularFactor") == 0) { i = cgltf_parse_json_float_array(tokens, i + 1, json_chunk, out_pbr->specular_factor, 3); - if (i < 0) - { - return i; - } } else if (cgltf_json_strcmp(tokens+i, json_chunk, "glossinessFactor") == 0) { @@ -2183,18 +2502,10 @@ static int cgltf_parse_json_pbr_specular_glossiness(jsmntok_t const* tokens, int else if (cgltf_json_strcmp(tokens+i, json_chunk, "diffuseTexture") == 0) { i = cgltf_parse_json_texture_view(tokens, i + 1, json_chunk, &out_pbr->diffuse_texture); - if (i < 0) - { - return i; - } } else if (cgltf_json_strcmp(tokens+i, json_chunk, "specularGlossinessTexture") == 0) { i = cgltf_parse_json_texture_view(tokens, i + 1, json_chunk, &out_pbr->specular_glossiness_texture); - if (i < 0) - { - return i; - } } else { @@ -2205,7 +2516,6 @@ static int cgltf_parse_json_pbr_specular_glossiness(jsmntok_t const* tokens, int { return i; } - } return i; @@ -2240,6 +2550,10 @@ static int cgltf_parse_json_image(cgltf_options* options, jsmntok_t const* token { i = cgltf_parse_json_string(options, tokens, i + 1, json_chunk, &out_image->name); } + else if (cgltf_json_strcmp(tokens + i, json_chunk, "extras") == 0) + { + i = cgltf_parse_json_extras(tokens, i + 1, json_chunk, &out_image->extras); + } else { i = cgltf_skip_json(tokens, i + 1); @@ -2256,6 +2570,7 @@ static int cgltf_parse_json_image(cgltf_options* options, jsmntok_t const* token static int cgltf_parse_json_sampler(cgltf_options* options, jsmntok_t const* tokens, int i, const uint8_t* json_chunk, cgltf_sampler* out_sampler) { + (void)options; CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT); out_sampler->wrap_s = 10497; @@ -2296,6 +2611,10 @@ static int cgltf_parse_json_sampler(cgltf_options* options, jsmntok_t const* tok = cgltf_json_to_int(tokens + i, json_chunk); ++i; } + else if (cgltf_json_strcmp(tokens + i, json_chunk, "extras") == 0) + { + i = cgltf_parse_json_extras(tokens, i + 1, json_chunk, &out_sampler->extras); + } else { i = cgltf_skip_json(tokens, i + 1); @@ -2338,6 +2657,10 @@ static int cgltf_parse_json_texture(cgltf_options* options, jsmntok_t const* tok out_texture->image = CGLTF_PTRINDEX(cgltf_image, cgltf_json_to_int(tokens + i, json_chunk)); ++i; } + else if (cgltf_json_strcmp(tokens + i, json_chunk, "extras") == 0) + { + i = cgltf_parse_json_extras(tokens, i + 1, json_chunk, &out_texture->extras); + } else { i = cgltf_skip_json(tokens, i + 1); @@ -2431,6 +2754,10 @@ static int cgltf_parse_json_material(cgltf_options* options, jsmntok_t const* to cgltf_json_to_bool(tokens + i, json_chunk); ++i; } + else if (cgltf_json_strcmp(tokens + i, json_chunk, "extras") == 0) + { + i = cgltf_parse_json_extras(tokens, i + 1, json_chunk, &out_material->extras); + } else if (cgltf_json_strcmp(tokens + i, json_chunk, "extensions") == 0) { ++i; @@ -2631,6 +2958,10 @@ static int cgltf_parse_json_buffer_view(jsmntok_t const* tokens, int i, const ui out_buffer_view->type = (cgltf_buffer_view_type)type; ++i; } + else if (cgltf_json_strcmp(tokens + i, json_chunk, "extras") == 0) + { + i = cgltf_parse_json_extras(tokens, i + 1, json_chunk, &out_buffer_view->extras); + } else { i = cgltf_skip_json(tokens, i+1); @@ -2686,6 +3017,10 @@ static int cgltf_parse_json_buffer(cgltf_options* options, jsmntok_t const* toke { i = cgltf_parse_json_string(options, tokens, i + 1, json_chunk, &out_buffer->uri); } + else if (cgltf_json_strcmp(tokens + i, json_chunk, "extras") == 0) + { + i = cgltf_parse_json_extras(tokens, i + 1, json_chunk, &out_buffer->extras); + } else { i = cgltf_skip_json(tokens, i+1); @@ -2762,6 +3097,10 @@ static int cgltf_parse_json_skin(cgltf_options* options, jsmntok_t const* tokens out_skin->inverse_bind_matrices = CGLTF_PTRINDEX(cgltf_accessor, cgltf_json_to_int(tokens + i, json_chunk)); ++i; } + else if (cgltf_json_strcmp(tokens + i, json_chunk, "extras") == 0) + { + i = cgltf_parse_json_extras(tokens, i + 1, json_chunk, &out_skin->extras); + } else { i = cgltf_skip_json(tokens, i+1); @@ -2862,6 +3201,10 @@ static int cgltf_parse_json_camera(cgltf_options* options, jsmntok_t const* toke out_camera->perspective.znear = cgltf_json_to_float(tokens + i, json_chunk); ++i; } + else if (cgltf_json_strcmp(tokens + i, json_chunk, "extras") == 0) + { + i = cgltf_parse_json_extras(tokens, i + 1, json_chunk, &out_camera->perspective.extras); + } else { i = cgltf_skip_json(tokens, i+1); @@ -2912,6 +3255,10 @@ static int cgltf_parse_json_camera(cgltf_options* options, jsmntok_t const* toke out_camera->orthographic.znear = cgltf_json_to_float(tokens + i, json_chunk); ++i; } + else if (cgltf_json_strcmp(tokens + i, json_chunk, "extras") == 0) + { + i = cgltf_parse_json_extras(tokens, i + 1, json_chunk, &out_camera->orthographic.extras); + } else { i = cgltf_skip_json(tokens, i+1); @@ -2923,6 +3270,10 @@ static int cgltf_parse_json_camera(cgltf_options* options, jsmntok_t const* toke } } } + else if (cgltf_json_strcmp(tokens + i, json_chunk, "extras") == 0) + { + i = cgltf_parse_json_extras(tokens, i + 1, json_chunk, &out_camera->extras); + } else { i = cgltf_skip_json(tokens, i+1); @@ -3162,6 +3513,10 @@ static int cgltf_parse_json_node(cgltf_options* options, jsmntok_t const* tokens i = cgltf_parse_json_float_array(tokens, i - 1, json_chunk, out_node->weights, (int)out_node->weights_count); } + else if (cgltf_json_strcmp(tokens + i, json_chunk, "extras") == 0) + { + i = cgltf_parse_json_extras(tokens, i + 1, json_chunk, &out_node->extras); + } else if (cgltf_json_strcmp(tokens + i, json_chunk, "extensions") == 0) { ++i; @@ -3279,6 +3634,10 @@ static int cgltf_parse_json_scene(cgltf_options* options, jsmntok_t const* token ++i; } } + else if (cgltf_json_strcmp(tokens + i, json_chunk, "extras") == 0) + { + i = cgltf_parse_json_extras(tokens, i + 1, json_chunk, &out_scene->extras); + } else { i = cgltf_skip_json(tokens, i+1); @@ -3314,6 +3673,7 @@ static int cgltf_parse_json_scenes(cgltf_options* options, jsmntok_t const* toke static int cgltf_parse_json_animation_sampler(cgltf_options* options, jsmntok_t const* tokens, int i, const uint8_t* json_chunk, cgltf_animation_sampler* out_sampler) { + (void)options; CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT); int size = tokens[i].size; @@ -3352,6 +3712,10 @@ static int cgltf_parse_json_animation_sampler(cgltf_options* options, jsmntok_t } ++i; } + else if (cgltf_json_strcmp(tokens + i, json_chunk, "extras") == 0) + { + i = cgltf_parse_json_extras(tokens, i + 1, json_chunk, &out_sampler->extras); + } else { i = cgltf_skip_json(tokens, i+1); @@ -3368,6 +3732,7 @@ static int cgltf_parse_json_animation_sampler(cgltf_options* options, jsmntok_t static int cgltf_parse_json_animation_channel(cgltf_options* options, jsmntok_t const* tokens, int i, const uint8_t* json_chunk, cgltf_animation_channel* out_channel) { + (void)options; CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT); int size = tokens[i].size; @@ -3423,6 +3788,10 @@ static int cgltf_parse_json_animation_channel(cgltf_options* options, jsmntok_t } ++i; } + else if (cgltf_json_strcmp(tokens + i, json_chunk, "extras") == 0) + { + i = cgltf_parse_json_extras(tokens, i + 1, json_chunk, &out_channel->extras); + } else { i = cgltf_skip_json(tokens, i+1); @@ -3497,6 +3866,10 @@ static int cgltf_parse_json_animation(cgltf_options* options, jsmntok_t const* t } } } + else if (cgltf_json_strcmp(tokens + i, json_chunk, "extras") == 0) + { + i = cgltf_parse_json_extras(tokens, i + 1, json_chunk, &out_animation->extras); + } else { i = cgltf_skip_json(tokens, i+1); @@ -3557,6 +3930,10 @@ static int cgltf_parse_json_asset(cgltf_options* options, jsmntok_t const* token { i = cgltf_parse_json_string(options, tokens, i + 1, json_chunk, &out_asset->min_version); } + else if (cgltf_json_strcmp(tokens + i, json_chunk, "extras") == 0) + { + i = cgltf_parse_json_extras(tokens, i + 1, json_chunk, &out_asset->extras); + } else { i = cgltf_skip_json(tokens, i+1); @@ -3571,58 +3948,58 @@ static int cgltf_parse_json_asset(cgltf_options* options, jsmntok_t const* token return i; } -static cgltf_size cgltf_calc_size(cgltf_type type, cgltf_component_type component_type) -{ - cgltf_size size = 0; +static cgltf_size cgltf_num_components(cgltf_type type) { + switch (type) + { + case cgltf_type_vec2: + return 2; + case cgltf_type_vec3: + return 3; + case cgltf_type_vec4: + return 4; + case cgltf_type_mat2: + return 4; + case cgltf_type_mat3: + return 9; + case cgltf_type_mat4: + return 16; + case cgltf_type_invalid: + case cgltf_type_scalar: + default: + return 1; + } +} +static cgltf_size cgltf_component_size(cgltf_component_type component_type) { switch (component_type) { case cgltf_component_type_r_8: case cgltf_component_type_r_8u: - size = 1; - break; + return 1; case cgltf_component_type_r_16: case cgltf_component_type_r_16u: - size = 2; - break; + return 2; case cgltf_component_type_r_32u: case cgltf_component_type_r_32f: - size = 4; - break; + return 4; case cgltf_component_type_invalid: default: - size = 0; - break; + return 0; } +} - switch (type) +static cgltf_size cgltf_calc_size(cgltf_type type, cgltf_component_type component_type) +{ + cgltf_size component_size = cgltf_component_size(component_type); + if (type == cgltf_type_mat2 && component_size == 1) { - case cgltf_type_vec2: - size *= 2; - break; - case cgltf_type_vec3: - size *= 3; - break; - case cgltf_type_vec4: - size *= 4; - break; - case cgltf_type_mat2: - size *= 4; - break; - case cgltf_type_mat3: - size *= 9; - break; - case cgltf_type_mat4: - size *= 16; - break; - case cgltf_type_invalid: - case cgltf_type_scalar: - default: - size *= 1; - break; + return 8 * component_size; } - - return size; + else if (type == cgltf_type_mat3 && (component_size == 1 || component_size == 2)) + { + return 12 * component_size; + } + return component_size * cgltf_num_components(type); } static int cgltf_fixup_pointers(cgltf_data* out_data); @@ -3700,6 +4077,10 @@ static int cgltf_parse_json_root(cgltf_options* options, jsmntok_t const* tokens { i = cgltf_parse_json_animations(options, tokens, i + 1, json_chunk, out_data); } + else if (cgltf_json_strcmp(tokens+i, json_chunk, "extras") == 0) + { + i = cgltf_parse_json_extras(tokens, i + 1, json_chunk, &out_data->extras); + } else if (cgltf_json_strcmp(tokens + i, json_chunk, "extensions") == 0) { ++i; @@ -3743,7 +4124,7 @@ static int cgltf_parse_json_root(cgltf_options* options, jsmntok_t const* tokens } else { - i = cgltf_skip_json(tokens, i+1); + i = cgltf_skip_json(tokens, i + 1); } if (i < 0) @@ -3752,6 +4133,14 @@ static int cgltf_parse_json_root(cgltf_options* options, jsmntok_t const* tokens } } } + else if (cgltf_json_strcmp(tokens + i, json_chunk, "extensionsUsed") == 0) + { + i = cgltf_parse_json_string_array(options, tokens, i + 1, json_chunk, &out_data->extensions_used, &out_data->extensions_used_count); + } + else if (cgltf_json_strcmp(tokens + i, json_chunk, "extensionsRequired") == 0) + { + i = cgltf_parse_json_string_array(options, tokens, i + 1, json_chunk, &out_data->extensions_required, &out_data->extensions_required_count); + } else { i = cgltf_skip_json(tokens, i + 1); @@ -3768,7 +4157,7 @@ static int cgltf_parse_json_root(cgltf_options* options, jsmntok_t const* tokens cgltf_result cgltf_parse_json(cgltf_options* options, const uint8_t* json_chunk, cgltf_size size, cgltf_data** out_data) { - jsmn_parser parser = { 0 }; + jsmn_parser parser = { 0, 0, 0 }; if (options->json_token_count == 0) { @@ -3782,7 +4171,7 @@ cgltf_result cgltf_parse_json(cgltf_options* options, const uint8_t* json_chunk, options->json_token_count = token_count; } - jsmntok_t* tokens = (jsmntok_t*)options->memory_alloc(options->memory_user_data, sizeof(jsmntok_t) * options->json_token_count); + jsmntok_t* tokens = (jsmntok_t*)options->memory_alloc(options->memory_user_data, sizeof(jsmntok_t) * (options->json_token_count + 1)); if (!tokens) { @@ -3799,6 +4188,10 @@ cgltf_result cgltf_parse_json(cgltf_options* options, const uint8_t* json_chunk, return cgltf_result_invalid_json; } + // this makes sure that we always have an UNDEFINED token at the end of the stream + // for invalid JSON inputs this makes sure we don't perform out of bound reads of token data + tokens[token_count].type = JSMN_UNDEFINED; + cgltf_data* data = (cgltf_data*)options->memory_alloc(options->memory_user_data, sizeof(cgltf_data)); if (!data) @@ -3827,6 +4220,9 @@ cgltf_result cgltf_parse_json(cgltf_options* options, const uint8_t* json_chunk, return cgltf_result_invalid_gltf; } + data->json = (const char*)json_chunk; + data->json_size = size; + *out_data = data; return cgltf_result_success; |
