summaryrefslogtreecommitdiff
path: root/public/movieobjects/dmemesh.h
diff options
context:
space:
mode:
Diffstat (limited to 'public/movieobjects/dmemesh.h')
-rw-r--r--public/movieobjects/dmemesh.h496
1 files changed, 496 insertions, 0 deletions
diff --git a/public/movieobjects/dmemesh.h b/public/movieobjects/dmemesh.h
new file mode 100644
index 0000000..8b4830c
--- /dev/null
+++ b/public/movieobjects/dmemesh.h
@@ -0,0 +1,496 @@
+//========= Copyright Valve Corporation, All rights reserved. ============//
+//
+// A class representing a mesh
+//
+//=============================================================================
+
+#ifndef DMEMESH_H
+#define DMEMESH_H
+
+#ifdef _WIN32
+#pragma once
+#endif
+
+#include "movieobjects/dmeshape.h"
+#include "movieobjects/dmevertexdata.h"
+#include "materialsystem/MaterialSystemUtil.h"
+#include "mathlib/vector.h"
+#include "tier1/utllinkedlist.h"
+#include "Color.h"
+
+
+//-----------------------------------------------------------------------------
+// Forward declarations
+//-----------------------------------------------------------------------------
+class CDmElement;
+class CDmeFaceSet;
+class CDmeVertexData;
+class IMaterial;
+class IMorph;
+class IMesh;
+class Vector;
+class Vector4D;
+class Color;
+class CDmeDag;
+class CMeshBuilder;
+class CDmeCombinationOperator;
+class CDmeSingleIndexedComponent;
+class CDmeDrawSettings;
+class CDmMeshComp;
+
+//-----------------------------------------------------------------------------
+// Mesh weights
+//-----------------------------------------------------------------------------
+enum MeshDeltaWeightType_t
+{
+ MESH_DELTA_WEIGHT_FIRST = 0,
+
+ MESH_DELTA_WEIGHT_NORMAL = 0,
+ MESH_DELTA_WEIGHT_LAGGED,
+
+ MESH_DELTA_WEIGHT_TYPE_COUNT,
+};
+
+
+//-----------------------------------------------------------------------------
+// Mesh representation
+//-----------------------------------------------------------------------------
+class CDmeMesh : public CDmeShape
+{
+DEFINE_ELEMENT( CDmeMesh, CDmeShape );
+
+public:
+ // resolve internal data from changed attributes
+ virtual void OnAttributeChanged( CDmAttribute *pAttribute );
+
+ void GetBoundingSphere( Vector &c, float &r, CDmeVertexData *pPassedBase, CDmeSingleIndexedComponent *pPassedSelection ) const;
+
+ virtual void GetBoundingSphere( Vector &c, float &r ) const { return GetBoundingSphere( c, r, NULL, NULL ); }
+
+ void GetBoundingBox( Vector &min, Vector &max, CDmeVertexData *pPassedBase /* = NULL */, CDmeSingleIndexedComponent *pPassedSelection /* = NULL */ ) const;
+
+ virtual void GetBoundingBox( Vector &min, Vector &max ) const { return GetBoundingBox( min, max, NULL, NULL ); }
+
+ // accessors
+ int FaceSetCount() const;
+ CDmeFaceSet *GetFaceSet( int nFaceSetIndex );
+ const CDmeFaceSet *GetFaceSet( int nFaceSetIndex ) const;
+ void AddFaceSet( CDmeFaceSet *faceSet );
+ void RemoveFaceSet( int nFaceSetIndex );
+
+ // Base states
+ int BaseStateCount() const;
+
+ CDmeVertexData *GetBaseState( int nBaseIndex ) const;
+
+ CDmeVertexData *FindBaseState( const char *pStateName ) const;
+
+ CDmeVertexData *FindOrCreateBaseState( const char *pStateName );
+ bool DeleteBaseState( const char *pStateName );
+
+ // Selects a particular base state to be current state
+ void SetCurrentBaseState( const char *pStateName );
+ CDmeVertexData *GetCurrentBaseState();
+ const CDmeVertexData *GetCurrentBaseState() const;
+
+ bool SetBindBaseState( CDmeVertexData *pBaseState );
+ CDmeVertexData *GetBindBaseState();
+ const CDmeVertexData *GetBindBaseState() const;
+
+ // Draws the mesh
+ void Draw( const matrix3x4_t &shapeToWorld, CDmeDrawSettings *pDrawSettings = NULL );
+
+ // Compute triangulated indices
+ void ComputeTriangulatedIndices( const CDmeVertexData *pBaseState, CDmeFaceSet *pFaceSet, int nFirstIndex, int *pIndices, int nOutCount );
+
+ // Compute a default per-vertex tangent given normal data + uv data for all vertex data referenced by this mesh
+ void ComputeDefaultTangentData( bool bSmoothTangents = false );
+
+ // Compute a default per-vertex tangent given normal data + uv data
+ void ComputeDefaultTangentData( CDmeVertexData *pVertexData, bool bSmoothTangents = false );
+
+ // Delta states
+ int DeltaStateCount() const;
+ CDmeVertexDeltaData *GetDeltaState( int nDeltaIndex ) const;
+ CDmeVertexDeltaData *FindDeltaState( const char *pDeltaName ) const;
+ CDmeVertexDeltaData *FindOrCreateDeltaState( const char *pDeltaName );
+ bool DeleteDeltaState( const char *pDeltaName );
+ bool ResetDeltaState( const char *pDeltaName );
+ int FindDeltaStateIndex( const char *pDeltaName ) const;
+ void SetDeltaStateWeight( int nDeltaIndex, MeshDeltaWeightType_t type, float flMorphWeight );
+ void SetDeltaStateWeight( int nDeltaIndex, MeshDeltaWeightType_t type, float flLeftWeight, float flRightWeight );
+ CDmeVertexDeltaData *ModifyOrCreateDeltaStateFromBaseState( const char *pDeltaName, CDmeVertexData *pPassedBase = NULL, bool absolute = false );
+
+ // Sets all of the data in the current base state to be the bind state plus the corrected delta, if delta is NULL then it's set to the bind state
+ bool SetBaseStateToDelta( const CDmeVertexDeltaData *pDelta, CDmeVertexData *pPassedBase = NULL );
+
+ // Selects the vertices from the delta that change position
+ void SelectVerticesFromDelta( CDmeVertexDeltaData *pDelta, CDmeSingleIndexedComponent *pSelection );
+
+ // Selects all the vertices in the mesh
+ void SelectAllVertices( CDmeSingleIndexedComponent *pSelection, CDmeVertexData *pPassedBase = NULL );
+
+ enum SelectHalfType_t
+ {
+ kLeft,
+ kRight
+ };
+
+ // Selects all the vertices in the mesh
+ void SelectHalfVertices( SelectHalfType_t selectHalfType, CDmeSingleIndexedComponent *pSelection, CDmeVertexData *pPassedBase = NULL );
+
+ // Add the delta into the vertex data state weighted by the weight and masked by the weight map
+ bool AddMaskedDelta(
+ CDmeVertexDeltaData *pDelta,
+ CDmeVertexData *pDst = NULL,
+ float weight = 1.0f,
+ const CDmeSingleIndexedComponent *pMask = NULL );
+
+ // Interpolate between the current state and the specified delta by the specified percentage masked by the selection
+ bool InterpMaskedDelta(
+ CDmeVertexDeltaData *pDelta,
+ CDmeVertexData *pDst = NULL,
+ float weight = 1.0f,
+ const CDmeSingleIndexedComponent *pMask = NULL );
+
+ // Grows the selection by a specified amount
+ void GrowSelection( int nSize, CDmeSingleIndexedComponent *pSelection, CDmMeshComp *pPassedMeshComp );
+
+ // Shrinks the selection by a specified amount
+ void ShrinkSelection( int nSize, CDmeSingleIndexedComponent *pSelection, CDmMeshComp *pPassedMeshComp );
+
+ enum Falloff_t
+ {
+ STRAIGHT = 0,
+ LINEAR = STRAIGHT,
+ BELL,
+ SMOOTH = BELL,
+ SPIKE,
+ DOME
+ };
+
+ enum Distance_t
+ {
+ DIST_ABSOLUTE = 0,
+ DIST_RELATIVE,
+ DIST_DEFAULT
+ };
+
+ CDmeSingleIndexedComponent *FeatherSelection( float falloffDistance, Falloff_t falloffType, Distance_t distanceType, CDmeSingleIndexedComponent *pSelection, CDmMeshComp *pPassedMeshComp );
+
+ // Computes new normal deltas for all states based on position deltas
+ void ComputeDeltaStateNormals();
+
+ struct DeltaComputation_t
+ {
+ int m_nDeltaIndex;
+ int m_nDimensionality;
+ CUtlVector<int> m_DependentDeltas;
+ };
+
+ // Construct list of all n-1 -> 1 dimensional delta states that will be active when this delta state is active
+ void ComputeDependentDeltaStateList( CUtlVector< DeltaComputation_t > &compList );
+
+ // Construct list of all > n dimensional delta states that when active have the specified state as a dependent
+ bool ComputeSuperiorDeltaStateList( const char *pDeltaName, CUtlVector< int > &superiorDeltaStates );
+
+ void SetDeltaNormalDataFromActualNormals( int nDeltaIndex, const CUtlVector<int> &deltaStateList, int nNormalCount, Vector *pNormals );
+
+ void ComputeAllCorrectedPositionsFromActualPositions();
+
+ // Computes adds a delta to the passed data weighted by the passed weight
+ template < class T_t > void AddDelta(
+ const CDmeVertexDeltaData *pDelta, T_t *pFullData, int nFullData, FieldIndex_t fieldIndex, float weight = 1.0f, const CDmeSingleIndexedComponent *pMask = NULL );
+
+ template < class T_t > void AddDelta(
+ const CDmeVertexDeltaData *pDelta, T_t *pFullData, int nFullData, CDmeVertexData::StandardFields_t standardField, float weight = 1.0f, const CDmeSingleIndexedComponent *pMask = NULL );
+
+ bool SetBaseStateToDeltas( CDmeVertexData *pPassedBase = NULL );
+
+ template < class T_t >
+ bool SetBaseDataToDeltas( CDmeVertexData *pBase, CDmeVertexData::StandardFields_t nStandardField, CDmrArrayConst< T_t > &srcData, CDmrArray< T_t > &dstData, bool bDoStereo, bool bDoLag );
+
+ // Replace all instances of a material with a different material
+ void ReplaceMaterial( const char *pOldMaterialName, const char *pNewMaterialName );
+
+ // makes all the normals in the mesh unit length
+ void NormalizeNormals();
+
+ // Collapses redundant normals in the model
+ // flNormalBlend is the maximum difference in the dot product between two normals to consider them
+ // to be the same normal, a value of cos( DEG2RAD( 2.0 ) ) is the default studiomdl uses, for example
+ void CollapseRedundantNormals( float flNormalBlend );
+
+ // SWIG errors on the parsing of something in the private section of DmeMesh, it isn't exposed by SWIG anyway, so have SWIG ignore it
+#ifndef SWIG
+ template < class T_t > static int GenerateCompleteDataForDelta( const CDmeVertexDeltaData *pDelta, T_t *pFullData, int nFullData, CDmeVertexData::StandardFields_t standardField );
+
+private:
+ friend class CDmMeshComp;
+
+ struct FaceSet_t
+ {
+ FaceSet_t() : m_bBuilt(false) {}
+ IMesh *m_pMesh;
+ bool m_bBuilt;
+ };
+
+ struct Triangle_t
+ {
+ int m_nIndex[3];
+ Vector m_vecTangentS;
+ Vector m_vecTangentT;
+ };
+
+ struct RenderVertexDelta_t
+ {
+ Vector m_vecDeltaPosition;
+ Vector m_vecDeltaNormal;
+ Vector2D m_vecDeltaUV;
+ Vector4D m_vecDeltaColor;
+ float m_flDeltaWrinkle;
+ };
+
+ VertexFormat_t ComputeHwMeshVertexFormat( void );
+ IMorph *CreateHwMorph( IMaterial *pMTL );
+ IMesh *CreateHwMesh( CDmeFaceSet *pFaceSet );
+
+ // Draws the mesh when it uses too many bones
+ void DrawDynamicMesh( CDmeFaceSet *pFaceSet, matrix3x4_t *pPoseToWorld, bool bHasActiveDeltaStates, CDmeDrawSettings *pDrawSettings = NULL );
+
+ // Build a map from vertex index to a list of triangles that share the vert.
+ void BuildTriangleMap( const CDmeVertexData *pBaseState, CDmeFaceSet* pFaceSet, CUtlVector<Triangle_t>& triangles, CUtlVector< CUtlVector<int> >* pVertToTriMap = NULL );
+
+ // Computes tangent space data for triangles
+ void ComputeTriangleTangets( const CDmeVertexData *pVertexData, CUtlVector<Triangle_t>& triangles );
+
+ // Build a map from vertex index to a list of triangles that share the vert.
+ void ComputeAverageTangent( CDmeVertexData *pVertexData, bool bSmoothTangents, CUtlVector< CUtlVector<int> >& vertToTriMap, CUtlVector<Triangle_t>& triangles );
+
+ // Do we have active delta state data?
+ bool HasActiveDeltaStates() const;
+
+ // Adds deltas into a delta mesh
+ template< class T > bool AddVertexDelta( CDmeVertexData *pBaseState, void *pVertexData, int nStride, CDmeVertexDataBase::StandardFields_t fieldId, int nIndex, bool bDoLag );
+ template< class T > bool AddStereoVertexDelta( CDmeVertexData *pBaseState, void *pVertexData, int nStride, CDmeVertexDataBase::StandardFields_t fieldId, int nIndex, bool bDoLag );
+ void AddTexCoordDelta( RenderVertexDelta_t *pRenderDelta, float flWeight, CDmeVertexDeltaData *pDeltaState );
+ void AddColorDelta( RenderVertexDelta_t *pRenderDelta, float flWeight, CDmeVertexDeltaData *pDeltaState );
+
+ // Builds deltas based on the current deltas, returns true if there was delta wrinkle data
+ bool BuildDeltaMesh( int nVertices, RenderVertexDelta_t *pDelta );
+
+ // Builds a map from vertex index to all triangles that use it
+ void BuildVertToTriMap( const CDmeVertexData *pVertexData, CUtlVector<Triangle_t> &triangles, CUtlVector< CUtlVector<int> > &vertToTriMap );
+
+ // Compute the dimensionality of the delta state (how many inputs affect it)
+ int ComputeDeltaStateDimensionality( int nDeltaIndex );
+
+ // Discovers the atomic controls used by the various delta states
+ void BuildAtomicControlLists( int nCount, DeltaComputation_t *pInfo, CUtlVector< CUtlVector< int > > &deltaStateUsage );
+
+ // Computes the aggregate position for all vertices after applying a set of delta states
+ void AddDelta( CDmeVertexData *pBaseState, Vector *pDeltaPosition, int nDeltaStateIndex, CDmeVertexData::StandardFields_t fieldId );
+
+ // Converts pose-space normals into deltas appropriate for correction delta states
+ void ComputeCorrectedNormalsFromActualNormals( const CUtlVector<int> &deltaStateList, int nNormalCount, Vector *pNormals );
+
+ // Copies the corrected normal data into a delta state
+ void SetDeltaNormalData( int nDeltaIndex, int nNormalCount, Vector *pNormals );
+ // Renders normals
+ void RenderNormals( matrix3x4_t *pPoseToWorld, RenderVertexDelta_t *pDelta );
+
+ // Writes triangulated indices for a face set into a meshbuilder
+ void WriteTriangluatedIndices( const CDmeVertexData *pBaseState, CDmeFaceSet *pFaceSet, CMeshBuilder &meshBuilder );
+
+ // Initializes the normal material
+ static void InitializeNormalMaterial();
+
+ // Sort function
+ static int DeltaStateLessFunc( const void * lhs, const void * rhs );
+
+ // Computes a list of the delta states ordered by dimensionality
+ void ComputeDeltaStateComputationList( CUtlVector< DeltaComputation_t > &compList );
+
+ // Compute the number of combinations of n items taken k at a time nCk - Probably doesn't belong here but it useful for combos
+ static void Combinations( int n, int k, CUtlVector< CUtlVector< int > > &combos, int *pTmpArray = NULL, int start = 0, int currentK = 0 );
+
+ // Splits the passed delta state name on '_' and finds all of the control Delta states which make up the name
+ bool GetControlDeltaIndices( CDmeVertexDeltaData *pDeltaState, CUtlVector< int > &controlDeltaIndices ) const;
+
+ // Splits the passed delta state name on '_' and finds all of the control Delta states which make up the name
+ bool GetControlDeltaIndices( const char *pDeltaStateName, CUtlVector< int > &controlDeltaIndices ) const;
+
+ // Builds a complete list of all of the delta states expressed as the control indices
+ bool BuildCompleteDeltaStateControlList( CUtlVector< CUtlVector< int > > &deltaStateControlList ) const;
+
+ // Given a list of control indices and a complete list of control indices for each delta state, returns the delta index or -1 if it doesn't exist
+ int FindDeltaIndexFromControlIndices( const CUtlVector< int > &controlIndices, const CUtlVector< CUtlVector< int > > &controlList ) const;
+
+ // Builds a list of all of the dependent delta states that do not already exist
+ bool BuildMissingDependentDeltaList( CDmeVertexDeltaData *pDeltaState, CUtlVector< int > &controlIndices, CUtlVector< CUtlVector< int > > &dependentStates ) const;
+
+ static void ComputeCorrectedPositionsFromActualPositions( const CUtlVector< int > &deltaStateList, int nPositionCount, Vector *pPositions );
+
+ template < class T_t > void AddCorrectedDelta(
+ CDmrArray< T_t > &baseDataArray,
+ const CUtlVector< int > &baseIndices,
+ const DeltaComputation_t &deltaComputation,
+ const char *pFieldName,
+ float weight = 1.0f,
+ const CDmeSingleIndexedComponent *pMask = NULL );
+
+ template < class T_t > void AddCorrectedDelta(
+ CUtlVector< T_t > &baseData,
+ const CUtlVector< int > &baseIndices,
+ const DeltaComputation_t &deltaComputation,
+ const char *pFieldName,
+ float weight = 1.0f,
+ const CDmeSingleIndexedComponent *pMask = NULL );
+
+ // Add the delta into the vertex data state weighted by the weight and masked by the weight map
+ bool AddCorrectedMaskedDelta(
+ CDmeVertexDeltaData *pDelta,
+ CDmeVertexData *pDst = NULL,
+ float weight = 1.0f,
+ const CDmeSingleIndexedComponent *pMask = NULL );
+
+ template < class T_t > void AddRawDelta(
+ CDmeVertexDeltaData *pDelta,
+ CDmrArray< T_t > &baseDataArray,
+ FieldIndex_t nDeltaFieldIndex,
+ float weight = 1.0f,
+ const CDmeSingleIndexedComponent *pMask = NULL );
+
+ template < class T_t > void AddRawDelta(
+ CDmeVertexDeltaData *pDelta,
+ CUtlVector< T_t > &baseData,
+ FieldIndex_t nDeltaFieldIndex,
+ float weight = 1.0f,
+ const CDmeSingleIndexedComponent *pMask = NULL );
+
+ friend class CDmxEdit;
+ bool RemoveBaseState( CDmeVertexData *pBase );
+ CDmeVertexData *FindOrAddBaseState( CDmeVertexData *pBase );
+
+ // CFalloff functors map [0, 1] values to [0, 1] values
+ template < int T >
+ class CFalloff
+ {
+ public:
+ virtual inline float operator()( float x ) { return 1 - x; }
+ };
+
+ template<>
+ class CFalloff< CDmeMesh::LINEAR >
+ {
+ public:
+ virtual inline float operator()( float x ) { return 1 - x; }
+ };
+
+ template<>
+ class CFalloff< CDmeMesh::SMOOTH >
+ {
+ public:
+ virtual inline float operator()( float x ) {
+ return ( cosf( x * M_PI ) + 1.0f ) / 2.0f;
+ }
+ };
+
+ template<>
+ class CFalloff< CDmeMesh::DOME >
+ {
+ public:
+ virtual inline float operator()( float x ) {
+ return ( cosf( x * M_PI / 2.0 ) );
+ }
+ };
+
+ template<>
+ class CFalloff< CDmeMesh::SPIKE >
+ {
+ public:
+ virtual inline float operator()( float x ) {
+ return ( 1.0f - cosf( ( 1.0f - x ) * M_PI / 2.0 ) );
+ }
+ };
+
+ // Feather's the selection by a specified amount, creates a new CDmeSingleIndexedComponent or NULL if error
+ template < int T >
+ CDmeSingleIndexedComponent *FeatherSelection( float fFalloffDistance, Distance_t distanceType, CDmeSingleIndexedComponent *pSelection, CDmMeshComp *pPassedMeshComp );
+
+ bool CreateDeltaFieldFromBaseField( CDmeVertexData::StandardFields_t nStandardFieldIndex, const CDmrArrayConst< float > &baseArray, const CDmrArrayConst< float > &bindArray, CDmeVertexDeltaData *pDelta );
+ bool CreateDeltaFieldFromBaseField( CDmeVertexData::StandardFields_t nStandardFieldIndex, const CDmrArrayConst< Vector2D > &baseArray, const CDmrArrayConst< Vector2D > &bindArray, CDmeVertexDeltaData *pDelta );
+ bool CreateDeltaFieldFromBaseField( CDmeVertexData::StandardFields_t nStandardFieldIndex, const CDmrArrayConst< Vector > &baseArray, const CDmrArrayConst< Vector > &bindArray, CDmeVertexDeltaData *pDelta );
+
+ template< class T_t > bool InterpMaskedData(
+ CDmrArray< T_t > &aData,
+ const CUtlVector< T_t > &bData,
+ float weight,
+ const CDmeSingleIndexedComponent *pMask ) const;
+
+ // Interpolate between the current state and the specified delta by the specified percentage masked by the selection
+ bool InterpMaskedData(
+ CDmeVertexData *paData,
+ const CDmeVertexData *pbData,
+ float weight,
+ const CDmeSingleIndexedComponent *pMask ) const;
+
+ // Find the closest vertex in the specified selection to the passed vertex in the specified base state, if the passed base state is NULL is the current base state
+ int ClosestSelectedVertex( int vIndex, CDmeSingleIndexedComponent *pSelection, const CDmeVertexData *pPassedBase = NULL ) const;
+
+ // Return the distance between the two vertices in the specified base state, if the specified base state is NULL the current state is used
+ float DistanceBetween( int vIndex0, int vIndex1, const CDmeVertexData *pPassedBase = NULL ) const;
+
+ void DrawWireframeFaceSet( CDmeFaceSet *pFaceSet, matrix3x4_t *pPoseToWorld, bool bHasActiveDeltaStates, CDmeDrawSettings *pDrawSettings );
+
+ void ComputeNormalsFromPositions( CDmeVertexData *pBase, const Vector *pPosition, const CUtlVector<Triangle_t> &triangles, int nNormalCount, Vector *pNormals );
+
+ CDmaElement< CDmeVertexData > m_BindBaseState;
+ CDmaElement< CDmeVertexData > m_CurrentBaseState;
+ CDmaElementArray< CDmeVertexData > m_BaseStates;
+ CDmaElementArray< CDmeVertexDeltaData > m_DeltaStates;
+ CDmaElementArray< CDmeFaceSet > m_FaceSets;
+
+ // x is left value, y is right value. If the delta state isn't split, they are the same value
+ CDmaArray<Vector2D> m_DeltaStateWeights[MESH_DELTA_WEIGHT_TYPE_COUNT];
+
+ // Cached-off map of fields->
+ CUtlVector< FaceSet_t > m_hwFaceSets;
+
+ // Normal rendering materials
+ static bool s_bNormalMaterialInitialized;
+ static CMaterialReference s_NormalMaterial;
+ static CMaterialReference s_NormalErrorMaterial;
+
+ static bool s_bMaterialsInitialized;
+ static CMaterialReference s_WireframeMaterial;
+ static CMaterialReference s_WireframeOnShadedMaterial;
+
+ friend class CRenderInfo;
+
+#endif // ndef SWIG
+};
+
+
+//-----------------------------------------------------------------------------
+// Inline methods
+//-----------------------------------------------------------------------------
+inline int CDmeMesh::BaseStateCount() const
+{
+ return m_BaseStates.Count();
+}
+
+
+inline CDmeVertexData *CDmeMesh::GetBaseState( int nBaseIndex ) const
+{
+ return m_BaseStates[ nBaseIndex ];
+}
+
+
+//-----------------------------------------------------------------------------
+// Utility method to compute default tangent data on all meshes in the sub-dag hierarchy
+//-----------------------------------------------------------------------------
+void ComputeDefaultTangentData( CDmeDag *pDag, bool bSmoothTangents );
+
+
+#endif // DMEMESH_H