doom3-bfg/neo/idlib/gltfParser.cpp

2428 lines
69 KiB
C++
Raw Normal View History

2022-06-18 09:09:09 +00:00
/*
===========================================================================
Doom 3 BFG Edition GPL Source Code
Copyright (C) 2022 Harrie van Ginneken
This file is part of the Doom 3 BFG Edition GPL Source Code ("Doom 3 BFG Edition Source Code").
Doom 3 BFG Edition Source Code is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Doom 3 BFG Edition Source Code is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Doom 3 BFG Edition Source Code. If not, see <http://www.gnu.org/licenses/>.
In addition, the Doom 3 BFG Edition Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 BFG Edition Source Code. If not, please request a copy in writing from id Software at the address below.
If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
===========================================================================
*/
#include "precompiled.h"
#pragma hdrstop
/// <TODO>
/// Clean up registerd gltfItem_Extra's
/// Clean up loaded gltfData;
/// </TODO>
static const unsigned int gltfChunk_Type_JSON = 0x4E4F534A; //1313821514
static const unsigned int gltfChunk_Type_BIN = 0x004E4942; //5130562
idCVar gltf_parseVerbose( "gltf_parseVerbose", "0", CVAR_RENDERER | CVAR_ARCHIVE | CVAR_BOOL, "print gltf json data while parsing" );
idCVar gltfParser_PrefixNodeWithID( "gltfParser_PrefixNodeWithID", "0", CVAR_SYSTEM | CVAR_BOOL, "The node's id is prefixed to the node's name during load" );
//
//gltf_sampler_wrap_type_map s_samplerWrapTypeMap[] = {
// //33071 CLAMP_TO_EDGE
// 33071, BGFX_SAMPLER_U_CLAMP, BGFX_SAMPLER_V_CLAMP,
// //33648 MIRRORED_REPEAT
// 33648, BGFX_SAMPLER_U_MIRROR, BGFX_SAMPLER_V_MIRROR,
// //10497 REPEAT
// 10497, BGFX_SAMPLER_NONE , BGFX_SAMPLER_NONE ,
// 0,0,0
//};
////todo
//gltf_sampler_mag_type_map s_samplerMagTypeMap[] = {
// //9728 NEAREST //mag/min
// 9728 , BGFX_SAMPLER_MIN_ANISOTROPIC
// //9729 LINEAR // mag/min
// //
// //9984 NEAREST_MIPMAP_NEAREST //min
// //
// //9985 LINEAR_MIPMAP_NEAREST //min
// //
// //9986 NEAREST_MIPMAP_LINEAR //min
// //
// //9987 LINEAR_MIPMAP_LINEAR //min
//};
//uint64_t GetSamplerFlags( gltfSampler * sampler) {
// // Ignore the sampling options for filter -- always use mag: LINEAR and min: LINEAR_MIPMAP_LINEAR
// uint64_t flags ;//= BGFX_TEXTURE_NONE | BGFX_SAMPLER_MIN_ANISOTROPIC ;
// int i = -1;
// while ( s_samplerWrapTypeMap[++i].id != 0 )
// {
// if ( s_samplerWrapTypeMap[i].id == sampler->wrapS)
// flags |= s_samplerWrapTypeMap[i].bgfxFlagU;
// if ( s_samplerWrapTypeMap[i].id == sampler->wrapT )
// flags |= s_samplerWrapTypeMap[i].bgfxFlagV;
// }
// return flags;
//}
gltf_mesh_attribute_map s_meshAttributeMap[] =
{
"POSITION", gltfMesh_Primitive_Attribute::Type::Position, 3,
"NORMAL", gltfMesh_Primitive_Attribute::Type::Normal, 3,
"TANGENT", gltfMesh_Primitive_Attribute::Type::Tangent, 3,
"TEXCOORD_0", gltfMesh_Primitive_Attribute::Type::TexCoord0, 2,
"TEXCOORD_1", gltfMesh_Primitive_Attribute::Type::TexCoord1, 2,
"TEXCOORD_2", gltfMesh_Primitive_Attribute::Type::TexCoord2, 2,
"TEXCOORD_3", gltfMesh_Primitive_Attribute::Type::TexCoord3, 2,
"TEXCOORD_4", gltfMesh_Primitive_Attribute::Type::TexCoord4, 2,
"TEXCOORD_5", gltfMesh_Primitive_Attribute::Type::TexCoord5, 2,
"TEXCOORD_6", gltfMesh_Primitive_Attribute::Type::TexCoord6, 2,
"TEXCOORD_7", gltfMesh_Primitive_Attribute::Type::TexCoord7, 2,
"COLOR_0", gltfMesh_Primitive_Attribute::Type::Color0, 4,
"COLOR_1", gltfMesh_Primitive_Attribute::Type::Color1, 4,
"COLOR_2", gltfMesh_Primitive_Attribute::Type::Color2, 4,
"COLOR_3", gltfMesh_Primitive_Attribute::Type::Color3, 4,
"WEIGHTS_0", gltfMesh_Primitive_Attribute::Type::Weight, 4,
"JOINTS_0", gltfMesh_Primitive_Attribute::Type::Joints, 4,
"", gltfMesh_Primitive_Attribute::Type::Count
};
gltfMesh_Primitive_Attribute::Type GetAttributeEnum( const char* str , uint* elementSize = nullptr )
{
int i = -1;
while( s_meshAttributeMap[++i].attib != gltfMesh_Primitive_Attribute::Type::Count )
if( !idStr::Icmp( s_meshAttributeMap[i].stringID, str ) )
{
if( elementSize != nullptr )
{
*elementSize = s_meshAttributeMap[i].elementSize;
}
return s_meshAttributeMap[i].attib;
}
return gltfMesh_Primitive_Attribute::Type::Count;
}
//https://github.com/KhronosGroup/glTF/issues/832
//gltf_accessor_component_type_map<bgfx::AttribType::Enum> s_bgfxComponentTypeMap[] = {
// "signed byte", 5120, bgfx::AttribType::Count, 1 ,
// "unsigned byte", 5121, bgfx::AttribType::Uint8, 1 ,
// "signed short", 5122, bgfx::AttribType::Int16, 2 ,
// "unsigned short", 5123, bgfx::AttribType::Count, 2 ,
// "unsigned int", 5125, bgfx::AttribType::Count, 4 ,
// "float", 5126, bgfx::AttribType::Float, 4 ,
// "double", 5130, bgfx::AttribType::Float, 8 ,
// "", 0, bgfx::AttribType::Count, 0
//};
//
gltf_accessor_component_type_map<gltf_accessor_component::Type> s_nativeComponentTypeMap[] =
{
"signed byte", 5120, gltf_accessor_component::Type::_byte, 1 ,
"unsigned byte", 5121, gltf_accessor_component::Type::_uByte, 1 ,
"signed short", 5122, gltf_accessor_component::Type::_short, 2 ,
"unsigned short", 5123, gltf_accessor_component::Type::_uShort, 2 ,
"unsigned int", 5125, gltf_accessor_component::Type::_uInt, 4 ,
"float", 5126, gltf_accessor_component::Type::_float, 4 ,
"double", 5130, gltf_accessor_component::Type::_double, 8 ,
"", 0, gltf_accessor_component::Type::Count, 0
};
//
gltf_accessor_component::Type GetComponentTypeEnum( int id , uint* sizeInBytes = nullptr )
{
int i = -1;
while( s_nativeComponentTypeMap[++i].id != 0 )
if( s_nativeComponentTypeMap[i].id == id )
{
if( sizeInBytes != nullptr )
{
*sizeInBytes = s_nativeComponentTypeMap[i].sizeInBytes;
}
return s_nativeComponentTypeMap[i].type;
}
return gltf_accessor_component::Type::Count;
}
//some arbitrary amount for now.
#define GLTF_MAX_CHUNKS 32
idList<gltfData*> gltfData::dataList;
idHashIndex gltfData::fileDataHash;
//Helper macros for gltf data deserialize
//NOTE: gltfItems that deviate from the default SET(T*) function cannot be handled with itemref macro.
// target must be an gltfArrayItem.
// type with name will be added to the array.
#define GLTFARRAYITEM(target,name,type) auto * name = new type (#name); target.AddItemDef((parsable*)name)
// name must point to an existing valid entry
// name->Set (&target->name);
#define GLTFARRAYITEMREF(target,name) name->Set(&target->name)
2022-06-18 08:43:30 +00:00
void gltfPropertyArray::Iterator::operator ++()
{
//check if by modification, we are iterating again.
//custom not AOS things can do this since it is not nicely guarded by braces
if( array->dirty && ( !array->iterating && !array->isArrayOfStructs ) )
{
array->iterating = array->parser->PeekTokenString( "," );
if( array->iterating )
{
2022-06-18 08:43:30 +00:00
array->properties.AssureSizeAlloc( array->properties.Num() + 1, idListNewElement<gltfPropertyItem> );
array->parser->ExpectTokenString( "," );
}
}
if( array->iterating )
{
2022-06-18 08:43:30 +00:00
p = array->properties[array->properties.Num() - 1];
p->array = array;
if( array->isArrayOfStructs )
{
array->parser->ParseBracedSection( p->item );
}
else
{
idToken token;
array->parser->ExpectAnyToken( &token );
p->item = token;
}
array->iterating = array->parser->PeekTokenString( "," );
if( array->iterating )
{
2022-06-18 08:43:30 +00:00
array->properties.AssureSizeAlloc( array->properties.Num() + 1, idListNewElement<gltfPropertyItem> );
array->parser->ExpectTokenString( "," );
}
}
else
{
if( array->dirty )
{
p = array->endPtr;
array->dirty = false;
}
else if( array->index + 1 < array->properties.Num() )
{
p = array->properties[++array->index];
}
else
{
p = array->endPtr;
}
}
}
2022-06-18 09:09:09 +00:00
gltfPropertyArray::~gltfPropertyArray()
{
delete endPtr;
properties.DeleteContents( true );
}
2022-06-18 09:09:09 +00:00
gltfPropertyArray::gltfPropertyArray( idLexer* Parser, bool AoS/* = true */ )
: parser( Parser ), iterating( true ), dirty( true ), index( 0 ), isArrayOfStructs( AoS )
{
properties.AssureSizeAlloc( 32, idListNewElement<gltfPropertyItem> );
properties.SetNum( 0 );
endPtr = new gltfPropertyItem();
endPtr->array = this;
}
2022-06-18 08:43:30 +00:00
gltfPropertyArray::Iterator gltfPropertyArray::begin()
{
if( iterating )
{
if( isArrayOfStructs && !parser->PeekTokenString( "{" ) )
{
if( !parser->ExpectTokenString( "[" ) && parser->PeekTokenString( "{" ) )
{
common->FatalError( "Malformed gltf array" );
}
}
else if( !isArrayOfStructs && !parser->ExpectTokenString( "[" ) )
{
common->FatalError( "Malformed gltf array" );
}
properties.AssureSizeAlloc( properties.Num() + 1, idListNewElement<gltfPropertyItem> );
gltfPropertyItem* start = properties[0];
start->array = this;
if( isArrayOfStructs )
{
parser->ParseBracedSection( start->item );
}
else
{
idToken token;
parser->ExpectAnyToken( &token );
start->item = token;
}
iterating = parser->PeekTokenString( "," );
if( iterating )
{
properties.AssureSizeAlloc( properties.Num() + 1, idListNewElement<gltfPropertyItem> );
parser->ExpectTokenString( "," );
}
return Iterator{ this , start };
}
index = 0;
return Iterator{ this , properties[index]};
}
2022-06-18 09:09:09 +00:00
2022-06-18 08:43:30 +00:00
gltfPropertyArray::Iterator gltfPropertyArray::end()
{
return Iterator{ this , endPtr};
}
2022-06-18 09:09:09 +00:00
gltfItemArray::~gltfItemArray()
{
items.DeleteContents( true );
}
int gltfItemArray::Fill( idLexer* lexer, idDict* strPairs )
{
idToken token;
bool parsing = true;
int parseCount = 0;
lexer->ReadToken( &token );
while( parsing && !lexer->PeekTokenString( "}" ) && lexer->ExpectAnyToken( &token ) )
{
lexer->ExpectTokenString( ":" );
idStr key = token;
idStr value;
2022-06-18 08:43:30 +00:00
key.StripTrailingWhitespace();
if( lexer->PeekTokenString( "[" ) )
{
lexer->ParseBracketSectionExact( value );
value.StripTrailingWhitespace();
strPairs->Set( key, value );
}
else if( lexer->PeekTokenString( "{" ) )
{
lexer->ParseBracedSectionExact( value );
2022-06-18 08:43:30 +00:00
value.StripTrailingWhitespace();
strPairs->Set( key, value );
}
else
{
lexer->ExpectAnyToken( &token );
value = token;
2022-06-18 08:43:30 +00:00
value.StripTrailingWhitespace();
key.StripTrailingWhitespace();
strPairs->Set( key, token );
}
parseCount++;
parsing = lexer->PeekTokenString( "," );
if( parsing )
{
lexer->ExpectTokenString( "," );
}
}
lexer->ExpectTokenString( "}" );
return parseCount;
}
2022-06-18 09:09:09 +00:00
int gltfItemArray::Parse( idLexer* lexer, bool forwardLexer/* = false*/ )
{
idToken token;
bool parsing = true;
int parseCount = 0;
lexer->ExpectTokenString( "{" );
while( parsing && !lexer->PeekTokenString( "}" ) && lexer->ExpectAnyToken( &token ) )
{
lexer->ExpectTokenString( ":" );
bool parsed = false;
for( auto item : items )
{
2022-06-18 08:43:30 +00:00
if( item->Name() == token )
{
lexer->ExpectAnyToken( &token );
if( forwardLexer )
{
item->parse( token , lexer );
}
else
{
item->parse( token );
}
parsed = true;
break;
}
}
if( !parsed )
{
lexer->SkipBracedSection( true, lexer->PeekTokenString( "{" ) ? BRSKIP_BRACES : BRSKIP_BRACKET );
}
else
{
parseCount++;
}
parsing = lexer->PeekTokenString( "," );
if( parsing )
{
lexer->ExpectTokenString( "," );
}
}
lexer->ExpectTokenString( "}" );
return parseCount;
}
byte* gltfData::AddData( int size, int* bufferID/*=nullptr*/ )
{
if( totalChunks == -1 )
{
json = ( byte* ) Mem_ClearedAlloc( size, TAG_IDLIB_GLTF );
totalChunks++;
jsonDataLength = size;
return json;
}
int id = totalChunks;
if( data == nullptr )
{
data = ( byte** ) Mem_ClearedAlloc( GLTF_MAX_CHUNKS * sizeof( byte* ), TAG_IDLIB_GLTF );
}
data[totalChunks++] = ( byte* ) Mem_ClearedAlloc( size, TAG_IDLIB_GLTF );
if( bufferID )
{
*bufferID = id;
}
return data[id];
}
2022-06-18 08:43:30 +00:00
bool gltfItem_uri::Convert()
{
//HVG_TODO
// uri cache.
//read data
2022-06-18 08:43:30 +00:00
int length = fileSystem->ReadFile( item->c_str(), NULL );
idFile* file = fileSystem->OpenFileRead( item->c_str() );
//create buffer
2022-06-18 08:43:30 +00:00
gltfBuffer* buffer = data->Buffer();
buffer->parent = data;
2022-06-18 08:43:30 +00:00
buffer->name = item->c_str();
buffer->byteLength = length;
int bufferID = -1;
byte* dest = data->AddData( length, &bufferID );
if( file->Read( dest, length ) != length )
{
common->FatalError( "Could not read %s", item->c_str() );
}
if( gltf_parseVerbose.GetBool() )
{
common->Warning( "gltf Uri %s loaded into buffer[ %i ]", buffer->name.c_str(), bufferID );
}
//create bufferview
//if bufferview is not set, this is an buffer.uri.
//A bufferview should aready be defined if the buffer is used.
if( bufferView != nullptr )
{
*bufferView = data->BufferViewList().Num();
2022-06-18 08:43:30 +00:00
gltfBufferView* newBufferView = data->BufferView();
newBufferView->buffer = bufferID;
newBufferView->byteLength = length;
newBufferView->parent = data;
}
fileSystem->CloseFile( file );
return false;
}
void gltfItem_Extra::parse( idToken& token )
{
parser->UnreadToken( &token );
parser->ParseBracedSectionExact( item->json );
gltfItemArray items;
idLexer lexer( LEXFL_ALLOWPATHNAMES | LEXFL_ALLOWMULTICHARLITERALS | LEXFL_NOSTRINGESCAPECHARS );
2022-06-18 08:43:30 +00:00
lexer.LoadMemory( item->json, item->json.Size(), "gltfItem_Extra", 0 );
items.Fill( &lexer, &item->strPairs );
lexer.Reset();
2022-06-18 08:43:30 +00:00
if( gltf_parseVerbose.GetBool() )
{
2022-06-18 08:43:30 +00:00
common->Printf( "%s", item->json.c_str() );
}
}
void gltfItem_animation_sampler::parse( idToken& token )
{
gltfItemArray animSampler;
GLTFARRAYITEM( animSampler, input, gltfItem_integer );
GLTFARRAYITEM( animSampler, interpolation, gltfItem );
GLTFARRAYITEM( animSampler, output, gltfItem_integer );
GLTFARRAYITEM( animSampler, extensions, gltfItem );
GLTFARRAYITEM( animSampler, extras, gltfItem_Extra );
gltfPropertyArray array = gltfPropertyArray( parser );
for( auto& prop : array )
{
idLexer lexer( LEXFL_ALLOWPATHNAMES | LEXFL_ALLOWMULTICHARLITERALS | LEXFL_NOSTRINGESCAPECHARS );
2022-06-18 08:43:30 +00:00
lexer.LoadMemory( prop.item.c_str(), prop.item.Size(), "gltfAnimation_Sampler", 0 );
2022-06-18 08:43:30 +00:00
item->AssureSizeAlloc( item->Num() + 1, idListNewElement<gltfAnimation_Sampler> );
gltfAnimation_Sampler* gltfAnimSampler = ( *item )[item->Num() - 1];
GLTFARRAYITEMREF( gltfAnimSampler, input );
GLTFARRAYITEMREF( gltfAnimSampler, interpolation );
GLTFARRAYITEMREF( gltfAnimSampler, output );
GLTFARRAYITEMREF( gltfAnimSampler, extensions );
extras->Set( &gltfAnimSampler->extras, &lexer );
animSampler.Parse( &lexer );
2022-06-18 08:43:30 +00:00
if( gltf_parseVerbose.GetBool() )
{
2022-06-18 08:43:30 +00:00
common->Printf( "%s", prop.item.c_str() );
}
gltfAnimSampler->intType = gltfAnimation_Sampler::resolveType( gltfAnimSampler->interpolation );
}
parser->ExpectTokenString( "]" );
}
void gltfItem_animation_channel_target::parse( idToken& token )
{
parser->UnreadToken( &token );
gltfItemArray animChannelTarget;
GLTFARRAYITEM( animChannelTarget, node, gltfItem_integer );
GLTFARRAYITEM( animChannelTarget, path, gltfItem );
GLTFARRAYITEM( animChannelTarget, extensions, gltfItem );
GLTFARRAYITEM( animChannelTarget, extras, gltfItem_Extra );
GLTFARRAYITEMREF( item, node );
GLTFARRAYITEMREF( item, path );
GLTFARRAYITEMREF( item, extensions );
extras->Set( &item->extras, parser );
animChannelTarget.Parse( parser );
2022-06-18 08:43:30 +00:00
if( gltf_parseVerbose.GetBool() )
{
2022-06-18 08:43:30 +00:00
common->Printf( "%s", token.c_str() );
}
item->TRS = gltfAnimation_Channel_Target::resolveType( item->path );
}
void gltfItem_animation_channel::parse( idToken& token )
{
//parser->UnreadToken( &token );
gltfItemArray anim;
GLTFARRAYITEM( anim, sampler, gltfItem_integer );
GLTFARRAYITEM( anim, target, gltfItem_animation_channel_target );
GLTFARRAYITEM( anim, extensions, gltfItem );
GLTFARRAYITEM( anim, extras, gltfItem_Extra );
gltfPropertyArray array = gltfPropertyArray( parser );
for( auto& prop : array )
{
idLexer lexer( LEXFL_ALLOWPATHNAMES | LEXFL_ALLOWMULTICHARLITERALS | LEXFL_NOSTRINGESCAPECHARS );
2022-06-18 08:43:30 +00:00
lexer.LoadMemory( prop.item.c_str(), prop.item.Size(), "gltfAnimation_Channel", 0 );
2022-06-18 08:43:30 +00:00
item->AssureSizeAlloc( item->Num() + 1, idListNewElement<gltfAnimation_Channel> );
gltfAnimation_Channel* gltfAnimationChannel = ( *item )[item->Num() - 1];
GLTFARRAYITEMREF( gltfAnimationChannel, sampler );
target->Set( &gltfAnimationChannel->target, &lexer );
GLTFARRAYITEMREF( gltfAnimationChannel, extensions );
extras->Set( &gltfAnimationChannel->extras, &lexer );
anim.Parse( &lexer );
2022-06-18 08:43:30 +00:00
if( gltf_parseVerbose.GetBool() )
{
2022-06-18 08:43:30 +00:00
common->Printf( "%s", token.c_str() );
}
}
parser->ExpectTokenString( "]" );
}
void gltfItem_mesh_primitive::parse( idToken& token )
{
gltfItemArray prim;
GLTFARRAYITEM( prim, attributes, gltfItem_mesh_primitive_attribute );
GLTFARRAYITEM( prim, indices, gltfItem_integer );
GLTFARRAYITEM( prim, material, gltfItem_integer );
GLTFARRAYITEM( prim, mode, gltfItem_integer );
GLTFARRAYITEM( prim, target, gltfItem );
GLTFARRAYITEM( prim, extensions, gltfItem );
GLTFARRAYITEM( prim, extras, gltfItem_Extra );
gltfPropertyArray array = gltfPropertyArray( parser );
for( auto& prop : array )
{
idLexer lexer( LEXFL_ALLOWPATHNAMES | LEXFL_ALLOWMULTICHARLITERALS | LEXFL_NOSTRINGESCAPECHARS );
2022-06-18 08:43:30 +00:00
lexer.LoadMemory( prop.item.c_str(), prop.item.Size(), "gltfItem_mesh_primitiveB", 0 );
item->AssureSizeAlloc( item->Num() + 1, idListNewElement<gltfMesh_Primitive> );
gltfMesh_Primitive* gltfMeshPrim = ( *item )[item->Num() - 1];
attributes->Set( &gltfMeshPrim->attributes, &lexer );
GLTFARRAYITEMREF( gltfMeshPrim, indices );
GLTFARRAYITEMREF( gltfMeshPrim, material );
GLTFARRAYITEMREF( gltfMeshPrim, mode );
GLTFARRAYITEMREF( gltfMeshPrim, target );
GLTFARRAYITEMREF( gltfMeshPrim, extensions );
extras->Set( &gltfMeshPrim->extras, &lexer );
prim.Parse( &lexer );
2022-06-18 08:43:30 +00:00
if( gltf_parseVerbose.GetBool() )
{
2022-06-18 08:43:30 +00:00
common->Printf( "%s", prop.item.c_str() );
}
}
parser->ExpectTokenString( "]" );
}
void gltfItem_mesh_primitive_attribute::parse( idToken& token )
{
bool parsing = true;
while( parsing && parser->ExpectAnyToken( &token ) )
{
2022-06-18 08:43:30 +00:00
item->AssureSizeAlloc( item->Num() + 1, idListNewElement<gltfMesh_Primitive_Attribute> );
gltfMesh_Primitive_Attribute* attr = ( *item )[item->Num() - 1];
parser->ExpectTokenString( ":" );
attr->attributeSemantic = token;
attr->type = GetAttributeEnum( attr->attributeSemantic.c_str(), &attr->elementSize );
parser->ExpectAnyToken( &token );
attr->accessorIndex = token.GetIntValue();
parsing = parser->PeekTokenString( "," );
if( parsing )
{
parser->ExpectTokenString( "," );
}
}
parser->ExpectTokenString( "}" );
2022-06-18 08:43:30 +00:00
if( gltf_parseVerbose.GetBool() )
{
2022-06-18 08:43:30 +00:00
common->Printf( "%s", token.c_str() );
}
}
void gltfItem_integer_array::parse( idToken& token )
{
parser->UnreadToken( &token );
gltfPropertyArray array = gltfPropertyArray( parser, false );
for( auto& prop : array )
{
idStr neg;
2022-06-18 08:43:30 +00:00
int& value = item->Alloc();
value = prop.item.GetIntValue();
if( prop.item.type == TT_PUNCTUATION && prop.item == "-" )
{
parser->ExpectTokenType( TT_NUMBER, 0, &prop.item );
2022-06-18 08:43:30 +00:00
value = -( prop.item.GetIntValue() );
neg = "-";
}
else if( prop.item.type == TT_NUMBER )
{
2022-06-18 08:43:30 +00:00
value = prop.item.GetIntValue();
}
else
{
common->FatalError( "parse error" );
}
2022-06-18 08:43:30 +00:00
if( gltf_parseVerbose.GetBool() )
{
2022-06-18 08:43:30 +00:00
common->Printf( "%s%s", neg.c_str(), prop.item.c_str() );
}
}
parser->ExpectTokenString( "]" );
}
void gltfItem_number_array::parse( idToken& token )
{
parser->UnreadToken( &token );
gltfPropertyArray array = gltfPropertyArray( parser, false );
for( auto& prop : array )
{
idStr neg;
2022-06-18 08:43:30 +00:00
double& value = item->Alloc();
if( prop.item.type == TT_PUNCTUATION && prop.item == "-" )
{
parser->ExpectTokenType( TT_NUMBER, 0, &prop.item );
value = -( prop.item.GetDoubleValue() );
neg = "-";
}
else if( prop.item.type == TT_NUMBER )
{
2022-06-18 08:43:30 +00:00
value = prop.item.GetDoubleValue();
}
else
{
common->FatalError( "parse error" );
}
2022-06-18 08:43:30 +00:00
if( gltf_parseVerbose.GetBool() )
{
2022-06-18 08:43:30 +00:00
common->Printf( "%s%s", neg.c_str(), prop.item.c_str() );
}
}
parser->ExpectTokenString( "]" );
}
void gltfItem_vec4::parse( idToken& token )
{
auto* numbers = new gltfItem_number_array( "" );
idList<double> numberarray;
numbers->Set( &numberarray, parser );
numbers->parse( token );
2022-06-18 08:43:30 +00:00
if( numbers->item->Num() != 4 )
{
2022-06-18 08:43:30 +00:00
common->FatalError( "gltfItem_vec4 : missing arguments, expected 4, got %i", numbers->item->Num() );
}
2022-06-18 08:43:30 +00:00
double* val = numbers->item->Ptr();
*item = idVec4( val[0], val[1], val[2], val[3] );
delete numbers;
}
void gltfItem_vec3::parse( idToken& token )
{
auto* numbers = new gltfItem_number_array( "" );
idList<double> numberarray;
numbers->Set( &numberarray, parser );
numbers->parse( token );
2022-06-18 08:43:30 +00:00
if( numbers->item->Num() != 3 )
{
2022-06-18 08:43:30 +00:00
common->FatalError( "gltfItem_vec3 : missing arguments, expected 3, got %i", numbers->item->Num() );
}
2022-06-18 08:43:30 +00:00
double* val = numbers->item->Ptr();
*item = idVec3( val[0], val[1], val[2] );
delete numbers;
}
void gltfItem_vec2::parse( idToken& token )
{
auto* numbers = new gltfItem_number_array( "" );
idList<double> numberarray;
numbers->Set( &numberarray, parser );
numbers->parse( token );
2022-06-18 08:43:30 +00:00
if( numbers->item->Num() != 2 )
{
2022-06-18 08:43:30 +00:00
common->FatalError( "gltfItem_vec3 : missing arguments, expected 2, got %i", numbers->item->Num() );
}
2022-06-18 08:43:30 +00:00
double* val = numbers->item->Ptr();
*item = idVec2( val[0], val[1] );
delete numbers;
}
void gltfItem_quat::parse( idToken& token )
{
auto* numbers = new gltfItem_number_array( "" );
idList<double> numberarray;
numbers->Set( &numberarray, parser );
numbers->parse( token );
if( numbers->item->Num() != 4 )
{
2022-06-18 08:43:30 +00:00
common->FatalError( "gltfItem_quat : missing arguments, expectd 4, got %i", numbers->item->Num() );
}
double* val = numbers->item->Ptr();
*item = idQuat( val[0] , val[1] , val[2] , val[3] );
delete numbers;
}
void gltfItem_mat4::parse( idToken& token )
{
auto* numbers = new gltfItem_number_array( "" );
idList<double> numberarray;
numbers->Set( &numberarray, parser );
numbers->parse( token );
2022-06-18 08:43:30 +00:00
if( numbers->item->Num() != 16 )
{
2022-06-18 08:43:30 +00:00
common->FatalError( "gltfItem_mat4 : missing arguments, expectd 16, got %i", numbers->item->Num() );
}
2022-06-18 08:43:30 +00:00
double* val = numbers->item->Ptr();
*item = idMat4(
val[0], val[1], val[2], val[3],
val[4], val[5], val[6], val[7],
val[8], val[9], val[10], val[11],
val[12], val[13], val[14], val[15]
);
delete numbers;
}
void gltfItem_accessor_sparse::parse( idToken& token )
{
parser->Warning( "%s is untested!", "gltfItem_accessor_sparse" );
gltfItemArray sparse;
GLTFARRAYITEM( sparse, count, gltfItem_integer );
GLTFARRAYITEM( sparse, indices, gltfItem_accessor_sparse_indices );
GLTFARRAYITEM( sparse, values, gltfItem_accessor_sparse_values );
GLTFARRAYITEM( sparse, extensions, gltfItem );
GLTFARRAYITEM( sparse, extras, gltfItem_Extra );
GLTFARRAYITEMREF( item, count );
indices->Set( &item->indices, parser );
values->Set( &item->values, parser );
GLTFARRAYITEMREF( item, extensions );
extras->Set( &item->extras, parser );
sparse.Parse( parser );
2022-06-18 08:43:30 +00:00
if( gltf_parseVerbose.GetBool() )
{
2022-06-18 08:43:30 +00:00
common->Printf( "%s", token.c_str() );
}
}
void gltfItem_accessor_sparse_values::parse( idToken& token )
{
parser->Warning( "%s is untested!", "gltfItem_accessor_sparse_values" );
gltfItemArray values;
GLTFARRAYITEM( values, bufferView, gltfItem_integer );
GLTFARRAYITEM( values, byteOffset, gltfItem_integer );
GLTFARRAYITEM( values, extensions, gltfItem );
GLTFARRAYITEM( values, extras, gltfItem_Extra );
GLTFARRAYITEMREF( item, bufferView );
GLTFARRAYITEMREF( item, byteOffset );
GLTFARRAYITEMREF( item, extensions );
extras->Set( &item->extras, parser );
2022-06-18 08:43:30 +00:00
if( gltf_parseVerbose.GetBool() )
{
2022-06-18 08:43:30 +00:00
common->Printf( "%s", token.c_str() );
}
}
void gltfItem_accessor_sparse_indices::parse( idToken& token )
{
parser->Warning( "%s is untested!", "gltfItem_accessor_sparse_indices" );
gltfItemArray indices;
GLTFARRAYITEM( indices, bufferView, gltfItem_integer );
GLTFARRAYITEM( indices, byteOffset, gltfItem_integer );
GLTFARRAYITEM( indices, componentType, gltfItem_integer );
GLTFARRAYITEM( indices, extensions, gltfItem );
GLTFARRAYITEM( indices, extras, gltfItem_Extra );
GLTFARRAYITEMREF( item, bufferView );
GLTFARRAYITEMREF( item, byteOffset );
GLTFARRAYITEMREF( item, componentType );
GLTFARRAYITEMREF( item, extensions );
extras->Set( &item->extras, parser );
indices.Parse( parser );
2022-06-18 08:43:30 +00:00
if( gltf_parseVerbose.GetBool() )
{
2022-06-18 08:43:30 +00:00
common->Printf( "%s", token.c_str() );
}
}
void gltfItem_camera_orthographic::parse( idToken& token )
{
gltfPropertyArray array = gltfPropertyArray( parser );
for( auto& prop : array )
{
2022-06-18 08:43:30 +00:00
common->Printf( "%s", prop.item.c_str() );
}
parser->ExpectTokenString( "]" );
}
void gltfItem_camera_perspective::parse( idToken& token )
{
parser->UnreadToken( &token );
gltfItemArray cameraPerspective;
GLTFARRAYITEM( cameraPerspective, aspectRatio, gltfItem_number );
GLTFARRAYITEM( cameraPerspective, yfov, gltfItem_number );
GLTFARRAYITEM( cameraPerspective, zfar, gltfItem_number );
GLTFARRAYITEM( cameraPerspective, znear, gltfItem_number );
GLTFARRAYITEM( cameraPerspective, extensions, gltfItem );
GLTFARRAYITEM( cameraPerspective, extras, gltfItem_Extra );
GLTFARRAYITEMREF( item, aspectRatio );
GLTFARRAYITEMREF( item, yfov );
GLTFARRAYITEMREF( item, zfar );
GLTFARRAYITEMREF( item, znear );
GLTFARRAYITEMREF( item, extensions );
extras->Set( &item->extras, parser );
cameraPerspective.Parse( parser );
2022-06-18 08:43:30 +00:00
if( gltf_parseVerbose.GetBool() )
{
2022-06-18 08:43:30 +00:00
common->Printf( "%s", token.c_str() );
}
}
void gltfItem_occlusion_texture::parse( idToken& token )
{
parser->UnreadToken( &token );
gltfItemArray textureInfo;
GLTFARRAYITEM( textureInfo, index, gltfItem_integer );
GLTFARRAYITEM( textureInfo, texCoord, gltfItem_integer );
GLTFARRAYITEM( textureInfo, strength, gltfItem_number );
GLTFARRAYITEM( textureInfo, extensions, gltfItem_texture_info_extensions );
GLTFARRAYITEM( textureInfo, extras, gltfItem_Extra );
GLTFARRAYITEMREF( item, index );
GLTFARRAYITEMREF( item, texCoord );
GLTFARRAYITEMREF( item, strength );
extensions->Set( &item->extensions, parser );
extras->Set( &item->extras, parser );
textureInfo.Parse( parser );
2022-06-18 08:43:30 +00:00
if( gltf_parseVerbose.GetBool() )
{
2022-06-18 08:43:30 +00:00
common->Printf( "%s", token.c_str() );
}
}
void gltfItem_normal_texture::parse( idToken& token )
{
parser->UnreadToken( &token );
gltfItemArray textureInfo;
GLTFARRAYITEM( textureInfo, index, gltfItem_integer );
GLTFARRAYITEM( textureInfo, texCoord, gltfItem_integer );
GLTFARRAYITEM( textureInfo, scale, gltfItem_number );
GLTFARRAYITEM( textureInfo, extensions, gltfItem_texture_info_extensions );
GLTFARRAYITEM( textureInfo, extras, gltfItem_Extra );
GLTFARRAYITEMREF( item, index );
GLTFARRAYITEMREF( item, texCoord );
GLTFARRAYITEMREF( item, scale );
extensions->Set( &item->extensions, parser );
extras->Set( &item->extras, parser );
textureInfo.Parse( parser );
2022-06-18 08:43:30 +00:00
if( gltf_parseVerbose.GetBool() )
{
2022-06-18 08:43:30 +00:00
common->Printf( "%s", token.c_str() );
}
}
void gltfItem_texture_info::parse( idToken& token )
{
parser->UnreadToken( &token );
gltfItemArray textureInfo;
GLTFARRAYITEM( textureInfo, index, gltfItem_integer );
GLTFARRAYITEM( textureInfo, texCoord, gltfItem_integer );
GLTFARRAYITEM( textureInfo, extensions, gltfItem_texture_info_extensions );
GLTFARRAYITEM( textureInfo, extras, gltfItem_Extra );
GLTFARRAYITEMREF( item, index );
GLTFARRAYITEMREF( item, texCoord );
extensions->Set( &item->extensions, parser );
extras->Set( &item->extras, parser );
textureInfo.Parse( parser );
2022-06-18 08:43:30 +00:00
if( gltf_parseVerbose.GetBool() )
{
2022-06-18 08:43:30 +00:00
common->Printf( "%s", token.c_str() );
}
}
void gltfItem_pbrMetallicRoughness::parse( idToken& token )
{
parser->UnreadToken( &token );
gltfItemArray pbrMetallicRoughness;
GLTFARRAYITEM( pbrMetallicRoughness, baseColorFactor, gltfItem_vec4 );
GLTFARRAYITEM( pbrMetallicRoughness, baseColorTexture, gltfItem_texture_info );
GLTFARRAYITEM( pbrMetallicRoughness, metallicFactor, gltfItem_number );
GLTFARRAYITEM( pbrMetallicRoughness, roughnessFactor, gltfItem_number );
GLTFARRAYITEM( pbrMetallicRoughness, metallicRoughnessTexture, gltfItem_texture_info );
GLTFARRAYITEM( pbrMetallicRoughness, extensions, gltfItem );
GLTFARRAYITEM( pbrMetallicRoughness, extras, gltfItem_Extra );
baseColorFactor->Set( &item->baseColorFactor, parser );
baseColorTexture->Set( &item->baseColorTexture, parser );
GLTFARRAYITEMREF( item, metallicFactor );
GLTFARRAYITEMREF( item, roughnessFactor );
metallicRoughnessTexture->Set( &item->metallicRoughnessTexture, parser );
GLTFARRAYITEMREF( item, extensions );
extras->Set( &item->extras, parser );
pbrMetallicRoughness.Parse( parser );
2022-06-18 08:43:30 +00:00
if( gltf_parseVerbose.GetBool() )
{
2022-06-18 08:43:30 +00:00
common->Printf( "%s", token.c_str() );
}
}
void gltfItem_TextureInfo_KHR_texture_transform::parse( idToken& token )
{
parser->UnreadToken( &token );
gltfItemArray texureTransform;
GLTFARRAYITEM( texureTransform, offset, gltfItem_vec2 );
GLTFARRAYITEM( texureTransform, rotation, gltfItem_number );
GLTFARRAYITEM( texureTransform, scale, gltfItem_vec2 );
GLTFARRAYITEM( texureTransform, texCoord, gltfItem_integer );
2022-06-18 08:43:30 +00:00
item->KHR_texture_transform = new gltfExt_KHR_texture_transform();
offset->Set( &item->KHR_texture_transform->offset, parser );
GLTFARRAYITEMREF( item->KHR_texture_transform, rotation );
scale->Set( &item->KHR_texture_transform->scale, parser );
GLTFARRAYITEMREF( item->KHR_texture_transform, texCoord );
texureTransform.Parse( parser );
2022-06-18 08:43:30 +00:00
if( gltf_parseVerbose.GetBool() )
{
2022-06-18 08:43:30 +00:00
common->Printf( "%s", token.c_str() );
}
}
void gltfItem_Material_KHR_materials_pbrSpecularGlossiness::parse( idToken& token )
{
parser->UnreadToken( &token );
gltfItemArray khrPbr;
GLTFARRAYITEM( khrPbr, diffuseFactor, gltfItem_vec4 );
GLTFARRAYITEM( khrPbr, diffuseTexture, gltfItem_texture_info );
GLTFARRAYITEM( khrPbr, specularFactor, gltfItem_vec3 );
GLTFARRAYITEM( khrPbr, glossinessFactor, gltfItem_number );
GLTFARRAYITEM( khrPbr, specularGlossinessTexture, gltfItem_texture_info );
GLTFARRAYITEM( khrPbr, extensions, gltfItem );
GLTFARRAYITEM( khrPbr, extras, gltfItem_Extra );
2022-06-18 08:43:30 +00:00
item->KHR_materials_pbrSpecularGlossiness = new gltfExt_KHR_materials_pbrSpecularGlossiness();
diffuseFactor->Set( &item->KHR_materials_pbrSpecularGlossiness->diffuseFactor, parser );
diffuseTexture->Set( &item->KHR_materials_pbrSpecularGlossiness->diffuseTexture, parser );
specularFactor->Set( &item->KHR_materials_pbrSpecularGlossiness->specularFactor, parser );
GLTFARRAYITEMREF( item->KHR_materials_pbrSpecularGlossiness, glossinessFactor );
specularGlossinessTexture->Set( &item->KHR_materials_pbrSpecularGlossiness->specularGlossinessTexture, parser );
GLTFARRAYITEMREF( item->KHR_materials_pbrSpecularGlossiness, extensions );
extras->Set( &item->KHR_materials_pbrSpecularGlossiness->extras, parser );
khrPbr.Parse( parser );
2022-06-18 08:43:30 +00:00
if( gltf_parseVerbose.GetBool() )
{
2022-06-18 08:43:30 +00:00
common->Printf( "%s", token.c_str() );
}
}
void gltfItem_Node_KHR_lights_punctual::parse( idToken& token )
{
parser->UnreadToken( &token );
gltfItemArray xlight;
GLTFARRAYITEM( xlight, light, gltfItem_integer );
2022-06-18 08:43:30 +00:00
item->KHR_lights_punctual = new gltfNode_KHR_lights_punctual();
light->Set( &item->KHR_lights_punctual->light );
xlight.Parse( parser );
2022-06-18 08:43:30 +00:00
if( gltf_parseVerbose.GetBool() )
{
2022-06-18 08:43:30 +00:00
common->Printf( "%s", token.c_str() );
}
}
void gltfItem_KHR_lights_punctual::parse( idToken& token )
{
idToken localToken;
parser->ExpectTokenString( "lights" );
parser->ExpectTokenString( ":" );
gltfItemArray light;
GLTFARRAYITEM( light, color, gltfItem_vec3 );
GLTFARRAYITEM( light, intensity, gltfItem_number );
//GLTFARRAYITEM( light, spot, gltfItem );
GLTFARRAYITEM( light, type, gltfItem );
GLTFARRAYITEM( light, range, gltfItem_number );
GLTFARRAYITEM( light, name, gltfItem );
GLTFARRAYITEM( light, extensions, gltfItem );
GLTFARRAYITEM( light, extras, gltfItem_Extra );
gltfPropertyArray array = gltfPropertyArray( parser );
for( auto& prop : array )
{
idLexer lexer( LEXFL_ALLOWPATHNAMES | LEXFL_ALLOWMULTICHARLITERALS | LEXFL_NOSTRINGESCAPECHARS );
2022-06-18 08:43:30 +00:00
lexer.LoadMemory( prop.item.c_str(), prop.item.Size(), "gltfNode_light", 0 );
item->KHR_lights_punctual.AssureSizeAlloc(
2022-06-18 08:43:30 +00:00
item->KHR_lights_punctual.Num() + 1,
idListNewElement<gltfExt_KHR_lights_punctual> );
gltfExt_KHR_lights_punctual* gltfLight =
2022-06-18 08:43:30 +00:00
item->KHR_lights_punctual[item->KHR_lights_punctual.Num() - 1];
color->Set( &gltfLight->color, &lexer );
GLTFARRAYITEMREF( gltfLight, intensity );
//GLTFARRAYITEMREF (gltfLight, spot );
GLTFARRAYITEMREF( gltfLight, type );
GLTFARRAYITEMREF( gltfLight, range );
GLTFARRAYITEMREF( gltfLight, name );
GLTFARRAYITEMREF( gltfLight, extensions );
extras->Set( &gltfLight->extras, &lexer );
light.Parse( &lexer );
gltfLight->intType = gltfExt_KHR_lights_punctual::resolveType( gltfLight->type );
2022-06-18 08:43:30 +00:00
if( gltf_parseVerbose.GetBool() )
{
2022-06-18 08:43:30 +00:00
common->Printf( "%s", prop.item.c_str() );
}
}
parser->ExpectTokenString( "]" );
parser->ExpectTokenString( "}" );
}
void gltfItem_node_extensions::parse( idToken& token )
{
parser->UnreadToken( &token );
gltfItemArray extensions;
GLTFARRAYITEM( extensions, KHR_lights_punctual, gltfItem_Node_KHR_lights_punctual );
KHR_lights_punctual->Set( item, parser );
extensions.Parse( parser );
2022-06-18 08:43:30 +00:00
if( gltf_parseVerbose.GetBool() )
{
2022-06-18 08:43:30 +00:00
common->Printf( "%s", token.c_str() );
}
}
void gltfItem_material_extensions::parse( idToken& token )
{
parser->UnreadToken( &token );
gltfItemArray extensions;
GLTFARRAYITEM( extensions, KHR_materials_pbrSpecularGlossiness, gltfItem_Material_KHR_materials_pbrSpecularGlossiness );
KHR_materials_pbrSpecularGlossiness->Set( item, parser );
extensions.Parse( parser );
2022-06-18 08:43:30 +00:00
if( gltf_parseVerbose.GetBool() )
{
2022-06-18 08:43:30 +00:00
common->Printf( "%s", token.c_str() );
}
}
void gltfItem_texture_info_extensions::parse( idToken& token )
{
parser->UnreadToken( &token );
gltfItemArray extensions;
GLTFARRAYITEM( extensions, KHR_texture_transform, gltfItem_TextureInfo_KHR_texture_transform );
KHR_texture_transform->Set( item, parser );
extensions.Parse( parser );
2022-06-18 08:43:30 +00:00
if( gltf_parseVerbose.GetBool() )
{
2022-06-18 08:43:30 +00:00
common->Printf( "%s", token.c_str() );
}
}
2022-06-18 08:43:30 +00:00
void GLTF_Parser::Shutdown()
{
currentFile.FreeData();
if( currentAsset )
{
delete currentAsset;
}
currentAsset = nullptr;
buffersDone = false;
bufferViewsDone = false;
}
GLTF_Parser::GLTF_Parser()
: parser( LEXFL_ALLOWPATHNAMES | LEXFL_ALLOWMULTICHARLITERALS | LEXFL_NOSTRINGESCAPECHARS | LEXFL_ALLOWPATHNAMES ) , buffersDone( false ), bufferViewsDone( false ), currentAsset( nullptr ) { }
void GLTF_Parser::Parse_ASSET( idToken& token )
{
idStr section;
parser.ParseBracedSection( section );
2022-06-18 08:43:30 +00:00
common->Printf( "%s\n", section.c_str() );
}
2022-06-18 09:09:09 +00:00
void GLTF_Parser::Parse_SCENE( idToken& token )
{
2022-06-18 08:43:30 +00:00
currentAsset->DefaultScene() = parser.ParseInt();
2022-06-18 08:43:30 +00:00
if( gltf_parseVerbose.GetBool() )
{
2022-06-18 08:43:30 +00:00
common->Printf( " ^1 %s scene ^6 : ^8 %i", token.c_str(), currentAsset->DefaultScene() );
}
}
2022-06-18 09:09:09 +00:00
void GLTF_Parser::Parse_SCENES( idToken& token )
{
gltfItemArray scene;
GLTFARRAYITEM( scene, nodes, gltfItem_integer_array );
GLTFARRAYITEM( scene, name, gltfItem );
GLTFARRAYITEM( scene, extensions, gltfItem );
GLTFARRAYITEM( scene, extras, gltfItem_Extra );
gltfPropertyArray array = gltfPropertyArray( &parser );
for( auto& prop : array )
{
idLexer lexer( LEXFL_ALLOWPATHNAMES | LEXFL_ALLOWMULTICHARLITERALS | LEXFL_NOSTRINGESCAPECHARS );
2022-06-18 08:43:30 +00:00
lexer.LoadMemory( prop.item.c_str(), prop.item.Size(), "gltfScene", 0 );
gltfScene* gltfscene = currentAsset->Scene();
nodes->Set( &gltfscene->nodes, &lexer );
GLTFARRAYITEMREF( gltfscene, name );
GLTFARRAYITEMREF( gltfscene, extensions );
extras->Set( &gltfscene->extras, &lexer );
scene.Parse( &lexer );
2022-06-18 08:43:30 +00:00
if( gltf_parseVerbose.GetBool() )
{
common->Printf( "%s", prop.item.c_str() );
}
}
parser.ExpectTokenString( "]" );
}
2022-06-18 09:09:09 +00:00
void GLTF_Parser::Parse_CAMERAS( idToken& token )
{
gltfItemArray camera;
GLTFARRAYITEM( camera, orthographic, gltfItem_camera_orthographic );
GLTFARRAYITEM( camera, perspective, gltfItem_camera_perspective );
GLTFARRAYITEM( camera, type, gltfItem );
GLTFARRAYITEM( camera, name, gltfItem );
GLTFARRAYITEM( camera, extensions, gltfItem );
GLTFARRAYITEM( camera, extras, gltfItem_Extra );
gltfPropertyArray array = gltfPropertyArray( &parser );
for( auto& prop : array )
{
idLexer lexer( LEXFL_ALLOWPATHNAMES | LEXFL_ALLOWMULTICHARLITERALS | LEXFL_NOSTRINGESCAPECHARS );
2022-06-18 08:43:30 +00:00
lexer.LoadMemory( prop.item.c_str(), prop.item.Size(), "gltfCamera", 0 );
2022-06-18 08:43:30 +00:00
gltfCamera* item = currentAsset->Camera();
orthographic->Set( &item->orthographic, &lexer );
perspective->Set( &item->perspective, &lexer );
GLTFARRAYITEMREF( item, type );
GLTFARRAYITEMREF( item, name );
GLTFARRAYITEMREF( item, extensions );
extras->Set( &item->extras, &lexer );
camera.Parse( &lexer );
2022-06-18 08:43:30 +00:00
if( gltf_parseVerbose.GetBool() )
{
2022-06-18 08:43:30 +00:00
common->Printf( "%s", prop.item.c_str() );
}
}
parser.ExpectTokenString( "]" );
}
2022-06-18 09:09:09 +00:00
void GLTF_Parser::Parse_NODES( idToken& token )
{
gltfItemArray node;
GLTFARRAYITEM( node, camera, gltfItem_integer );
GLTFARRAYITEM( node, children, gltfItem_integer_array );
GLTFARRAYITEM( node, skin, gltfItem_integer );
GLTFARRAYITEM( node, matrix, gltfItem_mat4 );
GLTFARRAYITEM( node, mesh, gltfItem_integer );
GLTFARRAYITEM( node, rotation, gltfItem_quat );
GLTFARRAYITEM( node, scale, gltfItem_vec3 );
GLTFARRAYITEM( node, translation, gltfItem_vec3 );
GLTFARRAYITEM( node, weights, gltfItem_number_array );
GLTFARRAYITEM( node, name, gltfItem );
GLTFARRAYITEM( node, extensions, gltfItem_node_extensions );
GLTFARRAYITEM( node, extras, gltfItem_Extra );
gltfPropertyArray array = gltfPropertyArray( &parser );
for( auto& prop : array )
{
idLexer lexer( LEXFL_ALLOWPATHNAMES | LEXFL_ALLOWMULTICHARLITERALS | LEXFL_NOSTRINGESCAPECHARS );
2022-06-18 08:43:30 +00:00
lexer.LoadMemory( prop.item.c_str(), prop.item.Size(), "gltfNode", 0 );
2022-06-18 08:43:30 +00:00
gltfNode* gltfnode = currentAsset->Node();
GLTFARRAYITEMREF( gltfnode, camera );
matrix->Set( &gltfnode->matrix, &lexer );
children->Set( &gltfnode->children, &lexer );
GLTFARRAYITEMREF( gltfnode, skin );
matrix->Set( &gltfnode->matrix, &lexer );
GLTFARRAYITEMREF( gltfnode, mesh );
rotation->Set( &gltfnode->rotation, &lexer );
scale->Set( &gltfnode->scale, &lexer );
translation->Set( &gltfnode->translation, &lexer );
weights->Set( &gltfnode->weights, &lexer );
GLTFARRAYITEMREF( gltfnode, name );
extensions->Set( &gltfnode->extensions, &lexer );
extras->Set( &gltfnode->extras, &lexer );
node.Parse( &lexer );
2022-06-18 08:43:30 +00:00
if( gltf_parseVerbose.GetBool() )
{
2022-06-18 08:43:30 +00:00
common->Printf( "%s", prop.item.c_str() );
}
}
parser.ExpectTokenString( "]" );
}
2022-06-18 09:09:09 +00:00
void GLTF_Parser::Parse_MATERIALS( idToken& token )
{
gltfItemArray material;
GLTFARRAYITEM( material, pbrMetallicRoughness, gltfItem_pbrMetallicRoughness );
GLTFARRAYITEM( material, normalTexture, gltfItem_normal_texture );
GLTFARRAYITEM( material, occlusionTexture, gltfItem_occlusion_texture );
GLTFARRAYITEM( material, emissiveTexture, gltfItem_texture_info );
GLTFARRAYITEM( material, emissiveFactor, gltfItem_vec3 );
GLTFARRAYITEM( material, alphaMode, gltfItem );
GLTFARRAYITEM( material, alphaCutoff, gltfItem_number );
GLTFARRAYITEM( material, doubleSided, gltfItem_boolean );
GLTFARRAYITEM( material, name, gltfItem );
GLTFARRAYITEM( material, extensions, gltfItem_material_extensions );
GLTFARRAYITEM( material, extras, gltfItem_Extra );
gltfPropertyArray array = gltfPropertyArray( &parser );
for( auto& prop : array )
{
idLexer lexer( LEXFL_ALLOWPATHNAMES | LEXFL_ALLOWMULTICHARLITERALS | LEXFL_NOSTRINGESCAPECHARS );
2022-06-18 08:43:30 +00:00
lexer.LoadMemory( prop.item.c_str(), prop.item.Size(), "gltfMaterial", 0 );
2022-06-18 08:43:30 +00:00
gltfMaterial* gltfmaterial = currentAsset->Material();
pbrMetallicRoughness->Set( &gltfmaterial->pbrMetallicRoughness, &lexer );
normalTexture->Set( &gltfmaterial->normalTexture, &lexer );
occlusionTexture->Set( &gltfmaterial->occlusionTexture, &lexer );
emissiveTexture->Set( &gltfmaterial->emissiveTexture, &lexer );
emissiveFactor->Set( &gltfmaterial->emissiveFactor, &lexer );
GLTFARRAYITEMREF( gltfmaterial, alphaMode );
GLTFARRAYITEMREF( gltfmaterial, alphaCutoff );
GLTFARRAYITEMREF( gltfmaterial, doubleSided );
GLTFARRAYITEMREF( gltfmaterial, name );
extensions->Set( &gltfmaterial->extensions, &lexer );
extras->Set( &gltfmaterial->extras, &lexer );
material.Parse( &lexer );
gltfmaterial->intType = gltfMaterial::resolveAlphaMode( gltfmaterial->alphaMode );
2022-06-18 08:43:30 +00:00
if( gltf_parseVerbose.GetBool() )
{
2022-06-18 08:43:30 +00:00
common->Printf( "%s", prop.item.c_str() );
}
}
parser.ExpectTokenString( "]" );
}
2022-06-18 09:09:09 +00:00
void GLTF_Parser::Parse_MESHES( idToken& token )
{
gltfItemArray mesh;
GLTFARRAYITEM( mesh, primitives, gltfItem_mesh_primitive ); // object
GLTFARRAYITEM( mesh, weights, gltfItem_number_array ); //number[1 - *]
GLTFARRAYITEM( mesh, name, gltfItem );
GLTFARRAYITEM( mesh, extensions, gltfItem );
GLTFARRAYITEM( mesh, extras, gltfItem_Extra );
gltfPropertyArray array = gltfPropertyArray( &parser );
for( auto& prop : array )
{
idLexer lexer( LEXFL_ALLOWPATHNAMES | LEXFL_ALLOWMULTICHARLITERALS | LEXFL_NOSTRINGESCAPECHARS );
2022-06-18 08:43:30 +00:00
lexer.LoadMemory( prop.item.c_str(), prop.item.Size(), "gltfMesh", 0 );
2022-06-18 08:43:30 +00:00
gltfMesh* gltfmesh = currentAsset->Mesh();
primitives->Set( &gltfmesh->primitives, &lexer );
weights->Set( &gltfmesh->weights, &lexer );
GLTFARRAYITEMREF( gltfmesh, name );
GLTFARRAYITEMREF( gltfmesh, extensions );
extras->Set( &gltfmesh->extras, &lexer );
mesh.Parse( &lexer );
2022-06-18 08:43:30 +00:00
if( gltf_parseVerbose.GetBool() )
{
2022-06-18 08:43:30 +00:00
common->Printf( "%s", prop.item.c_str() );
}
}
parser.ExpectTokenString( "]" );
}
2022-06-18 09:09:09 +00:00
void GLTF_Parser::Parse_TEXTURES( idToken& token )
{
gltfItemArray texture;
GLTFARRAYITEM( texture, sampler, gltfItem_integer );
GLTFARRAYITEM( texture, source, gltfItem_integer );
GLTFARRAYITEM( texture, name, gltfItem );
GLTFARRAYITEM( texture, extensions, gltfItem_texture_info_extensions );
GLTFARRAYITEM( texture, extras, gltfItem_Extra );
gltfPropertyArray array = gltfPropertyArray( &parser );
for( auto& prop : array )
{
idLexer lexer( LEXFL_ALLOWPATHNAMES | LEXFL_ALLOWMULTICHARLITERALS | LEXFL_NOSTRINGESCAPECHARS );
2022-06-18 08:43:30 +00:00
lexer.LoadMemory( prop.item.c_str(), prop.item.Size(), "gltfTexture", 0 );
2022-06-18 08:43:30 +00:00
gltfTexture* gltftexture = currentAsset->Texture();
GLTFARRAYITEMREF( gltftexture, sampler );
GLTFARRAYITEMREF( gltftexture, source );
GLTFARRAYITEMREF( gltftexture, name );
extensions->Set( &gltftexture->extensions, &lexer );
extras->Set( &gltftexture->extras, &lexer );
texture.Parse( &lexer );
2022-06-18 08:43:30 +00:00
if( gltf_parseVerbose.GetBool() )
{
2022-06-18 08:43:30 +00:00
common->Printf( "%s", prop.item.c_str() );
}
}
parser.ExpectTokenString( "]" );
}
2022-06-18 09:09:09 +00:00
void GLTF_Parser::Parse_IMAGES( idToken& token )
{
//reference impl
gltfPropertyArray array = gltfPropertyArray( &parser );
gltfItemArray propItems;
auto uri = new gltfItem_uri( "uri" );
propItems.AddItemDef( ( parsable* )uri );
auto mimeType = new gltfItem( "mimeType" );
propItems.AddItemDef( ( parsable* )mimeType );
auto bufferView = new gltfItem_integer( "bufferView" );
propItems.AddItemDef( ( parsable* )bufferView );
auto name = new gltfItem( "name" );
propItems.AddItemDef( ( parsable* )name );
auto extensions = new gltfItem( "extensions" );
propItems.AddItemDef( ( parsable* )extensions );
auto extras = new gltfItem_Extra( "extras" );
propItems.AddItemDef( ( parsable* ) extras );
for( auto& prop : array )
{
idLexer lexer( LEXFL_ALLOWPATHNAMES | LEXFL_ALLOWMULTICHARLITERALS | LEXFL_NOSTRINGESCAPECHARS );
lexer.LoadMemory( prop.item.c_str(), prop.item.Size(), "gltfImage", 0 );
gltfImage* image = currentAsset->Image();
uri->Set( &image->uri, &image->bufferView, currentAsset );
mimeType->Set( &image->mimeType );
bufferView->Set( &image->bufferView );
name->Set( &image->name );
extensions->Set( &image->extensions );
extras->Set( &image->extras, &lexer );
propItems.Parse( &lexer );
2022-06-18 08:43:30 +00:00
if( gltf_parseVerbose.GetBool() )
{
2022-06-18 08:43:30 +00:00
common->Printf( "%s", prop.item.c_str() );
}
//automate..
//image->bgfxTexture.handle.idx = UINT16_MAX;
}
parser.ExpectTokenString( "]" );
}
2022-06-18 09:09:09 +00:00
void GLTF_Parser::Parse_ACCESSORS( idToken& token )
{
gltfItemArray accessor;
GLTFARRAYITEM( accessor, bufferView, gltfItem_integer );
GLTFARRAYITEM( accessor, byteOffset, gltfItem_integer );
GLTFARRAYITEM( accessor, componentType, gltfItem_integer );
GLTFARRAYITEM( accessor, normalized, gltfItem_boolean );
GLTFARRAYITEM( accessor, count, gltfItem_integer );
GLTFARRAYITEM( accessor, type, gltfItem );
GLTFARRAYITEM( accessor, max, gltfItem_number_array );
GLTFARRAYITEM( accessor, min, gltfItem_number_array );
GLTFARRAYITEM( accessor, sparse, gltfItem_accessor_sparse );
GLTFARRAYITEM( accessor, name, gltfItem );
GLTFARRAYITEM( accessor, extensions, gltfItem );
GLTFARRAYITEM( accessor, extras, gltfItem_Extra );
gltfPropertyArray array = gltfPropertyArray( &parser );
for( auto& prop : array )
{
idLexer lexer( LEXFL_ALLOWPATHNAMES | LEXFL_ALLOWMULTICHARLITERALS | LEXFL_NOSTRINGESCAPECHARS );
2022-06-18 08:43:30 +00:00
lexer.LoadMemory( prop.item.c_str(), prop.item.Size(), "gltfAccessor", 0 );
gltfAccessor* item = currentAsset->Accessor();
GLTFARRAYITEMREF( item, bufferView );
GLTFARRAYITEMREF( item, byteOffset );
GLTFARRAYITEMREF( item, componentType );
GLTFARRAYITEMREF( item, normalized );
GLTFARRAYITEMREF( item, count );
GLTFARRAYITEMREF( item, type );
max->Set( &item->max, &lexer );
min->Set( &item->min, &lexer );
sparse->Set( &item->sparse, &lexer );
GLTFARRAYITEMREF( item, name );
GLTFARRAYITEMREF( item, extensions );
extras->Set( &item->extras, &lexer );
accessor.Parse( &lexer );
GetComponentTypeEnum( item->componentType, &item->typeSize );
2022-06-18 08:43:30 +00:00
if( gltf_parseVerbose.GetBool() )
{
2022-06-18 08:43:30 +00:00
common->Printf( "%s", prop.item.c_str() );
}
}
parser.ExpectTokenString( "]" );
}
2022-06-18 09:09:09 +00:00
void GLTF_Parser::Parse_BUFFERVIEWS( idToken& token )
{
gltfItemArray bv;
GLTFARRAYITEM( bv, buffer, gltfItem_integer );
GLTFARRAYITEM( bv, byteLength, gltfItem_integer );
GLTFARRAYITEM( bv, byteStride, gltfItem_integer );
GLTFARRAYITEM( bv, byteOffset, gltfItem_integer );
GLTFARRAYITEM( bv, target, gltfItem_integer );
GLTFARRAYITEM( bv, name, gltfItem );
GLTFARRAYITEM( bv, extensions, gltfItem );
GLTFARRAYITEM( bv, extras, gltfItem_Extra );
gltfPropertyArray array = gltfPropertyArray( &parser );
for( auto& prop : array )
{
idLexer lexer( LEXFL_ALLOWPATHNAMES | LEXFL_ALLOWMULTICHARLITERALS | LEXFL_NOSTRINGESCAPECHARS );
2022-06-18 08:43:30 +00:00
lexer.LoadMemory( prop.item.c_str(), prop.item.Size(), "gltfBufferView", 0 );
gltfBufferView* gltfBV = currentAsset->BufferView();
GLTFARRAYITEMREF( gltfBV, buffer );
GLTFARRAYITEMREF( gltfBV, byteLength );
GLTFARRAYITEMREF( gltfBV, byteStride );
GLTFARRAYITEMREF( gltfBV, byteOffset );
GLTFARRAYITEMREF( gltfBV, target );
GLTFARRAYITEMREF( gltfBV, name );
GLTFARRAYITEMREF( gltfBV, extensions );
extras->Set( &gltfBV->extras, &lexer );
bv.Parse( &lexer );
gltfBV->parent = currentAsset;
if( gltf_parseVerbose.GetBool() )
{
2022-06-18 08:43:30 +00:00
common->Printf( "%s", prop.item.c_str() );
}
}
parser.ExpectTokenString( "]" );
}
2022-06-18 09:09:09 +00:00
void GLTF_Parser::Parse_SAMPLERS( idToken& token )
{
gltfItemArray sampl;
GLTFARRAYITEM( sampl, magFilter, gltfItem_integer );
GLTFARRAYITEM( sampl, minFilter, gltfItem_integer );
GLTFARRAYITEM( sampl, wrapS, gltfItem_integer );
GLTFARRAYITEM( sampl, wrapT, gltfItem_integer );
GLTFARRAYITEM( sampl, name, gltfItem );
GLTFARRAYITEM( sampl, extensions, gltfItem );
GLTFARRAYITEM( sampl, extras, gltfItem_Extra );
gltfPropertyArray array = gltfPropertyArray( &parser );
for( auto& prop : array )
{
idLexer lexer( LEXFL_ALLOWPATHNAMES | LEXFL_ALLOWMULTICHARLITERALS | LEXFL_NOSTRINGESCAPECHARS );
2022-06-18 08:43:30 +00:00
lexer.LoadMemory( prop.item.c_str(), prop.item.Size(), "gltfSampler", 0 );
gltfSampler* gltfSampl = currentAsset->Sampler();
GLTFARRAYITEMREF( gltfSampl, magFilter );
GLTFARRAYITEMREF( gltfSampl, minFilter );
GLTFARRAYITEMREF( gltfSampl, wrapS );
GLTFARRAYITEMREF( gltfSampl, wrapT );
GLTFARRAYITEMREF( gltfSampl, name );
GLTFARRAYITEMREF( gltfSampl, extensions );
extras->Set( &gltfSampl->extras, &lexer );
sampl.Parse( &lexer );
if( gltf_parseVerbose.GetBool() )
{
2022-06-18 08:43:30 +00:00
common->Printf( "%s", prop.item.c_str() );
}
}
parser.ExpectTokenString( "]" );
}
2022-06-18 09:09:09 +00:00
void GLTF_Parser::Parse_BUFFERS( idToken& token )
{
gltfItemArray buf;
GLTFARRAYITEM( buf, uri, gltfItem_uri );
GLTFARRAYITEM( buf, byteLength, gltfItem_integer );
GLTFARRAYITEM( buf, name, gltfItem );
GLTFARRAYITEM( buf, extensions, gltfItem );
GLTFARRAYITEM( buf, extras, gltfItem_Extra );
gltfPropertyArray array = gltfPropertyArray( &parser );
for( auto& prop : array )
{
idLexer lexer( LEXFL_ALLOWPATHNAMES | LEXFL_ALLOWMULTICHARLITERALS | LEXFL_NOSTRINGESCAPECHARS );
2022-06-18 08:43:30 +00:00
lexer.LoadMemory( prop.item.c_str(), prop.item.Size(), "gltfBuffer", 0 );
2022-06-18 08:43:30 +00:00
gltfBuffer* gltfBuf = currentAsset->Buffer();
gltfBuf->parent = currentAsset;
uri->Set( &gltfBuf->uri, nullptr , currentAsset );
GLTFARRAYITEMREF( gltfBuf, byteLength );
GLTFARRAYITEMREF( gltfBuf, name );
GLTFARRAYITEMREF( gltfBuf, extensions );
extras->Set( &gltfBuf->extras, &lexer );
buf.Parse( &lexer );
2022-06-18 08:43:30 +00:00
if( gltf_parseVerbose.GetBool() )
{
2022-06-18 08:43:30 +00:00
common->Printf( "%s", prop.item.c_str() );
}
}
parser.ExpectTokenString( "]" );
}
2022-06-18 09:09:09 +00:00
void GLTF_Parser::Parse_ANIMATIONS( idToken& token )
{
gltfItemArray anim;
GLTFARRAYITEM( anim, channels, gltfItem_animation_channel ); //channel[1 - *]
GLTFARRAYITEM( anim, samplers, gltfItem_animation_sampler ); //sampler[1 - *]
GLTFARRAYITEM( anim, name, gltfItem );
GLTFARRAYITEM( anim, extensions, gltfItem );
GLTFARRAYITEM( anim, extras, gltfItem_Extra );
gltfPropertyArray array = gltfPropertyArray( &parser );
for( auto& prop : array )
{
idLexer lexer( LEXFL_ALLOWPATHNAMES | LEXFL_ALLOWMULTICHARLITERALS | LEXFL_NOSTRINGESCAPECHARS );
2022-06-18 08:43:30 +00:00
lexer.LoadMemory( prop.item.c_str(), prop.item.Size(), "gltfAnimation", 0 );
2022-06-18 08:43:30 +00:00
gltfAnimation* gltfanim = currentAsset->Animation();
channels->Set( &gltfanim->channels, &lexer );
samplers->Set( &gltfanim->samplers, &lexer );
GLTFARRAYITEMREF( gltfanim, name );
GLTFARRAYITEMREF( gltfanim, extensions );
extras->Set( &gltfanim->extras, &lexer );
anim.Parse( &lexer );
2022-06-18 08:43:30 +00:00
if( gltf_parseVerbose.GetBool() )
{
2022-06-18 08:43:30 +00:00
common->Printf( "%s", prop.item.c_str() );
}
}
parser.ExpectTokenString( "]" );
}
2022-06-18 09:09:09 +00:00
void GLTF_Parser::Parse_SKINS( idToken& token )
{
gltfItemArray skin;
GLTFARRAYITEM( skin, inverseBindMatrices, gltfItem_integer );
GLTFARRAYITEM( skin, skeleton, gltfItem_integer );
GLTFARRAYITEM( skin, joints, gltfItem_integer_array );
GLTFARRAYITEM( skin, name, gltfItem );
GLTFARRAYITEM( skin, extensions, gltfItem );
GLTFARRAYITEM( skin, extras, gltfItem_Extra );
gltfPropertyArray array = gltfPropertyArray( &parser );
for( auto& prop : array )
{
idLexer lexer( LEXFL_ALLOWPATHNAMES | LEXFL_ALLOWMULTICHARLITERALS | LEXFL_NOSTRINGESCAPECHARS );
2022-06-18 08:43:30 +00:00
lexer.LoadMemory( prop.item.c_str(), prop.item.Size(), "gltfSkin", 0 );
2022-06-18 08:43:30 +00:00
gltfSkin* gltfSkin = currentAsset->Skin();
GLTFARRAYITEMREF( gltfSkin, inverseBindMatrices );
GLTFARRAYITEMREF( gltfSkin, skeleton );
joints->Set( &gltfSkin->joints, &lexer );
GLTFARRAYITEMREF( gltfSkin, name );
GLTFARRAYITEMREF( gltfSkin, extensions );
extras->Set( &gltfSkin->extras, &lexer );
skin.Parse( &lexer );
2022-06-18 08:43:30 +00:00
if( gltf_parseVerbose.GetBool() )
{
2022-06-18 08:43:30 +00:00
common->Printf( "%s", prop.item.c_str() );
}
}
parser.ExpectTokenString( "]" );
}
2022-06-18 09:09:09 +00:00
void GLTF_Parser::Parse_EXTENSIONS( idToken& token )
{
idStr json;
parser.ParseBracedSection( json );
gltfItemArray extensions;
//GLTFARRAYITEM( extensions, KHR_materials_pbrSpecularGlossiness, gltfItem_KHR_materials_pbrSpecularGlossiness );
GLTFARRAYITEM( extensions, KHR_lights_punctual, gltfItem_KHR_lights_punctual );
idLexer lexer( LEXFL_ALLOWPATHNAMES | LEXFL_ALLOWMULTICHARLITERALS | LEXFL_NOSTRINGESCAPECHARS );
2022-06-18 08:43:30 +00:00
lexer.LoadMemory( json.c_str(), json.Size(), "Extensions", 0 );
gltfExtensions* gltfextension = currentAsset->Extensions();
//KHR_materials_pbrSpecularGlossiness->Set( &gltfextensions, &lexer );
KHR_lights_punctual->Set( gltfextension, &lexer );
extensions.Parse( &lexer );
2022-06-18 08:43:30 +00:00
if( gltf_parseVerbose.GetBool() )
{
2022-06-18 08:43:30 +00:00
common->Printf( "%s", json.c_str() );
}
}
2022-06-18 09:09:09 +00:00
void GLTF_Parser::Parse_EXTENSIONS_USED( idToken& token )
{
gltfPropertyArray array = gltfPropertyArray( &parser, false );
for( auto& prop : array )
{
2022-06-18 08:43:30 +00:00
gltfExtensionsUsed* ext = currentAsset->ExtensionsUsed();
ext->extension = prop.item;
2022-06-18 08:43:30 +00:00
if( gltf_parseVerbose.GetBool() )
{
2022-06-18 08:43:30 +00:00
common->Printf( "%s", prop.item.c_str() );
}
}
parser.ExpectTokenString( "]" );
}
2022-06-18 09:09:09 +00:00
void GLTF_Parser::Parse_EXTENSIONS_REQUIRED( idToken& token )
{
parser.ExpectTokenString( "[" );
idStrList exts;
idToken item;
bool parsing = true;
while( parsing && parser.ExpectAnyToken( &item ) )
{
if( item.type != TT_STRING )
{
common->FatalError( "malformed extensions_used array" );
}
2022-06-18 08:43:30 +00:00
idStr& extension = exts.Alloc();
extension = item.c_str();
parsing = parser.PeekTokenString( "," );
if( parsing )
{
parser.ExpectTokenString( "," );
}
}
parser.ExpectTokenString( "]" );
for( auto& out : exts )
{
2022-06-18 08:43:30 +00:00
common->Printf( "%s", out.c_str() );
}
}
gltfProperty GLTF_Parser::ParseProp( idToken& token )
{
parser.ExpectTokenString( ":" );
gltfProperty prop = ResolveProp( token );
bool skipping = false;
if( !buffersDone || !bufferViewsDone )
{
if( prop == BUFFERS && !buffersDone )
{
Parse_BUFFERS( token );
return prop;
}
if( prop == BUFFERVIEWS && !bufferViewsDone )
{
Parse_BUFFERVIEWS( token );
return prop;
}
skipping = true;
2022-06-18 08:43:30 +00:00
if( gltf_parseVerbose.GetBool() )
{
common->DPrintf( "Searching for buffer tag. Skipping %s.", token.c_str() );
}
}
else
{
if( ( prop == BUFFERS && buffersDone ) || ( prop == BUFFERVIEWS && bufferViewsDone ) )
{
skipping = true;
2022-06-18 08:43:30 +00:00
if( gltf_parseVerbose.GetBool() )
{
2022-06-18 08:43:30 +00:00
common->DPrintf( "Skipping %s , already done.", token.c_str() );
}
}
}
if( skipping )
{
//1. search for {} scope.
//2. search for [] scope.
//3. single token.
idToken skipTok;
int sectionsSkipped = 0;
if( parser.PeekTokenString( "{" ) )
{
parser.SkipBracedSection( true, BRSKIP_BRACES, &sectionsSkipped );
}
if( !sectionsSkipped && parser.PeekTokenString( "[" ) )
{
parser.SkipBracedSection( true, BRSKIP_BRACKET, &sectionsSkipped );
}
if( !sectionsSkipped )
{
parser.ExpectAnyToken( &skipTok );
}
return gltfProperty::INVALID;
}
switch( prop )
{
case ASSET:
Parse_ASSET( token );
break;
case CAMERAS:
Parse_CAMERAS( token );
break;
case SCENE:
Parse_SCENE( token );
break;
case SCENES:
Parse_SCENES( token );
break;
case NODES:
Parse_NODES( token );
break;
case MATERIALS:
Parse_MATERIALS( token );
break;
case MESHES:
Parse_MESHES( token );
break;
case TEXTURES:
Parse_TEXTURES( token );
break;
case IMAGES:
Parse_IMAGES( token );
break;
case ACCESSORS:
Parse_ACCESSORS( token );
break;
case BUFFERVIEWS:
//Parse_BUFFERVIEWS( token );
if( !bufferViewsDone )
{
common->FatalError( "Bufferviews should already be parsed!" );
}
break;
case SAMPLERS:
Parse_SAMPLERS( token );
break;
case BUFFERS:
if( !buffersDone )
{
common->FatalError( "Buffers should already be parsed!" );
}
break;
case ANIMATIONS:
Parse_ANIMATIONS( token );
break;
case SKINS:
Parse_SKINS( token );
break;
case EXTENSIONS:
Parse_EXTENSIONS( token );
break;
case EXTENSIONS_USED:
Parse_EXTENSIONS_USED( token );
break;
case EXTENSIONS_REQUIRED:
Parse_EXTENSIONS_REQUIRED( token );
break;
default:
common->FatalError( "UnImplemented GLTF property : %s", token.c_str() );
}
return prop;
}
2022-06-18 09:09:09 +00:00
gltfProperty GLTF_Parser::ResolveProp( idToken& token )
{
2022-06-18 08:43:30 +00:00
if( !idStr::Icmp( token.c_str(), "asset" ) )
{
return gltfProperty::ASSET;
}
2022-06-18 08:43:30 +00:00
else if( !idStr::Icmp( token.c_str(), "cameras" ) )
{
return gltfProperty::CAMERAS;
}
2022-06-18 08:43:30 +00:00
else if( !idStr::Icmp( token.c_str(), "scene" ) )
{
return gltfProperty::SCENE;
}
2022-06-18 08:43:30 +00:00
else if( !idStr::Icmp( token.c_str(), "scenes" ) )
{
return gltfProperty::SCENES;
}
2022-06-18 08:43:30 +00:00
else if( !idStr::Icmp( token.c_str(), "nodes" ) )
{
return gltfProperty::NODES;
}
2022-06-18 08:43:30 +00:00
else if( !idStr::Icmp( token.c_str(), "materials" ) )
{
return gltfProperty::MATERIALS;
}
2022-06-18 08:43:30 +00:00
else if( !idStr::Icmp( token.c_str(), "meshes" ) )
{
return gltfProperty::MESHES;
}
2022-06-18 08:43:30 +00:00
else if( !idStr::Icmp( token.c_str(), "textures" ) )
{
return gltfProperty::TEXTURES;
}
2022-06-18 08:43:30 +00:00
else if( !idStr::Icmp( token.c_str(), "images" ) )
{
return gltfProperty::IMAGES;
}
2022-06-18 08:43:30 +00:00
else if( !idStr::Icmp( token.c_str(), "accessors" ) )
{
return gltfProperty::ACCESSORS;
}
2022-06-18 08:43:30 +00:00
else if( !idStr::Icmp( token.c_str(), "bufferViews" ) )
{
return gltfProperty::BUFFERVIEWS;
}
2022-06-18 08:43:30 +00:00
else if( !idStr::Icmp( token.c_str(), "samplers" ) )
{
return gltfProperty::SAMPLERS;
}
2022-06-18 08:43:30 +00:00
else if( !idStr::Icmp( token.c_str(), "buffers" ) )
{
return gltfProperty::BUFFERS;
}
2022-06-18 08:43:30 +00:00
else if( !idStr::Icmp( token.c_str(), "animations" ) )
{
return gltfProperty::ANIMATIONS;
}
2022-06-18 08:43:30 +00:00
else if( !idStr::Icmp( token.c_str(), "skins" ) )
{
return gltfProperty::SKINS;
}
2022-06-18 08:43:30 +00:00
else if( !idStr::Icmp( token.c_str(), "extensions" ) )
{
return gltfProperty::EXTENSIONS;
}
2022-06-18 08:43:30 +00:00
else if( !idStr::Icmp( token.c_str(), "extensionsused" ) )
{
return gltfProperty::EXTENSIONS_USED;
}
2022-06-18 08:43:30 +00:00
else if( !idStr::Icmp( token.c_str(), "extensionsrequired" ) )
{
return gltfProperty::EXTENSIONS_REQUIRED;
}
return gltfProperty::INVALID;
}
bool GLTF_Parser::loadGLB( idStr filename )
{
if( fileSystem->GetFileLength( filename ) <= 0 )
{
common->Warning( " %s does not exist!", filename.c_str() );
return false;
}
idFile* file = fileSystem->OpenFileRead( filename );
if( file->Length() < 20 )
{
common->FatalError( "Too short data size for glTF Binary." );
return false;
}
idStr gltfMagic( "glTF" );
unsigned char fileMagic[5];
file->Read( ( void* )&fileMagic, 4 );
fileMagic[4] = 0;
if( gltfMagic.Icmp( ( const char* )&fileMagic ) == 0 )
{
common->Printf( "reading %s...\n", filename.c_str() );
}
else
{
common->Error( "invalid magic" );
return false;
}
unsigned int version = 0; // 4 bytes
unsigned int length = 0; // 4 bytes
//HVG_TODO
//handle 0 bin chunk -> size is chunk[0].size + 20;
file->ReadUnsignedInt( version );
file->ReadUnsignedInt( length );
length -= 12; // header size
unsigned int chunk_type = 0; // 4 bytes
unsigned int chunk_length = 0; // 4 bytes
byte* data = nullptr;
gltfData* dataCache = gltfData::Data( filename, true );
currentAsset = dataCache;
int chunkCount = 0;
while( length )
{
unsigned int prev_length = chunk_length;
length -= file->ReadUnsignedInt( chunk_length );
length -= file->ReadUnsignedInt( chunk_type );
data = dataCache->AddData( chunk_length );
int read = file->Read( ( void* )data, chunk_length );
if( read != chunk_length )
{
common->FatalError( "Could not read full chunk (%i bytes) in file %s", chunk_length, filename.c_str() );
}
length -= read;
if( chunk_type == gltfChunk_Type_JSON )
{
currentFile = filename ;
parser.LoadMemory( ( const char* )data, chunk_length, "gltfJson", 0 );
}
else if( !chunkCount )
{
common->FatalError( "first chunk was not a json chunk" );
}
else
{
common->Printf( "BINCHUNK %i %i bytes\n", chunkCount, chunk_length );
}
if( chunkCount++ && length )
{
common->FatalError( "corrupt glb file." );
}
}
Parse();
delete file;
return true;
}
2022-06-18 08:43:30 +00:00
bool GLTF_Parser::Parse()
{
bool parsing = true;
parser.ExpectTokenString( "{" );
while( parsing && parser.ExpectAnyToken( &token ) )
{
if( token.type != TT_STRING )
{
common->FatalError( "Expected an \"string\" " );
}
2022-06-18 08:43:30 +00:00
if( gltf_parseVerbose.GetBool() )
{
2022-06-18 08:43:30 +00:00
common->Printf( token.c_str() );
}
gltfProperty prop = ParseProp( token );
if( ( prop == BUFFERS && !buffersDone ) )
{
parser.Reset();
parser.ExpectTokenString( "{" );
buffersDone = true;
continue;
}
if( ( prop == BUFFERVIEWS && !bufferViewsDone ) )
{
2022-06-18 08:43:30 +00:00
parser.Reset();
parser.ExpectTokenString( "{" );
bufferViewsDone = true;
continue;
}
2022-06-18 08:43:30 +00:00
if( gltf_parseVerbose.GetBool() )
{
common->Printf( "\n" );
}
parsing = parser.PeekTokenString( "," );
if( parsing )
{
parser.ExpectTokenString( "," );
}
else
{
//we are at the end, and no bufferview or buffer has been found.
if( !buffersDone || !bufferViewsDone )
{
if( !buffersDone )
{
buffersDone = true;
common->Printf( "no %s found", "buffers" );
}
if( !bufferViewsDone )
{
common->Printf( "no %s found", "bufferviews" );
bufferViewsDone = true;
}
2022-06-18 08:43:30 +00:00
parser.Reset();
parser.ExpectTokenString( "{" );
parsing = true;
continue;
}
parser.ExpectTokenString( "}" );
}
}
//parser should be at end.
#if 0
// RB: this results into a random "Unknown punctuation" error sometimes
parser.ReadToken( &token );
2022-06-18 08:43:30 +00:00
if( parser.EndOfFile() )
{
2022-06-18 08:43:30 +00:00
common->Printf( "%s ^2loaded\n", currentFile.c_str() );
}
else
{
common->FatalError( "%s not fully loaded.", currentFile.c_str() );
}
#else
common->Printf( "%s ^2loaded\n", currentFile.c_str() );
#endif
buffersDone = false;
bufferViewsDone = false;
return true;
}
bool GLTF_Parser::Load( idStr filename )
{
//.. and destroy data !!
gltfData* data = gltfData::Data( filename );
currentFile = filename;
if( data != nullptr )
{
currentAsset = data;
parser.FreeSource();
return true;
}
common->SetRefreshOnPrint( true );
if( filename.CheckExtension( ".glb" ) )
{
if( !loadGLB( filename ) )
{
return false;
}
}
else if( filename.CheckExtension( ".gltf" ) )
{
int length = fileSystem->ReadFile( filename, NULL );
if( !length )
{
common->FatalError( "Failed to read file" );
}
data = gltfData::Data( filename , true );
byte* dataBuff = data->AddData( length );
currentAsset = data;
idFile* file = fileSystem->OpenFileRead( filename );
if( file->Read( dataBuff, length ) != length )
{
common->FatalError( "Cannot read file, %s", filename.c_str() );
}
fileSystem->CloseFile( file );
if( !parser.LoadMemory( ( const char* )dataBuff, length, "GLTF_ASCII_JSON", 0 ) )
{
return false;
}
Parse();
}
else
{
return false;
}
parser.Reset();
parser.FreeSource();
common->SetRefreshOnPrint( false );
//fix up node hierarchy
2022-06-18 08:43:30 +00:00
auto& nodeList = currentAsset->NodeList();
for( auto& scene : currentAsset->SceneList() )
{
for( auto& node : scene->nodes )
{
SetNodeParent( nodeList[node] );
}
}
//set skeleton ID's
for( auto* skin : currentAsset->SkinList() )
{
if( skin->skeleton == -1 )
{
skin->skeleton = currentAsset->GetNodeIndex( currentAsset->GetNode( skin->name ) );
}
}
//prefix with id
if( gltfParser_PrefixNodeWithID.GetBool() )
{
for( int i = 0; i < nodeList.Num(); i++ )
{
nodeList[i]->name = "[" + idStr( i ) + "]" + nodeList[i]->name;
}
}
//CreateBgfxData();
return true;
}
void GLTF_Parser::SetNodeParent( gltfNode* node, gltfNode* parent )
{
node->parent = parent;
for( auto& child : node->children )
{
SetNodeParent( currentAsset->NodeList()[child], node );
}
}
idList<float>& gltfData::GetAccessorView( gltfAccessor* accessor )
{
idList<float>*& floatView = accessor->floatView;;
if( floatView == nullptr )
{
gltfBufferView* attrBv = bufferViews[accessor->bufferView];
gltfData* attrData = attrBv->parent;
2022-06-18 08:43:30 +00:00
gltfBuffer* attrbuff = attrData->BufferList()[attrBv->buffer];
assert( sizeof( float ) == accessor->typeSize );
idFile_Memory bin = idFile_Memory( "GetAccessorView(float)",
( const char* )( ( attrData->GetData( attrBv->buffer ) + attrBv->byteOffset + accessor->byteOffset ) ), attrBv->byteLength );
floatView = new idList<float>( 16 );
floatView->AssureSize( accessor->count );
for( int i = 0; i < accessor->count; i++ )
{
bin.Read( ( void* ) & ( *floatView )[i] , accessor->typeSize );
}
if( attrBv->byteStride )
{
bin.Seek( attrBv->byteStride - ( accessor->typeSize ), FS_SEEK_CUR );
}
}
return *floatView;
}
idList<idMat4>& gltfData::GetAccessorViewMat( gltfAccessor* accessor )
{
idList<idMat4>*& matView = accessor->matView;
if( matView == nullptr )
{
gltfBufferView* attrBv = bufferViews[accessor->bufferView];
gltfData* attrData = attrBv->parent;
2022-06-18 08:43:30 +00:00
gltfBuffer* attrbuff = attrData->BufferList()[attrBv->buffer];
assert( sizeof( float ) == accessor->typeSize );
idFile_Memory bin = idFile_Memory( "GetAccessorView(idMat4*)",
( const char* )( ( attrData->GetData( attrBv->buffer ) + attrBv->byteOffset + accessor->byteOffset ) ), attrBv->byteLength );
size_t elementSize = accessor->typeSize * 16;
matView = new idList<idMat4>( 16 );
matView->AssureSize( accessor->count );
for( int i = 0; i < accessor->count; i++ )
{
bin.Read( ( void* ) & ( *matView )[i] , elementSize );
}
if( attrBv->byteStride )
{
bin.Seek( attrBv->byteStride - elementSize, FS_SEEK_CUR );
}
}
return *matView;
}
template <>
idList<idVec3*>& gltfData::GetAccessorView( gltfAccessor* accessor )
{
idList<idVec3*>*& vecView = accessor->vecView;
if( vecView == nullptr )
{
gltfBufferView* attrBv = bufferViews[accessor->bufferView];
gltfData* attrData = attrBv->parent;
2022-06-18 08:43:30 +00:00
gltfBuffer* attrbuff = attrData->BufferList()[attrBv->buffer];
assert( sizeof( float ) == accessor->typeSize );
idFile_Memory bin = idFile_Memory( "GetAccessorView(idVec3*)",
( const char* )( ( attrData->GetData( attrBv->buffer ) + attrBv->byteOffset + accessor->byteOffset ) ), attrBv->byteLength );
vecView = new idList<idVec3*>( 16 );
vecView->AssureSizeAlloc( accessor->count, idListNewElement<idVec3> );
for( int i = 0; i < accessor->count; i++ )
{
idVec3& vec = *( *vecView )[i];
bin.Read( ( void* ) &vec.x , accessor->typeSize );
bin.Read( ( void* ) &vec.y , accessor->typeSize );
bin.Read( ( void* ) &vec.z , accessor->typeSize );
}
if( attrBv->byteStride )
{
bin.Seek( attrBv->byteStride - ( 3 * accessor->typeSize ), FS_SEEK_CUR );
}
}
return *vecView;
}
template <>
idList<idQuat*>& gltfData::GetAccessorView( gltfAccessor* accessor )
{
idList<idQuat*>*& quatView = accessor->quatView;
if( quatView == nullptr )
{
gltfBufferView* attrBv = bufferViews[accessor->bufferView];
gltfData* attrData = attrBv->parent;
2022-06-18 08:43:30 +00:00
gltfBuffer* attrbuff = attrData->BufferList()[attrBv->buffer];
assert( sizeof( float ) == accessor->typeSize );
idFile_Memory bin = idFile_Memory( "GetAccessorView(idQuat*)",
( const char* )( ( attrData->GetData( attrBv->buffer ) + attrBv->byteOffset + accessor->byteOffset ) ), attrBv->byteLength );
quatView = new idList<idQuat*>( 16 );
quatView->AssureSizeAlloc( accessor->count, idListNewElement<idQuat> );
for( int i = 0; i < accessor->count; i++ )
{
idQuat& vec = *( *quatView )[i];
bin.Read( ( void* ) &vec.x, accessor->typeSize );
bin.Read( ( void* ) &vec.y, accessor->typeSize );
bin.Read( ( void* ) &vec.z, accessor->typeSize );
bin.Read( ( void* ) &vec.w, accessor->typeSize );
}
if( attrBv->byteStride )
{
bin.Seek( attrBv->byteStride - ( 4 * accessor->typeSize ), FS_SEEK_CUR );
}
}
return *quatView;
}
gltfData::~gltfData()
{
if( data )
{
while( totalChunks )
{
Mem_Free( data[--totalChunks] );
}
Mem_Free( data );
}
if( json )
{
Mem_Free( json );
}
data = nullptr;
json = nullptr;
ClearData( fileName );
}
void gltfData::ClearData( idStr& fileName )
{
int key = fileDataHash.GenerateKey( fileName );
int index = fileDataHash.GetFirst( key );
if( index != -1 )
{
dataList.RemoveIndex( index );
dataList.Condense();
fileDataHash.RemoveIndex( key, index );
}
else
{
2022-08-15 10:23:38 +00:00
common->DWarning( " tried to clear GLTF data while no data was loaded for %s", fileName.c_str() );
}
}
#undef GLTFARRAYITEM
#undef GLTFARRAYITEMREF
CONSOLE_COMMAND( LoadGLTF, "Loads an .gltf or .glb file", idCmdSystem::ArgCompletion_MapName )
{
2022-06-18 08:43:30 +00:00
if( args.Argc() > 1 )
{
GLTF_Parser gltf;
gltf.Load( args.Argv( 1 ) );
}
}
//+set r_fullscreen 0 +set com_allowConsole 1 +set developer 1 +set fs_debug 0 +set win_outputDebugString 1 +set fs_basepath "E:\SteamLibrary\steamapps\common\DOOM 3 BFG Edition\"
// not dots allowed in [%s]!
2022-07-31 10:13:07 +00:00
// [filename].[%i|%s].[gltf|glb]
bool gltfManager::ExtractIdentifier( idStr& filename, int& id, idStr& name )
{
idStr extension;
idStr targetStr;
filename.ExtractFileExtension( extension );
idStr file = filename;
file = file.StripFileExtension();
file.ExtractFileExtension( targetStr );
2023-04-08 16:47:27 +00:00
id = -1;
if( !extension.Length() )
{
idLib::Warning( "no gltf identifier" );
return false;
}
if( targetStr.Length() )
{
filename = file.Left( file.Length() - targetStr.Length() - 1 ) + "." + extension;
idParser parser( LEXFL_ALLOWPATHNAMES | LEXFL_NOSTRINGESCAPECHARS );
parser.LoadMemory( targetStr.c_str(), targetStr.Size(), "model:GltfID" );
idToken token;
if( parser.ExpectAnyToken( &token ) )
{
if( ( token.type == TT_NUMBER ) && ( token.subtype & TT_INTEGER ) )
{
id = token.GetIntValue();
}
else if( token.type == TT_NAME )
{
name = token;
}
else
{
parser.Warning( "malformed gltf mesh identifier" );
return false;
}
return true;
}
else
{
parser.Warning( "malformed gltf mesh identifier" );
}
}
return false;
}