[!] Fixed runtime reloading for gltf models

[!] Fixed timestamp check for static models
This commit is contained in:
HarrievG 2022-11-10 22:01:48 +01:00 committed by Robert Beckebans
parent e9284c3818
commit 3d366ba386
6 changed files with 89 additions and 32 deletions

View file

@ -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 )
{

View file

@ -401,11 +401,6 @@ public:
{
return false;
}
const idVec3& TotalMovementDelta() const
{
static idVec3 temp;
return temp;
}
int NumFrames() const
{
return numFrames;

View file

@ -315,8 +315,12 @@ void idRenderModelStatic::InitFromFile( const char* fileName )
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;

View file

@ -291,6 +291,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 ) )
@ -307,7 +314,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() )
{
@ -315,7 +337,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
@ -342,7 +371,7 @@ idRenderModel* idRenderModelManagerLocal::GetModel( const char* _modelName, bool
idRenderModel* model = NULL;
// HvG: GLTF 2 support
if( ( extension.Icmp( GLTF_GLB_EXT ) == 0 ) || ( extension.Icmp( GLTF_EXT ) == 0 ) )
if( isGLTF )
{
model = new( TAG_MODEL ) idRenderModelGLTF;
}
@ -615,22 +644,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, &current );
if( isGltf )
{
idStr meshName;
int meshID = -1;
gltfManager::ExtractIdentifier( name, meshID, meshName );
}
fileSystem->ReadFile( name, NULL, &current );
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

View file

@ -149,7 +149,7 @@ void idRenderModelGLTF::InitFromFile( const char* fileName )
//FIXME FIXME FIXME
maxJointVertDist = 10;
idStr gltfFileName = idStr( fileName );
gltfFileName = idStr( fileName );
model_state = DM_STATIC;
gltfManager::ExtractIdentifier( gltfFileName, meshID, meshName );
@ -162,13 +162,13 @@ void idRenderModelGLTF::InitFromFile( const char* fileName )
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] )
@ -212,7 +212,7 @@ void idRenderModelGLTF::InitFromFile( const char* fileName )
if( tmpNode->skin >= 0 )
{
currentSkin = data->SkinList()[tmpNode->skin];
assert( currentSkin );
idassert( currentSkin );
if( currentSkin->joints.Num() )
{
bones.Append( currentSkin->joints );
@ -237,6 +237,7 @@ void idRenderModelGLTF::InitFromFile( const char* fileName )
{
common->Warning( "Couldn't load model: '%s'", name.c_str() );
MakeDefaultModel();
data = nullptr;
return;
}
@ -244,6 +245,7 @@ void idRenderModelGLTF::InitFromFile( const char* fileName )
// derive mikktspace tangents from normals
FinishSurfaces( true );
LoadModel();
UpdateMd5Joints();
@ -259,6 +261,7 @@ bool idRenderModelGLTF::LoadBinaryModel( idFile* file, const ID_TIME_T sourceTim
if( !idRenderModelStatic::LoadBinaryModel( file, sourceTimeStamp ) )
{
data = nullptr;
return false;
}
@ -267,6 +270,7 @@ bool idRenderModelGLTF::LoadBinaryModel( idFile* file, const ID_TIME_T sourceTim
if( magic != GLMB_MAGIC )
{
data = nullptr;
return false;
}
@ -343,6 +347,7 @@ bool idRenderModelGLTF::LoadBinaryModel( idFile* file, const ID_TIME_T sourceTim
model_state = hasAnimations ? DM_CONTINUOUS : DM_STATIC;
lastMeshFromFile = this;
data = nullptr;
return true;
}
@ -355,7 +360,7 @@ const idMD5Joint* idRenderModelGLTF::FindMD5Joint( const idStr& name ) const
return &joint;
}
}
assert( 0 );
idassert( 0 );
static idMD5Joint staticJoint;
return &staticJoint;
}
@ -488,7 +493,7 @@ bool gatherBoneInfo( gltfData* data, gltfAnimation* gltfAnim, const idList<gltfN
{
skin = data->GetSkin( targetNode );
}
assert( skin );
idassert( skin );
bones.Append( skin->joints );
}
else
@ -586,7 +591,7 @@ int copyBones( gltfData* data, const idList<int>& bones, idList<gltfNode>& out )
idFile_Memory* idRenderModelGLTF::GetAnimBin( idStr animName , const ID_TIME_T sourceTimeStamp )
{
assert( lastMeshFromFile );
idassert( lastMeshFromFile );
///keep in sync with game!
static const byte B_ANIM_MD5_VERSION = 101;
static const unsigned int B_ANIM_MD5_MAGIC = ( 'B' << 24 ) | ( 'M' << 16 ) | ( 'D' << 8 ) | B_ANIM_MD5_VERSION;
@ -696,7 +701,7 @@ idFile_Memory* idRenderModelGLTF::GetAnimBin( idStr animName , const ID_TIME_T
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() );
@ -815,7 +820,7 @@ idFile_Memory* idRenderModelGLTF::GetAnimBin( idStr animName , const ID_TIME_T
}
}
assert( componentFrames.Num() == ( componentFrameIndex + 1 ) );
idassert( componentFrames.Num() == ( componentFrameIndex + 1 ) );
bounds.SetGranularity( 1 );
bounds.AssureSize( numFrames );
@ -1049,6 +1054,7 @@ void idRenderModelGLTF::WriteBinaryModel( idFile* file, ID_TIME_T* _timeStamp /*
void idRenderModelGLTF::PurgeModel()
{
idRenderModelStatic::PurgeModel();
purged = true;
md5joints.Clear();
defaultPose.Clear();
@ -1057,16 +1063,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();
@ -1074,6 +1084,7 @@ void idRenderModelGLTF::LoadModel()
if( !fileExclusive )
{
meshRoot = data->GetNode( gltf_ModelSceneName.GetString(), meshName );
idassert( meshRoot );
}
gltfSkin* skin = nullptr;
@ -1462,9 +1473,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();
}
@ -1484,8 +1492,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
@ -1523,7 +1531,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() );
@ -1552,7 +1560,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 );
}

View file

@ -73,6 +73,7 @@ private:
idList<int, TAG_MODEL> MeshNodeIds;
dynamicModel_t model_state;
idStr meshName;
idStr gltfFileName;
idList<idMD5Joint, TAG_MODEL> md5joints;
idList<idJointQuat, TAG_MODEL> defaultPose;