optimize meshes where all vertices are associated with the same bone

This commit is contained in:
Chris Danford
2004-04-05 10:05:15 +00:00
parent 2a4dc7808d
commit 957b03f325
5 changed files with 83 additions and 9 deletions
+37 -7
View File
@@ -111,7 +111,22 @@ void Model::LoadPieces( CString sMeshesPath, CString sMaterialsPath, CString sBo
// //
// Setup temp vertices (if necessary) // Setup temp vertices (if necessary)
// //
m_bUseTempVertices = m_mapNameToAnimation[DEFAULT_ANIMATION_NAME].Bones.size() > 0; // if there are no bones, then there's no reason to use temp vertices bool bHasAnyPerVertexBones = false;
for (int i = 0; i < (int)m_pGeometry->m_Meshes.size(); i++)
{
msMesh& mesh = m_pGeometry->m_Meshes[i];
for (int j = 0; j < (int)mesh.Vertices.size(); j++)
{
RageModelVertex &vert = mesh.Vertices[j];
if( vert.boneIndex != -1 )
{
bHasAnyPerVertexBones = true;
break;
}
}
}
m_bUseTempVertices = bHasAnyPerVertexBones;
if( m_bUseTempVertices ) if( m_bUseTempVertices )
{ {
m_vTempVerticesByMesh.resize( m_pGeometry->m_Meshes.size() ); m_vTempVerticesByMesh.resize( m_pGeometry->m_Meshes.size() );
@@ -476,9 +491,6 @@ void Model::DrawPrimitives()
// UGLY: This overrides the Actor's BlendMode // UGLY: This overrides the Actor's BlendMode
DISPLAY->SetTextureModeAdd(); DISPLAY->SetTextureModeAdd();
} }
DISPLAY->DrawIndexedTriangles( &TempVertices[0], pMesh->Vertices.size(), (Uint16*)&pMesh->Triangles[0], pMesh->Triangles.size()*3 );
DISPLAY->SetSphereEnironmentMapping( false );
} }
else else
{ {
@@ -495,7 +507,23 @@ void Model::DrawPrimitives()
shininess ); shininess );
DISPLAY->ClearAllTextures(); DISPLAY->ClearAllTextures();
DISPLAY->SetSphereEnironmentMapping( false ); DISPLAY->SetSphereEnironmentMapping( false );
DISPLAY->DrawIndexedTriangles( &TempVertices[0], pMesh->Vertices.size(), (Uint16*)&pMesh->Triangles[0], pMesh->Triangles.size()*3 ); }
// apply mesh-specific bone (if any)
if( pMesh->nBoneIndex != -1 )
{
DISPLAY->PushMatrix();
RageMatrix &mat = m_vpBones[pMesh->nBoneIndex].mFinal;
DISPLAY->PreMultMatrix( mat );
}
DISPLAY->DrawIndexedTriangles( &TempVertices[0], pMesh->Vertices.size(), (Uint16*)&pMesh->Triangles[0], pMesh->Triangles.size()*3 );
DISPLAY->SetSphereEnironmentMapping( false );
if( pMesh->nBoneIndex != -1 )
{
DISPLAY->PopMatrix();
} }
} }
} }
@@ -611,12 +639,14 @@ void Model::PlayAnimation( CString sAniName, float fPlayRate )
} }
} }
// subtract out the bone's resting position
for (i = 0; i < (int)m_pGeometry->m_Meshes.size(); i++) for (i = 0; i < (int)m_pGeometry->m_Meshes.size(); i++)
{ {
msMesh *pMesh = &m_pGeometry->m_Meshes[i]; msMesh *pMesh = &m_pGeometry->m_Meshes[i];
for (j = 0; j < (int)pMesh->Vertices.size(); j++) for (j = 0; j < (int)pMesh->Vertices.size(); j++)
{ {
RageModelVertex *pVertex = &pMesh->Vertices[j]; RageModelVertex *pVertex = &pMesh->Vertices[j];
int nBoneIndex = (pMesh->nBoneIndex!=-1) ? pMesh->nBoneIndex : pVertex->boneIndex;
if (pVertex->boneIndex != -1) if (pVertex->boneIndex != -1)
{ {
pVertex->p[0] -= m_vpBones[pVertex->boneIndex].mAbsolute.m[3][0]; pVertex->p[0] -= m_vpBones[pVertex->boneIndex].mAbsolute.m[3][0];
@@ -785,9 +815,9 @@ void Model::Update( float fDelta )
} }
// //
// process vertices // process per-vertex bones
// //
if( m_bUseTempVertices && m_pGeometry ) if( m_pGeometry && m_bUseTempVertices )
{ {
for (int i = 0; i < (int)m_pGeometry->m_Meshes.size(); i++) for (int i = 0; i < (int)m_pGeometry->m_Meshes.size(); i++)
{ {
+1 -1
View File
@@ -11,7 +11,7 @@
Chris Danford Chris Danford
----------------------------------------------------------------------------- -----------------------------------------------------------------------------
*/ */
#include "Model.h" #include "RageModelGeometry.h"
#include <map> #include <map>
+5
View File
@@ -78,6 +78,11 @@ typedef struct msMesh
// vector<msVec3> Normals; // each vertex holds its own normal // vector<msVec3> Normals; // each vertex holds its own normal
// OPTIMIZATION: If all verts in a mesh are transformed by the same bone,
// then send the transform to the graphics card for the whole mesh instead
// of transforming each vertex on the CPU;
char nBoneIndex; // -1 = no bone
vector<msTriangle> Triangles; vector<msTriangle> Triangles;
} msMesh; } msMesh;
+39 -1
View File
@@ -24,6 +24,41 @@ RageModelGeometry::~RageModelGeometry ()
{ {
} }
void RageModelGeometry::OptimizeBones()
{
for (unsigned i = 0; i < m_Meshes.size(); i++)
{
msMesh& mesh = m_Meshes[i];
// check to see if all vertices have the same bone index
bool bAllVertsUseSameBone = true;
char nBoneIndex = !mesh.Vertices.empty() ? mesh.Vertices[0].boneIndex : -1;
if( nBoneIndex != -1 )
{
for (unsigned j = 1; j < mesh.Vertices.size(); j++)
{
RageModelVertex& vertex = mesh.Vertices[j];
if( vertex.boneIndex != nBoneIndex )
{
bAllVertsUseSameBone = false;
break;
}
}
}
if( bAllVertsUseSameBone )
{
mesh.nBoneIndex = nBoneIndex;
// clear all vertex/bone associations;
for (unsigned j = 0; j < mesh.Vertices.size(); j++)
{
RageModelVertex& vertex = mesh.Vertices[j];
vertex.boneIndex = -1;
}
}
}
}
#define THROW RageException::Throw( "Parse at line %d: '%s'", sLine.c_str() ); #define THROW RageException::Throw( "Parse at line %d: '%s'", sLine.c_str() );
void RageModelGeometry::LoadMilkshapeAscii( CString sPath ) void RageModelGeometry::LoadMilkshapeAscii( CString sPath )
@@ -81,6 +116,8 @@ void RageModelGeometry::LoadMilkshapeAscii( CString sPath )
// mesh.nFlags = nFlags; // mesh.nFlags = nFlags;
mesh.nMaterialIndex = (byte)nIndex; mesh.nMaterialIndex = (byte)nIndex;
mesh.nBoneIndex = -1;
// //
// vertices // vertices
// //
@@ -119,7 +156,6 @@ void RageModelGeometry::LoadMilkshapeAscii( CString sPath )
} }
// //
// normals // normals
// //
@@ -193,6 +229,8 @@ void RageModelGeometry::LoadMilkshapeAscii( CString sPath )
} }
} }
OptimizeBones();
f.Close(); f.Close();
} }
+1
View File
@@ -28,6 +28,7 @@ public:
public: public:
void LoadMilkshapeAscii( CString sMilkshapeAsciiFile ); void LoadMilkshapeAscii( CString sMilkshapeAsciiFile );
void OptimizeBones();
int m_iRefCount; int m_iRefCount;