QuatT GetWorldOffset(const QuatT& origin, const QuatT& destination) { CRY_ASSERT(origin.IsValid()); CRY_ASSERT(destination.IsValid()); QuatT offset(destination.t - origin.t, origin.q.GetInverted() * destination.q); offset.q.Normalize(); CRY_ASSERT(offset.IsValid()); return offset; }
QuatT ApplyWorldOffset(const QuatT& origin, const QuatT& offset) { CRY_ASSERT(origin.IsValid()); CRY_ASSERT(offset.IsValid()); QuatT destination(origin.q * offset.q, origin.t + offset.t); destination.q.Normalize(); CRY_ASSERT(destination.IsValid()); return destination; }
bool CTransformationPinning::Execute(const SAnimationPoseModifierParams& params) { if (m_factor == 0.0f) return false; CRY_ASSERT(m_source && (m_jointID > 0.0f)); if (!m_jointsInitialised) { Init(params); } ISkeletonPose* pSkeletonPose = params.pCharacterInstance->GetISkeletonPose(); int sourceJoints = m_source->GetJointCount(); CRY_ASSERT(sourceJoints == pSkeletonPose->GetJointCount()); for (int i=0; i<sourceJoints; i++) { const QuatT &sourceJoint = m_source->GetAbsJointByID(i); const QuatT &relSourceJoint = m_source->GetRelJointByID(i); CRY_ASSERT(params.pPoseData->GetJointAbsolute(i).IsValid()); CRY_ASSERT(sourceJoint.IsValid()); switch (m_jointTypes[i]) { case TransformationPinJoint::Copy: if (m_factor < 1.0f) { QuatT diff = params.pPoseData->GetJointAbsolute(i).GetInverted() * sourceJoint; params.pPoseData->SetJointAbsolute(i, params.pPoseData->GetJointAbsolute(i) * diff.GetScaled(m_factor)); diff = params.pPoseData->GetJointRelative(i).GetInverted() * relSourceJoint; params.pPoseData->SetJointRelative(i, params.pPoseData->GetJointRelative(i) * diff.GetScaled(m_factor)); } else { params.pPoseData->SetJointAbsolute(i, sourceJoint); params.pPoseData->SetJointRelative(i, relSourceJoint); } break; case TransformationPinJoint::Feather: { int16 parent = m_source->GetParentIDByID(i); QuatT invParent = params.pPoseData->GetJointAbsolute(parent).GetInverted(); params.pPoseData->SetJointRelative(i, invParent * params.pPoseData->GetJointAbsolute(i)); QuatT thisJnt = params.pPoseData->GetJointAbsolute(parent) * params.pPoseData->GetJointRelative(i); CRY_ASSERT(params.pPoseData->GetJointRelative(i).IsValid()); CRY_ASSERT(thisJnt.IsValid()); } break; case TransformationPinJoint::Inherit: break; } } return true; }
QuatT CombineHVComponents2D(const QuatT& cmpH, const QuatT& cmpV) { ANIMCHAR_PROFILE_DETAILED; // NOTE: This function assumes there is no pitch/bank and totally ignores XY rotations. CRY_ASSERT(cmpH.IsValid()); CRY_ASSERT(cmpV.IsValid()); QuatT cmb; cmb.t.x = cmpH.t.x; cmb.t.y = cmpH.t.y; cmb.t.z = cmpV.t.z; cmb.q.SetRotationZ(cmpH.q.GetRotZ()); CRY_ASSERT(cmb.IsValid()); return cmb; }
QuatT /*CAnimatedCharacter::*/ExtractVComponent(const QuatT& m) /*const*/ { ANIMCHAR_PROFILE_DETAILED; // NOTE: This function assumes there is no pitch/bank and totally ignores XY rotations. CRY_ASSERT(m.IsValid()); QuatT ext;//(IDENTITY); ext.t.z = m.t.z; ext.t.x = 0.0f; ext.t.y = 0.0f; /* Ang3 a(m.q); a.z = 0.0f; ext.q.SetRotationXYZ(a); */ ext.q.SetIdentity(); CRY_ASSERT(ext.IsValid()); return ext; }
QuatT CombineHVComponents3D(const QuatT& cmpH, const QuatT& cmpV) { ANIMCHAR_PROFILE_DETAILED; //return CombineHVComponents2D(cmpH, cmpV); CRY_ASSERT(cmpH.IsValid()); CRY_ASSERT(cmpV.IsValid()); QuatT cmb; cmb.t.x = cmpH.t.x; cmb.t.y = cmpH.t.y; cmb.t.z = cmpV.t.z; // TODO: This should be optimized! Ang3 ah(cmpH.q); Ang3 av(cmpV.q); Ang3 a(av.x, av.y, ah.z); cmb.q.SetRotationXYZ(a); CRY_ASSERT(cmb.IsValid()); return cmb; }
void CAnimatedCharacter::SetDesiredLocalLocation( ISkeletonAnim* pSkeletonAnim, const QuatT& desiredLocalLocation, float fDeltaTime) { CRY_ASSERT(desiredLocalLocation.IsValid()); { uint32 NumAnimsInQueue = pSkeletonAnim->GetNumAnimsInFIFO(0); uint32 nMaxActiveInQueue=MAX_EXEC_QUEUE; if (nMaxActiveInQueue>NumAnimsInQueue) nMaxActiveInQueue=NumAnimsInQueue; if (NumAnimsInQueue>nMaxActiveInQueue) NumAnimsInQueue=nMaxActiveInQueue; uint32 active=0; for (uint32 a=0; a<NumAnimsInQueue; a++) { const CAnimation& anim = pSkeletonAnim->GetAnimFromFIFO(0,a); active += anim.IsActivated() ? 1 : 0; } if (active>nMaxActiveInQueue) active=nMaxActiveInQueue; nMaxActiveInQueue=active; const SParametricSampler *pLMG = NULL; for (int32 a=nMaxActiveInQueue-1; (a >= 0) && !pLMG; --a) { const CAnimation& anim = pSkeletonAnim->GetAnimFromFIFO(0,a); pLMG = anim.GetParametricSampler(); } } const Vec3 dir = desiredLocalLocation.GetColumn1(); float turnAngle = atan2f(-dir.x, dir.y); float turnSpeed = turnAngle / fDeltaTime; const Vec2 deltaVector(desiredLocalLocation.t.x, desiredLocalLocation.t.y); const float travelDist = deltaVector.GetLength(); const Vec2 deltaDir = (travelDist > 0.0f) ? (deltaVector / travelDist) : Vec2(0,0); float travelAngle = (deltaDir.x == 0.0f && deltaDir.y == 0.0f ? 0.0f : atan2f(-deltaDir.x, deltaDir.y)); float travelSpeed; if (gEnv->bMultiplayer) { travelSpeed = travelDist / fDeltaTime; } else { const float cosGroundSlope = fabsf(cosf(m_fGroundSlopeMoveDirSmooth)); travelSpeed = (cosGroundSlope > FLT_EPSILON) ? (travelDist / (fDeltaTime * cosGroundSlope)) : (travelDist / fDeltaTime); } // TravelAngle smoothing { const Vec2 newStrafe = Vec2(-sin_tpl(travelAngle), cos_tpl(travelAngle)); if (CAnimationGraphCVars::Get().m_enableTurnAngleSmoothing) { SmoothCD(m_fDesiredStrafeSmoothQTX, m_fDesiredStrafeSmoothRateQTX, fDeltaTime, newStrafe, 0.10f); } else { m_fDesiredStrafeSmoothQTX=newStrafe; m_fDesiredStrafeSmoothRateQTX.zero(); } travelAngle = Ang3::CreateRadZ(Vec2(0,1),m_fDesiredStrafeSmoothQTX); } const bool modulateTurnSpeedByTravelAngle = true; if (modulateTurnSpeedByTravelAngle) { static float minimum = DEG2RAD(10.0f); // do not change turnSpeed when travelAngle is below this static float maximum = DEG2RAD(40.0f); // force turnspeed to zero when travelAngle is above this const float turnSpeedScale = 1.0f - clamp_tpl( fabsf(travelAngle) - minimum, 0.0f, maximum - minimum ) / ( maximum - minimum ); turnSpeed *= turnSpeedScale; } // TurnSpeed smoothing { if (CAnimationGraphCVars::Get().m_enableTurnSpeedSmoothing) { SmoothCD(m_fDesiredTurnSpeedSmoothQTX, m_fDesiredTurnSpeedSmoothRateQTX, fDeltaTime, turnSpeed, 0.40f); } else { m_fDesiredTurnSpeedSmoothQTX = turnSpeed; m_fDesiredTurnSpeedSmoothRateQTX = 0.0f; } } // TravelSpeed smoothing { if (CAnimationGraphCVars::Get().m_enableTravelSpeedSmoothing) { SmoothCD(m_fDesiredMoveSpeedSmoothQTX, m_fDesiredMoveSpeedSmoothRateQTX, fDeltaTime, travelSpeed, 0.04f); } else { m_fDesiredMoveSpeedSmoothQTX = travelSpeed; m_fDesiredMoveSpeedSmoothRateQTX = 0.0f; } } SetMotionParam(pSkeletonAnim, eMotionParamID_TravelSpeed, m_fDesiredMoveSpeedSmoothQTX); SetMotionParam(pSkeletonAnim, eMotionParamID_TurnSpeed, m_fDesiredTurnSpeedSmoothQTX * CAnimationGraphCVars::Get().m_turnSpeedParamScale); SetMotionParam(pSkeletonAnim, eMotionParamID_TravelAngle, travelAngle); // eMotionParamID_TravelSlope SetMotionParam(pSkeletonAnim, eMotionParamID_TurnAngle, turnAngle); // eMotionParamID_TravelDist SetMotionParam(pSkeletonAnim, eMotionParamID_StopLeg, 0); }
QuatT CAnimatedCharacter::MergeMCM(const QuatT& ent, const QuatT& anim, bool flat) const { ANIMCHAR_PROFILE_DETAILED; CRY_ASSERT(ent.IsValid()); CRY_ASSERT(anim.IsValid()); EMovementControlMethod mcmh = GetMCMH(); EMovementControlMethod mcmv = GetMCMV(); CRY_ASSERT(mcmh >= 0 && mcmh < eMCM_COUNT); CRY_ASSERT(mcmv >= 0 && mcmv < eMCM_COUNT); if (mcmh == mcmv) { switch (mcmh /*or mcmv*/) { case eMCM_Entity: case eMCM_ClampedEntity: case eMCM_SmoothedEntity: return ent; case eMCM_DecoupledCatchUp: case eMCM_Animation: case eMCM_AnimationHCollision: return anim; default: GameWarning("CAnimatedCharacter::MergeMCM() - Horizontal & Vertical MCM %s not implemented!", g_szMCMString[mcmh]); return ent; } } QuatT mergedH, mergedV; switch (mcmh) { case eMCM_Entity: case eMCM_ClampedEntity: case eMCM_SmoothedEntity: mergedH = ent; break; case eMCM_DecoupledCatchUp: case eMCM_Animation: case eMCM_AnimationHCollision: mergedH = anim; break; default: mergedH = ent; GameWarning("CAnimatedCharacter::MergeMCM() - Horizontal MCM %s not implemented!", g_szMCMString[mcmh]); break; } switch (mcmv) { case eMCM_Entity: case eMCM_ClampedEntity: case eMCM_SmoothedEntity: mergedV = ent; break; case eMCM_DecoupledCatchUp: case eMCM_Animation: mergedV = anim; break; default: mergedV = ent; GameWarning("CAnimatedCharacter::MergeMCM() - Vertical MCM %s not implemented!", g_szMCMString[mcmv]); break; } QuatT merged; if (flat) merged = CombineHVComponents2D(mergedH, mergedV); else merged = CombineHVComponents3D(mergedH, mergedV); CRY_ASSERT(merged.IsValid()); return merged; }