You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
243 lines
7.6 KiB
243 lines
7.6 KiB
//========= Copyright © 1996-2008, Valve Corporation, All rights reserved. ============//
|
|
//
|
|
// Purpose:
|
|
//
|
|
// $NoKeywords: $
|
|
//=============================================================================//
|
|
|
|
#include "flexrenderdata.h"
|
|
|
|
// memdbgon must be the last include file in a .cpp file!!!
|
|
#include "tier0/memdbgon.h"
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Constructor
|
|
//-----------------------------------------------------------------------------
|
|
|
|
CCachedRenderData::CCachedRenderData() : m_CurrentTag(0), m_pFirstFlexIndex(0),
|
|
m_pFirstWorldIndex(0)
|
|
{
|
|
#ifdef _DEBUG
|
|
int i;
|
|
float val = VEC_T_NAN;
|
|
for( i = 0; i < MAXSTUDIOFLEXVERTS; i++ )
|
|
{
|
|
m_pFlexVerts[i].m_Position[0] = val;
|
|
m_pFlexVerts[i].m_Position[1] = val;
|
|
m_pFlexVerts[i].m_Position[2] = val;
|
|
m_pFlexVerts[i].m_Normal[0] = val;
|
|
m_pFlexVerts[i].m_Normal[1] = val;
|
|
m_pFlexVerts[i].m_Normal[2] = val;
|
|
|
|
m_pThinFlexVerts[i].m_Position[0] = val;
|
|
m_pThinFlexVerts[i].m_Position[1] = val;
|
|
m_pThinFlexVerts[i].m_Position[2] = val;
|
|
m_pThinFlexVerts[i].m_Normal[0] = val;
|
|
m_pThinFlexVerts[i].m_Normal[1] = val;
|
|
m_pThinFlexVerts[i].m_Normal[2] = val;
|
|
|
|
m_pFlexVerts[i].m_TangentS[0] = val;
|
|
m_pFlexVerts[i].m_TangentS[1] = val;
|
|
m_pFlexVerts[i].m_TangentS[2] = val;
|
|
m_pFlexVerts[i].m_TangentS[3] = val;
|
|
}
|
|
#endif
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Call this before rendering the model
|
|
//-----------------------------------------------------------------------------
|
|
|
|
void CCachedRenderData::StartModel()
|
|
{
|
|
++m_CurrentTag;
|
|
m_IndexCount = 0;
|
|
m_FlexVertexCount = 0;
|
|
m_ThinFlexVertexCount = 0;
|
|
m_WorldVertexCount = 0;
|
|
m_pFirstFlexIndex = 0;
|
|
m_pFirstThinFlexIndex = 0;
|
|
m_pFirstWorldIndex = 0;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Used to hook ourselves into a particular body part, model, and mesh
|
|
//-----------------------------------------------------------------------------
|
|
|
|
void CCachedRenderData::SetBodyPart( int bodypart )
|
|
{
|
|
m_Body = bodypart;
|
|
m_CacheDict.EnsureCount(m_Body+1);
|
|
m_Model = m_Mesh = -1;
|
|
m_pFirstFlexIndex = 0;
|
|
m_pFirstThinFlexIndex = 0;
|
|
m_pFirstWorldIndex = 0;
|
|
}
|
|
|
|
void CCachedRenderData::SetModel( int model )
|
|
{
|
|
Assert(m_Body >= 0);
|
|
m_Model = model;
|
|
m_CacheDict[m_Body].EnsureCount(m_Model+1);
|
|
m_Mesh = -1;
|
|
m_pFirstFlexIndex = 0;
|
|
m_pFirstThinFlexIndex = 0;
|
|
m_pFirstWorldIndex = 0;
|
|
}
|
|
|
|
void CCachedRenderData::SetMesh( int mesh )
|
|
{
|
|
Assert((m_Model >= 0) && (m_Body >= 0));
|
|
|
|
m_Mesh = mesh;
|
|
m_CacheDict[m_Body][m_Model].EnsureCount(m_Mesh+1);
|
|
|
|
// At this point, we should have all 3 defined.
|
|
CacheDict_t& dict = m_CacheDict[m_Body][m_Model][m_Mesh];
|
|
|
|
if (dict.m_Tag == m_CurrentTag)
|
|
{
|
|
m_pFirstFlexIndex = &m_pFlexIndex[dict.m_FirstIndex];
|
|
m_pFirstThinFlexIndex = &m_pThinFlexIndex[dict.m_FirstIndex];
|
|
m_pFirstWorldIndex = &m_pWorldIndex[dict.m_FirstIndex];
|
|
}
|
|
else
|
|
{
|
|
m_pFirstFlexIndex = 0;
|
|
m_pFirstThinFlexIndex = 0;
|
|
m_pFirstWorldIndex = 0;
|
|
}
|
|
}
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Used to set up a flex computation
|
|
//-----------------------------------------------------------------------------
|
|
|
|
bool CCachedRenderData::IsFlexComputationDone( ) const
|
|
{
|
|
Assert((m_Model >= 0) && (m_Body >= 0) && (m_Mesh >= 0));
|
|
|
|
// Lets create the dictionary entry
|
|
// If the tags match, that means we're doing the computation twice!!!
|
|
CacheDict_t const& dict = m_CacheDict[m_Body][m_Model][m_Mesh];
|
|
return (dict.m_FlexTag == m_CurrentTag);
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Used to set up a computation (modifies vertex data)
|
|
//-----------------------------------------------------------------------------
|
|
|
|
void CCachedRenderData::SetupComputation( mstudiomesh_t *pMesh, bool flexComputation )
|
|
{
|
|
Assert((m_Model >= 0) && (m_Body >= 0) && (m_Mesh >= 0));
|
|
// Assert( !m_pFirstIndex );
|
|
|
|
// Lets create the dictionary entry
|
|
// If the tags match, that means we're doing the computation twice!!!
|
|
CacheDict_t& dict = m_CacheDict[m_Body][m_Model][m_Mesh];
|
|
if (dict.m_Tag != m_CurrentTag)
|
|
{
|
|
dict.m_FirstIndex = m_IndexCount;
|
|
dict.m_IndexCount = pMesh->numvertices;
|
|
dict.m_Tag = m_CurrentTag;
|
|
m_IndexCount += dict.m_IndexCount;
|
|
}
|
|
|
|
if (flexComputation)
|
|
dict.m_FlexTag = m_CurrentTag;
|
|
|
|
m_pFirstFlexIndex = &m_pFlexIndex[dict.m_FirstIndex];
|
|
m_pFirstThinFlexIndex = &m_pThinFlexIndex[dict.m_FirstIndex];
|
|
m_pFirstWorldIndex = &m_pWorldIndex[dict.m_FirstIndex];
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Creates a new flexed vertex to be associated with a vertex
|
|
//-----------------------------------------------------------------------------
|
|
|
|
CachedPosNormTan_t* CCachedRenderData::CreateFlexVertex( int vertex )
|
|
{
|
|
Assert( m_pFirstFlexIndex );
|
|
Assert( m_pFirstFlexIndex[vertex].m_Tag != m_CurrentTag );
|
|
|
|
Assert ( m_FlexVertexCount < MAXSTUDIOFLEXVERTS );
|
|
if ( m_FlexVertexCount >= MAXSTUDIOFLEXVERTS )
|
|
return NULL;
|
|
|
|
// Point the flex list to the new flexed vertex
|
|
m_pFirstFlexIndex[vertex].m_Tag = m_CurrentTag;
|
|
m_pFirstFlexIndex[vertex].m_VertexIndex = m_FlexVertexCount;
|
|
|
|
// Add a new flexed vert to the flexed vertex list
|
|
++m_FlexVertexCount;
|
|
|
|
return GetFlexVertex( vertex );
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Creates a new flexed vertex to be associated with a vertex
|
|
//-----------------------------------------------------------------------------
|
|
|
|
CachedPosNorm_t* CCachedRenderData::CreateThinFlexVertex( int vertex )
|
|
{
|
|
Assert( m_pFirstThinFlexIndex );
|
|
Assert( m_pFirstThinFlexIndex[vertex].m_Tag != m_CurrentTag );
|
|
|
|
Assert ( m_ThinFlexVertexCount < MAXSTUDIOFLEXVERTS );
|
|
if ( m_ThinFlexVertexCount >= MAXSTUDIOFLEXVERTS )
|
|
return NULL;
|
|
|
|
// Point the flex list to the new flexed vertex
|
|
m_pFirstThinFlexIndex[vertex].m_Tag = m_CurrentTag;
|
|
m_pFirstThinFlexIndex[vertex].m_VertexIndex = m_ThinFlexVertexCount;
|
|
|
|
// Add a new flexed vert to the thin flexed vertex list
|
|
++m_ThinFlexVertexCount;
|
|
|
|
return GetThinFlexVertex( vertex );
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Re-normalize the surface normals and tangents of the flexed vertices
|
|
// No thin ones since they're intended to be deltas, not unit vectors
|
|
//-----------------------------------------------------------------------------
|
|
void CCachedRenderData::RenormalizeFlexVertices( bool bHasTangentData, bool bQuadList )
|
|
{
|
|
for ( int i = 0; i < m_FlexVertexCount; i++ )
|
|
{
|
|
m_pFlexVerts[i].m_Normal.AsVector3D().NormalizeInPlace();
|
|
if ( bHasTangentData )
|
|
{
|
|
m_pFlexVerts[i].m_TangentS.AsVector3D().NormalizeInPlace();
|
|
|
|
if ( bQuadList )
|
|
{
|
|
float flClampedWrinkle = MAX( MIN( m_pFlexVerts[i].m_Position.w, 1 ), -1 ); // -1 to 1
|
|
float fl1to3Wrinkle = flClampedWrinkle + 2; // 1 to 3
|
|
m_pFlexVerts[i].m_Position.w = m_pFlexVerts[i].m_TangentS.w * fl1to3Wrinkle;// Sign is tangent flip
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Creates a new flexed vertex to be associated with a vertex
|
|
//-----------------------------------------------------------------------------
|
|
|
|
CachedPosNorm_t* CCachedRenderData::CreateWorldVertex( int vertex )
|
|
{
|
|
Assert( m_pFirstWorldIndex );
|
|
if ( m_pFirstWorldIndex[vertex].m_Tag != m_CurrentTag )
|
|
{
|
|
// Point the world list to the new world vertex
|
|
Assert( m_WorldVertexCount < MAXSTUDIOVERTS );
|
|
m_pFirstWorldIndex[vertex].m_Tag = m_CurrentTag;
|
|
m_pFirstWorldIndex[vertex].m_VertexIndex = m_WorldVertexCount;
|
|
|
|
// Add a new world vert to the world vertex list
|
|
++m_WorldVertexCount;
|
|
}
|
|
return GetWorldVertex( vertex );
|
|
}
|
|
|