@ -1,7 +1,7 @@
/**
* cgltf - a single - file glTF 2.0 parser written in C99 .
*
* Version : 1.8
* Version : 1.10
*
* Website : https : / / github . com / jkuhlmann / cgltf
*
@ -24,7 +24,7 @@
*
* ` cgltf_options ` is the struct passed to ` cgltf_parse ( ) ` to control
* parts of the parsing process . You can use it to force the file type
* and provide memory allocation as well as file operation callbacks .
* and provide memory allocation as well as file operation callbacks .
* Should be zero - initialized to trigger default behavior .
*
* ` cgltf_data ` is the struct allocated and filled by ` cgltf_parse ( ) ` .
@ -42,8 +42,8 @@
*
* ` 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 fil es.
* base64 - encoded data content . Used internally by ` cgltf_load_buffers ( ) ` .
* This is useful when decoding data URIs in imag es.
*
* ` cgltf_result cgltf_parse_file ( const cgltf_options * options , const
* char * path , cgltf_data * * out_data ) ` can be used to open the given
@ -246,6 +246,7 @@ typedef struct cgltf_extension {
typedef struct cgltf_buffer
{
char * name ;
cgltf_size size ;
char * uri ;
void * data ; /* loaded by cgltf_load_buffers */
@ -281,6 +282,7 @@ typedef struct cgltf_meshopt_compression
typedef struct cgltf_buffer_view
{
char * name ;
cgltf_buffer * buffer ;
cgltf_size offset ;
cgltf_size size ;
@ -315,6 +317,7 @@ typedef struct cgltf_accessor_sparse
typedef struct cgltf_accessor
{
char * name ;
cgltf_component_type component_type ;
cgltf_bool normalized ;
cgltf_type type ;
@ -354,6 +357,7 @@ typedef struct cgltf_image
typedef struct cgltf_sampler
{
char * name ;
cgltf_int mag_filter ;
cgltf_int min_filter ;
cgltf_int wrap_s ;
@ -439,10 +443,19 @@ typedef struct cgltf_ior
typedef struct cgltf_specular
{
cgltf_texture_view specular_texture ;
cgltf_texture_view specular_color_texture ;
cgltf_float specular_color_factor [ 3 ] ;
cgltf_float specular_factor ;
} cgltf_specular ;
typedef struct cgltf_volume
{
cgltf_texture_view thickness_texture ;
cgltf_float thickness_factor ;
cgltf_float attenuation_color [ 3 ] ;
cgltf_float attenuation_distance ;
} cgltf_volume ;
typedef struct cgltf_sheen
{
cgltf_texture_view sheen_color_texture ;
@ -458,6 +471,7 @@ typedef struct cgltf_material
cgltf_bool has_pbr_specular_glossiness ;
cgltf_bool has_clearcoat ;
cgltf_bool has_transmission ;
cgltf_bool has_volume ;
cgltf_bool has_ior ;
cgltf_bool has_specular ;
cgltf_bool has_sheen ;
@ -468,6 +482,7 @@ typedef struct cgltf_material
cgltf_specular specular ;
cgltf_sheen sheen ;
cgltf_transmission transmission ;
cgltf_volume volume ;
cgltf_texture_view normal_texture ;
cgltf_texture_view occlusion_texture ;
cgltf_texture_view emissive_texture ;
@ -481,6 +496,13 @@ typedef struct cgltf_material
cgltf_extension * extensions ;
} cgltf_material ;
typedef struct cgltf_material_mapping
{
cgltf_size variant ;
cgltf_material * material ;
cgltf_extras extras ;
} cgltf_material_mapping ;
typedef struct cgltf_morph_target {
cgltf_attribute * attributes ;
cgltf_size attributes_count ;
@ -503,6 +525,8 @@ typedef struct cgltf_primitive {
cgltf_extras extras ;
cgltf_bool has_draco_mesh_compression ;
cgltf_draco_mesh_compression draco_mesh_compression ;
cgltf_material_mapping * mappings ;
cgltf_size mappings_count ;
cgltf_size extensions_count ;
cgltf_extension * extensions ;
} cgltf_primitive ;
@ -534,8 +558,10 @@ typedef struct cgltf_skin {
} cgltf_skin ;
typedef struct cgltf_camera_perspective {
cgltf_bool has_aspect_ratio ;
cgltf_float aspect_ratio ;
cgltf_float yfov ;
cgltf_bool has_zfar ;
cgltf_float zfar ;
cgltf_float znear ;
cgltf_extras extras ;
@ -633,6 +659,12 @@ typedef struct cgltf_animation {
cgltf_extension * extensions ;
} cgltf_animation ;
typedef struct cgltf_material_variant
{
char * name ;
cgltf_extras extras ;
} cgltf_material_variant ;
typedef struct cgltf_asset {
char * copyright ;
char * generator ;
@ -694,6 +726,9 @@ typedef struct cgltf_data
cgltf_animation * animations ;
cgltf_size animations_count ;
cgltf_material_variant * variants ;
cgltf_size variants_count ;
cgltf_extras extras ;
cgltf_size data_extensions_count ;
@ -776,6 +811,7 @@ cgltf_result cgltf_copy_extras_json(const cgltf_data* data, const cgltf_extras*
# include <string.h> /* For strncpy */
# include <stdio.h> /* For fopen */
# include <limits.h> /* For UINT_MAX etc */
# include <float.h> /* For FLT_MAX */
# if !defined(CGLTF_MALLOC) || !defined(CGLTF_FREE) || !defined(CGLTF_ATOI) || !defined(CGLTF_ATOF)
# include <stdlib.h> /* For malloc, free, atoi, atof */
@ -847,6 +883,9 @@ static const uint32_t GlbMagicBinChunk = 0x004E4942;
# ifndef CGLTF_ATOF
# define CGLTF_ATOF(str) atof(str)
# endif
# ifndef CGLTF_VALIDATE_ENABLE_ASSERTS
# define CGLTF_VALIDATE_ENABLE_ASSERTS 0
# endif
static void * cgltf_default_alloc ( void * user , cgltf_size size )
{
@ -1344,6 +1383,12 @@ static cgltf_size cgltf_calc_index_bound(cgltf_buffer_view* buffer_view, cgltf_s
return bound ;
}
# if CGLTF_VALIDATE_ENABLE_ASSERTS
# define CGLTF_ASSERT_IF(cond, result) assert(!(cond)); if (cond) return result;
# else
# define CGLTF_ASSERT_IF(cond, result) if (cond) return result;
# endif
cgltf_result cgltf_validate ( cgltf_data * data )
{
for ( cgltf_size i = 0 ; i < data - > accessors_count ; + + i )
@ -1356,10 +1401,7 @@ cgltf_result cgltf_validate(cgltf_data* data)
{
cgltf_size req_size = accessor - > offset + accessor - > stride * ( accessor - > count - 1 ) + element_size ;
if ( accessor - > buffer_view - > size < req_size )
{
return cgltf_result_data_too_short ;
}
CGLTF_ASSERT_IF ( accessor - > buffer_view - > size < req_size , cgltf_result_data_too_short ) ;
}
if ( accessor - > is_sparse )
@ -1370,27 +1412,18 @@ cgltf_result cgltf_validate(cgltf_data* data)
cgltf_size indices_req_size = sparse - > indices_byte_offset + indices_component_size * sparse - > count ;
cgltf_size values_req_size = sparse - > values_byte_offset + element_size * sparse - > count ;
if ( sparse - > indices_buffer_view - > size < indices_req_size | |
sparse - > values_buffer_view - > size < values_req_size )
{
return cgltf_result_data_too_short ;
}
CGLTF_ASSERT_IF ( sparse - > indices_buffer_view - > size < indices_req_size | |
sparse - > values_buffer_view - > size < values_req_size , cgltf_result_data_too_short ) ;
if ( sparse - > indices_component_type ! = cgltf_component_type_r_8u & &
sparse - > indices_component_type ! = cgltf_component_type_r_16u & &
sparse - > indices_component_type ! = cgltf_component_type_r_32u )
{
return cgltf_result_invalid_gltf ;
}
CGLTF_ASSERT_IF ( sparse - > indices_component_type ! = cgltf_component_type_r_8u & &
sparse - > indices_component_type ! = cgltf_component_type_r_16u & &
sparse - > indices_component_type ! = cgltf_component_type_r_32u , cgltf_result_invalid_gltf ) ;
if ( sparse - > indices_buffer_view - > buffer - > data )
{
cgltf_size index_bound = cgltf_calc_index_bound ( sparse - > indices_buffer_view , sparse - > indices_byte_offset , sparse - > indices_component_type , sparse - > count ) ;
if ( index_bound > = accessor - > count )
{
return cgltf_result_data_too_short ;
}
CGLTF_ASSERT_IF ( index_bound > = accessor - > count , cgltf_result_data_too_short ) ;
}
}
}
@ -1399,64 +1432,31 @@ cgltf_result cgltf_validate(cgltf_data* data)
{
cgltf_size req_size = data - > buffer_views [ i ] . offset + data - > buffer_views [ i ] . size ;
if ( data - > buffer_views [ i ] . buffer & & data - > buffer_views [ i ] . buffer - > size < req_size )
{
return cgltf_result_data_too_short ;
}
CGLTF_ASSERT_IF ( data - > buffer_views [ i ] . buffer & & data - > buffer_views [ i ] . buffer - > size < req_size , cgltf_result_data_too_short ) ;
if ( data - > buffer_views [ i ] . has_meshopt_compression )
{
cgltf_meshopt_compression * mc = & data - > buffer_views [ i ] . meshopt_compression ;
if ( mc - > buffer = = NULL | | mc - > buffer - > size < mc - > offset + mc - > size )
{
return cgltf_result_data_too_short ;
}
CGLTF_ASSERT_IF ( mc - > buffer = = NULL | | mc - > buffer - > size < mc - > offset + mc - > size , cgltf_result_data_too_short ) ;
if ( data - > buffer_views [ i ] . stride & & mc - > stride ! = data - > buffer_views [ i ] . stride )
{
return cgltf_result_invalid_gltf ;
}
CGLTF_ASSERT_IF ( data - > buffer_views [ i ] . stride & & mc - > stride ! = data - > buffer_views [ i ] . stride , cgltf_result_invalid_gltf ) ;
if ( data - > buffer_views [ i ] . size ! = mc - > stride * mc - > count )
{
return cgltf_result_invalid_gltf ;
}
CGLTF_ASSERT_IF ( data - > buffer_views [ i ] . size ! = mc - > stride * mc - > count , cgltf_result_invalid_gltf ) ;
if ( mc - > mode = = cgltf_meshopt_compression_mode_invalid )
{
return cgltf_result_invalid_gltf ;
}
CGLTF_ASSERT_IF ( mc - > mode = = cgltf_meshopt_compression_mode_invalid , cgltf_result_invalid_gltf ) ;
if ( mc - > mode = = cgltf_meshopt_compression_mode_attributes & & ! ( mc - > stride % 4 = = 0 & & mc - > stride < = 256 ) )
{
return cgltf_result_invalid_gltf ;
}
CGLTF_ASSERT_IF ( mc - > mode = = cgltf_meshopt_compression_mode_attributes & & ! ( mc - > stride % 4 = = 0 & & mc - > stride < = 256 ) , cgltf_result_invalid_gltf ) ;
if ( mc - > mode = = cgltf_meshopt_compression_mode_triangles & & mc - > count % 3 ! = 0 )
{
return cgltf_result_invalid_gltf ;
}
CGLTF_ASSERT_IF ( mc - > mode = = cgltf_meshopt_compression_mode_triangles & & mc - > count % 3 ! = 0 , cgltf_result_invalid_gltf ) ;
if ( ( mc - > mode = = cgltf_meshopt_compression_mode_triangles | | mc - > mode = = cgltf_meshopt_compression_mode_indices ) & & mc - > stride ! = 2 & & mc - > stride ! = 4 )
{
return cgltf_result_invalid_gltf ;
}
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 ) ;
if ( ( mc - > mode = = cgltf_meshopt_compression_mode_triangles | | mc - > mode = = cgltf_meshopt_compression_mode_indices ) & & mc - > filter ! = cgltf_meshopt_compression_filter_none )
{
return cgltf_result_invalid_gltf ;
}
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 ) ;
if ( mc - > filter = = cgltf_meshopt_compression_filter_octahedral & & mc - > stride ! = 4 & & mc - > stride ! = 8 )
{
return cgltf_result_invalid_gltf ;
}
CGLTF_ASSERT_IF ( mc - > filter = = cgltf_meshopt_compression_filter_octahedral & & mc - > stride ! = 4 & & mc - > stride ! = 8 , cgltf_result_invalid_gltf ) ;
if ( mc - > filter = = cgltf_meshopt_compression_filter_quaternion & & mc - > stride ! = 8 )
{
return cgltf_result_invalid_gltf ;
}
CGLTF_ASSERT_IF ( mc - > filter = = cgltf_meshopt_compression_filter_quaternion & & mc - > stride ! = 8 , cgltf_result_invalid_gltf ) ;
}
}
@ -1464,26 +1464,17 @@ cgltf_result cgltf_validate(cgltf_data* data)
{
if ( data - > meshes [ i ] . weights )
{
if ( data - > meshes [ i ] . primitives_count & & data - > meshes [ i ] . primitives [ 0 ] . targets_count ! = data - > meshes [ i ] . weights_count )
{
return cgltf_result_invalid_gltf ;
}
CGLTF_ASSERT_IF ( data - > meshes [ i ] . primitives_count & & data - > meshes [ i ] . primitives [ 0 ] . targets_count ! = data - > meshes [ i ] . weights_count , cgltf_result_invalid_gltf ) ;
}
if ( data - > meshes [ i ] . target_names )
{
if ( data - > meshes [ i ] . primitives_count & & data - > meshes [ i ] . primitives [ 0 ] . targets_count ! = data - > meshes [ i ] . target_names_count )
{
return cgltf_result_invalid_gltf ;
}
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 ) ;
}
for ( cgltf_size j = 0 ; j < data - > meshes [ i ] . primitives_count ; + + j )
{
if ( data - > meshes [ i ] . primitives [ j ] . targets_count ! = data - > meshes [ i ] . primitives [ 0 ] . targets_count )
{
return cgltf_result_invalid_gltf ;
}
CGLTF_ASSERT_IF ( data - > meshes [ i ] . primitives [ j ] . targets_count ! = data - > meshes [ i ] . primitives [ 0 ] . targets_count , cgltf_result_invalid_gltf ) ;
if ( data - > meshes [ i ] . primitives [ j ] . attributes_count )
{
@ -1491,41 +1482,34 @@ cgltf_result cgltf_validate(cgltf_data* data)
for ( cgltf_size k = 0 ; k < data - > meshes [ i ] . primitives [ j ] . attributes_count ; + + k )
{
if ( data - > meshes [ i ] . primitives [ j ] . attributes [ k ] . data - > count ! = first - > count )
{
return cgltf_result_invalid_gltf ;
}
CGLTF_ASSERT_IF ( data - > meshes [ i ] . primitives [ j ] . attributes [ k ] . data - > count ! = first - > count , cgltf_result_invalid_gltf ) ;
}
for ( cgltf_size k = 0 ; k < data - > meshes [ i ] . primitives [ j ] . targets_count ; + + k )
{
for ( cgltf_size m = 0 ; m < data - > meshes [ i ] . primitives [ j ] . targets [ k ] . attributes_count ; + + m )
{
if ( data - > meshes [ i ] . primitives [ j ] . targets [ k ] . attributes [ m ] . data - > count ! = first - > count )
{
return cgltf_result_invalid_gltf ;
}
CGLTF_ASSERT_IF ( data - > meshes [ i ] . primitives [ j ] . targets [ k ] . attributes [ m ] . data - > count ! = first - > count , cgltf_result_invalid_gltf ) ;
}
}
cgltf_accessor * indices = data - > meshes [ i ] . primitives [ j ] . indices ;
k">if ( indices & &
n">CGLTF_ASSERT_IF ( indices & &
indices - > component_type ! = cgltf_component_type_r_8u & &
indices - > component_type ! = cgltf_component_type_r_16u & &
indices - > component_type ! = cgltf_component_type_r_32u )
{
return cgltf_result_invalid_gltf ;
}
indices - > component_type ! = cgltf_component_type_r_32u , cgltf_result_invalid_gltf ) ;
if ( indices & & indices - > buffer_view & & indices - > buffer_view - > buffer - > data )
{
cgltf_size index_bound = cgltf_calc_index_bound ( indices - > buffer_view , indices - > offset , indices - > component_type , indices - > count ) ;
if ( index_bound > = first - > count )
{
return cgltf_result_data_too_short ;
}
CGLTF_ASSERT_IF ( index_bound > = first - > count , cgltf_result_data_too_short ) ;
}
for ( cgltf_size k = 0 ; k < data - > meshes [ i ] . primitives [ j ] . mappings_count ; + + k )
{
CGLTF_ASSERT_IF ( data - > meshes [ i ] . primitives [ j ] . mappings [ k ] . variant > = data - > variants_count , cgltf_result_invalid_gltf ) ;
}
}
}
@ -1535,10 +1519,7 @@ cgltf_result cgltf_validate(cgltf_data* data)
{
if ( data - > nodes [ i ] . weights & & data - > nodes [ i ] . mesh )
{
if ( data - > nodes [ i ] . mesh - > primitives_count & & data - > nodes [ i ] . mesh - > primitives [ 0 ] . targets_count ! = data - > nodes [ i ] . weights_count )
{
return cgltf_result_invalid_gltf ;
}
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 ) ;
}
}
@ -1549,10 +1530,7 @@ cgltf_result cgltf_validate(cgltf_data* data)
while ( p1 & & p2 )
{
if ( p1 = = p2 )
{
return cgltf_result_invalid_gltf ;
}
CGLTF_ASSERT_IF ( p1 = = p2 , cgltf_result_invalid_gltf ) ;
p1 = p1 - > parent ;
p2 = p2 - > parent ? p2 - > parent - > parent : NULL ;
@ -1563,10 +1541,7 @@ cgltf_result cgltf_validate(cgltf_data* data)
{
for ( cgltf_size j = 0 ; j < data - > scenes [ i ] . nodes_count ; + + j )
{
if ( data - > scenes [ i ] . nodes [ j ] - > parent )
{
return cgltf_result_invalid_gltf ;
}
CGLTF_ASSERT_IF ( data - > scenes [ i ] . nodes [ j ] - > parent , cgltf_result_invalid_gltf ) ;
}
}
@ -1585,20 +1560,14 @@ cgltf_result cgltf_validate(cgltf_data* data)
if ( channel - > target_path = = cgltf_animation_path_type_weights )
{
if ( ! channel - > target_node - > mesh | | ! channel - > target_node - > mesh - > primitives_count )
{
return cgltf_result_invalid_gltf ;
}
CGLTF_ASSERT_IF ( ! channel - > target_node - > mesh | | ! channel - > target_node - > mesh - > primitives_count , cgltf_result_invalid_gltf ) ;
components = channel - > target_node - > mesh - > primitives [ 0 ] . targets_count ;
}
cgltf_size values = channel - > sampler - > interpolation = = cgltf_interpolation_type_cubic_spline ? 3 : 1 ;
if ( channel - > sampler - > input - > count * components * values ! = channel - > sampler - > output - > count )
{
return cgltf_result_data_too_short ;
}
CGLTF_ASSERT_IF ( channel - > sampler - > input - > count * components * values ! = channel - > sampler - > output - > count , cgltf_result_data_too_short ) ;
}
}
@ -1661,6 +1630,8 @@ void cgltf_free(cgltf_data* data)
for ( cgltf_size i = 0 ; i < data - > accessors_count ; + + i )
{
data - > memory . free ( data - > memory . user_data , data - > accessors [ i ] . name ) ;
if ( data - > accessors [ i ] . is_sparse )
{
cgltf_free_extensions ( data , data - > accessors [ i ] . sparse . extensions , data - > accessors [ i ] . sparse . extensions_count ) ;
@ -1673,6 +1644,7 @@ void cgltf_free(cgltf_data* data)
for ( cgltf_size i = 0 ; i < data - > buffer_views_count ; + + i )
{
data - > memory . free ( data - > memory . user_data , data - > buffer_views [ i ] . name ) ;
data - > memory . free ( data - > memory . user_data , data - > buffer_views [ i ] . data ) ;
cgltf_free_extensions ( data , data - > buffer_views [ i ] . extensions , data - > buffer_views [ i ] . extensions_count ) ;
@ -1681,6 +1653,8 @@ void cgltf_free(cgltf_data* data)
for ( cgltf_size i = 0 ; i < data - > buffers_count ; + + i )
{
data - > memory . free ( data - > memory . user_data , data - > buffers [ i ] . name ) ;
if ( data - > buffers [ i ] . data ! = data - > bin )
{
file_release ( & data - > memory , & data - > file , data - > buffers [ i ] . data ) ;
@ -1727,6 +1701,8 @@ void cgltf_free(cgltf_data* data)
data - > memory . free ( data - > memory . user_data , data - > meshes [ i ] . primitives [ j ] . draco_mesh_compression . attributes ) ;
}
data - > memory . free ( data - > memory . user_data , data - > meshes [ i ] . primitives [ j ] . mappings ) ;
cgltf_free_extensions ( data , data - > meshes [ i ] . primitives [ j ] . extensions , data - > meshes [ i ] . primitives [ j ] . extensions_count ) ;
}
@ -1768,11 +1744,16 @@ void cgltf_free(cgltf_data* data)
if ( data - > materials [ i ] . has_specular )
{
cgltf_free_extensions ( data , data - > materials [ i ] . specular . specular_texture . extensions , data - > materials [ i ] . specular . specular_texture . extensions_count ) ;
cgltf_free_extensions ( data , data - > materials [ i ] . specular . specular_color_texture . extensions , data - > materials [ i ] . specular . specular_color_texture . extensions_count ) ;
}
if ( data - > materials [ i ] . has_transmission )
{
cgltf_free_extensions ( data , data - > materials [ i ] . transmission . transmission_texture . extensions , data - > materials [ i ] . transmission . transmission_texture . extensions_count ) ;
}
if ( data - > materials [ i ] . has_volume )
{
cgltf_free_extensions ( data , data - > materials [ i ] . volume . thickness_texture . extensions , data - > materials [ i ] . volume . thickness_texture . extensions_count ) ;
}
if ( data - > materials [ i ] . has_sheen )
{
cgltf_free_extensions ( data , data - > materials [ i ] . sheen . sheen_color_texture . extensions , data - > materials [ i ] . sheen . sheen_color_texture . extensions_count ) ;
@ -1809,6 +1790,7 @@ void cgltf_free(cgltf_data* data)
for ( cgltf_size i = 0 ; i < data - > samplers_count ; + + i )
{
data - > memory . free ( data - > memory . user_data , data - > samplers [ i ] . name ) ;
cgltf_free_extensions ( data , data - > samplers [ i ] . extensions , data - > samplers [ i ] . extensions_count ) ;
}
@ -1879,6 +1861,13 @@ void cgltf_free(cgltf_data* data)
data - > memory . free ( data - > memory . user_data , data - > animations ) ;
for ( cgltf_size i = 0 ; i < data - > variants_count ; + + i )
{
data - > memory . free ( data - > memory . user_data , data - > variants [ i ] . name ) ;
}
data - > memory . free ( data - > memory . user_data , data - > variants ) ;
cgltf_free_extensions ( data , data - > data_extensions , data - > data_extensions_count ) ;
for ( cgltf_size i = 0 ; i < data - > extensions_used_count ; + + i )
@ -2608,6 +2597,136 @@ static int cgltf_parse_json_draco_mesh_compression(cgltf_options* options, jsmnt
out_draco_mesh_compression - > buffer_view = CGLTF_PTRINDEX ( cgltf_buffer_view , cgltf_json_to_int ( tokens + i , json_chunk ) ) ;
+ + i ;
}
if ( i < 0 )
{
return i ;
}
}
return i ;
}
static int cgltf_parse_json_material_mapping_data ( cgltf_options * options , jsmntok_t const * tokens , int i , const uint8_t * json_chunk , cgltf_material_mapping * out_mappings , cgltf_size * offset )
{
( void ) options ;
CGLTF_CHECK_TOKTYPE ( tokens [ i ] , JSMN_ARRAY ) ;
int size = tokens [ i ] . size ;
+ + i ;
for ( int j = 0 ; j < size ; + + j )
{
CGLTF_CHECK_TOKTYPE ( tokens [ i ] , JSMN_OBJECT ) ;
int obj_size = tokens [ i ] . size ;
+ + i ;
int material = - 1 ;
int variants_tok = - 1 ;
cgltf_extras extras = { 0 , 0 } ;
for ( int k = 0 ; k < obj_size ; + + k )
{
CGLTF_CHECK_KEY ( tokens [ i ] ) ;
if ( cgltf_json_strcmp ( tokens + i , json_chunk , " material " ) = = 0 )
{
+ + i ;
material = cgltf_json_to_int ( tokens + i , json_chunk ) ;
+ + i ;
}
else if ( cgltf_json_strcmp ( tokens + i , json_chunk , " variants " ) = = 0 )
{
variants_tok = i + 1 ;
CGLTF_CHECK_TOKTYPE ( tokens [ variants_tok ] , JSMN_ARRAY ) ;
i = cgltf_skip_json ( tokens , i + 1 ) ;
}
else if ( cgltf_json_strcmp ( tokens + i , json_chunk , " extras " ) = = 0 )
{
i = cgltf_parse_json_extras ( tokens , i + 1 , json_chunk , & extras ) ;
}
else
{
i = cgltf_skip_json ( tokens , i + 1 ) ;
}
if ( i < 0 )
{
return i ;
}
}
if ( material < 0 | | variants_tok < 0 )
{
return CGLTF_ERROR_JSON ;
}
if ( out_mappings )
{
for ( int k = 0 ; k < tokens [ variants_tok ] . size ; + + k )
{
int variant = cgltf_json_to_int ( & tokens [ variants_tok + 1 + k ] , json_chunk ) ;
if ( variant < 0 )
return variant ;
out_mappings [ * offset ] . material = CGLTF_PTRINDEX ( cgltf_material , material ) ;
out_mappings [ * offset ] . variant = variant ;
out_mappings [ * offset ] . extras = extras ;
( * offset ) + + ;
}
}
else
{
( * offset ) + = tokens [ variants_tok ] . size ;
}
}
return i ;
}
static int cgltf_parse_json_material_mappings ( cgltf_options * options , jsmntok_t const * tokens , int i , const uint8_t * json_chunk , cgltf_primitive * out_prim )
{
CGLTF_CHECK_TOKTYPE ( tokens [ i ] , JSMN_OBJECT ) ;
int size = tokens [ i ] . size ;
+ + i ;
for ( int j = 0 ; j < size ; + + j )
{
CGLTF_CHECK_KEY ( tokens [ i ] ) ;
if ( cgltf_json_strcmp ( tokens + i , json_chunk , " mappings " ) = = 0 )
{
if ( out_prim - > mappings )
{
return CGLTF_ERROR_JSON ;
}
cgltf_size mappings_offset = 0 ;
int k = cgltf_parse_json_material_mapping_data ( options , tokens , i + 1 , json_chunk , NULL , & mappings_offset ) ;
if ( k < 0 )
{
return k ;
}
out_prim - > mappings_count = mappings_offset ;
out_prim - > mappings = ( cgltf_material_mapping * ) cgltf_calloc ( options , sizeof ( cgltf_material_mapping ) , out_prim - > mappings_count ) ;
mappings_offset = 0 ;
i = cgltf_parse_json_material_mapping_data ( options , tokens , i + 1 , json_chunk , out_prim - > mappings , & mappings_offset ) ;
}
else
{
i = cgltf_skip_json ( tokens , i + 1 ) ;
}
if ( i < 0 )
{
return i ;
}
}
return i ;
@ -2700,6 +2819,10 @@ static int cgltf_parse_json_primitive(cgltf_options* options, jsmntok_t const* t
out_prim - > has_draco_mesh_compression = 1 ;
i = cgltf_parse_json_draco_mesh_compression ( options , tokens , i + 1 , json_chunk , & out_prim - > draco_mesh_compression ) ;
}
else if ( cgltf_json_strcmp ( tokens + i , json_chunk , " KHR_materials_variants " ) = = 0 )
{
i = cgltf_parse_json_material_mappings ( options , tokens , i + 1 , json_chunk , out_prim ) ;
}
else
{
i = cgltf_parse_json_unprocessed_extension ( options , tokens , i , json_chunk , & ( out_prim - > extensions [ out_prim - > extensions_count + + ] ) ) ;
@ -2783,7 +2906,7 @@ static int cgltf_parse_json_mesh(cgltf_options* options, jsmntok_t const* tokens
{
CGLTF_CHECK_KEY ( tokens [ i ] ) ;
if ( cgltf_json_strcmp ( tokens + i , json_chunk , " targetNames " ) = = 0 )
if ( cgltf_json_strcmp ( tokens + i , json_chunk , " targetNames " ) = = 0 & & tokens [ i + 1 ] . type = = JSMN_ARRAY )
{
i = cgltf_parse_json_string_array ( options , tokens , i + 1 , json_chunk , & out_mesh - > target_names , & out_mesh - > target_names_count ) ;
}
@ -3005,7 +3128,11 @@ static int cgltf_parse_json_accessor(cgltf_options* options, jsmntok_t const* to
{
CGLTF_CHECK_KEY ( tokens [ i ] ) ;
if ( cgltf_json_strcmp ( tokens + i , json_chunk , " bufferView " ) = = 0 )
if ( cgltf_json_strcmp ( tokens + i , json_chunk , " name " ) = = 0 )
{
i = cgltf_parse_json_string ( options , tokens , i + 1 , json_chunk , & out_accessor - > name ) ;
}
else if ( cgltf_json_strcmp ( tokens + i , json_chunk , " bufferView " ) = = 0 )
{
+ + i ;
out_accessor - > buffer_view = CGLTF_PTRINDEX ( cgltf_buffer_view , cgltf_json_to_int ( tokens + i , json_chunk ) ) ;
@ -3467,6 +3594,10 @@ static int cgltf_parse_json_specular(cgltf_options* options, jsmntok_t const* to
{
i = cgltf_parse_json_texture_view ( options , tokens , i + 1 , json_chunk , & out_specular - > specular_texture ) ;
}
else if ( cgltf_json_strcmp ( tokens + i , json_chunk , " specularColorTexture " ) = = 0 )
{
i = cgltf_parse_json_texture_view ( options , tokens , i + 1 , json_chunk , & out_specular - > specular_color_texture ) ;
}
else
{
i = cgltf_skip_json ( tokens , i + 1 ) ;
@ -3515,6 +3646,50 @@ static int cgltf_parse_json_transmission(cgltf_options* options, jsmntok_t const
return i ;
}
static int cgltf_parse_json_volume ( cgltf_options * options , jsmntok_t const * tokens , int i , const uint8_t * json_chunk , cgltf_volume * out_volume )
{
CGLTF_CHECK_TOKTYPE ( tokens [ i ] , JSMN_OBJECT ) ;
int size = tokens [ i ] . size ;
+ + i ;
for ( int j = 0 ; j < size ; + + j )
{
CGLTF_CHECK_KEY ( tokens [ i ] ) ;
if ( cgltf_json_strcmp ( tokens + i , json_chunk , " thicknessFactor " ) = = 0 )
{
+ + i ;
out_volume - > thickness_factor = cgltf_json_to_float ( tokens + i , json_chunk ) ;
+ + i ;
}
else if ( cgltf_json_strcmp ( tokens + i , json_chunk , " thicknessTexture " ) = = 0 )
{
i = cgltf_parse_json_texture_view ( options , tokens , i + 1 , json_chunk , & out_volume - > thickness_texture ) ;
}
else if ( cgltf_json_strcmp ( tokens + i , json_chunk , " attenuationColor " ) = = 0 )
{
i = cgltf_parse_json_float_array ( tokens , i + 1 , json_chunk , out_volume - > attenuation_color , 3 ) ;
}
else if ( cgltf_json_strcmp ( tokens + i , json_chunk , " attenuationDistance " ) = = 0 )
{
+ + i ;
out_volume - > attenuation_distance = cgltf_json_to_float ( tokens + i , json_chunk ) ;
+ + i ;
}
else
{
i = cgltf_skip_json ( tokens , i + 1 ) ;
}
if ( i < 0 )
{
return i ;
}
}
return i ;
}
static int cgltf_parse_json_sheen ( cgltf_options * options , jsmntok_t const * tokens , int i , const uint8_t * json_chunk , cgltf_sheen * out_sheen )
{
CGLTF_CHECK_TOKTYPE ( tokens [ i ] , JSMN_OBJECT ) ;
@ -3623,7 +3798,11 @@ static int cgltf_parse_json_sampler(cgltf_options* options, jsmntok_t const* tok
{
CGLTF_CHECK_KEY ( tokens [ i ] ) ;
if ( cgltf_json_strcmp ( tokens + i , json_chunk , " magFilter " ) = = 0 )
if ( cgltf_json_strcmp ( tokens + i , json_chunk , " name " ) = = 0 )
{
i = cgltf_parse_json_string ( options , tokens , i + 1 , json_chunk , & out_sampler - > name ) ;
}
else if ( cgltf_json_strcmp ( tokens + i , json_chunk , " magFilter " ) = = 0 )
{
+ + i ;
out_sampler - > mag_filter
@ -3734,6 +3913,9 @@ static int cgltf_parse_json_material(cgltf_options* options, jsmntok_t const* to
cgltf_fill_float_array ( out_material - > pbr_specular_glossiness . specular_factor , 3 , 1.0f ) ;
out_material - > pbr_specular_glossiness . glossiness_factor = 1.0f ;
cgltf_fill_float_array ( out_material - > volume . attenuation_color , 3 , 1.0f ) ;
out_material - > volume . attenuation_distance = FLT_MAX ;
out_material - > alpha_cutoff = 0.5f ;
int size = tokens [ i ] . size ;
@ -3859,6 +4041,11 @@ static int cgltf_parse_json_material(cgltf_options* options, jsmntok_t const* to
out_material - > has_transmission = 1 ;
i = cgltf_parse_json_transmission ( options , tokens , i + 1 , json_chunk , & out_material - > transmission ) ;
}
else if ( cgltf_json_strcmp ( tokens + i , json_chunk , " KHR_materials_volume " ) = = 0 )
{
out_material - > has_volume = 1 ;
i = cgltf_parse_json_volume ( options , tokens , i + 1 , json_chunk , & out_material - > volume ) ;
}
else if ( cgltf_json_strcmp ( tokens + i , json_chunk , " KHR_materials_sheen " ) = = 0 )
{
out_material - > has_sheen = 1 ;
@ -4089,7 +4276,11 @@ static int cgltf_parse_json_buffer_view(cgltf_options* options, jsmntok_t const*
{
CGLTF_CHECK_KEY ( tokens [ i ] ) ;
if ( cgltf_json_strcmp ( tokens + i , json_chunk , " buffer " ) = = 0 )
if ( cgltf_json_strcmp ( tokens + i , json_chunk , " name " ) = = 0 )
{
i = cgltf_parse_json_string ( options , tokens , i + 1 , json_chunk , & out_buffer_view - > name ) ;
}
else if ( cgltf_json_strcmp ( tokens + i , json_chunk , " buffer " ) = = 0 )
{
+ + i ;
out_buffer_view - > buffer = CGLTF_PTRINDEX ( cgltf_buffer , cgltf_json_to_int ( tokens + i , json_chunk ) ) ;
@ -4223,7 +4414,11 @@ static int cgltf_parse_json_buffer(cgltf_options* options, jsmntok_t const* toke
{
CGLTF_CHECK_KEY ( tokens [ i ] ) ;
if ( cgltf_json_strcmp ( tokens + i , json_chunk , " byteLength " ) = = 0 )
if ( cgltf_json_strcmp ( tokens + i , json_chunk , " name " ) = = 0 )
{
i = cgltf_parse_json_string ( options , tokens , i + 1 , json_chunk , & out_buffer - > name ) ;
}
else if ( cgltf_json_strcmp ( tokens + i , json_chunk , " byteLength " ) = = 0 )
{
+ + i ;
out_buffer - > size =
@ -4405,6 +4600,7 @@ static int cgltf_parse_json_camera(cgltf_options* options, jsmntok_t const* toke
if ( cgltf_json_strcmp ( tokens + i , json_chunk , " aspectRatio " ) = = 0 )
{
+ + i ;
out_camera - > data . perspective . has_aspect_ratio = 1 ;
out_camera - > data . perspective . aspect_ratio = cgltf_json_to_float ( tokens + i , json_chunk ) ;
+ + i ;
}
@ -4417,6 +4613,7 @@ static int cgltf_parse_json_camera(cgltf_options* options, jsmntok_t const* toke
else if ( cgltf_json_strcmp ( tokens + i , json_chunk , " zfar " ) = = 0 )
{
+ + i ;
out_camera - > data . perspective . has_zfar = 1 ;
out_camera - > data . perspective . zfar = cgltf_json_to_float ( tokens + i , json_chunk ) ;
+ + i ;
}
@ -5160,6 +5357,58 @@ static int cgltf_parse_json_animations(cgltf_options* options, jsmntok_t const*
return i ;
}
static int cgltf_parse_json_variant ( cgltf_options * options , jsmntok_t const * tokens , int i , const uint8_t * json_chunk , cgltf_material_variant * out_variant )
{
CGLTF_CHECK_TOKTYPE ( tokens [ i ] , JSMN_OBJECT ) ;
int size = tokens [ i ] . size ;
+ + i ;
for ( int j = 0 ; j < size ; + + j )
{
CGLTF_CHECK_KEY ( tokens [ i ] ) ;
if ( cgltf_json_strcmp ( tokens + i , json_chunk , " name " ) = = 0 )
{
i = cgltf_parse_json_string ( options , tokens , i + 1 , json_chunk , & out_variant - > name ) ;
}
else if ( cgltf_json_strcmp ( tokens + i , json_chunk , " extras " ) = = 0 )
{
i = cgltf_parse_json_extras ( tokens , i + 1 , json_chunk , & out_variant - > extras ) ;
}
else
{
i = cgltf_skip_json ( tokens , i + 1 ) ;
}
if ( i < 0 )
{
return i ;
}
}
return i ;
}
static int cgltf_parse_json_variants ( cgltf_options * options , jsmntok_t const * tokens , int i , const uint8_t * json_chunk , cgltf_data * out_data )
{
i = cgltf_parse_json_array ( options , tokens , i , json_chunk , sizeof ( cgltf_material_variant ) , ( void * * ) & out_data - > variants , & out_data - > variants_count ) ;
if ( i < 0 )
{
return i ;
}
for ( cgltf_size j = 0 ; j < out_data - > variants_count ; + + j )
{
i = cgltf_parse_json_variant ( options , tokens , i , json_chunk , & out_data - > variants [ j ] ) ;
if ( i < 0 )
{
return i ;
}
}
return i ;
}
static int cgltf_parse_json_asset ( cgltf_options * options , jsmntok_t const * tokens , int i , const uint8_t * json_chunk , cgltf_asset * out_asset )
{
CGLTF_CHECK_TOKTYPE ( tokens [ i ] , JSMN_OBJECT ) ;
@ -5400,6 +5649,34 @@ static int cgltf_parse_json_root(cgltf_options* options, jsmntok_t const* tokens
}
}
}
else if ( cgltf_json_strcmp ( tokens + i , json_chunk , " KHR_materials_variants " ) = = 0 )
{
+ + i ;
CGLTF_CHECK_TOKTYPE ( tokens [ i ] , JSMN_OBJECT ) ;
int data_size = tokens [ i ] . size ;
+ + i ;
for ( int m = 0 ; m < data_size ; + + m )
{
CGLTF_CHECK_KEY ( tokens [ i ] ) ;
if ( cgltf_json_strcmp ( tokens + i , json_chunk , " variants " ) = = 0 )
{
i = cgltf_parse_json_variants ( options , tokens , i + 1 , json_chunk , out_data ) ;
}
else
{
i = cgltf_skip_json ( tokens , i + 1 ) ;
}
if ( i < 0 )
{
return i ;
}
}
}
else
{
i = cgltf_parse_json_unprocessed_extension ( options , tokens , i , json_chunk , & ( out_data - > data_extensions [ out_data - > data_extensions_count + + ] ) ) ;
@ -5542,6 +5819,11 @@ static int cgltf_fixup_pointers(cgltf_data* data)
CGLTF_PTRFIXUP_REQ ( data - > meshes [ i ] . primitives [ j ] . draco_mesh_compression . attributes [ m ] . data , data - > accessors , data - > accessors_count ) ;
}
}
for ( cgltf_size k = 0 ; k < data - > meshes [ i ] . primitives [ j ] . mappings_count ; + + k )
{
CGLTF_PTRFIXUP_REQ ( data - > meshes [ i ] . primitives [ j ] . mappings [ k ] . material , data - > materials , data - > materials_count ) ;
}
}
}
@ -5594,9 +5876,12 @@ static int cgltf_fixup_pointers(cgltf_data* data)
CGLTF_PTRFIXUP ( data - > materials [ i ] . clearcoat . clearcoat_normal_texture . texture , data - > textures , data - > textures_count ) ;
CGLTF_PTRFIXUP ( data - > materials [ i ] . specular . specular_texture . texture , data - > textures , data - > textures_count ) ;
CGLTF_PTRFIXUP ( data - > materials [ i ] . specular . specular_color_texture . texture , data - > textures , data - > textures_count ) ;
CGLTF_PTRFIXUP ( data - > materials [ i ] . transmission . transmission_texture . texture , data - > textures , data - > textures_count ) ;
CGLTF_PTRFIXUP ( data - > materials [ i ] . volume . thickness_texture . texture , data - > textures , data - > textures_count ) ;
CGLTF_PTRFIXUP ( data - > materials [ i ] . sheen . sheen_color_texture . texture , data - > textures , data - > textures_count ) ;
CGLTF_PTRFIXUP ( data - > materials [ i ] . sheen . sheen_roughness_texture . texture , data - > textures , data - > textures_count ) ;
}