diff --git a/neo/d3xp/Camera.cpp b/neo/d3xp/Camera.cpp index 6e9d2435..d858700d 100644 --- a/neo/d3xp/Camera.cpp +++ b/neo/d3xp/Camera.cpp @@ -3,6 +3,7 @@ Doom 3 BFG Edition GPL Source Code Copyright (C) 1993-2012 id Software LLC, a ZeniMax Media company. +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"). @@ -30,7 +31,10 @@ If you have questions concerning this license or the applicable additional terms #pragma hdrstop #include "Game_local.h" +#include "gltfParser.h" + +static const idMat4 blenderToDoomTransform( idAngles( 0.0f, 0.0f, 90 ).ToMat3(), vec3_origin ); /* =============================================================================== @@ -363,6 +367,10 @@ void idCameraAnim::LoadAnim() int i; idStr filename; const char* key; + idStr gltfFileName; + int animID = -1; + idStr animName; + bool isGLTF = false; key = spawnArgs.GetString( "anim" ); if( !key ) @@ -373,86 +381,102 @@ void idCameraAnim::LoadAnim() filename = spawnArgs.GetString( va( "anim %s", key ) ); if( !filename.Length() ) { - // RB: TrenchBroom interop use anim. instead so we can build this up using the FGD files - filename = spawnArgs.GetString( va( "anim.%s", key ) ); - if( !filename.Length() ) + gltfFileName = key; + gltfManager::ExtractIdentifier( gltfFileName, animID, animName ); + if( animName.Length() ) { - gameLocal.Error( "Missing 'anim.%s' key on '%s'", key, name.c_str() ); + isGLTF = true; } - // RB end - } - - filename.SetFileExtension( MD5_CAMERA_EXT ); - if( !parser.LoadFile( filename ) ) - { - gameLocal.Error( "Unable to load '%s' on '%s'", filename.c_str(), name.c_str() ); - } - - cameraCuts.Clear(); - cameraCuts.SetGranularity( 1 ); - camera.Clear(); - camera.SetGranularity( 1 ); - - parser.ExpectTokenString( MD5_VERSION_STRING ); - version = parser.ParseInt(); - if( version != MD5_VERSION ) - { - parser.Error( "Invalid version %d. Should be version %d\n", version, MD5_VERSION ); - } - - // skip the commandline - parser.ExpectTokenString( "commandline" ); - parser.ReadToken( &token ); - - // parse num frames - parser.ExpectTokenString( "numFrames" ); - numFrames = parser.ParseInt(); - if( numFrames <= 0 ) - { - parser.Error( "Invalid number of frames: %d", numFrames ); - } - - // parse framerate - parser.ExpectTokenString( "frameRate" ); - frameRate = parser.ParseInt(); - if( frameRate <= 0 ) - { - parser.Error( "Invalid framerate: %d", frameRate ); - } - - // parse num cuts - parser.ExpectTokenString( "numCuts" ); - numCuts = parser.ParseInt(); - if( ( numCuts < 0 ) || ( numCuts > numFrames ) ) - { - parser.Error( "Invalid number of camera cuts: %d", numCuts ); - } - - // parse the camera cuts - parser.ExpectTokenString( "cuts" ); - parser.ExpectTokenString( "{" ); - cameraCuts.SetNum( numCuts ); - for( i = 0; i < numCuts; i++ ) - { - cameraCuts[ i ] = parser.ParseInt(); - if( ( cameraCuts[ i ] < 1 ) || ( cameraCuts[ i ] >= numFrames ) ) + else { - parser.Error( "Invalid camera cut" ); + // RB: TrenchBroom interop use anim. instead so we can build this up using the FGD files + filename = spawnArgs.GetString( va( "anim.%s", key ) ); + if( !filename.Length() ) + { + gameLocal.Error( "Missing 'anim.%s' key on '%s'", key, name.c_str() ); + } + // RB end } } - parser.ExpectTokenString( "}" ); - // parse the camera frames - parser.ExpectTokenString( "camera" ); - parser.ExpectTokenString( "{" ); - camera.SetNum( numFrames ); - for( i = 0; i < numFrames; i++ ) + if( isGLTF ) { - parser.Parse1DMatrix( 3, camera[ i ].t.ToFloatPtr() ); - parser.Parse1DMatrix( 3, camera[ i ].q.ToFloatPtr() ); - camera[ i ].fov = parser.ParseFloat(); + gltfLoadAnim( gltfFileName, animName ); + } + else + { + filename.SetFileExtension( MD5_CAMERA_EXT ); + if( !parser.LoadFile( filename ) ) + { + gameLocal.Error( "Unable to load '%s' on '%s'", filename.c_str(), name.c_str() ); + } + + cameraCuts.Clear(); + cameraCuts.SetGranularity( 1 ); + camera.Clear(); + camera.SetGranularity( 1 ); + + parser.ExpectTokenString( MD5_VERSION_STRING ); + version = parser.ParseInt(); + if( version != MD5_VERSION ) + { + parser.Error( "Invalid version %d. Should be version %d\n", version, MD5_VERSION ); + } + + // skip the commandline + parser.ExpectTokenString( "commandline" ); + parser.ReadToken( &token ); + + // parse num frames + parser.ExpectTokenString( "numFrames" ); + numFrames = parser.ParseInt(); + if( numFrames <= 0 ) + { + parser.Error( "Invalid number of frames: %d", numFrames ); + } + + // parse framerate + parser.ExpectTokenString( "frameRate" ); + frameRate = parser.ParseInt(); + if( frameRate <= 0 ) + { + parser.Error( "Invalid framerate: %d", frameRate ); + } + + // parse num cuts + parser.ExpectTokenString( "numCuts" ); + numCuts = parser.ParseInt(); + if( ( numCuts < 0 ) || ( numCuts > numFrames ) ) + { + parser.Error( "Invalid number of camera cuts: %d", numCuts ); + } + + // parse the camera cuts + parser.ExpectTokenString( "cuts" ); + parser.ExpectTokenString( "{" ); + cameraCuts.SetNum( numCuts ); + for( i = 0; i < numCuts; i++ ) + { + cameraCuts[i] = parser.ParseInt(); + if( ( cameraCuts[i] < 1 ) || ( cameraCuts[i] >= numFrames ) ) + { + parser.Error( "Invalid camera cut" ); + } + } + parser.ExpectTokenString( "}" ); + + // parse the camera frames + parser.ExpectTokenString( "camera" ); + parser.ExpectTokenString( "{" ); + camera.SetNum( numFrames ); + for( i = 0; i < numFrames; i++ ) + { + parser.Parse1DMatrix( 3, camera[i].t.ToFloatPtr() ); + parser.Parse1DMatrix( 3, camera[i].q.ToFloatPtr() ); + camera[i].fov = parser.ParseFloat(); + } + parser.ExpectTokenString( "}" ); } - parser.ExpectTokenString( "}" ); } /* @@ -692,6 +716,123 @@ void idCameraAnim::Event_Activate( idEntity* _activator ) } } +void idCameraAnim::gltfLoadAnim( idStr gltfFileName, idStr animName ) +{ + //we dont wat to load the gltb all the time. write custom binary format ! + GLTF_Parser gltf; + if( gltf.Load( gltfFileName ) ) + { + ID_TIME_T timeStamp = fileSystem->GetTimestamp( gltfFileName ); + gltfData* data = gltf.currentAsset; + auto& accessors = data->AccessorList(); + auto& nodes = data->NodeList(); + + gltfNode* cameraNode = data->GetNode( name ); + assert( cameraNode ); + + gltfAnimation* anim = data->GetAnimation( animName, data->GetNodeIndex( cameraNode ) ); + assert( anim ); + + cameraCuts.Clear(); + cameraCuts.SetGranularity( 1 ); + camera.Clear(); + camera.SetGranularity( 1 ); + frameRate = 24; + for( auto channel : anim->channels ) + { + auto* sampler = anim->samplers[channel->sampler]; + auto* input = accessors[sampler->input]; + auto* output = accessors[sampler->output]; + auto* target = nodes[channel->target.node]; + + idList& timeStamps = data->GetAccessorView( input ); + int frames = timeStamps.Num(); + if( !camera.Num() ) + { + cameraFrame_t t; + t.fov = 90; + t.q = mat3_identity.ToCQuat(); + t.t = vec3_origin; + for( int i = 0; i < frames; i++ ) + { + camera.Alloc() = t; + } + } + //This has to be replaced for correct interpolation between frames + for( int i = 0; i < frames; i++ ) + { + cameraFrame_t& cameraFrame = camera[i]; + + cameraFrame.fov = 90.0f; + switch( channel->target.TRS ) + { + default: + break; + case gltfAnimation_Channel_Target::none: + break; + case gltfAnimation_Channel_Target::rotation: + { + idList& values = data->GetAccessorView( output ); + if( values.Num() > i ) + { + + idQuat q = ( *values[i] ); + q = idAngles( 90.0f, 0.0, -90.0f ).ToQuat() + * q.Inverse() + * blenderToDoomTransform.ToMat3().ToQuat(); + cameraFrame.q = q.ToCQuat(); + + //This has to be replaced with correct interpolation between frames. + if( ( ( i + 1 ) == frames ) && ( frames < camera.Num() ) ) + { + while( i++ < camera.Num() - 1 ) + { + camera[i].q = cameraFrame.q; + } + } + } + + } + break; + case gltfAnimation_Channel_Target::translation: + { + idList& values = data->GetAccessorView( output ); + if( values.Num() > i ) + { + idVec3 val = *values[i]; + cameraFrame.t = blenderToDoomTransform * val; + + //This has to be replaced with correct interpolation between frames. + if( ( ( i + 1 ) == frames ) && ( frames < camera.Num() ) ) + { + while( i++ < camera.Num() - 1 ) + { + camera[i].t = cameraFrame.t; + } + } + } + } + break; + case gltfAnimation_Channel_Target::scale: + idList& values = data->GetAccessorView( output ); + if( values.Num() > i ) + { + gameLocal.Printf( "^5Frame: ^7%i ignored scale on /%s \n\n\n", i, anim->name.c_str() ); + } + break; + } + } + } + } + else + { + gameLocal.Error( "Missing 'anim' key on '%s'", name.c_str() ); + } + + + +} + /* =============== idCameraAnim::Event_Start diff --git a/neo/d3xp/Camera.h b/neo/d3xp/Camera.h index fc3e32ff..600da6ec 100644 --- a/neo/d3xp/Camera.h +++ b/neo/d3xp/Camera.h @@ -131,6 +131,8 @@ private: void Event_Stop(); void Event_SetCallback(); void Event_Activate( idEntity* activator ); + + void gltfLoadAnim( idStr gltfFileName, idStr animName ); }; #endif /* !__GAME_CAMERA_H__ */ diff --git a/neo/idlib/MapFile_gltf.cpp b/neo/idlib/MapFile_gltf.cpp index 182d3f00..e6349f9b 100644 --- a/neo/idlib/MapFile_gltf.cpp +++ b/neo/idlib/MapFile_gltf.cpp @@ -457,13 +457,15 @@ void ResolveLight( gltfData* data, idMapEntity* newEntity, gltfNode* node ) case gltfExt_KHR_lights_punctual::Spot: { + // RB: this code is based on Cmd_TestLight_f which sets the light properties in world space idMat4 entityToWorldTransform = mat4_identity; gltfData::ResolveNodeMatrix( node, &entityToWorldTransform ); - idMat4 worldToEntityTransform = entityToWorldTransform.Inverse(); - float fov = tan( light->spot.outerConeAngle ) / 2 ; - idMat3 axis = idAngles( 0.0f, 90.0f, 90.0f ).ToMat3() * entityToWorldTransform.ToMat3(); + // HarrievG: TODO cleanup this was done by try & error until it worked + idQuat q = ( entityToWorldTransform ).ToMat3().ToQuat(); + q = idAngles( 90.0f, 0.0, -90.0f ).ToQuat() * q * idAngles( 180.0f, 180.0f, -90.0f ).ToQuat(); + idMat3 axis = q.ToMat3(); newEntity->epairs.SetVector( "light_target", axis[0] ); newEntity->epairs.SetVector( "light_right", axis[1] * -fov ); newEntity->epairs.SetVector( "light_up", axis[2] * fov ); @@ -507,10 +509,13 @@ void ResolveEntity( gltfData* data, idMapEntity* newEntity, gltfNode* node ) newEntity->epairs = newPairs; // gather entity transform and bring it into id Tech 4 space - gltfData::ResolveNodeMatrix( node ); + idMat4 entityToWorldTransform = mat4_identity; + gltfData::ResolveNodeMatrix( node, &entityToWorldTransform ); // set entity transform in a way the game and physics code understand it idVec3 origin = blenderToDoomTransform * node->translation; + // RB: should be idVec3 origin = ( blenderToDoomTransform * entityToWorldTransform ).GetTranslation(); + newEntity->epairs.SetVector( "origin", origin ); if( node->extensions.KHR_lights_punctual != nullptr ) @@ -518,12 +523,32 @@ void ResolveEntity( gltfData* data, idMapEntity* newEntity, gltfNode* node ) ResolveLight( data, newEntity, node ); } - // TODO set rotation key to store rotation and scaling - //if (idStr::Icmp(classname, "info_player_start") == 0) - // if( !node->matrix.IsIdentity() ) - //{ - // newEntity->epairs.SetMatrix("rotation", axis ); - //} + // HarrievG: TODO cleanup this was done by try & error until it worked + if( node->camera >= 0 && !newEntity->epairs.FindKey( "rotation" ) ) + { + idQuat q = entityToWorldTransform.ToMat3().ToQuat(); + q = idAngles( 90.0f, 0.0, -90.0f ).ToQuat() * q * blenderToDoomTransform.ToMat3().ToQuat(); + newEntity->epairs.SetMatrix( "rotation", q.ToMat3() ); + } + else if( idStr::Icmp( classname, "info_player_start" ) == 0 && !newEntity->epairs.FindKey( "rotation" ) ) + { + idQuat q = entityToWorldTransform.ToMat3().ToQuat(); + q = idAngles( -90.0f, 0.0, -90.0f ).ToQuat() * q * blenderToDoomTransform.ToMat3().ToQuat(); + newEntity->epairs.SetMatrix( "rotation", q.ToMat3() ); + } + else if( node->extras.strPairs.GetBool( "useNodeOrientation", false ) ) + { + //Nodes that are an instance of an collection containing a mesh that is not inline, ea; a gltfModel; static _or_ dynamic, + //which has its transformations applied on vertex level so we do not apply it here. + origin = blenderToDoomTransform * ( node->translation * ( entityToWorldTransform * node->matrix.Inverse() ) ); + newEntity->epairs.SetVector( "origin", origin ); + + idQuat q = ( entityToWorldTransform * node->matrix.Inverse() ).ToMat3().ToQuat(); + q = blenderToDoomTransform.Inverse().ToMat3().ToQuat() * q * blenderToDoomTransform.ToMat3().ToQuat(); + idMat3 rot = q.ToMat3(); + //idMat3 rot = ( blenderToDoomTransform * entityToWorldTransform ).ToMat3(); + newEntity->epairs.SetMatrix( "rotation", rot ); + } #if 0 for( int i = 0; i < newEntity->epairs.GetNumKeyVals(); i++ ) diff --git a/neo/idlib/gltfParser.cpp b/neo/idlib/gltfParser.cpp index a0198180..5adc672f 100644 --- a/neo/idlib/gltfParser.cpp +++ b/neo/idlib/gltfParser.cpp @@ -1150,7 +1150,7 @@ void GLTF_Parser::Shutdown() bufferViewsDone = false; } GLTF_Parser::GLTF_Parser() - : parser( LEXFL_ALLOWPATHNAMES | LEXFL_ALLOWMULTICHARLITERALS | LEXFL_NOSTRINGESCAPECHARS | LEXFL_ALLOWPATHNAMES ) , buffersDone( false ), bufferViewsDone( false ) { } + : parser( LEXFL_ALLOWPATHNAMES | LEXFL_ALLOWMULTICHARLITERALS | LEXFL_NOSTRINGESCAPECHARS | LEXFL_ALLOWPATHNAMES ) , buffersDone( false ), bufferViewsDone( false ), currentAsset( nullptr ) { } void GLTF_Parser::Parse_ASSET( idToken& token ) { diff --git a/neo/idlib/gltfProperties.h b/neo/idlib/gltfProperties.h index 2e9aee96..dc5fb5dc 100644 --- a/neo/idlib/gltfProperties.h +++ b/neo/idlib/gltfProperties.h @@ -401,11 +401,6 @@ public: { return false; } - const idVec3& TotalMovementDelta() const - { - static idVec3 temp; - return temp; - } int NumFrames() const { return numFrames; diff --git a/neo/idlib/math/Matrix.h b/neo/idlib/math/Matrix.h index c78f1a72..1ada10ce 100644 --- a/neo/idlib/math/Matrix.h +++ b/neo/idlib/math/Matrix.h @@ -963,6 +963,7 @@ public: // jmarshall idMat3 ToMat3() const; // jmarshall end + idVec3 GetTranslation() const; private: idVec4 mat[ 4 ]; }; @@ -991,6 +992,19 @@ ID_INLINE idMat3 idMat4::ToMat3() const } // jmarshall end +// RB begin +ID_INLINE idVec3 idMat4::GetTranslation() const +{ + idVec3 pos; + + pos.x = mat[ 0 ][ 3 ]; + pos.y = mat[ 1 ][ 3 ]; + pos.z = mat[ 2 ][ 3 ]; + + return pos; +} +// RB end + ID_INLINE idMat4::idMat4() { } diff --git a/neo/renderer/Model.cpp b/neo/renderer/Model.cpp index 01fe18fa..744bb316 100644 --- a/neo/renderer/Model.cpp +++ b/neo/renderer/Model.cpp @@ -313,8 +313,12 @@ void idRenderModelStatic::InitFromFile( const char* fileName, const idImportOpti ID_TIME_T sourceTimeStamp; name.ExtractFileExtension( extension ); - - if( extension.Icmp( "ase" ) == 0 ) + if( extension.Icmp( "glb" ) == 0 || extension.Icmp( "gltf" ) == 0 ) + { + loaded = false; + reloadable = true; + } + else if( extension.Icmp( "ase" ) == 0 ) { loaded = LoadASE( name, &sourceTimeStamp ); reloadable = true; diff --git a/neo/renderer/ModelManager.cpp b/neo/renderer/ModelManager.cpp index 687035da..df99b669 100644 --- a/neo/renderer/ModelManager.cpp +++ b/neo/renderer/ModelManager.cpp @@ -292,6 +292,13 @@ idRenderModel* idRenderModelManagerLocal::GetModel( const char* _modelName, bool idStrStatic< MAX_OSPATH > extension; canonical.ExtractFileExtension( extension ); + bool isGLTF = false; + // HvG: GLTF 2 support + if( ( extension.Icmp( GLTF_GLB_EXT ) == 0 ) || ( extension.Icmp( GLTF_EXT ) == 0 ) ) + { + isGLTF = true; + } + // see if it is already present int key = hash.GenerateKey( canonical, false ); for( int i = hash.First( key ); i != -1; i = hash.Next( i ) ) @@ -308,7 +315,22 @@ idRenderModel* idRenderModelManagerLocal::GetModel( const char* _modelName, bool generatedFileName.SetFileExtension( va( "b%s", extension.c_str() ) ); // Get the timestamp on the original file, if it's newer than what is stored in binary model, regenerate it - ID_TIME_T sourceTimeStamp = fileSystem->GetTimestamp( canonical ); + + ID_TIME_T sourceTimeStamp; + + if( isGLTF ) + { + idStr gltfFileName = idStr( canonical ); + int gltfMeshId = -1; + idStr gltfMeshName; + gltfManager::ExtractIdentifier( gltfFileName, gltfMeshId, gltfMeshName ); + + sourceTimeStamp = fileSystem->GetTimestamp( gltfFileName ); + } + else + { + sourceTimeStamp = fileSystem->GetTimestamp( canonical ); + } if( model->SupportsBinaryModel() && binaryLoadRenderModels.GetBool() ) { @@ -316,7 +338,14 @@ idRenderModel* idRenderModelManagerLocal::GetModel( const char* _modelName, bool model->PurgeModel(); if( !model->LoadBinaryModel( file, sourceTimeStamp ) ) { - model->LoadModel(); + if( isGLTF ) + { + model->InitFromFile( canonical ); + } + else + { + model->LoadModel(); + } } } else @@ -344,7 +373,7 @@ idRenderModel* idRenderModelManagerLocal::GetModel( const char* _modelName, bool idRenderModel* model = NULL; bool isGLTF = false; // HvG: GLTF 2 support - if( ( extension.Icmp( GLTF_GLB_EXT ) == 0 ) || ( extension.Icmp( GLTF_EXT ) == 0 ) ) + if( isGLTF ) { model = new( TAG_MODEL ) idRenderModelGLTF; isGLTF = true; @@ -632,22 +661,42 @@ void idRenderModelManagerLocal::ReloadModels( bool forceAll ) { continue; } - + bool isGltf = false; + idStr name = model->Name(); + idStr extension; + idStr assetName = name; + assetName.ExtractFileExtension( extension ); + isGltf = extension.Icmp( "glb" ) == 0 || extension.Icmp( "gltf" ) == 0; if( !forceAll ) { // check timestamp ID_TIME_T current; - fileSystem->ReadFile( model->Name(), NULL, ¤t ); + if( isGltf ) + { + idStr meshName; + int meshID = -1; + gltfManager::ExtractIdentifier( name, meshID, meshName ); + } + + fileSystem->ReadFile( name, NULL, ¤t ); if( current <= model->Timestamp() ) { continue; } } - common->DPrintf( "reloading %s.\n", model->Name() ); + common->DPrintf( "^1Reloading %s.\n", model->Name() ); + + if( isGltf ) + { + model->InitFromFile( model->Name() ); + } + else + { + model->LoadModel(); + } - model->LoadModel(); } // we must force the world to regenerate, because models may diff --git a/neo/renderer/Model_gltf.cpp b/neo/renderer/Model_gltf.cpp index 45c5d2df..32e09820 100644 --- a/neo/renderer/Model_gltf.cpp +++ b/neo/renderer/Model_gltf.cpp @@ -150,7 +150,7 @@ void idRenderModelGLTF::InitFromFile( const char* fileName, const idImportOption //FIXME FIXME FIXME maxJointVertDist = 10; - idStr gltfFileName = idStr( fileName ); + gltfFileName = idStr( fileName ); model_state = DM_STATIC; gltfManager::ExtractIdentifier( gltfFileName, meshID, meshName ); @@ -163,13 +163,13 @@ void idRenderModelGLTF::InitFromFile( const char* fileName, const idImportOption bounds.Clear(); int sceneId = data->DefaultScene(); - assert( sceneId >= 0 ); + idassert( sceneId >= 0 ); auto scene = data->SceneList()[sceneId]; - assert( scene ); + idassert( scene ); auto nodes = data->NodeList(); - assert( nodes.Num() ); + idassert( nodes.Num() ); //determine root node if( !meshName[0] ) @@ -213,7 +213,7 @@ void idRenderModelGLTF::InitFromFile( const char* fileName, const idImportOption if( tmpNode->skin >= 0 ) { currentSkin = data->SkinList()[tmpNode->skin]; - assert( currentSkin ); + idassert( currentSkin ); if( currentSkin->joints.Num() ) { bones.Append( currentSkin->joints ); @@ -250,6 +250,7 @@ void idRenderModelGLTF::InitFromFile( const char* fileName, const idImportOption { common->Warning( "Couldn't load model: '%s'", name.c_str() ); MakeDefaultModel(); + data = nullptr; return; } @@ -257,6 +258,7 @@ void idRenderModelGLTF::InitFromFile( const char* fileName, const idImportOption // derive mikktspace tangents from normals FinishSurfaces( true ); + LoadModel(); UpdateMd5Joints(); @@ -272,6 +274,7 @@ bool idRenderModelGLTF::LoadBinaryModel( idFile* file, const ID_TIME_T sourceTim if( !idRenderModelStatic::LoadBinaryModel( file, sourceTimeStamp ) ) { + data = nullptr; return false; } @@ -280,6 +283,7 @@ bool idRenderModelGLTF::LoadBinaryModel( idFile* file, const ID_TIME_T sourceTim if( magic != GLMB_MAGIC ) { + data = nullptr; return false; } @@ -356,6 +360,7 @@ bool idRenderModelGLTF::LoadBinaryModel( idFile* file, const ID_TIME_T sourceTim model_state = hasAnimations ? DM_CONTINUOUS : DM_STATIC; lastMeshFromFile = this; + data = nullptr; return true; } @@ -368,7 +373,7 @@ const idMD5Joint* idRenderModelGLTF::FindMD5Joint( const idStr& name ) const return &joint; } } - assert( 0 ); + idassert( 0 ); static idMD5Joint staticJoint; return &staticJoint; } @@ -501,7 +506,7 @@ static bool GatherBoneInfo( gltfData* data, gltfAnimation* gltfAnim, const idLis { skin = data->GetSkin( targetNode ); } - assert( skin ); + idassert( skin ); bones.Append( skin->joints ); } else @@ -599,7 +604,7 @@ static int CopyBones( gltfData* data, const idList& bones, idList idFile_Memory* idRenderModelGLTF::GetAnimBin( const idStr& animName, const ID_TIME_T sourceTimeStamp, const idImportOptions* options ) { - assert( lastMeshFromFile ); + idassert( lastMeshFromFile ); //keep in sync with game! static const byte B_ANIM_MD5_VERSION = 101; @@ -718,7 +723,7 @@ idFile_Memory* idRenderModelGLTF::GetAnimBin( const idStr& animName, const ID_TI for( int i = 0; i < numFrames; i++ ) { int totalCopied = CopyBones( data, bones, animBones[i] ); - assert( totalCopied ); + idassert( totalCopied ); } gameLocal.Printf( "Total bones %i \n", bones.Num() ); @@ -844,7 +849,7 @@ idFile_Memory* idRenderModelGLTF::GetAnimBin( const idStr& animName, const ID_TI } } - assert( componentFrames.Num() == ( componentFrameIndex + 1 ) ); + idassert( componentFrames.Num() == ( componentFrameIndex + 1 ) ); bounds.SetGranularity( 1 ); bounds.AssureSize( numFrames ); @@ -1075,6 +1080,7 @@ void idRenderModelGLTF::WriteBinaryModel( idFile* file, ID_TIME_T* _timeStamp /* void idRenderModelGLTF::PurgeModel() { + idRenderModelStatic::PurgeModel(); purged = true; md5joints.Clear(); defaultPose.Clear(); @@ -1083,16 +1089,20 @@ void idRenderModelGLTF::PurgeModel() animIds.Clear(); bones.Clear(); MeshNodeIds.Clear(); + gltfFileName.Clear(); //if no root id was set, it is a generated one. if( rootID == -1 && root ) { delete root; } + data = nullptr; } void idRenderModelGLTF::LoadModel() { + idassert( data ); + int num; auto& accessors = data->AccessorList(); auto& nodes = data->NodeList(); @@ -1100,6 +1110,7 @@ void idRenderModelGLTF::LoadModel() if( !fileExclusive ) { meshRoot = data->GetNode( gltf_ModelSceneName.GetString(), meshName ); + idassert( meshRoot ); } gltfSkin* skin = nullptr; @@ -1488,9 +1499,6 @@ idRenderModel* idRenderModelGLTF::InstantiateDynamicModel( const struct renderEn if( purged ) { common->DWarning( "model %s instantiated while purged", Name() ); - GLTF_Parser gltf; - gltf.Load( name ); - data = gltf.currentAsset; LoadModel(); } @@ -1510,8 +1518,8 @@ idRenderModel* idRenderModelGLTF::InstantiateDynamicModel( const struct renderEn idRenderModelStatic* staticModel; if( cachedModel != NULL ) { - assert( dynamic_cast< idRenderModelStatic* >( cachedModel ) != NULL ); - assert( idStr::Icmp( cachedModel->Name(), GLTF_SnapshotName ) == 0 ); + idassert( dynamic_cast< idRenderModelStatic* >( cachedModel ) != NULL ); + idassert( idStr::Icmp( cachedModel->Name(), GLTF_SnapshotName ) == 0 ); staticModel = static_cast< idRenderModelStatic* >( cachedModel ); } else @@ -1549,7 +1557,7 @@ idRenderModel* idRenderModelGLTF::InstantiateDynamicModel( const struct renderEn } else { - assert( staticModel->numInvertedJoints == numInvertedJoints ); + idassert( staticModel->numInvertedJoints == numInvertedJoints ); } TransformJointsFast( staticModel->jointsInverted, md5joints.Num(), ent->joints, invertedDefaultPose.Ptr() ); @@ -1578,7 +1586,7 @@ idRenderModel* idRenderModelGLTF::InstantiateDynamicModel( const struct renderEn } UpdateSurface( ent, ent->joints, staticModel->jointsInverted, &surf, surfaces[surfIdx++] ); - assert( surf.geometry != NULL ); + idassert( surf.geometry != NULL ); surf.geometry->staticModelWithJoints = staticModel; staticModel->bounds.AddBounds( surf.geometry->bounds ); } diff --git a/neo/renderer/Model_gltf.h b/neo/renderer/Model_gltf.h index adff45a9..899013fb 100644 --- a/neo/renderer/Model_gltf.h +++ b/neo/renderer/Model_gltf.h @@ -73,6 +73,7 @@ private: idList MeshNodeIds; dynamicModel_t model_state; idStr meshName; + idStr gltfFileName; idList md5joints; idList defaultPose;