forked from a1batross/Paranoia2_original
209 lines
5.4 KiB
C++
209 lines
5.4 KiB
C++
/*
|
|
ikcontext.h - Inverse Kinematic implementation
|
|
Copyright (C) 2017 Uncle Mike
|
|
|
|
This program is free software: you can redistribute it and/or modify
|
|
it under the terms of the GNU General Public License as published by
|
|
the Free Software Foundation, either version 3 of the License, or
|
|
(at your option) any later version.
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
GNU General Public License for more details.
|
|
*/
|
|
|
|
#ifndef IKCONTEXT_H
|
|
#define IKCONTEXT_H
|
|
|
|
#include <studio.h>
|
|
#include <utlarray.h>
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Purpose:
|
|
//-----------------------------------------------------------------------------
|
|
class CIKContext;
|
|
|
|
// ik info
|
|
class CIKTarget
|
|
{
|
|
public:
|
|
void SetOwner( int entindex, const Vector &pos, const Vector &angles );
|
|
void ClearOwner( void );
|
|
int GetOwner( void );
|
|
void UpdateOwner( int entindex, const Vector &pos, const Vector &angles );
|
|
void SetPos( const Vector &pos );
|
|
void SetAngles( const Vector &angles );
|
|
void SetQuaternion( const Vector4D &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, Vector &deltaAngles );
|
|
// accumulated offset from ideal footplant location
|
|
public:
|
|
struct x2
|
|
{
|
|
int attachmentIndex;
|
|
Vector pos;
|
|
Vector4D q;
|
|
} offset;
|
|
private:
|
|
struct x3
|
|
{
|
|
Vector pos;
|
|
Vector4D q;
|
|
} ideal;
|
|
public:
|
|
struct x4
|
|
{
|
|
float latched;
|
|
float release;
|
|
float height;
|
|
float floor;
|
|
float radius;
|
|
float flWeight;
|
|
Vector pos;
|
|
Vector4D 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
|
|
{
|
|
bool bNeedsLatch;
|
|
bool bHasLatch;
|
|
float influence;
|
|
int iFramecounter;
|
|
int owner;
|
|
Vector absOrigin;
|
|
Vector absAngles;
|
|
Vector pos;
|
|
Vector4D q;
|
|
Vector deltaPos; // acculated error
|
|
Vector4D deltaQ;
|
|
Vector debouncePos;
|
|
Vector4D debounceQ;
|
|
} latched;
|
|
|
|
struct x6
|
|
{
|
|
float flTime; // time last error was detected
|
|
float flErrorTime;
|
|
float ramp;
|
|
bool bInError;
|
|
} error;
|
|
|
|
friend class CIKContext;
|
|
};
|
|
|
|
typedef struct
|
|
{
|
|
// accumulated offset from ideal footplant location
|
|
int target;
|
|
Vector pos;
|
|
Vector4D q;
|
|
float flWeight;
|
|
} ikchainresult_t;
|
|
|
|
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;
|
|
Vector4D 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?
|
|
int iAttachment;
|
|
|
|
Vector kneeDir;
|
|
Vector kneePos;
|
|
|
|
ikcontextikrule_t() {}
|
|
|
|
private:
|
|
// No copy constructors allowed
|
|
ikcontextikrule_t(const ikcontextikrule_t& vOther);
|
|
};
|
|
|
|
class CIKContext
|
|
{
|
|
public:
|
|
CIKContext( );
|
|
void Init( const CStudioBoneSetup *pBoneSetup, const Vector &angles, const Vector &pos, float flTime, int iFramecounter );
|
|
void AddDependencies( mstudioseqdesc_t *pseqdesc, int iSequence, float flCycle, float flWeight = 1.0f );
|
|
|
|
void ClearTargets( void );
|
|
void UpdateTargets( Vector pos[], Vector4D q[], matrix3x4 boneToWorld[], byte *pBoneSet = NULL );
|
|
void AutoIKRelease( void );
|
|
void SolveDependencies( Vector pos[], Vector4D q[], matrix3x4 boneToWorld[], byte *pBoneSet = NULL );
|
|
|
|
void AddAutoplayLocks( Vector pos[], Vector4D q[] );
|
|
void SolveAutoplayLocks( Vector pos[], Vector4D q[] );
|
|
|
|
void AddSequenceLocks( mstudioseqdesc_t *pseqdesc, Vector pos[], Vector4D q[] );
|
|
void SolveSequenceLocks( mstudioseqdesc_t *pseqdesc, Vector pos[], Vector4D q[] );
|
|
|
|
void AddAllLocks( Vector pos[], Vector4D q[] );
|
|
void SolveAllLocks( Vector pos[], Vector4D q[] );
|
|
|
|
void SolveLock( const mstudioiklock_t *plock, int i, Vector pos[], Vector4D q[], matrix3x4 boneToWorld[], byte *pBoneSet = NULL );
|
|
|
|
CUtlArrayFixed< CIKTarget, 12 > m_target;
|
|
|
|
private:
|
|
CStudioBoneSetup *m_pBoneSetup;
|
|
|
|
bool Estimate( int iSequence, float flCycle, int iTarget, const float poseParameter[], float flWeight = 1.0f );
|
|
void BuildBoneChain( const Vector pos[], const Vector4D q[], int iBone, matrix3x4 *pBoneToWorld, byte *pBoneSet = NULL );
|
|
|
|
// virtual IK rules, filtered and combined from each sequence
|
|
CUtlArray< CUtlArray< ikcontextikrule_t > > m_ikChainRule;
|
|
CUtlArray< ikcontextikrule_t > m_ikLock;
|
|
|
|
static matrix3x4 m_boneToWorld[MAXSTUDIOBONES];
|
|
matrix3x4 m_rootxform;
|
|
|
|
int m_iFramecounter;
|
|
float m_flTime;
|
|
};
|
|
|
|
#endif//IKCONTEXT
|