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;
}
Пример #3
0
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;
}