//====== Copyright © 1996-2004, Valve Corporation, All rights reserved. =====// // // Dme version of a skeletal model (gets compiled into a MDL) // //===========================================================================// #ifndef DMEMODEL_H #define DMEMODEL_H #ifdef _WIN32 #pragma once #endif #include "tier1/utlstack.h" #include "tier1/utlstringtoken.h" #include "movieobjects/dmejoint.h" #include "movieobjects/dmetransformlist.h" #include "movieobjects/dmeaxissystem.h" class CDmeDrawSettings; class CDmeMesh; //----------------------------------------------------------------------------- // A class representing a skeletal model //----------------------------------------------------------------------------- class CDmeModel : public CDmeDag { DEFINE_ELEMENT( CDmeModel, CDmeDag ); public: // Add joint CDmeJoint *AddJoint( const char *pJointName, CDmeDag *pParent = NULL ); int AddJoint( CDmeDag *pJoint ); // Returns the number of joint transforms we know about int GetJointCount() const; // Returns the DmeDag for the specified joint index CDmeDag *GetJoint( int nIndex ); const CDmeDag *GetJoint( int nIndex ) const; // Returns the DmeTransform for the specified joint index CDmeTransform *GetJointTransform( int nIndex ); const CDmeTransform *GetJointTransform( int nIndex ) const; // Determines joint index of a given a joint int GetJointIndex( CDmeDag *pJoint ) const; int GetJointIndex( const char *pJointName ) const; int GetJointIndex( CUtlStringToken nJointNameHash ) const; // Captures the current joint transforms into a base state void CaptureJointsToBaseState( const char *pBaseStateName ); // Sets the joint transforms to the values in the specified base state, if it exists void PushBaseStateToJoints( const char *pBaseStateName ); // Finds a base state by name, returns NULL if not found CDmeTransformList *FindBaseState( const char *pBaseStateName ); // Recursively render the Dag hierarchy virtual void Draw( CDmeDrawSettings *pDrawSettings = NULL ); // NOTE: See comment for m_upAxis attribute below // Set if Z is the up axis of the model // Set to true if the data under the DmeModel is AS_VALVE_ENGINE space( Up: Z, Fwd: X, Left: Y ) // Set to false if the data under the DmeModel is AS_MAYA_YUP space ( Up: Y, Fwd: Z, Left: X ) // See SetAxisSystem() for anything other than AS_VALVE_ENGINE or AS_MAYA_YUP void ZUp( bool bZUp ); // Returns true if the DmeModel is Z Up. bool IsZUp() const; // Returns the matrix that moves DmeModel data to engine space void GetModelToEngineMat( matrix3x4_t &modelToEngineMat ); // Returns the matrix that moves engine data to DmeModel space void GetEngineToModelMat( matrix3x4_t &engineToModelMat ); // Replace all instances of a material with a different material // Using a NULL material name will replace *all* materials with the new material void ReplaceMaterial( const char *pOldMaterialName, const char *pNewMaterialName ); // Collapses all joints below the specified joint name, reskinning any meshes // referring to collapsed joints to use the specified joint instead void CollapseJoints( const char *pJointName ); // Gets the joint with the specified name CDmeDag *GetJoint( const char *pJointName ); // Reskin all meshes under the DmeModel void ReskinMeshes( const int *pJointTransformIndexRemap ); // Sets the DmeAxisSystem, no reorientation is done, see ConvertToAxisSystem bool SetAxisSystem( CDmeAxisSystem::PredefinedAxisSystem ePredefAxisSystem ); bool SetAxisSystem( CDmeAxisSystem::Axis_t eUpAxis, CDmeAxisSystem::ForwardParity_t eForwardParity, CDmeAxisSystem::CoordSys_t eCoordSys = CDmeAxisSystem::AS_RIGHT_HANDED ); // Sets the DmeAxisSystem and reorients all of the data under the DmeModel // as necessary to change from the current DmeAxisSystem to the specified DmeAxisSystem // Currently private, will be made public soon, upAxis is still authoritative bool ConvertToAxisSystem( CDmeAxisSystem::PredefinedAxisSystem ePredefAxisSystem ); bool ConvertToAxisSystem( CDmeAxisSystem::Axis_t eUpAxis, CDmeAxisSystem::ForwardParity_t eForwardParity, CDmeAxisSystem::CoordSys_t eCoordSys = CDmeAxisSystem::AS_RIGHT_HANDED ); // Returns the matrix to convert data from the current axisSystem to the specified axisSystem bool GetConversionMatrix( matrix3x4a_t &mConversion, CDmeAxisSystem::PredefinedAxisSystem eToPredefinedAxisSystem ); // Freeze child meshes, pushes transform into vertices of mesh, used to be part of Reorient void FreezeChildMeshes(); // TransformScene void TransformScene( const Vector &vScale = Vector( 1.0f, 1.0f, 1.0f ), const Vector &vTranslate = vec3_origin, const DegreeEuler &eRotation = DegreeEuler( 0.0f, 0.0f, 0.0f ), float flEps = 1.0e-4 ); void ScaleScene( const Vector &vScale ); // Updates all base states by adding missing joints void UpdateBaseStates(); private: // Reskin meshes based on bone collapse void ReskinMeshes( CDmeDag *pDag, const int *pJointTransformIndexRemap ); // Remove joints void RemoveJoints( int nNewJointCount, const int *pInvJointRemap ); // Removes all children from this joint, moving shapes to be void RemoveAllChildren( CDmeDag *pDag, CDmeDag *pSubtreeRoot, const matrix3x4_t &jointToSubtreeRoot ); void RemoveAllChildren( CDmeDag *pSubtreeRoot ); // Helper functions for ReorientToEngineSpace() and ReorientToDCCToolSpace() static void GetReorientData( matrix3x4_t &m, Quaternion &q, bool bMakeZUp ); static void ReorientDmeAnimation( CDmeDag *pDmeDag, const matrix3x4_t &mOrient, const Quaternion &qOrient ); static void ReorientDmeTransform( CDmeTransform *pDmeTransform, const matrix3x4_t &mOrient, const Quaternion &qOrient ); static void ReorientDmeModelChildren( CDmeModel *pDmeModel, const matrix3x4_t &mOrient, const Quaternion &qOrient ); static void ReorientChildDmeMeshes_R( CDmeDag *pDmeDag ); static void ReorientDmeMesh( CDmeMesh *pDmeMesh, matrix3x4_t absMat ); protected: // The order in which the joint transform names appear in this list // indicates the joint index for each dag CDmaElementArray< CDmeDag > m_JointList; // Stores a list of base poses for all the joint transforms CDmaElementArray m_BaseStates; // Stores the up axis of the model // One of Y or Z // // NOTE: Y up is Maya's typical coordinate system. Setting the up axis to Z // won't quite give you the engine's coordinate system (even though it // has an Up Axis of Z as well). The difference is the forward axis. // // A DmeModel with m_UpAxis = Y gives the data in a coordinate system // that is Maya's typical coordinate system. Y Up, Z Foward, X Right. // // A DmeModel with m_UpAxis = Z gives the data in a coordinate system // that is compatible with typical SMD data. This is data that can // be compiled in studiomdl without any special options. // // Neither Y up or Z up is engine space. Z up is closer but still // requires another 90 degree rotation to align things. This can be // changed in the future if required but Z up was added for legacy // SMD compatibility. // // In this table, missing entries mean it's not required or isn't // supported // // m_UpAxis Desc Up Forward Right studiomdl // -------- ------------- ------- ------- ------- --------- // Y Maya Y Up Y Z X $upaxis Y // Z Maya Z Up/XSI Z -Y X // Engine Z X Y $origin 0 0 0 0 //----------------------------------------------------------------------------- CDmaString m_UpAxis; CDmaElement< CDmeAxisSystem > m_eAxisSystem; CDmaElement< CDmeModel > m_eModel; CDmaElement< CDmeModel > m_eSkeleton; private: enum SetupBoneRetval_t { NO_SKIN_DATA = 0, TOO_MANY_BONES, BONES_SET_UP }; // Sets up the render state for the model SetupBoneRetval_t SetupBoneMatrixState( const matrix3x4_t& shapeToWorld, bool bForceSoftwareSkin ); // Loads up joint transforms for this model void LoadJointTransform( CDmeDag *pJoint, CDmeTransformList *pBindPose, const matrix3x4_t &parentToWorld, const matrix3x4_t &parentToBindPose, bool bSetHardwareState ); // Implementation of ReplaceMaterial void ReplaceMaterial( CDmeDag *pDag, const char *pOldMaterialName, const char *pNewMaterialName ); // Sets up the render state for the model static matrix3x4_t *SetupModelRenderState( const matrix3x4_t& shapeToWorld, bool bHasSkinningData, bool bForceSoftwareSkin ); static void CleanupModelRenderState(); // Stack of DmeModels currently being rendered. Used to set up render state static CUtlStack< CDmeModel * > s_ModelStack; friend class CDmeMesh; friend bool SetMeshFromSkeleton( CDmeMesh *pDmeMesh ); // dmx edit function - to do skin weights }; #endif // DMEMODEL_H