//====== Copyright © 1996-2004, Valve Corporation, All rights reserved. ======= // // A class representing vertex data // //============================================================================= #ifndef DMEVERTEXDATA_H #define DMEVERTEXDATA_H #ifdef _WIN32 #pragma once #endif #include "datamodel/dmelement.h" #include "datamodel/dmattribute.h" #include "datamodel/dmattributevar.h" #include "mathlib/vector.h" #include "Color.h" //----------------------------------------------------------------------------- // Forward declarations //----------------------------------------------------------------------------- class Vector; class Vector4D; class Color; //----------------------------------------------------------------------------- // Used to represent fields //----------------------------------------------------------------------------- typedef int FieldIndex_t; class CDmeVertexDataBase : public CDmElement { DEFINE_ELEMENT( CDmeVertexDataBase, CDmElement ); public: // NOTE: If you add fields to this, add to g_pStandardFieldNames in dmevertexdata.cpp enum StandardFields_t { FIELD_POSITION, FIELD_NORMAL, FIELD_TANGENT, FIELD_TEXCOORD, FIELD_COLOR, FIELD_JOINT_WEIGHTS, FIELD_JOINT_INDICES, FIELD_BALANCE, // Used by left/right delta states FIELD_MORPH_SPEED, // Used to author morph speeds FIELD_WRINKLE, // Used to author morphed wrinklemaps FIELD_WEIGHT, // Weight is just the different between the base position and the delta position FIELD_CLOTH_ENABLE, STANDARD_FIELD_COUNT, }; // resolve internal data from changed attributes virtual void Resolve(); // Returns the number of joints per vertex int JointCount() const; // Vertex accessors int VertexCount() const; const Vector& GetPosition( int nVertexIndex ) const; const Vector& GetNormal( int nVertexIndex ) const; const Vector2D& GetTexCoord( int nVertexIndex ) const; const Vector4D& GetTangent( int nVertexIndex ) const; const Color& GetColor( int nVertexIndex ) const; const float *GetJointWeights( int nVertexIndex ) const; const float *GetJointPositionWeights( int nPositionIndex ) const; const int *GetJointIndices( int nVertexIndex ) const; const int *GetJointPositionIndices( int nPositionIndex ) const; float GetBalance( int nVertexIndex ) const; float GetMorphSpeed( int nVertexIndex ) const; float GetWrinkle( int nVertexIndex ) const; float GetWeight( int nVertexIndex ) const; // Returns indices into the various fields int GetPositionIndex( int nVertexIndex ) const; int GetNormalIndex( int nVertexIndex ) const; int GetTangentIndex( int nVertexIndex ) const; int GetTexCoordIndex( int nVertexIndex ) const; int GetColorIndex( int nVertexIndex ) const; int GetBalanceIndex( int nVertexIndex ) const; int GetMorphSpeedIndex( int nVertexIndex ) const; int GetWrinkleIndex( int nVertexIndex ) const; int GetWeightIndex( int nVertexIndex ) const; // Creates a new vertex field. NOTE: This cannot be used to create joint weights + indices template< class T > FieldIndex_t CreateField( const char *pFieldName ); FieldIndex_t CreateField( const char *pFieldName, DmAttributeType_t type ); FieldIndex_t CreateField( StandardFields_t fieldId ); // Use this to create vertex fields for joint weights + indices void CreateJointWeightsAndIndices( int nJointCount, FieldIndex_t *pJointWeightsField, FieldIndex_t *pJointIndicesField ); // Returns the field index of a particular field FieldIndex_t FindFieldIndex( const char *pFieldName ) const; FieldIndex_t FindFieldIndex( StandardFields_t nFieldIndex ) const; // Adds a new vertex, returns the vertex index // NOTE: This will also add vertex indices for DmeMeshDeltaData int AddVertexData( FieldIndex_t nFieldIndex, int nCount ); // Sets vertex data void SetVertexData( FieldIndex_t nFieldIndex, int nFirstVertex, int nCount, DmAttributeType_t valueType, const void *pData ); void SetVertexIndices( FieldIndex_t nFieldIndex, int nFirstIndex, int nCount, const int *pIndices ); // Removes all vertex data associated with a particular field void RemoveAllVertexData( FieldIndex_t nFieldIndex ); // Returns arbitrary vertex + index data CDmAttribute* GetVertexData( FieldIndex_t nFieldIndex ); const CDmAttribute* GetVertexData( FieldIndex_t nFieldIndex ) const; CDmAttribute* GetIndexData( FieldIndex_t nFieldIndex ); const CDmAttribute* GetIndexData( FieldIndex_t nFieldIndex ) const; // Returns well-known vertex data const CUtlVector &GetPositionData( ) const; const CUtlVector &GetNormalData( ) const; const CUtlVector &GetTangentData( ) const; const CUtlVector &GetTextureCoordData( ) const; const CUtlVector &GetColorData( ) const; const float *GetJointWeightData( int nDataIndex ) const; const int *GetJointIndexData( int nDataIndex ) const; const CUtlVector &GetBalanceData( ) const; const CUtlVector &GetMorphSpeedData( ) const; const CUtlVector &GetWrinkleData( ) const; const CUtlVector &GetWeightData( ) const; // Returns well-known index data const CUtlVector &GetVertexIndexData( FieldIndex_t nFieldIndex ) const; const CUtlVector &GetVertexIndexData( StandardFields_t fieldId ) const; // Do we have skinning data? bool HasSkinningData() const; // Do we have cloth_enable data? bool HasClothData(); // Do we need tangent data? (Utility method for applications to know if they should call ComputeDefaultTangentData) bool NeedsTangentData() const; // Should we flip the V coordinates? bool IsVCoordinateFlipped() const; void FlipVCoordinate( bool bFlip ); // Returns an inverse map from vertex data index to vertex index const CUtlVector< int > &FindVertexIndicesFromDataIndex( FieldIndex_t nFieldIndex, int nDataIndex ); const CUtlVector< int > &FindVertexIndicesFromDataIndex( StandardFields_t nFieldIndex, int nDataIndex ); int FieldCount() const; const char *FieldName( int i ) const; void CopyFrom( CDmeVertexDataBase *pSrc ); void CopyTo( CDmeVertexDataBase *pDst ) const; // Reskins the vertex data to new bones // The joint index remap maps an initial bone index to a new bone index void Reskin( const int *pJointTransformIndexRemap ); protected: struct FieldInfo_t { CUtlString m_Name; CDmAttribute *m_pVertexData; CDmAttribute* m_pIndexData; CUtlVector< CUtlVector< int > > m_InverseMap; bool m_bInverseMapDirty; }; // Derived classes must inherit virtual bool IsVertexDeltaData() const { Assert(0); return false; } // Computes the vertex count ( min of the index buffers ) void ComputeFieldInfo(); // Computes the vertex count ( min of the index buffers ) void ComputeVertexCount(); // Updates info for fast lookups for well-known fields void UpdateStandardFieldInfo( int nFieldIndex, const char *pFieldName, DmAttributeType_t attrType ); // Adds a field to the vertex format void FindOrAddVertexField( const char *pFieldName ); // Returns the index of a particular field int GetFieldIndex( int nVertexIndex, StandardFields_t nFieldIndex ) const; // List of names of attributes containing vertex data CDmaStringArray m_VertexFormat; CDmaVar< int > m_nJointCount; CDmaVar< bool > m_bFlipVCoordinates; CUtlVector< FieldInfo_t > m_FieldInfo; FieldIndex_t m_pStandardFieldIndex[STANDARD_FIELD_COUNT]; int m_nVertexCount; }; //----------------------------------------------------------------------------- // Creates a particular vertex data field + associated index field //----------------------------------------------------------------------------- template< class T > inline FieldIndex_t CDmeVertexDataBase::CreateField( const char *pFieldName ) { return CreateField( pFieldName, CDmAttributeInfo< CUtlVector >::AttributeType() ); } //----------------------------------------------------------------------------- // Returns a standard field index //----------------------------------------------------------------------------- inline FieldIndex_t CDmeVertexDataBase::FindFieldIndex( StandardFields_t nFieldIndex ) const { return m_pStandardFieldIndex[ nFieldIndex ]; } //----------------------------------------------------------------------------- // Vertex field accessors //----------------------------------------------------------------------------- inline int CDmeVertexDataBase::VertexCount() const { return m_nVertexCount; } //----------------------------------------------------------------------------- // Returns the number of joints per vertex //----------------------------------------------------------------------------- inline int CDmeVertexDataBase::JointCount() const { return m_nJointCount; } //----------------------------------------------------------------------------- // Should we flip the V coordinates? //----------------------------------------------------------------------------- inline bool CDmeVertexDataBase::IsVCoordinateFlipped() const { return m_bFlipVCoordinates; } inline void CDmeVertexDataBase::FlipVCoordinate( bool bFlip ) { m_bFlipVCoordinates = bFlip; } //----------------------------------------------------------------------------- // Returns arbitrary vertex data //----------------------------------------------------------------------------- inline CDmAttribute* CDmeVertexDataBase::GetVertexData( FieldIndex_t nFieldIndex ) { return m_FieldInfo[ nFieldIndex ].m_pVertexData; } inline const CDmAttribute* CDmeVertexDataBase::GetVertexData( FieldIndex_t nFieldIndex ) const { return m_FieldInfo[ nFieldIndex ].m_pVertexData; } //----------------------------------------------------------------------------- // Returns arbitrary index data //----------------------------------------------------------------------------- inline CDmAttribute* CDmeVertexDataBase::GetIndexData( FieldIndex_t nFieldIndex ) { return m_FieldInfo[ nFieldIndex ].m_pIndexData; } inline const CDmAttribute* CDmeVertexDataBase::GetIndexData( FieldIndex_t nFieldIndex ) const { return m_FieldInfo[ nFieldIndex ].m_pIndexData; } //----------------------------------------------------------------------------- // Utility method for getting at various vertex field indices //----------------------------------------------------------------------------- inline int CDmeVertexDataBase::GetFieldIndex( int nVertexIndex, StandardFields_t nFieldId ) const { Assert( nVertexIndex < m_nVertexCount ); FieldIndex_t nFieldIndex = m_pStandardFieldIndex[nFieldId]; if ( nFieldIndex < 0 ) return -1; CDmrArrayConst indices( GetIndexData( nFieldIndex ) ); return indices[ nVertexIndex ]; } //----------------------------------------------------------------------------- // // Vertex Data for base states // //----------------------------------------------------------------------------- class CDmeVertexData : public CDmeVertexDataBase { DEFINE_ELEMENT( CDmeVertexData, CDmeVertexDataBase ); public: // Adds a new vertex; creates a new entry in all vertex data fields int AddVertexIndices( int nCount ); private: virtual bool IsVertexDeltaData() const { return false; } }; //----------------------------------------------------------------------------- // // Vertex Data for delta states // //----------------------------------------------------------------------------- class CDmeVertexDeltaData : public CDmeVertexDataBase { DEFINE_ELEMENT( CDmeVertexDeltaData, CDmeVertexDataBase ); public: // Computes wrinkle data from position deltas // NOTE: Pass in negative scales to get 'compression', positive to get 'expansion' void GenerateWrinkleDelta( CDmeVertexData *pBindState, float flScale, bool bOverwrite, bool bUseNormalForSign = false ); // Updates existing data or generates new data void UpdateWrinkleDelta( CDmeVertexData *pBindState, float flOldScale, float flNewScale ); // Computes a float map which is the distance between the base and delta position // The maximum distance any vertex is moved is returned float GenerateWeightDelta( CDmeVertexData *pBindState ); CDmaVar< bool > m_bCorrected; CDmaVar< bool > m_bRenderVerts; private: virtual bool IsVertexDeltaData() const { return true; } // Computes max positional delta length float ComputeMaxDeflection( ); }; #endif // DMEVERTEXDATA_H