summaryrefslogtreecommitdiff
path: root/studiorender/flexrenderdata.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'studiorender/flexrenderdata.cpp')
-rw-r--r--studiorender/flexrenderdata.cpp238
1 files changed, 238 insertions, 0 deletions
diff --git a/studiorender/flexrenderdata.cpp b/studiorender/flexrenderdata.cpp
new file mode 100644
index 0000000..5162bd8
--- /dev/null
+++ b/studiorender/flexrenderdata.cpp
@@ -0,0 +1,238 @@
+//========= Copyright 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 )
+{
+ int i;
+
+ for (i = 0; i < m_FlexVertexCount; i++)
+ {
+ m_pFlexVerts[ i ].m_Normal.NormalizeInPlace();
+ if (bHasTangentData)
+ {
+ m_pFlexVerts[ i ].m_TangentS.AsVector3D().NormalizeInPlace();
+ }
+ }
+}
+
+//-----------------------------------------------------------------------------
+// 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 );
+}
+