- Skinned / animated GLTF models

This commit is contained in:
HarrievG 2022-07-31 12:13:07 +02:00
parent edf657f50d
commit e56f696c9c
9 changed files with 848 additions and 345 deletions

View file

@ -484,6 +484,8 @@ endif (RAPIDJSON_FOUND)
add_subdirectory(idlib)
file(GLOB NATVIS_SOURCES .natvis)
file(GLOB AAS_INCLUDES aas/*.h)
file(GLOB AAS_SOURCES aas/*.cpp)
@ -1389,6 +1391,7 @@ set(RBDOOM3_INCLUDES
)
set(RBDOOM3_SOURCES
${NATVIS_SOURCES}
${AAS_SOURCES}
${CM_SOURCES}
${FRAMEWORK_SOURCES}

63
neo/idStuff.natvis Normal file
View file

@ -0,0 +1,63 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- natvis file for Visual Studio debugger (you can include this in a project file, or install in visual studio folder) -->
<AutoVisualizer xmlns="http://schemas.microsoft.com/vstudio/debugger/natvis/2010">
<Type Name="idList&lt;*&gt;">
<DisplayString>{{Size={num} Capacity={size}}}</DisplayString>
<Expand>
<Item Name="[size]">num</Item>
<Item Name="[capacity]">size</Item>
<ArrayItems>
<Size>num</Size>
<ValuePointer>list</ValuePointer>
</ArrayItems>
</Expand>
</Type>
<Type Name="idVec4">
<DisplayString>{{{x,g},{y,g},{z,g},{w,g}}}</DisplayString>
</Type>
<Type Name="idVec2">
<DisplayString>{{{x},{y}}}</DisplayString>
</Type>
<Type Name="idStr">
<DisplayString>{data,s}</DisplayString>
</Type>
<Type Name="idSWFDictionaryEntry">
<DisplayString Condition="name != 0">{name}</DisplayString>
<Expand>
<Item Condition="type == SWF_DICT_SPRITE" Name=" [ Sprite ]">sprite</Item>
<Item Condition="type == SWF_DICT_EDITTEXT" Name=" [ EditText ]">edittext</Item>
<Item Condition="type == SWF_DICT_FONT" Name=" [ Font ] ">font</Item>
<Item Condition="type == SWF_DICT_TEXT" Name=" [ Text ] ">text</Item>
<Item Condition="type == SWF_DICT_IMAGE" Name=" [ Image ]">imageSize</Item>
<Item Condition="type == SWF_DICT_NULL" Name=" [ Empty ] ">name</Item>
</Expand>
</Type>
<Type Name="idSWFScriptVar">
<Expand>
<Item Condition="type == SWF_VAR_OBJECT" Name=" [ Object ]">value.object</Item>
<Item Condition="type == SWF_VAR_FUNCTION" Name=" [ Function ]">value.function</Item>
<Item Condition="type == SWF_VAR_STRING" Name=" [ String ]">value.string</Item>
<Item Condition="type == SWF_VAR_FLOAT" Name=" [ Float ]">value.f</Item>
<Item Condition="type == SWF_VAR_UNDEF" Name=" [ UNDEFINED ]">value</Item>
<Item Condition="type == SWF_VAR_BOOL" Name=" [ Bool ]">value.b</Item>
<Item Condition="type == SWF_VAR_INTEGER" Name=" [ Int ]">value.i</Item>
<Item Condition="type == SWF_VAR_STRINGID" Name=" [ StrID ]">value.i</Item>
</Expand>
</Type>
<Type Name="idSWFScriptObject::swfNamedVar_t">
<DisplayString >[{name}]{value}</DisplayString>
</Type>
<Type Name="swfMethod_info">
<DisplayString >[{name}]</DisplayString>
</Type>
</AutoVisualizer>

View file

@ -218,17 +218,14 @@ MapPolygonMesh* MapPolygonMesh::ConvertFromMeshGltf( const gltfMesh_Primitive* p
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;
mesh->verts[i].SetColor2( PackColor( vec ) );
}
break;
}
case gltfMesh_Primitive_Attribute::Type::Indices:
{
idVec4 vec;
idVec4i vec;
for( int i = 0; i < attrAcc->count; i++ )
{
bin.Read( ( void* )( &vec.x ), attrAcc->typeSize );

View file

@ -2318,7 +2318,7 @@ CONSOLE_COMMAND_COMPILE( LoadGLTF, "Loads an .gltf or .glb file", idCmdSystem::A
// not dots allowed in [%s]!
// [filename].[%i|%s].[gltf/glb]
// [filename].[%i|%s].[gltf|glb]
bool gltfManager::ExtractIdentifier( idStr& filename, int& id, idStr& name )
{
idStr extension;

View file

@ -134,6 +134,11 @@ public:
gltfNode() : camera( -1 ), skin( -1 ), matrix( mat4_zero ),
mesh( -1 ), rotation( 0.f, 0.f, 0.f, 1.f ), scale( 1.f, 1.f, 1.f ),
translation( vec3_zero ), parent( nullptr ), dirty( true ) { }
//Only checks name!
bool operator == ( const gltfNode& rhs )
{
return name == rhs.name;
}
int camera;
idList<int> children;
int skin;
@ -866,23 +871,6 @@ public:
return nullptr;
}
gltfNode* GetNode( gltfScene* scene, idStr name )
{
assert( scene );
assert( name[0] );
auto& nodeList = scene->nodes;
for( auto& nodeId : nodeList )
{
if( nodes[nodeId]->name == name )
{
return nodes[nodeId];
}
}
return nullptr;
}
gltfNode* GetNode( idStr sceneName, int id, idStr* name = nullptr )
{
int sceneId = GetSceneId( sceneName );
@ -913,7 +901,7 @@ public:
return nullptr;
}
gltfNode* GetNode( idStr sceneName, idStr name , int* id = nullptr )
gltfNode* GetNode( idStr sceneName, idStr name , int* id = nullptr , bool caseSensitive = false )
{
int sceneId = GetSceneId( sceneName );
if( sceneId < 0 || sceneId > scenes.Num() )
@ -927,9 +915,9 @@ public:
assert( name[0] );
auto& nodeList = scene->nodes;
for( auto& nodeId : nodeList )
for( auto nodeId : nodeList )
{
if( nodes[nodeId]->name.Icmp( name ) == 0 )
if( caseSensitive ? nodes[nodeId]->name.Cmp( name ) : nodes[nodeId]->name.Icmp( name ) == 0 )
{
if( id != nullptr )
{
@ -946,10 +934,10 @@ public:
int GetNodeIndex( gltfNode* node )
{
int index = -1;
for( auto* node : nodes )
for( auto& it : nodes )
{
index++;
if( node == node )
if( it == node )
{
return index;
}
@ -984,19 +972,81 @@ public:
return nullptr;
}
int GetSceneId( idStr sceneName ) const
int GetSceneId( idStr sceneName , gltfScene* result = nullptr ) const
{
for( int i = 0; i < scenes.Num(); i++ )
{
if( scenes[i]->name == sceneName )
{
if( result != nullptr )
{
result = scenes[i];
}
return i;
}
}
return -1;
}
idList<int> GetChannelIds( gltfAnimation* anim , gltfNode* node )
void GetAllMeshes( gltfNode* node, idList<int>& meshIds )
{
if( node->mesh != -1 )
{
meshIds.Append( GetNodeIndex( node ) );
}
for( auto child : node->children )
{
GetAllMeshes( nodes[child], meshIds );
}
}
gltfSkin* GetSkin( int boneNodeId )
{
for( auto skin : skins )
{
if( skin->joints.Find( boneNodeId ) )
{
return skin;
}
}
return nullptr;
}
gltfSkin* GetSkin( gltfAnimation* anim )
{
auto animTargets = GetAnimTargets( anim );
if( !animTargets.Num() )
{
return nullptr;
}
for( int nodeID : animTargets )
{
gltfSkin* foundSkin = GetSkin( nodeID );
if( foundSkin != nullptr )
{
return foundSkin;
}
}
return nullptr;
}
idList<int> GetAnimTargets( gltfAnimation* anim ) const
{
idList<int> result;
for( auto channel : anim->channels )
{
result.AddUnique( channel->target.node );
}
return result;
}
idList<int> GetChannelIds( gltfAnimation* anim , gltfNode* node ) const
{
idList<int> result;
int channelIdx = 0;
@ -1012,9 +1062,9 @@ public:
return result;
}
idList<int> GetAnimationIds( gltfNode* node )
int GetAnimationIds( gltfNode* node , idList<int>& result )
{
idList<int> result;
int animIdx = 0;
for( auto anim : animations )
{
@ -1022,13 +1072,16 @@ public:
{
if( channel->target.node >= 0 && nodes[channel->target.node] == node )
{
result.Append( animIdx );
break;
result.AddUnique( animIdx );
}
}
animIdx++;
}
return result;
for( int nodeId : node->children )
{
GetAnimationIds( nodes[nodeId], result );
}
return result.Num();
}
idMat4 GetViewMatrix( int camId ) const

View file

@ -360,6 +360,8 @@ public:
static void Init();
static float RSqrt( float x ); // reciprocal square root, returns huge number when x == 0.0
static float InvSqrt( float x ); // inverse square root with 32 bits precision, returns huge number when x == 0.0
static float InvSqrt16( float x ); // inverse square root with 16 bits precision, returns huge number when x == 0.0
@ -502,6 +504,21 @@ ID_INLINE byte CLAMP_BYTE( int x )
return ( ( x ) < 0 ? ( 0 ) : ( ( x ) > 255 ? 255 : ( byte )( x ) ) );
}
ID_INLINE float idMath::RSqrt( float x )
{
int i;
float y, r;
y = x * 0.5f;
i = *reinterpret_cast< int* >( &x );
i = 0x5f3759df - ( i >> 1 );
r = *reinterpret_cast< float* >( &i );
r = r * ( 1.5f - r * r * y );
return r;
}
/*
========================
idMath::InvSqrt

View file

@ -280,4 +280,258 @@ public:
}
};
//===============================================================
//
// idVec4i - 4D vector
//
//===============================================================
class idVec4i
{
public:
uint8 x;
uint8 y;
uint8 z;
uint8 w;
idVec4i( void );
explicit idVec4i( const uint8 x )
{
Set( x, x, x, x );
}
explicit idVec4i( const uint8 x, const uint8 y, const uint8 z, const uint8 w );
void Set( const uint8 x, const uint8 y, const uint8 z, const uint8 w );
void Zero( void );
int operator[]( const int index ) const;
uint8& operator[]( const int index );
idVec4i operator-( ) const;
uint8 operator*( const idVec4i& a ) const;
idVec4i operator*( const uint8 a ) const;
idVec4i operator/( const uint8 a ) const;
idVec4i operator+( const idVec4i& a ) const;
idVec4i operator-( const idVec4i& a ) const;
idVec4i& operator+=( const idVec4i& a );
idVec4i& operator-=( const idVec4i& a );
idVec4i& operator/=( const idVec4i& a );
idVec4i& operator/=( const uint8 a );
idVec4i& operator*=( const uint8 a );
friend idVec4i operator*( const uint8 a, const idVec4i b );
idVec4i Multiply( const idVec4i& a ) const;
bool Compare( const idVec4i& a ) const; // exact compare, no epsilon
bool operator==( const idVec4i& a ) const; // exact compare, no epsilon
bool operator!=( const idVec4i& a ) const; // exact compare, no epsilon
float Length( void ) const;
float LengthSqr( void ) const;
float Normalize( void ); // returns length
float NormalizeFast( void ); // returns length
int GetDimension( void ) const;
const uint8* ToIntPtr( void ) const;
uint8* ToIntPtr( void );
const char* ToString( int precision = 2 ) const;
void Lerp( const idVec4i& v1, const idVec4i& v2, const float l );
};
ID_INLINE idVec4i::idVec4i( void ) { }
ID_INLINE idVec4i::idVec4i( const uint8 x, const uint8 y, const uint8 z, const uint8 w )
{
this->x = x;
this->y = y;
this->z = z;
this->w = w;
}
ID_INLINE void idVec4i::Set( const uint8 x, const uint8 y, const uint8 z, const uint8 w )
{
this->x = x;
this->y = y;
this->z = z;
this->w = w;
}
ID_INLINE void idVec4i::Zero( void )
{
x = y = z = w = 0.0f;
}
ID_INLINE int idVec4i::operator[]( int index ) const
{
return ( &x )[index];
}
ID_INLINE uint8& idVec4i::operator[]( int index )
{
return ( &x )[index];
}
ID_INLINE idVec4i idVec4i::operator-( ) const
{
return idVec4i( -x, -y, -z, -w );
}
ID_INLINE idVec4i idVec4i::operator-( const idVec4i& a ) const
{
return idVec4i( x - a.x, y - a.y, z - a.z, w - a.w );
}
ID_INLINE uint8 idVec4i::operator*( const idVec4i& a ) const
{
return x * a.x + y * a.y + z * a.z + w * a.w;
}
ID_INLINE idVec4i idVec4i::operator*( const uint8 a ) const
{
return idVec4i( x * a, y * a, z * a, w * a );
}
ID_INLINE idVec4i idVec4i::operator/( const uint8 a ) const
{
float inva = 1.0f / a;
return idVec4i( x * inva, y * inva, z * inva, w * inva );
}
ID_INLINE idVec4i operator*( const int a, const idVec4i b )
{
return idVec4i( b.x * a, b.y * a, b.z * a, b.w * a );
}
ID_INLINE idVec4i idVec4i::operator+( const idVec4i& a ) const
{
return idVec4i( x + a.x, y + a.y, z + a.z, w + a.w );
}
ID_INLINE idVec4i& idVec4i::operator+=( const idVec4i& a )
{
x += a.x;
y += a.y;
z += a.z;
w += a.w;
return *this;
}
ID_INLINE idVec4i& idVec4i::operator/=( const idVec4i& a )
{
x /= a.x;
y /= a.y;
z /= a.z;
w /= a.w;
return *this;
}
ID_INLINE idVec4i& idVec4i::operator/=( const uint8 a )
{
float inva = 1.0f / a;
x *= inva;
y *= inva;
z *= inva;
w *= inva;
return *this;
}
ID_INLINE idVec4i& idVec4i::operator-=( const idVec4i& a )
{
x -= a.x;
y -= a.y;
z -= a.z;
w -= a.w;
return *this;
}
ID_INLINE idVec4i& idVec4i::operator*=( const uint8 a )
{
x *= a;
y *= a;
z *= a;
w *= a;
return *this;
}
ID_INLINE idVec4i idVec4i::Multiply( const idVec4i& a ) const
{
return idVec4i( x * a.x, y * a.y, z * a.z, w * a.w );
}
ID_INLINE bool idVec4i::Compare( const idVec4i& a ) const
{
return ( ( x == a.x ) && ( y == a.y ) && ( z == a.z ) && w == a.w );
}
ID_INLINE bool idVec4i::operator==( const idVec4i& a ) const
{
return Compare( a );
}
ID_INLINE bool idVec4i::operator!=( const idVec4i& a ) const
{
return !Compare( a );
}
ID_INLINE float idVec4i::Length( void ) const
{
return ( float ) idMath::Sqrt( x * x + y * y + z * z + w * w );
}
ID_INLINE float idVec4i::LengthSqr( void ) const
{
return ( x * x + y * y + z * z + w * w );
}
ID_INLINE float idVec4i::Normalize( void )
{
float sqrLength, invLength;
sqrLength = x * x + y * y + z * z + w * w;
invLength = idMath::InvSqrt( sqrLength );
x *= invLength;
y *= invLength;
z *= invLength;
w *= invLength;
return invLength * sqrLength;
}
ID_INLINE float idVec4i::NormalizeFast( void )
{
float sqrLength, invLength;
sqrLength = x * x + y * y + z * z + w * w;
invLength = idMath::RSqrt( sqrLength );
x *= invLength;
y *= invLength;
z *= invLength;
w *= invLength;
return invLength * sqrLength;
}
ID_INLINE int idVec4i::GetDimension( void ) const
{
return 4;
}
ID_INLINE const uint8* idVec4i::ToIntPtr( void ) const
{
return &x;
}
ID_INLINE uint8* idVec4i::ToIntPtr( void )
{
return &x;
}
#endif

File diff suppressed because it is too large Load diff

View file

@ -68,16 +68,14 @@ private:
float maxJointVertDist; // maximum distance a vertex is separated from a joint
idList<int, TAG_MODEL> animIds;
idList<int, TAG_MODEL> bones;
idList<int, TAG_MODEL> MeshNodeIds;
dynamicModel_t model_state;
idList<gltfNode*, TAG_MODEL> SkeletonNodes;
idStr meshName;
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;
gltfSkin* currentSkin;
private:
void DrawJoints( const struct renderEntity_s* ent, const viewDef_t* view );
};