mirror of
https://github.com/id-Software/DOOM-3-BFG.git
synced 2025-03-14 22:50:45 +00:00
- Initial GLTF Animation Implementation. For now only supports boneless TRS animations without scale.
![only works with r_UseGpuSkinning 0]! - Writes bmd5anim for each animation. its not perfect yet but, rot + trans looks good. - Model tag supports gltf Animations. Indexed the same way as meshes. - Enabled weights and bone index in ConvertFromMeshGltf
This commit is contained in:
parent
833f112f4e
commit
edf657f50d
10 changed files with 1314 additions and 237 deletions
|
@ -633,7 +633,7 @@ bool idCollisionModelManagerLocal::LoadCollisionModelFile( const char* name, uns
|
|||
int id;
|
||||
idStr tmp;
|
||||
idStr file = fileName;
|
||||
gltfManager::ExtractMeshIdentifier( file, id, tmp );
|
||||
gltfManager::ExtractIdentifier( file, id, tmp );
|
||||
|
||||
currentTimeStamp = fileSystem->GetTimestamp( file );
|
||||
}
|
||||
|
|
|
@ -4574,7 +4574,7 @@ cmHandle_t idCollisionModelManagerLocal::LoadModel( const char* modelName, const
|
|||
int id;
|
||||
idStr tmp;
|
||||
idStr file = modelName;
|
||||
gltfManager::ExtractMeshIdentifier( file, id, tmp );
|
||||
gltfManager::ExtractIdentifier( file, id, tmp );
|
||||
|
||||
sourceTimeStamp = fileSystem->GetTimestamp( file );
|
||||
}
|
||||
|
|
|
@ -31,6 +31,8 @@ If you have questions concerning this license or the applicable additional terms
|
|||
|
||||
|
||||
#include "../Game_local.h"
|
||||
//should go before release?
|
||||
#include "renderer/Model_gltf.h"
|
||||
|
||||
idCVar binaryLoadAnim( "binaryLoadAnim", "1", 0, "enable binary load/write of idMD5Anim" );
|
||||
|
||||
|
@ -177,18 +179,47 @@ idMD5Anim::LoadAnim
|
|||
*/
|
||||
bool idMD5Anim::LoadAnim( const char* filename )
|
||||
{
|
||||
|
||||
idLexer parser( LEXFL_ALLOWPATHNAMES | LEXFL_NOSTRINGESCAPECHARS | LEXFL_NOSTRINGCONCAT );
|
||||
idToken token;
|
||||
idStr extension;
|
||||
idStr filenameStr = idStr( filename );
|
||||
filenameStr.ExtractFileExtension( extension );
|
||||
|
||||
idStr generatedFileName = "generated/anim/";
|
||||
generatedFileName.AppendPath( filename );
|
||||
generatedFileName.SetFileExtension( ".bMD5anim" );
|
||||
|
||||
// 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( filename );
|
||||
idStr gltfFileName = idStr( filename );
|
||||
int gltfAnimId = -1;
|
||||
idStr gltfAnimName;
|
||||
|
||||
|
||||
// Get the timestamp on the original file, if it's newer than what is stored in binary model, regenerate it
|
||||
ID_TIME_T sourceTimeStamp;
|
||||
|
||||
bool isGLTF = ( extension.Icmp( GLTF_GLB_EXT ) == 0 ) || ( extension.Icmp( GLTF_EXT ) == 0 ) ;
|
||||
|
||||
if( isGLTF )
|
||||
{
|
||||
gltfManager::ExtractIdentifier( gltfFileName, gltfAnimId, gltfAnimName );
|
||||
|
||||
sourceTimeStamp = fileSystem->GetTimestamp( gltfFileName );
|
||||
}
|
||||
else
|
||||
{
|
||||
sourceTimeStamp = fileSystem->GetTimestamp( filename );
|
||||
}
|
||||
|
||||
idFile* fileptr = fileSystem->OpenFileReadMemory( generatedFileName );
|
||||
bool doWrite = false;
|
||||
if( fileptr == nullptr && isGLTF )
|
||||
{
|
||||
fileptr = idRenderModelGLTF::GetAnimBin( filenameStr , sourceTimeStamp );
|
||||
doWrite = fileptr != nullptr;
|
||||
}
|
||||
|
||||
idFileLocal file( fileptr );
|
||||
|
||||
idFileLocal file( fileSystem->OpenFileReadMemory( generatedFileName ) );
|
||||
if( binaryLoadAnim.GetBool() && LoadBinary( file, sourceTimeStamp ) )
|
||||
{
|
||||
name = filename;
|
||||
|
@ -197,6 +228,14 @@ bool idMD5Anim::LoadAnim( const char* filename )
|
|||
// for resource gathering write this anim to the preload file for this map
|
||||
fileSystem->AddAnimPreload( name );
|
||||
}
|
||||
if( doWrite && binaryLoadAnim.GetBool( ) )
|
||||
{
|
||||
idLib::Printf( "Writing %s\n", generatedFileName.c_str( ) );
|
||||
fileptr->Seek( 0, FS_SEEK_SET );
|
||||
idFile_Memory* memFile = static_cast<idFile_Memory*>( fileptr );
|
||||
fileSystem->WriteFile( generatedFileName, memFile->GetDataPtr(), memFile->GetAllocated(), "fs_basepath" );
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -3361,7 +3361,7 @@ bool idDeclModelDef::Parse( const char* text, const int textLength, bool allowBi
|
|||
|
||||
// get the number of joints
|
||||
num = modelHandle->NumJoints();
|
||||
if( !num )
|
||||
if( !num && !isGltf )
|
||||
{
|
||||
src.Warning( "Model '%s' has no joints", filename.c_str() );
|
||||
}
|
||||
|
|
|
@ -204,30 +204,50 @@ MapPolygonMesh* MapPolygonMesh::ConvertFromMeshGltf( const gltfMesh_Primitive* p
|
|||
}
|
||||
break;
|
||||
}
|
||||
//case gltfMesh_Primitive_Attribute::Type::Weight:
|
||||
//{
|
||||
// for ( int i = 0; i < attrAcc->count; i++ ) {
|
||||
// bin.Read( ( void * ) ( &vtxData[i].weight.x ), attrAcc->typeSize );
|
||||
// bin.Read( ( void * ) ( &vtxData[i].weight.y ), attrAcc->typeSize );
|
||||
// bin.Read( ( void * ) ( &vtxData[i].weight.z ), attrAcc->typeSize );
|
||||
// bin.Read( ( void * ) ( &vtxData[i].weight.w ), attrAcc->typeSize );
|
||||
// if ( attrBv->byteStride )
|
||||
// bin.Seek( attrBv->byteStride - ( attrib->elementSize * attrAcc->typeSize ), FS_SEEK_CUR );
|
||||
// }
|
||||
// break;
|
||||
//}
|
||||
//case gltfMesh_Primitive_Attribute::Type::Indices:
|
||||
//{
|
||||
// for ( int i = 0; i < attrAcc->count; i++ ) {
|
||||
// bin.Read( ( void * ) ( &vtxData[i].boneIndex.x ), attrAcc->typeSize );
|
||||
// bin.Read( ( void * ) ( &vtxData[i].boneIndex.y ), attrAcc->typeSize );
|
||||
// bin.Read( ( void * ) ( &vtxData[i].boneIndex.z ), attrAcc->typeSize );
|
||||
// bin.Read( ( void * ) ( &vtxData[i].boneIndex.w ), attrAcc->typeSize );
|
||||
// if ( attrBv->byteStride )
|
||||
// bin.Seek( attrBv->byteStride - ( attrib->elementSize * attrAcc->typeSize ), FS_SEEK_CUR );
|
||||
// }
|
||||
// break;
|
||||
//}
|
||||
case gltfMesh_Primitive_Attribute::Type::Weight:
|
||||
{
|
||||
idVec4 vec;
|
||||
for( int i = 0; i < attrAcc->count; i++ )
|
||||
{
|
||||
bin.Read( ( void* )( &vec.x ), attrAcc->typeSize );
|
||||
bin.Read( ( void* )( &vec.y ), attrAcc->typeSize );
|
||||
bin.Read( ( void* )( &vec.z ), attrAcc->typeSize );
|
||||
bin.Read( ( void* )( &vec.w ), attrAcc->typeSize );
|
||||
if( attrBv->byteStride )
|
||||
{
|
||||
bin.Seek( attrBv->byteStride - ( attrib->elementSize * attrAcc->typeSize ), FS_SEEK_CUR );
|
||||
}
|
||||
|
||||
mesh->verts[i].color2[0] = vec.x;
|
||||
mesh->verts[i].color2[1] = vec.y;
|
||||
mesh->verts[i].color2[2] = vec.z;
|
||||
mesh->verts[i].color2[3] = vec.w;
|
||||
|
||||
}
|
||||
break;
|
||||
}
|
||||
case gltfMesh_Primitive_Attribute::Type::Indices:
|
||||
{
|
||||
idVec4 vec;
|
||||
for( int i = 0; i < attrAcc->count; i++ )
|
||||
{
|
||||
bin.Read( ( void* )( &vec.x ), attrAcc->typeSize );
|
||||
bin.Read( ( void* )( &vec.y ), attrAcc->typeSize );
|
||||
bin.Read( ( void* )( &vec.z ), attrAcc->typeSize );
|
||||
bin.Read( ( void* )( &vec.w ), attrAcc->typeSize );
|
||||
if( attrBv->byteStride )
|
||||
{
|
||||
bin.Seek( attrBv->byteStride - ( attrib->elementSize * attrAcc->typeSize ), FS_SEEK_CUR );
|
||||
}
|
||||
|
||||
mesh->verts[i].color[0] = vec.x;
|
||||
mesh->verts[i].color[1] = vec.y;
|
||||
mesh->verts[i].color[2] = vec.z;
|
||||
mesh->verts[i].color[3] = vec.w;
|
||||
}
|
||||
break;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -2319,38 +2319,38 @@ CONSOLE_COMMAND_COMPILE( LoadGLTF, "Loads an .gltf or .glb file", idCmdSystem::A
|
|||
|
||||
// not dots allowed in [%s]!
|
||||
// [filename].[%i|%s].[gltf/glb]
|
||||
bool gltfManager::ExtractMeshIdentifier( idStr& filename, int& meshId, idStr& meshName )
|
||||
bool gltfManager::ExtractIdentifier( idStr& filename, int& id, idStr& name )
|
||||
{
|
||||
idStr extension;
|
||||
idStr meshStr;
|
||||
idStr targetStr;
|
||||
filename.ExtractFileExtension( extension );
|
||||
idStr file = filename;
|
||||
file = file.StripFileExtension();
|
||||
file.ExtractFileExtension( meshStr );
|
||||
file.ExtractFileExtension( targetStr );
|
||||
|
||||
if( !extension.Length() )
|
||||
{
|
||||
idLib::Warning( "no gltf mesh identifier" );
|
||||
idLib::Warning( "no gltf identifier" );
|
||||
return false;
|
||||
}
|
||||
|
||||
if( meshStr.Length() )
|
||||
if( targetStr.Length() )
|
||||
{
|
||||
filename = file.Left( file.Length() - meshStr.Length() - 1 ) + "." + extension;
|
||||
filename = file.Left( file.Length() - targetStr.Length() - 1 ) + "." + extension;
|
||||
|
||||
idParser parser( LEXFL_ALLOWPATHNAMES | LEXFL_NOSTRINGESCAPECHARS );
|
||||
parser.LoadMemory( meshStr.c_str(), meshStr.Size(), "model:GltfmeshID" );
|
||||
parser.LoadMemory( targetStr.c_str(), targetStr.Size(), "model:GltfID" );
|
||||
|
||||
idToken token;
|
||||
if( parser.ExpectAnyToken( &token ) )
|
||||
{
|
||||
if( ( token.type == TT_NUMBER ) && ( token.subtype & TT_INTEGER ) )
|
||||
{
|
||||
meshId = token.GetIntValue();
|
||||
id = token.GetIntValue();
|
||||
}
|
||||
else if( token.type == TT_NAME )
|
||||
{
|
||||
meshName = token;
|
||||
name = token;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
|
@ -349,7 +349,7 @@ private:
|
|||
class gltfManager
|
||||
{
|
||||
public:
|
||||
static bool ExtractMeshIdentifier( idStr& filename , int& meshId, idStr& meshName );
|
||||
static bool ExtractIdentifier( idStr& filename , int& id, idStr& name );
|
||||
};
|
||||
|
||||
extern GLTF_Parser* gltfParser;
|
|
@ -943,6 +943,20 @@ public:
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
int GetNodeIndex( gltfNode* node )
|
||||
{
|
||||
int index = -1;
|
||||
for( auto* node : nodes )
|
||||
{
|
||||
index++;
|
||||
if( node == node )
|
||||
{
|
||||
return index;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
bool HasAnimation( int nodeID )
|
||||
{
|
||||
for( auto anim : animations )
|
||||
|
@ -958,6 +972,18 @@ public:
|
|||
return false;
|
||||
}
|
||||
|
||||
gltfAnimation* GetAnimation( idStr animName )
|
||||
{
|
||||
for( auto anim : animations )
|
||||
{
|
||||
if( anim->name == animName )
|
||||
{
|
||||
return anim;
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
int GetSceneId( idStr sceneName ) const
|
||||
{
|
||||
for( int i = 0; i < scenes.Num(); i++ )
|
||||
|
@ -970,6 +996,41 @@ public:
|
|||
return -1;
|
||||
}
|
||||
|
||||
idList<int> GetChannelIds( gltfAnimation* anim , gltfNode* node )
|
||||
{
|
||||
idList<int> result;
|
||||
int channelIdx = 0;
|
||||
for( auto channel : anim->channels )
|
||||
{
|
||||
if( channel->target.node >= 0 && nodes[channel->target.node] == node )
|
||||
{
|
||||
result.Append( channelIdx );
|
||||
break;
|
||||
}
|
||||
channelIdx++;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
idList<int> GetAnimationIds( gltfNode* node )
|
||||
{
|
||||
idList<int> result;
|
||||
int animIdx = 0;
|
||||
for( auto anim : animations )
|
||||
{
|
||||
for( auto channel : anim->channels )
|
||||
{
|
||||
if( channel->target.node >= 0 && nodes[channel->target.node] == node )
|
||||
{
|
||||
result.Append( animIdx );
|
||||
break;
|
||||
}
|
||||
}
|
||||
animIdx++;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
idMat4 GetViewMatrix( int camId ) const
|
||||
{
|
||||
//if (cameraManager->HasOverideID(camId) )
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -29,19 +29,6 @@ If you have questions concerning this license or the applicable additional terms
|
|||
#pragma once
|
||||
#include "Model_local.h"
|
||||
|
||||
|
||||
|
||||
class idGltfMesh
|
||||
{
|
||||
public:
|
||||
idGltfMesh( ) {};
|
||||
idGltfMesh( gltfMesh* _mesh, gltfData* _data );
|
||||
private:
|
||||
gltfMesh* mesh;
|
||||
gltfData* data;
|
||||
idMD5Mesh md5Mesh;
|
||||
};
|
||||
|
||||
class idRenderModelGLTF : public idRenderModelStatic
|
||||
{
|
||||
public:
|
||||
|
@ -67,20 +54,30 @@ public:
|
|||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
void MakeMD5Mesh() ;
|
||||
static idFile_Memory* GetAnimBin( idStr animName, const ID_TIME_T sourceTimeStamp );
|
||||
private:
|
||||
void ProcessNode( gltfNode* modelNode, idMat4 trans, gltfData* data );
|
||||
void UpdateSurface( const struct renderEntity_s* ent, idMat4 trans, modelSurface_t* surf );
|
||||
void UpdateSurface( const struct renderEntity_s* ent, const idJointMat* entJoints, const idJointMat* entJointsInverted, modelSurface_t* surf );
|
||||
void UpdateMd5Joints();
|
||||
int rootID;
|
||||
|
||||
gltfData* data;
|
||||
gltfNode* root;
|
||||
bool fileExclusive;
|
||||
bool hasAnimations;
|
||||
idList<int> animIds;
|
||||
idList<idGltfMesh, TAG_MODEL> meshes;
|
||||
|
||||
float maxJointVertDist; // maximum distance a vertex is separated from a joint
|
||||
idList<int, TAG_MODEL> animIds;
|
||||
idList<int, TAG_MODEL> bones;
|
||||
dynamicModel_t model_state;
|
||||
idMat4 prevTrans;
|
||||
idList<gltfNode*, TAG_MODEL> SkeletonNodes;
|
||||
|
||||
idList<idMD5Joint, TAG_MODEL> md5joints;
|
||||
idList<idJointQuat, TAG_MODEL> defaultPose;
|
||||
idList<idJointMat, TAG_MODEL> invertedDefaultPose;
|
||||
idList<idMD5Mesh, TAG_MODEL> meshes;
|
||||
deformInfo_t* deformInfo;
|
||||
|
||||
MapPolygonMesh* mesh;
|
||||
private:
|
||||
void DrawJoints( const struct renderEntity_s* ent, const viewDef_t* view );
|
||||
};
|
Loading…
Reference in a new issue