29 #include "../idlib/precompiled.h"
87 savefile->
ReadObject( reinterpret_cast<idClass *&>(
self ) );
94 gameLocal.
Warning(
"idIK::Restore: IK for entity '%s' at (%s) has no model set.",
95 self->
name.
c_str(),
self->GetPhysics()->GetOrigin().ToString(0) );
99 gameLocal.
Warning(
"idIK::Restore: IK for entity '%s' at (%s) has no modified animation.",
100 self->
name.
c_str(),
self->GetPhysics()->GetOrigin().ToString(0) );
125 if (
self ==
NULL ) {
133 gameLocal.
Warning(
"idIK::Init: IK for entity '%s' at (%s) has no model set.",
134 self->
name.
c_str(),
self->GetPhysics()->GetOrigin().ToString(0) );
138 gameLocal.
Warning(
"idIK::Init: IK for entity '%s' at (%s) uses default model.",
139 self->
name.
c_str(),
self->GetPhysics()->GetOrigin().ToString(0) );
143 if ( model ==
NULL ) {
144 gameLocal.
Warning(
"idIK::Init: IK for entity '%s' at (%s) has no model set.",
145 self->
name.
c_str(),
self->GetPhysics()->GetOrigin().ToString(0) );
150 gameLocal.
Warning(
"idIK::Init: IK for entity '%s' at (%s) has no modified animation.",
151 self->
name.
c_str(),
self->GetPhysics()->GetOrigin().ToString(0) );
183 float length, lengthSqr, lengthInv,
x,
y;
186 vec0 = endPos - startPos;
189 length = lengthInv * lengthSqr;
192 if ( length > len0 + len1 || length <
idMath::Fabs( len0 - len1 ) ) {
193 jointPos = startPos + 0.5f * vec0;
198 vec1 = dir - vec0 * dir * vec0;
201 x = ( length * length + len0 * len0 - len1 * len1 ) * ( 0.5
f * lengthInv );
204 jointPos = startPos + x * vec0 + y * vec1;
216 axis[0] = endPos - startPos;
217 length = axis[0].Normalize();
218 axis[1] = dir - axis[0] * dir * axis[0];
220 axis[2].Cross( axis[1], axis[0] );
428 const char *jointName;
429 idVec3 dir, ankleOrigin, kneeOrigin, hipOrigin, dirOrigin;
430 idMat3 axis, ankleAxis, kneeAxis, hipAxis;
432 static idVec3 footWinding[4] = {
448 if ( !
idIK::Init(
self, anim, modelOffset ) ) {
461 for ( i = 0; i <
numLegs; i++ ) {
463 jointName =
self->spawnArgs.GetString(
va(
"ik_foot%d", i+1 ) );
466 gameLocal.
Error(
"idIK_Walk::Init: invalid foot joint '%s'", jointName );
469 jointName =
self->spawnArgs.GetString(
va(
"ik_ankle%d", i+1 ) );
472 gameLocal.
Error(
"idIK_Walk::Init: invalid ankle joint '%s'", jointName );
475 jointName =
self->spawnArgs.GetString(
va(
"ik_knee%d", i+1 ) );
478 gameLocal.
Error(
"idIK_Walk::Init: invalid knee joint '%s'\n", jointName );
481 jointName =
self->spawnArgs.GetString(
va(
"ik_hip%d", i+1 ) );
484 gameLocal.
Error(
"idIK_Walk::Init: invalid hip joint '%s'\n", jointName );
487 jointName =
self->spawnArgs.GetString(
va(
"ik_dir%d", i+1 ) );
493 jointName =
self->spawnArgs.GetString(
"ik_waist" );
496 gameLocal.
Error(
"idIK_Walk::Init: invalid waist joint '%s'\n", jointName );
500 for ( i = 0; i <
numLegs; i++ ) {
510 hipOrigin = joints[
hipJoints[
i ] ].ToVec3();
514 dirOrigin = joints[
dirJoints[
i ] ].ToVec3();
515 dir = dirOrigin - kneeOrigin;
517 dir.
Set( 1.0
f, 0.0
f, 0.0
f );
532 smoothing =
self->spawnArgs.GetFloat(
"ik_smoothing",
"0.75" );
533 waistSmoothing =
self->spawnArgs.GetFloat(
"ik_waistSmoothing",
"0.75" );
534 footShift =
self->spawnArgs.GetFloat(
"ik_footShift",
"0" );
535 waistShift =
self->spawnArgs.GetFloat(
"ik_waistShift",
"0" );
538 footUpTrace =
self->spawnArgs.GetFloat(
"ik_footUpTrace",
"32" );
539 footDownTrace =
self->spawnArgs.GetFloat(
"ik_footDownTrace",
"32" );
540 tiltWaist =
self->spawnArgs.GetBool(
"ik_tiltWaist",
"0" );
541 usePivot =
self->spawnArgs.GetBool(
"ik_usePivot",
"0" );
544 footSize =
self->spawnArgs.GetFloat(
"ik_footSize",
"4" ) * 0.5f;
545 if ( footSize > 0.0
f ) {
546 for ( i = 0; i < 4; i++ ) {
547 verts[
i] = footWinding[
i] * footSize;
565 float modelHeight, jointHeight, lowestHeight, floorHeights[
MAX_LEGS];
566 float shift, smallestShift, newHeight, step, newPivotYaw,
height, largestAnkleHeight;
568 idVec3 footOrigin, ankleOrigin, kneeOrigin, hipOrigin, waistOrigin;
569 idMat3 modelAxis, waistAxis, axis;
582 normal = -
self->GetPhysics()->GetGravityNormal();
583 modelOrigin =
self->GetPhysics()->GetOrigin();
584 modelAxis =
self->GetRenderEntity()->axis;
585 modelHeight = modelOrigin * normal;
594 for ( i = 0; i <
numLegs; i++ ) {
596 jointOrigins[
i] = modelOrigin + footOrigin * modelAxis;
597 jointHeight = jointOrigins[
i] * normal;
598 if ( jointHeight < lowestHeight ) {
599 lowestHeight = jointHeight;
606 newPivotYaw = modelAxis[0].ToYaw();
613 pivotPos = modelOrigin + footOrigin * modelAxis;
621 for ( i = 0; i <
numLegs; i++ ) {
630 floorHeights[
i] = results.
endpos * normal;
641 const idPhysics *phys =
self->GetPhysics();
650 if ( ent !=
NULL && ent->
IsType( idPlat::Type ) ) {
659 for ( i = 0; i <
numLegs; i++ ) {
662 shift = floorHeights[
i] - modelHeight +
footShift;
667 if ( shift < smallestShift ) {
668 smallestShift = shift;
672 jointOrigins[
i] = modelOrigin + ankleOrigin * modelAxis;
674 height = jointOrigins[
i] * normal;
681 newHeight = height + shift;
682 if ( newHeight > largestAnkleHeight ) {
683 largestAnkleHeight = newHeight;
688 jointOrigins[
i] += shift * normal;
692 waistOrigin = modelOrigin + waistOrigin * modelAxis;
703 if ( height < minWaistFloorDist ) {
718 newHeight = ( waistOrigin +
waistOffset ) * normal;
732 for ( i = 0; i <
numLegs; i++ ) {
736 hipOrigin = modelOrigin +
waistOffset + hipOrigin * modelAxis;
754 GetBoneAxis( hipOrigin, kneeOrigin, hipDir, axis );
758 GetBoneAxis( kneeOrigin, jointOrigins[i], kneeDir, axis );
765 for ( i = 0; i <
numLegs; i++ ) {
788 for ( i = 0; i <
numLegs; i++ ) {
956 const char *jointName;
958 idVec3 dir, handOrigin, elbowOrigin, shoulderOrigin, dirOrigin;
959 idMat3 axis, handAxis, elbowAxis, shoulderAxis;
970 if ( !
idIK::Init(
self, anim, modelOffset ) ) {
983 for ( i = 0; i <
numArms; i++ ) {
985 jointName =
self->spawnArgs.GetString(
va(
"ik_hand%d", i+1 ) );
988 gameLocal.
Error(
"idIK_Reach::Init: invalid hand joint '%s'", jointName );
991 jointName =
self->spawnArgs.GetString(
va(
"ik_elbow%d", i+1 ) );
994 gameLocal.
Error(
"idIK_Reach::Init: invalid elbow joint '%s'\n", jointName );
997 jointName =
self->spawnArgs.GetString(
va(
"ik_shoulder%d", i+1 ) );
1000 gameLocal.
Error(
"idIK_Reach::Init: invalid shoulder joint '%s'\n", jointName );
1003 jointName =
self->spawnArgs.GetString(
va(
"ik_elbowDir%d", i+1 ) );
1010 for ( i = 0; i <
numArms; i++ ) {
1023 dirOrigin = joints[
dirJoints[
i ] ].ToVec3();
1024 dir = dirOrigin - elbowOrigin;
1026 dir.
Set( -1.0
f, 0.0
f, 0.0
f );
1053 idVec3 modelOrigin, shoulderOrigin, elbowOrigin, handOrigin, shoulderDir, elbowDir;
1058 modelOrigin =
self->GetRenderEntity()->origin;
1059 modelAxis =
self->GetRenderEntity()->axis;
1062 for ( i = 0; i <
numArms; i++ ) {
1066 shoulderOrigin = modelOrigin + shoulderOrigin * modelAxis;
1071 handOrigin = modelOrigin + handOrigin * modelAxis;
1075 handOrigin = trace.
endpos;
1092 GetBoneAxis( shoulderOrigin, elbowOrigin, shoulderDir, axis );
1096 GetBoneAxis( elbowOrigin, handOrigin, elbowDir, axis );
1100 for ( i = 0; i <
numArms; i++ ) {
1120 for ( i = 0; i <
numArms; i++ ) {
void SetupPolygon(const idVec3 *v, const int count)
float lowerArmLength[MAX_ARMS]
bool TracePoint(trace_t &results, const idVec3 &start, const idVec3 &end, int contentMask, const idEntity *passEntity)
void Restore(idRestoreGame *savefile)
virtual void ClearJointMods(void)
static const float INFINITY
bool GetJointTransform(jointHandle_t jointHandle, int currenttime, idVec3 &offset, idMat3 &axis)
virtual bool Init(idEntity *self, const char *anim, const idVec3 &modelOffset)
void WriteString(const char *string)
int GetInt(const char *key, const char *defaultString="0") const
jointHandle_t elbowJoints[MAX_ARMS]
virtual void Evaluate(void)
void Save(idSaveGame *savefile) const
void Restore(idRestoreGame *savefile)
idMat3 mat3_identity(idVec3(1, 0, 0), idVec3(0, 1, 0), idVec3(0, 0, 1))
void WriteObject(const idClass *obj)
idMat3 upperLegToHipJoint[MAX_LEGS]
traceModelVert_t verts[MAX_TRACEMODEL_VERTS]
idMat3 lowerArmToElbowJoint[MAX_ARMS]
float oldAnkleHeights[MAX_LEGS]
jointHandle_t dirJoints[MAX_LEGS]
idRenderModel * ModelHandle(void) const
idVec3 elbowForward[MAX_ARMS]
idMat3 Transpose(void) const
void void void void void Error(const char *fmt,...) const id_attribute((format(printf
int NumJoints(void) const
bool IsType(const idTypeInfo &c) const
void Set(const float x, const float y, const float z)
virtual bool Init(idEntity *self, const char *anim, const idVec3 &modelOffset)
bool SolveTwoBones(const idVec3 &startPos, const idVec3 &endPos, const idVec3 &dir, float len0, float len1, idVec3 &jointPos)
bool CreateFrame(int animtime, bool force)
jointHandle_t GetJointHandle(const char *name) const
float GetBoneAxis(const idVec3 &startPos, const idVec3 &endPos, const idVec3 &dir, idMat3 &axis)
void ReadBool(bool &value)
static float Sqrt(float x)
void SetJointPos(jointHandle_t jointnum, jointModTransform_t transform_type, const idVec3 &pos)
jointHandle_t shoulderJoints[MAX_ARMS]
void WriteClipModel(const class idClipModel *clipModel)
void WriteVec3(const idVec3 &vec)
virtual void ClearJointMods(void)
virtual void ANIM_CreateAnimFrame(const idRenderModel *model, const idMD5Anim *anim, int numJoints, idJointMat *frame, int time, const idVec3 &offset, bool remove_origin_offset)
void SetJointAxis(jointHandle_t jointnum, jointModTransform_t transform_type, const idMat3 &mat)
void WriteBool(const bool value)
idMat3 lowerLegToKneeJoint[MAX_LEGS]
void void void Warning(const char *fmt,...) const id_attribute((format(printf
jointHandle_t ankleJoints[MAX_LEGS]
virtual void DebugWinding(const idVec4 &color, const idWinding &w, const idVec3 &origin, const idMat3 &axis, const int lifetime=0, const bool depthTest=false)=0
static const int MAX_ARMS
float upperLegLength[MAX_LEGS]
virtual const contactInfo_t & GetContact(int num) const =0
virtual void DebugLine(const idVec4 &color, const idVec3 &start, const idVec3 &end, const int lifetime=0, const bool depthTest=false)=0
GLubyte GLubyte GLubyte GLubyte w
void ReadFloat(float &value)
idVec3 vec3_origin(0.0f, 0.0f, 0.0f)
virtual void Evaluate(void)
void WriteFloat(const float value)
static float Fabs(float f)
virtual void ClearJointMods(void)
const idMD5Anim * MD5Anim(int num) const
float lowerLegLength[MAX_LEGS]
jointHandle_t hipJoints[MAX_LEGS]
jointHandle_t kneeJoints[MAX_LEGS]
void Save(idSaveGame *savefile) const
const idAnim * GetAnim(int index) const
virtual bool Init(idEntity *self, const char *anim, const idVec3 &modelOffset)
idCVar ik_enable("ik_enable","1", CVAR_GAME|CVAR_BOOL,"enable IK")
virtual bool HasGroundContacts(void) const =0
bool IsInitialized(void) const
const idDeclModelDef * ModelDef(void) const
static float InvSqrt(float x)
float LengthSqr(void) const
const idVec3 & GetVisualOffset(void) const
const char * Name(void) const
float upperArmLength[MAX_ARMS]
GLenum GLsizei GLsizei height
void WriteInt(const int value)
void WriteMat3(const idMat3 &mat)
void ReadMat3(idMat3 &mat)
idEntity * entities[MAX_GENTITIES]
idVec3 kneeForward[MAX_LEGS]
void ReadClipModel(idClipModel *&clipModel)
void Save(idSaveGame *savefile) const
virtual int GetNumContacts(void) const =0
idVec3 shoulderForward[MAX_ARMS]
static float AngleNormalize180(float angle)
idMat3 upperArmToShoulderJoint[MAX_ARMS]
jointHandle_t handJoints[MAX_ARMS]
GLsizei const GLcharARB const GLint * length
void ReadVec3(idVec3 &vec)
const char * c_str(void) const
jointHandle_t footJoints[MAX_LEGS]
idVec3 hipForward[MAX_LEGS]
void Restore(idRestoreGame *savefile)
jointHandle_t dirJoints[MAX_ARMS]
idRenderModel * ModelHandle(void) const
virtual ~idIK_Reach(void)
const idTraceModel * GetTraceModel(void) const
idRenderWorld * gameRenderWorld
char * va(const char *fmt,...)
virtual void Evaluate(void)
bool Translation(trace_t &results, const idVec3 &start, const idVec3 &end, const idClipModel *mdl, const idMat3 &trmAxis, int contentMask, const idEntity *passEntity)
static const int MAX_LEGS
void ReadString(idStr &string)
ID_INLINE T Min(T x, T y)
idCVar ik_debug("ik_debug","0", CVAR_GAME|CVAR_BOOL,"show IK debug lines")
void ReadObject(idClass *&obj)
bool RemoveOrigin(void) const