diff options
| author | FluorescentCIAAfricanAmerican <[email protected]> | 2020-04-22 12:56:21 -0400 |
|---|---|---|
| committer | FluorescentCIAAfricanAmerican <[email protected]> | 2020-04-22 12:56:21 -0400 |
| commit | 3bf9df6b2785fa6d951086978a3e66f49427166a (patch) | |
| tree | 2c0f1f0c63c4832882bc93814ebd2c2b1c6224e5 /studiorender/flexrenderdata.h | |
| download | archived-source-engine-2018-hl2-src-master.tar.xz archived-source-engine-2018-hl2-src-master.zip | |
Diffstat (limited to 'studiorender/flexrenderdata.h')
| -rw-r--r-- | studiorender/flexrenderdata.h | 335 |
1 files changed, 335 insertions, 0 deletions
diff --git a/studiorender/flexrenderdata.h b/studiorender/flexrenderdata.h new file mode 100644 index 0000000..ac43f53 --- /dev/null +++ b/studiorender/flexrenderdata.h @@ -0,0 +1,335 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $NoKeywords: $ +//=============================================================================// + +#ifndef FLEXRENDERDATA_H +#define FLEXRENDERDATA_H +#ifdef _WIN32 +#pragma once +#endif + +#include "mathlib/vector.h" +#include "utlvector.h" +#include "studio.h" + +//----------------------------------------------------------------------------- +// forward declarations +//----------------------------------------------------------------------------- + +struct mstudiomesh_t; + +//----------------------------------------------------------------------------- +// Used by flex vertex data cache +//----------------------------------------------------------------------------- + +struct CachedPosNormTan_t +{ + Vector m_Position; + Vector m_Normal; + Vector4D m_TangentS; + + CachedPosNormTan_t() {} + + CachedPosNormTan_t( CachedPosNormTan_t const& src ) + { + VectorCopy( src.m_Position, m_Position ); + VectorCopy( src.m_Normal, m_Normal ); + Vector4DCopy( src.m_TangentS, m_TangentS ); + Assert( m_TangentS.w == 1.0f || m_TangentS.w == -1.0f ); + } +}; + +//----------------------------------------------------------------------------- +// Used by world (decal) vertex data cache +//----------------------------------------------------------------------------- + +struct CachedPosNorm_t +{ + Vector4DAligned m_Position; + Vector4DAligned m_Normal; + + CachedPosNorm_t() {} + + CachedPosNorm_t( CachedPosNorm_t const& src ) + { + Vector4DCopy( src.m_Position, m_Position ); + Vector4DCopy( src.m_Normal, m_Normal ); + } +}; + + +//----------------------------------------------------------------------------- +// Stores flex vertex data and world (decal) vertex data for the lifetime of the model rendering +//----------------------------------------------------------------------------- + + +class CCachedRenderData +{ +public: + // Constructor + CCachedRenderData(); + + // Call this when we start to render a new model + void StartModel(); + + // Used to hook ourselves into a particular body part, model, and mesh + void SetBodyPart( int bodypart ); + void SetModel( int model ); + void SetMesh( int mesh ); + + // For faster setup in the decal code + void SetBodyModelMesh( int body, int model, int mesh ); + + // Used to set up a flex computation + bool IsFlexComputationDone( ) const; + + // Used to set up a computation (for world or flex data) + void SetupComputation( mstudiomesh_t *pMesh, bool flexComputation = false ); + + // Is a particular vertex flexed? + bool IsVertexFlexed( int vertex ) const; + bool IsThinVertexFlexed( int vertex ) const; + + // Checks to see if the vertex is defined + bool IsVertexPositionCached( int vertex ) const; + + // Gets a flexed vertex + CachedPosNormTan_t* GetFlexVertex( int vertex ); + + // Gets a flexed vertex + CachedPosNorm_t* GetThinFlexVertex( int vertex ); + + // Creates a new flexed vertex to be associated with a vertex + CachedPosNormTan_t* CreateFlexVertex( int vertex ); + + // Creates a new flexed vertex to be associated with a vertex + CachedPosNorm_t* CreateThinFlexVertex( int vertex ); + + // Renormalizes the normals and tangents of the flex verts + void RenormalizeFlexVertices( bool bHasTangentData ); + + // Gets a decal vertex + CachedPosNorm_t* GetWorldVertex( int vertex ); + + // Creates a new decal vertex to be associated with a vertex + CachedPosNorm_t* CreateWorldVertex( int vertex ); + + template< class T > + void ComputeFlexedVertex_StreamOffset( studiohdr_t *pStudioHdr, mstudioflex_t *pflex, T *pvanim, int vertCount, float w1, float w2, float w3, float w4 ); + +#ifdef PLATFORM_WINDOWS + void ComputeFlexedVertex_StreamOffset_Optimized( studiohdr_t *pStudioHdr, mstudioflex_t *pflex, mstudiovertanim_t *pvanim, int vertCount, float w1, float w2, float w3, float w4); + void ComputeFlexedVertexWrinkle_StreamOffset_Optimized( studiohdr_t *pStudioHdr, mstudioflex_t *pflex, mstudiovertanim_wrinkle_t *pvanim, int vertCount, float w1, float w2, float w3, float w4); +#endif // PLATFORM_WINDOWS + +private: + // Used to create the flex render data. maps + struct CacheIndex_t + { + unsigned short m_Tag; + unsigned short m_VertexIndex; + }; + + // A dictionary for the cached data + struct CacheDict_t + { + unsigned short m_FirstIndex; + unsigned short m_IndexCount; + unsigned short m_Tag; + unsigned short m_FlexTag; + + CacheDict_t() : m_Tag(0), m_FlexTag(0) {} + }; + + typedef CUtlVector< CacheDict_t > CacheMeshDict_t; + typedef CUtlVector< CacheMeshDict_t > CacheModelDict_t; + typedef CUtlVector< CacheModelDict_t > CacheBodyPartDict_t; + + // Flex data, allocated for the lifespan of rendering + // Can't use UtlVector due to alignment issues + int m_FlexVertexCount; + CachedPosNormTan_t m_pFlexVerts[MAXSTUDIOFLEXVERTS+1]; + + // Flex data, allocated for the lifespan of rendering + // Can't use UtlVector due to alignment issues + int m_ThinFlexVertexCount; + CachedPosNorm_t m_pThinFlexVerts[MAXSTUDIOFLEXVERTS+1]; + + // World data, allocated for the lifespan of rendering + // Can't use UtlVector due to alignment issues + int m_WorldVertexCount; + CachedPosNorm_t m_pWorldVerts[MAXSTUDIOVERTS+1]; + + // Maps actual mesh vertices into flex cache + world cache indices + int m_IndexCount; + CacheIndex_t m_pFlexIndex[MAXSTUDIOVERTS+1]; + CacheIndex_t m_pThinFlexIndex[MAXSTUDIOVERTS+1]; + CacheIndex_t m_pWorldIndex[MAXSTUDIOVERTS+1]; + + CacheBodyPartDict_t m_CacheDict; + + // The flex tag + unsigned short m_CurrentTag; + + // the current body, model, and mesh + int m_Body; + int m_Model; + int m_Mesh; + + // mapping for the current mesh to flex data + CacheIndex_t* m_pFirstFlexIndex; + CacheIndex_t* m_pFirstThinFlexIndex; + CacheIndex_t* m_pFirstWorldIndex; + + friend class CStudioRender; +}; + + +//----------------------------------------------------------------------------- +// Checks to see if the vertex is defined +//----------------------------------------------------------------------------- + +inline bool CCachedRenderData::IsVertexFlexed( int vertex ) const +{ + return (m_pFirstFlexIndex && (m_pFirstFlexIndex[vertex].m_Tag == m_CurrentTag)); +} + +inline bool CCachedRenderData::IsThinVertexFlexed( int vertex ) const +{ + return (m_pFirstThinFlexIndex && (m_pFirstThinFlexIndex[vertex].m_Tag == m_CurrentTag)); +} + +//----------------------------------------------------------------------------- +// Gets an existing flexed vertex associated with a vertex +//----------------------------------------------------------------------------- + +inline CachedPosNormTan_t* CCachedRenderData::GetFlexVertex( int vertex ) +{ + Assert( m_pFirstFlexIndex ); + Assert( m_pFirstFlexIndex[vertex].m_Tag == m_CurrentTag ); + return &m_pFlexVerts[ m_pFirstFlexIndex[vertex].m_VertexIndex ]; +} + +inline CachedPosNorm_t* CCachedRenderData::GetThinFlexVertex( int vertex ) +{ + Assert( m_pFirstThinFlexIndex ); + Assert( m_pFirstThinFlexIndex[vertex].m_Tag == m_CurrentTag ); + return &m_pThinFlexVerts[ m_pFirstThinFlexIndex[vertex].m_VertexIndex ]; +} + + + + +//----------------------------------------------------------------------------- +// Checks to see if the vertex is defined +//----------------------------------------------------------------------------- + +inline bool CCachedRenderData::IsVertexPositionCached( int vertex ) const +{ + return (m_pFirstWorldIndex && (m_pFirstWorldIndex[vertex].m_Tag == m_CurrentTag)); +} + +//----------------------------------------------------------------------------- +// Gets an existing world vertex associated with a vertex +//----------------------------------------------------------------------------- + +inline CachedPosNorm_t* CCachedRenderData::GetWorldVertex( int vertex ) +{ + Assert( m_pFirstWorldIndex ); + Assert( m_pFirstWorldIndex[vertex].m_Tag == m_CurrentTag ); + return &m_pWorldVerts[ m_pFirstWorldIndex[vertex].m_VertexIndex ]; +} + +//----------------------------------------------------------------------------- +// For faster setup in the decal code +//----------------------------------------------------------------------------- + +inline void CCachedRenderData::SetBodyModelMesh( int body, int model, int mesh) +{ + m_Body = body; + m_Model = model; + m_Mesh = mesh; + + Assert((m_Model >= 0) && (m_Body >= 0)); + 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; + } +} + + +//----------------------------------------------------------------------------- +// Purpose: +// +// ** Only execute this function if device supports stream offset ** +// +// Input : pmesh - pointer to a studio mesh +// lod - integer lod (0 is most detailed) +// Output : none +//----------------------------------------------------------------------------- +template< class T > +void CCachedRenderData::ComputeFlexedVertex_StreamOffset( studiohdr_t *pStudioHdr, mstudioflex_t *pflex, + T *pvanim, int vertCount, float w1, float w2, float w3, float w4 ) +{ + float w12 = w1 - w2; + float w34 = w3 - w4; + float flVertAnimFixedPointScale = pStudioHdr->VertAnimFixedPointScale(); + + CachedPosNorm_t *pFlexedVertex = NULL; + for (int j = 0; j < pflex->numverts; j++) + { + int n = pvanim[j].index; + + // only flex the indices that are (still) part of this mesh at this lod + if ( n >= vertCount ) + continue; + + float s = pvanim[j].speed; + float b = pvanim[j].side; + + Vector4DAligned vPosition, vNormal; + pvanim[j].GetDeltaFixed4DAligned( &vPosition, flVertAnimFixedPointScale ); + pvanim[j].GetNDeltaFixed4DAligned( &vNormal, flVertAnimFixedPointScale ); + + if ( !IsThinVertexFlexed(n) ) + { + // Add a new flexed vert to the flexed vertex list + pFlexedVertex = CreateThinFlexVertex(n); + + Assert( pFlexedVertex != NULL); + + pFlexedVertex->m_Position.InitZero(); + pFlexedVertex->m_Normal.InitZero(); + } + else + { + pFlexedVertex = GetThinFlexVertex(n); + } + + s *= 1.0f / 255.0f; + b *= 1.0f / 255.0f; + + float wa = w2 + w12 * s; + float wb = w4 + w34 * s; + float w = wa + ( wb - wa ) * b; + Vector4DWeightMAD( w, vPosition, pFlexedVertex->m_Position, vNormal, pFlexedVertex->m_Normal ); + } +} + +#endif // FLEXRENDERDATA_H |