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 /public/bone_setup.h | |
| download | archived-source-engine-2018-hl2-src-master.tar.xz archived-source-engine-2018-hl2-src-master.zip | |
Diffstat (limited to 'public/bone_setup.h')
| -rw-r--r-- | public/bone_setup.h | 449 |
1 files changed, 449 insertions, 0 deletions
diff --git a/public/bone_setup.h b/public/bone_setup.h new file mode 100644 index 0000000..76f00a6 --- /dev/null +++ b/public/bone_setup.h @@ -0,0 +1,449 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $NoKeywords: $ +//=============================================================================// + +#ifndef BONE_SETUP_H +#define BONE_SETUP_H +#ifdef _WIN32 +#pragma once +#endif + + +#include "studio.h" +#include "cmodel.h" +#include "bitvec.h" + + +class CBoneToWorld; +class CIKContext; +class CBoneAccessor; +class IPoseDebugger; + + +// This provides access to networked arrays, so if this code actually changes a value, +// the entity is marked as changed. +abstract_class IParameterAccess +{ +public: + virtual float GetParameter( int iParam ) = 0; + virtual void SetParameter( int iParam, float flValue ) = 0; +}; + + + +class CBoneBitList : public CBitVec<MAXSTUDIOBONES> +{ +public: + inline void MarkBone(int iBone) + { + Set(iBone); + } + inline bool IsBoneMarked(int iBone) + { + return Get(iBone) != 0 ? true : false; + } +}; + +class CBoneSetup; +class IBoneSetup +{ +public: + IBoneSetup( const CStudioHdr *pStudioHdr, int boneMask, const float poseParameter[], IPoseDebugger *pPoseDebugger = NULL ); + ~IBoneSetup( void ); + void InitPose( Vector pos[], Quaternion[] ); + void AccumulatePose( Vector pos[], Quaternion q[], int sequence, float cycle, float flWeight, float flTime, CIKContext *pIKContext ); + void CalcAutoplaySequences( Vector pos[], Quaternion q[], float flRealTime, CIKContext *pIKContext ); + void CalcBoneAdj( Vector pos[], Quaternion q[], const float controllers[] ); + CStudioHdr *GetStudioHdr(); +private: + CBoneSetup *m_pBoneSetup; +}; + +//----------------------------------------------------------------------------- +// Purpose: blends together all the bones from two p:q lists +// +// p1 = p1 * (1 - s) + p2 * s +// q1 = q1 * (1 - s) + q2 * s +//----------------------------------------------------------------------------- +void SlerpBones( + const CStudioHdr *pStudioHdr, + Quaternion q1[MAXSTUDIOBONES], + Vector pos1[MAXSTUDIOBONES], + mstudioseqdesc_t &seqdesc, // source of q2 and pos2 + int sequence, + const Quaternion q2[MAXSTUDIOBONES], + const Vector pos2[MAXSTUDIOBONES], + float s, + int boneMask + ); + +// Given two samples of a bone separated in time by dt, +// compute the velocity and angular velocity of that bone +void CalcBoneDerivatives( Vector &velocity, AngularImpulse &angVel, const matrix3x4_t &prev, const matrix3x4_t ¤t, float dt ); +// Give a derivative of a bone, compute the velocity & angular velocity of that bone +void CalcBoneVelocityFromDerivative( const QAngle &vecAngles, Vector &velocity, AngularImpulse &angVel, const matrix3x4_t ¤t ); + +// This function sets up the local transform for a single frame of animation. It doesn't handle +// pose parameters or interpolation between frames. +void SetupSingleBoneMatrix( + CStudioHdr *pOwnerHdr, + int nSequence, + int iFrame, + int iBone, + matrix3x4_t &mBoneLocal ); + + +// Purpose: build boneToWorld transforms for a specific bone +void BuildBoneChain( + const CStudioHdr *pStudioHdr, + const matrix3x4_t &rootxform, + const Vector pos[], + const Quaternion q[], + int iBone, + matrix3x4_t *pBoneToWorld ); + +void BuildBoneChain( + const CStudioHdr *pStudioHdr, + const matrix3x4_t &rootxform, + const Vector pos[], + const Quaternion q[], + int iBone, + matrix3x4_t *pBoneToWorld, + CBoneBitList &boneComputed ); + + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- + +// ik info +class CIKTarget +{ +public: + void SetOwner( int entindex, const Vector &pos, const QAngle &angles ); + void ClearOwner( void ); + int GetOwner( void ); + void UpdateOwner( int entindex, const Vector &pos, const QAngle &angles ); + void SetPos( const Vector &pos ); + void SetAngles( const QAngle &angles ); + void SetQuaternion( const Quaternion &q ); + void SetNormal( const Vector &normal ); + void SetPosWithNormalOffset( const Vector &pos, const Vector &normal ); + void SetOnWorld( bool bOnWorld = true ); + + bool IsActive( void ); + void IKFailed( void ); + int chain; + int type; + void MoveReferenceFrame( Vector &deltaPos, QAngle &deltaAngles ); + // accumulated offset from ideal footplant location +public: + struct x2 { + char *pAttachmentName; + Vector pos; + Quaternion q; + } offset; +private: + struct x3 { + Vector pos; + Quaternion q; + } ideal; +public: + struct x4 { + float latched; + float release; + float height; + float floor; + float radius; + float flTime; + float flWeight; + Vector pos; + Quaternion q; + bool onWorld; + } est; // estimate contact position + struct x5 { + float hipToFoot; // distance from hip + float hipToKnee; // distance from hip to knee + float kneeToFoot; // distance from knee to foot + Vector hip; // location of hip + Vector closest; // closest valid location from hip to foot that the foot can move to + Vector knee; // pre-ik location of knee + Vector farthest; // farthest valid location from hip to foot that the foot can move to + Vector lowest; // lowest position directly below hip that the foot can drop to + } trace; +private: + // internally latched footset, position + struct x1 { + // matrix3x4_t worldTarget; + bool bNeedsLatch; + bool bHasLatch; + float influence; + int iFramecounter; + int owner; + Vector absOrigin; + QAngle absAngles; + Vector pos; + Quaternion q; + Vector deltaPos; // acculated error + Quaternion deltaQ; + Vector debouncePos; + Quaternion debounceQ; + } latched; + struct x6 { + float flTime; // time last error was detected + float flErrorTime; + float ramp; + bool bInError; + } error; + + friend class CIKContext; +}; + + +struct ikchainresult_t +{ + // accumulated offset from ideal footplant location + int target; + Vector pos; + Quaternion q; + float flWeight; +}; + + + +struct ikcontextikrule_t +{ + int index; + + int type; + int chain; + + int bone; + + int slot; // iktarget slot. Usually same as chain. + float height; + float radius; + float floor; + Vector pos; + Quaternion q; + + float start; // beginning of influence + float peak; // start of full influence + float tail; // end of full influence + float end; // end of all influence + + float top; + float drop; + + float commit; // frame footstep target should be committed + float release; // frame ankle should end rotation from latched orientation + + float flWeight; // processed version of start-end cycle + float flRuleWeight; // blending weight + float latched; // does the IK rule use a latched value? + char *szLabel; + + Vector kneeDir; + Vector kneePos; + + ikcontextikrule_t() {} + +private: + // No copy constructors allowed + ikcontextikrule_t(const ikcontextikrule_t& vOther); +}; + + +void Studio_AlignIKMatrix( matrix3x4_t &mMat, const Vector &vAlignTo ); + +bool Studio_SolveIK( int iThigh, int iKnee, int iFoot, Vector &targetFoot, matrix3x4_t* pBoneToWorld ); + +bool Studio_SolveIK( int iThigh, int iKnee, int iFoot, Vector &targetFoot, Vector &targetKneePos, Vector &targetKneeDir, matrix3x4_t* pBoneToWorld ); + + + +class CIKContext +{ +public: + CIKContext( ); + void Init( const CStudioHdr *pStudioHdr, const QAngle &angles, const Vector &pos, float flTime, int iFramecounter, int boneMask ); + void AddDependencies( mstudioseqdesc_t &seqdesc, int iSequence, float flCycle, const float poseParameters[], float flWeight = 1.0f ); + + void ClearTargets( void ); + void UpdateTargets( Vector pos[], Quaternion q[], matrix3x4_t boneToWorld[], CBoneBitList &boneComputed ); + void AutoIKRelease( void ); + void SolveDependencies( Vector pos[], Quaternion q[], matrix3x4_t boneToWorld[], CBoneBitList &boneComputed ); + + void AddAutoplayLocks( Vector pos[], Quaternion q[] ); + void SolveAutoplayLocks( Vector pos[], Quaternion q[] ); + + void AddSequenceLocks( mstudioseqdesc_t &SeqDesc, Vector pos[], Quaternion q[] ); + void SolveSequenceLocks( mstudioseqdesc_t &SeqDesc, Vector pos[], Quaternion q[] ); + + void AddAllLocks( Vector pos[], Quaternion q[] ); + void SolveAllLocks( Vector pos[], Quaternion q[] ); + + void SolveLock( const mstudioiklock_t *plock, int i, Vector pos[], Quaternion q[], matrix3x4_t boneToWorld[], CBoneBitList &boneComputed ); + + CUtlVectorFixed< CIKTarget, 12 > m_target; + +private: + + CStudioHdr const *m_pStudioHdr; + + bool Estimate( int iSequence, float flCycle, int iTarget, const float poseParameter[], float flWeight = 1.0f ); + void BuildBoneChain( const Vector pos[], const Quaternion q[], int iBone, matrix3x4_t *pBoneToWorld, CBoneBitList &boneComputed ); + + // virtual IK rules, filtered and combined from each sequence + CUtlVector< CUtlVector< ikcontextikrule_t > > m_ikChainRule; + CUtlVector< ikcontextikrule_t > m_ikLock; + matrix3x4_t m_rootxform; + + int m_iFramecounter; + float m_flTime; + int m_boneMask; +}; + + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- + +// replaces the bonetoworld transforms for all bones that are procedural +bool CalcProceduralBone( + const CStudioHdr *pStudioHdr, + int iBone, + CBoneAccessor &bonetoworld + ); + +void Studio_BuildMatrices( + const CStudioHdr *pStudioHdr, + const QAngle& angles, + const Vector& origin, + const Vector pos[], + const Quaternion q[], + int iBone, + float flScale, + matrix3x4_t bonetoworld[MAXSTUDIOBONES], + int boneMask + ); + + +// Get a bone->bone relative transform +void Studio_CalcBoneToBoneTransform( const CStudioHdr *pStudioHdr, int inputBoneIndex, int outputBoneIndex, matrix3x4_t &matrixOut ); + +// Given a bone rotation value, figures out the value you need to give to the controller +// to have the bone at that value. +// [in] flValue = the desired bone rotation value +// [out] ctlValue = the (0-1) value to set the controller t. +// return value = flValue, unwrapped to lie between the controller's start and end. +float Studio_SetController( const CStudioHdr *pStudioHdr, int iController, float flValue, float &ctlValue ); + + +// Given a 0-1 controller value, maps it into the controller's start and end and returns the bone rotation angle. +// [in] ctlValue = value in controller space (0-1). +// return value = value in bone space +float Studio_GetController( const CStudioHdr *pStudioHdr, int iController, float ctlValue ); + +void Studio_CalcDefaultPoseParameters( const CStudioHdr *pStudioHdr, float flPoseParameter[MAXSTUDIOPOSEPARAM], int nCount ); +float Studio_GetPoseParameter( const CStudioHdr *pStudioHdr, int iParameter, float ctlValue ); +float Studio_SetPoseParameter( const CStudioHdr *pStudioHdr, int iParameter, float flValue, float &ctlValue ); + +// converts a global 0..1 pose parameter into the local sequences blending value +void Studio_LocalPoseParameter( const CStudioHdr *pStudioHdr, const float poseParameter[], mstudioseqdesc_t &seqdesc, int iSequence, int iLocalIndex, float &flSetting, int &index ); + +void Studio_SeqAnims( const CStudioHdr *pStudioHdr, mstudioseqdesc_t &seqdesc, int iSequence, const float poseParameter[], mstudioanimdesc_t *panim[4], float *weight ); +int Studio_MaxFrame( const CStudioHdr *pStudioHdr, int iSequence, const float poseParameter[] ); +float Studio_FPS( const CStudioHdr *pStudioHdr, int iSequence, const float poseParameter[] ); +float Studio_CPS( const CStudioHdr *pStudioHdr, mstudioseqdesc_t &seqdesc, int iSequence, const float poseParameter[] ); +float Studio_Duration( const CStudioHdr *pStudioHdr, int iSequence, const float poseParameter[] ); +void Studio_MovementRate( const CStudioHdr *pStudioHdr, int iSequence, const float poseParameter[], Vector *pVec ); + +// void Studio_Movement( const CStudioHdr *pStudioHdr, int iSequence, const float poseParameter[], Vector *pVec ); + +//void Studio_AnimPosition( mstudioanimdesc_t *panim, float flCycle, Vector &vecPos, Vector &vecAngle ); +//void Studio_AnimVelocity( mstudioanimdesc_t *panim, float flCycle, Vector &vecVelocity ); +//float Studio_FindAnimDistance( mstudioanimdesc_t *panim, float flDist ); +bool Studio_AnimMovement( mstudioanimdesc_t *panim, float flCycleFrom, float flCycleTo, Vector &deltaPos, QAngle &deltaAngle ); +bool Studio_SeqMovement( const CStudioHdr *pStudioHdr, int iSequence, float flCycleFrom, float flCycleTo, const float poseParameter[], Vector &deltaMovement, QAngle &deltaAngle ); +bool Studio_SeqVelocity( const CStudioHdr *pStudioHdr, int iSequence, float flCycle, const float poseParameter[], Vector &vecVelocity ); +float Studio_FindSeqDistance( const CStudioHdr *pStudioHdr, int iSequence, const float poseParameter[], float flDist ); +float Studio_FindSeqVelocity( const CStudioHdr *pStudioHdr, int iSequence, const float poseParameter[], float flVelocity ); +int Studio_FindAttachment( const CStudioHdr *pStudioHdr, const char *pAttachmentName ); +int Studio_FindRandomAttachment( const CStudioHdr *pStudioHdr, const char *pAttachmentName ); +int Studio_BoneIndexByName( const CStudioHdr *pStudioHdr, const char *pName ); +const char *Studio_GetDefaultSurfaceProps( CStudioHdr *pstudiohdr ); +float Studio_GetMass( CStudioHdr *pstudiohdr ); +const char *Studio_GetKeyValueText( const CStudioHdr *pStudioHdr, int iSequence ); + +FORWARD_DECLARE_HANDLE( memhandle_t ); +struct bonecacheparams_t +{ + CStudioHdr *pStudioHdr; + matrix3x4_t *pBoneToWorld; + float curtime; + int boneMask; +}; + +class CBoneCache +{ +public: + + // you must implement these static functions for the ResourceManager + // ----------------------------------------------------------- + static CBoneCache *CreateResource( const bonecacheparams_t ¶ms ); + static unsigned int EstimatedSize( const bonecacheparams_t ¶ms ); + // ----------------------------------------------------------- + // member functions that must be present for the ResourceManager + void DestroyResource(); + CBoneCache *GetData() { return this; } + unsigned int Size() { return m_size; } + // ----------------------------------------------------------- + + CBoneCache(); + + // was constructor, but placement new is messy wrt memdebug - so cast & init instead + void Init( const bonecacheparams_t ¶ms, unsigned int size, short *pStudioToCached, short *pCachedToStudio, int cachedBoneCount ); + + void UpdateBones( const matrix3x4_t *pBoneToWorld, int numbones, float curtime ); + matrix3x4_t *GetCachedBone( int studioIndex ); + void ReadCachedBones( matrix3x4_t *pBoneToWorld ); + void ReadCachedBonePointers( matrix3x4_t **bones, int numbones ); + + bool IsValid( float curtime, float dt = 0.1f ); + +public: + float m_timeValid; + int m_boneMask; + +private: + matrix3x4_t *BoneArray(); + short *StudioToCached(); + short *CachedToStudio(); + + unsigned int m_size; + unsigned short m_cachedBoneCount; + unsigned short m_matrixOffset; + unsigned short m_cachedToStudioOffset; + unsigned short m_boneOutOffset; +}; + +CBoneCache *Studio_GetBoneCache( memhandle_t cacheHandle ); +memhandle_t Studio_CreateBoneCache( bonecacheparams_t ¶ms ); +void Studio_DestroyBoneCache( memhandle_t cacheHandle ); +void Studio_InvalidateBoneCache( memhandle_t cacheHandle ); + +// Given a ray, trace for an intersection with this studiomodel. Get the array of bones from StudioSetupHitboxBones +bool TraceToStudio( class IPhysicsSurfaceProps *pProps, const Ray_t& ray, CStudioHdr *pStudioHdr, mstudiohitboxset_t *set, matrix3x4_t **hitboxbones, int fContentsMask, const Vector &vecOrigin, float flScale, trace_t &trace ); + +void QuaternionSM( float s, const Quaternion &p, const Quaternion &q, Quaternion &qt ); +void QuaternionMA( const Quaternion &p, float s, const Quaternion &q, Quaternion &qt ); + +bool Studio_PrefetchSequence( const CStudioHdr *pStudioHdr, int iSequence ); + +void Studio_RunBoneFlexDrivers( float *pFlexController, const CStudioHdr *pStudioHdr, const Vector *pPositions, const matrix3x4_t *pBoneToWorld, const matrix3x4_t &mRootToWorld ); + +#endif // BONE_SETUP_H |