Vec3 CCameraPolar::GetDir() const
{
	Vec3 vDir = Vec3Constants<float>::fVec3_OneY;

	//assume normalized vector and compute coordinates
	float fSinPitch = cry_sinf(m_fPitch);
	vDir.x = -cry_sinf(m_fYaw) * fSinPitch;
	vDir.y = cry_cosf(m_fYaw) * fSinPitch;
	vDir.z = cry_cosf(m_fPitch);

	//directions have to be normalized
	CRY_ASSERT(fabsf(vDir.len() - 1.0f) < g_fCamError);

	return vDir;
}
Exemple #2
0
void CAutoAimManager::DrawDisc(const Vec3& center, Vec3 axis, float innerRadius, float outerRadius, const ColorB& innerColor, const ColorB& outerColor)
{
	axis.NormalizeSafe(Vec3Constants<float>::fVec3_OneZ);
	Vec3 u = ((axis * Vec3Constants<float>::fVec3_OneZ) > 0.5f) ? Vec3Constants<float>::fVec3_OneY : Vec3Constants<float>::fVec3_OneZ;
	Vec3 v = u.cross(axis);
	u = v.cross(axis);

	float sides = cry_ceilf(3.0f * (float)g_PI * outerRadius);
	//sides = 20.0f;
	float step = (sides > 0.0f) ? 1.0f / sides : 1.0f;
	for (float i = 0.0f; i < 0.99f; i += step)
	{
		float a0 = i * 2.0f * (float)g_PI;
		float a1 = (i+step) * 2.0f * (float)g_PI;
		Vec3 i0 = center + innerRadius * (u*cry_cosf(a0) + v*cry_sinf(a0));
		Vec3 i1 = center + innerRadius * (u*cry_cosf(a1) + v*cry_sinf(a1));
		Vec3 o0 = center + outerRadius * (u*cry_cosf(a0) + v*cry_sinf(a0));
		Vec3 o1 = center + outerRadius * (u*cry_cosf(a1) + v*cry_sinf(a1));
		gEnv->pRenderer->GetIRenderAuxGeom()->DrawTriangle(i0, innerColor, i1, innerColor, o1, outerColor);
		gEnv->pRenderer->GetIRenderAuxGeom()->DrawTriangle(i0, innerColor, o1, outerColor, o0, outerColor);
	}
}
Exemple #3
0
void CBirdsFlock::UpdateLandingPoints()
{
	int numPoints = m_boids.size()*3 /2;
	if(m_LandingPoints.size() < (size_t) numPoints )
	{
		if(!m_landCollisionInfo.IsRequestingRayCast())
		{
			float maxradius = m_bc.fSpawnRadius *0.6f;
			Vec3 origin(m_bc.flockPos);
			float angle = Boid::Frand()*gf_PI;
			float radius = (Boid::Frand()+1)/2 * maxradius;

			origin += Vec3(cry_cosf(angle)*radius, cry_sinf(angle)*radius, 5.f);

			Vec3 vDir = Vec3(0,0,-10);
			m_landCollisionInfo.QueueRaycast(m_pEntity->GetId(),origin,vDir,&m_landCollisionCallback);
		}
	}
}
//------------------------------------------------------------------------
void CScriptControlledPhysics::OnPostStep(EventPhysPostStep *pPostStep)
{
	pe_action_set_velocity av;

	bool moving=m_moving;
	bool rotating=m_rotating;

	float dt=pPostStep->dt;

	if(m_moving)
	{
		Vec3 current=pPostStep->pos;
		Vec3 target=m_moveTarget;
		Vec3 delta=target-current;
		float distance=delta.len();
		Vec3 dir=delta;

		if(distance>0.01f)
			dir *= (1.0f/distance);

		if(distance<0.01f)
		{
			m_speed=0.0f;
			m_moving=false;

			pPostStep->pos=target;

			av.v=ZERO;
		}
		else
		{
			float a=m_speed/m_stopTime;
			float d=m_speed*m_stopTime-0.5f*a*m_stopTime*m_stopTime;

			if(distance<=(d+0.01f))
				m_acceleration=(distance-m_speed*m_stopTime)/(m_stopTime*m_stopTime);

			m_speed=m_speed+m_acceleration*dt;

			if(m_speed>=m_maxSpeed)
			{
				m_speed=m_maxSpeed;
				m_acceleration=0.0f;
			}
			else if(m_speed*dt>distance)
				m_speed=distance/dt;
			else if(m_speed<0.05f)
				m_speed=0.05f;

			av.v=dir*m_speed;
		}
	}

	if(m_rotating)
	{
		Quat current=pPostStep->q;
		Quat target=m_rotationTarget;

		Quat rotation=target*!current;
		float angle=cry_acosf(CLAMP(rotation.w, -1.0f, 1.0f))*2.0f;
		float original=angle;

		if(angle>gf_PI)
			angle=angle-gf_PI2;
		else if(angle<-gf_PI)
			angle=angle+gf_PI2;

		if(cry_fabsf(angle)<0.001f)
		{
			m_rotationSpeed=0.0f;
			m_rotating=false;
			pPostStep->q=m_rotationTarget;
			av.w=ZERO;
		}
		else
		{
			float a=m_rotationSpeed/m_rotationStopTime;
			float d=m_rotationSpeed*m_stopTime-0.5f*a*m_rotationStopTime*m_rotationStopTime;

			if(cry_fabsf(angle)<d+0.001f)
				m_rotationAcceleration=(angle-m_rotationSpeed*m_rotationStopTime)/(m_rotationStopTime*m_rotationStopTime);

			m_rotationSpeed=m_rotationSpeed+sgn(angle)*m_rotationAcceleration*dt;

			if(cry_fabsf(m_rotationSpeed*dt)>cry_fabsf(angle))
				m_rotationSpeed=angle/dt;
			else if(cry_fabsf(m_rotationSpeed)<0.001f)
				m_rotationSpeed=sgn(m_rotationSpeed)*0.001f;
			else if(cry_fabsf(m_rotationSpeed)>=m_rotationMaxSpeed)
			{
				m_rotationSpeed=sgn(m_rotationSpeed)*m_rotationMaxSpeed;
				m_rotationAcceleration=0.0f;
			}

		}

		if(cry_fabsf(angle)>=0.001f)
			av.w=(rotation.v/cry_sinf(original*0.5f)).normalized();

		av.w*=m_rotationSpeed;
	}

	if(moving || rotating)
	{
		if(IPhysicalEntity *pPE=GetEntity()->GetPhysics())
			pPE->Action(&av);
	}

	if((moving && !m_moving) || (rotating && !m_rotating))
		GetEntity()->SetWorldTM(Matrix34::Create(GetEntity()->GetScale(), pPostStep->q, pPostStep->pos));
}
Exemple #5
0
//--------------------------------------------------------------------------
void CIronSight::ZoomSway(float time, float &x, float &y)
{
	static bool  firing = false;

	bool wasFiring = firing;

	//Update while not firing...
	if(IFireMode *pFM = m_pWeapon->GetFireMode(m_pWeapon->GetCurrentFireMode()))
	{
		if(pFM->IsFiring())
			firing = true;
		else
			firing = false;
	}

	//Reset cycle after firing
	if(wasFiring && !firing)
		m_swayTime = m_pShared->zoomSway.stabilizeTime*(1.0f-m_pShared->zoomSway.scaleAfterFiring);

	m_swayCycle+=(0.3f*time);

	if(m_swayCycle>1.0f)
		m_swayCycle-=1.0f;

	//Just a simple sin/cos function
	float dtX = cry_sinf(m_swayCycle*gf_PI*4.0f);
	float dtY = -cry_cosf(m_swayCycle*gf_PI*2.0f);

	m_swayTime += time;

	//Strength scale
	float strengthScale = 1.0f;
	float stanceScale = 1.0f;

	if(CPlayer *pPlayer = static_cast<CPlayer *>(m_pWeapon->GetOwnerActor()))
	{
		if(SPlayerStats *pStats = static_cast<SPlayerStats *>(pPlayer->GetActorStats()))
			pStats->FPWeaponSwayOn = true;

		//Stance mods
		if(pPlayer->GetStance()==STANCE_CROUCH)
			stanceScale = m_pShared->zoomSway.crouchScale;
		else if(pPlayer->GetStance()==STANCE_PRONE)
			stanceScale = m_pShared->zoomSway.proneScale;
	}

	//Time factor
	float factor = m_pShared->zoomSway.minScale;
	float settleTime = m_pShared->zoomSway.stabilizeTime*m_pShared->zoomSway.strengthScaleTime;

	if(m_swayTime<settleTime)
	{
		factor = (settleTime-m_swayTime)/settleTime;

		if(factor<m_pShared->zoomSway.minScale)
			factor = m_pShared->zoomSway.minScale;
	}

	//Final displacement
	x = dtX*m_pShared->zoomSway.maxX*factor*strengthScale*stanceScale;
	y = dtY*m_pShared->zoomSway.maxY*factor*strengthScale*stanceScale;
}
//------------------------------------------------------------------------
void CScriptControlledPhysics::OnPostStep(EventPhysPostStep *pPostStep)
{
    pe_action_set_velocity av;

    const bool moving = m_moving;
    const bool rotating = m_rotating;

    const float deltaTime = pPostStep->dt;

    if (m_moving)
        {
            const Vec3 current = pPostStep->pos;
            const Vec3 target = m_moveTarget;
            const Vec3 delta = target - current;
            const float distanceSq = delta.len2();

            if (distanceSq <= sqr(0.025f) || (delta.dot(m_lastVelocity) < 0.0f))
                {
                    m_speed = 0.0f;
                    m_moving = false;
                    m_lastVelocity.zero();

                    pPostStep->pos = target;

                    av.v = ZERO;
                }
            else
                {
                    float velocity = m_speed;
                    float acceleration = m_acceleration;
                    Vec3 direction = delta;
                    const float distanceToEnd = direction.NormalizeSafe();

                    // Accelerate
                    velocity = std::min(velocity + acceleration * deltaTime, m_maxSpeed);

                    // Calculate acceleration and time needed to stop
                    const float accelerationNeededToStop = (-(velocity*velocity) / distanceToEnd) / 2;
                    if (fabsf(accelerationNeededToStop) > 0.0f)
                        {
                            const float timeNeededToStop = sqrtf((distanceToEnd / 0.5f) / fabsf(accelerationNeededToStop));

                            if (timeNeededToStop < m_stopTime)
                                {
                                    acceleration = accelerationNeededToStop;
                                }
                        }

                    // Prevent overshooting
                    if ((velocity * deltaTime) > distanceToEnd)
                        {
                            const float multiplier = distanceToEnd / fabsf(velocity * deltaTime);
                            velocity *= multiplier;
                            acceleration *= multiplier;
                        }

                    m_acceleration = acceleration;
                    m_speed = velocity;

                    m_lastVelocity = direction * velocity;
                    av.v = direction * velocity;
                }
        }

    if (m_rotating)
        {
            Quat current=pPostStep->q;
            Quat target=m_rotationTarget;

            Quat rotation=target*!current;
            float angle=cry_acosf(CLAMP(rotation.w, -1.0f, 1.0f))*2.0f;
            float original=angle;
            if (angle>gf_PI)
                angle=angle-gf_PI2;
            else if (angle<-gf_PI)
                angle=angle+gf_PI2;

            if (cry_fabsf(angle)<0.01f)
                {
                    m_rotationSpeed=0.0f;
                    m_rotating=false;
                    pPostStep->q=m_rotationTarget;
                    av.w=ZERO;
                }
            else
                {
                    float a=m_rotationSpeed/m_rotationStopTime;
                    float d=m_rotationSpeed*m_stopTime-0.5f*a*m_rotationStopTime*m_rotationStopTime;

                    if (cry_fabsf(angle)<d+0.001f)
                        m_rotationAcceleration=(angle-m_rotationSpeed*m_rotationStopTime)/(m_rotationStopTime*m_rotationStopTime);

                    m_rotationSpeed=m_rotationSpeed+sgn(angle)*m_rotationAcceleration*deltaTime;
                    if (cry_fabsf(m_rotationSpeed*deltaTime)>cry_fabsf(angle))
                        m_rotationSpeed=angle/deltaTime;
                    else if (cry_fabsf(m_rotationSpeed)<0.001f)
                        m_rotationSpeed=sgn(m_rotationSpeed)*0.001f;
                    else if (cry_fabsf(m_rotationSpeed)>=m_rotationMaxSpeed)
                        {
                            m_rotationSpeed=sgn(m_rotationSpeed)*m_rotationMaxSpeed;
                            m_rotationAcceleration=0.0f;
                        }
                }

            if(cry_fabsf(angle)>=0.001f)
                av.w=(rotation.v/cry_sinf(original*0.5f)).normalized();
            av.w*=m_rotationSpeed;
        }

    if (moving || rotating)
        {
            if (IPhysicalEntity *pPE=GetEntity()->GetPhysics())
                pPE->Action(&av, 1);
        }
    /*
    	if ((moving && !m_moving) || (rotating && !m_rotating))
    		GetEntity()->SetWorldTM(Matrix34::Create(GetEntity()->GetScale(), pPostStep->q, pPostStep->pos));
    */
}
void SBasicReplayMovementParams::SetDesiredLocalLocation2( ISkeletonAnim* pSkeletonAnim, const QuatT& desiredLocalLocation, float lookaheadTime, float fDeltaTime, float turnSpeedMultiplier)
{
	QuatT m_desiredLocalLocationQTX			= desiredLocalLocation;
	assert(m_desiredLocalLocationQTX.q.IsValid());
	f32 m_desiredArrivalDeltaTimeQTX		= lookaheadTime;
	f32 m_desiredTurnSpeedMultiplierQTX = turnSpeedMultiplier;

	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++)
	{
		CAnimation& anim = pSkeletonAnim->GetAnimFromFIFO(0,a);
		active += anim.IsActivated() ? 1 : 0;
	}

	if (active>nMaxActiveInQueue)
		active=nMaxActiveInQueue;
	nMaxActiveInQueue=active;


	const QuatT &rDesiredLocation = m_desiredLocalLocationQTX;

	const SParametricSampler *pLMG = NULL;
	for (int32 a=nMaxActiveInQueue-1; (a >= 0) && !pLMG; --a)
	{
		const CAnimation& anim = pSkeletonAnim->GetAnimFromFIFO(0,a);
		pLMG = anim.GetParametricSampler();
	}

	Vec3 dir = rDesiredLocation.q * FORWARD_DIRECTION;
	Vec2 predictedDir( dir.x, dir.y );

	float predictedAngle = RAD2DEG(atan2f(-predictedDir.x, predictedDir.y));
	float turnSpeed = m_desiredTurnSpeedMultiplierQTX * DEG2RAD(predictedAngle) / max(0.1f, m_desiredArrivalDeltaTimeQTX);
	float turnAngle = DEG2RAD(predictedAngle);

	Vec2 deltaVector(rDesiredLocation.t.x, rDesiredLocation.t.y);
	float deltaDist = deltaVector.GetLength();

	const float thresholdDistMin = 0.05f;
	const float thresholdDistMax = 0.15f;
	f32 uniform_scale = 1.0f;//m_pInstance->CCharInstance::GetUniformScale();

	float travelDistScale = CLAMP((deltaDist - thresholdDistMin) / (thresholdDistMax - thresholdDistMin), 0.0f, 1.0f);
	pSkeletonAnim->SetDesiredMotionParam(eMotionParamID_TravelDistScale, travelDistScale/uniform_scale, fDeltaTime);

	Vec2 deltaDir = (deltaDist > 0.0f) ? (deltaVector / deltaDist) : Vec2(0,0);
	float deltaAngle = (deltaDir.x == 0.0f && deltaDir.y == 0.0f  ? 0.0f : RAD2DEG(atan2f(-deltaDir.x, deltaDir.y)) );
	float travelAngle = DEG2RAD(deltaAngle);

	// Update travel direction only if distance bigger (more secure) than thresholdDistMax.
	// Though, also update travel direction if distance is small enough to not have any visible effect (since distance scale is zero).
	bool initOnly = DO_INIT_ONLY_TEST && ((deltaDist > thresholdDistMin) && (deltaDist < thresholdDistMax));

	Vec2 newStrafe = Vec2(-cry_sinf(travelAngle), cry_cosf(travelAngle));
	if (pLMG) 
	{
		SmoothCD(m_desiredStrafeSmoothQTX, m_desiredStrafeSmoothRateQTX, fDeltaTime, newStrafe, 0.10f);
	}
	else 
	{
		//	CryFatalError("CryAnimation: no smooth");
		m_desiredStrafeSmoothQTX=newStrafe;
		m_desiredStrafeSmoothRateQTX.zero();
	}
	travelAngle=Ang3::CreateRadZ(Vec2(0,1),m_desiredStrafeSmoothQTX);
	pSkeletonAnim->SetDesiredMotionParam(eMotionParamID_TravelAngle, travelAngle, fDeltaTime);

	float curvingFraction = 0.0f;

	if (pLMG)
	{
		SmoothCD(m_fDesiredTurnSpeedSmoothQTX, m_fDesiredTurnSpeedSmoothRateQTX, fDeltaTime, turnSpeed, 0.40f);
	}
	else
	{
		m_fDesiredTurnSpeedSmoothQTX=turnSpeed;
		m_fDesiredTurnSpeedSmoothRateQTX = 0.0f;
	}
	pSkeletonAnim->SetDesiredMotionParam(eMotionParamID_TurnSpeed, m_fDesiredTurnSpeedSmoothQTX, fDeltaTime);
	pSkeletonAnim->SetDesiredMotionParam(eMotionParamID_TurnAngle, turnAngle, fDeltaTime);

	// Curving Distance	
	float div = cry_cosf(DEG2RAD(90.0f - predictedAngle));
	float curveRadius = (deltaDist / 2.0f);

	if( abs(div) > 0.0f )
		curveRadius = curveRadius / div;
	float circumference = curveRadius * 2.0f * gf_PI;
	float curveDist = circumference * (predictedAngle * 2.0f / 360.0f);
	curveDist = max(deltaDist, curveDist);

	// Travel Speed/Distance
	float travelDist = LERP(deltaDist, curveDist, curvingFraction);
	float travelSpeed = travelDist / max(0.1f, m_desiredArrivalDeltaTimeQTX);
	//travelDist *= travelDistScale;
	//travelSpeed *= travelDistScale;

	//	float fColDebug[4] = {1,0,0,1};
	//	g_pIRenderer->Draw2dLabel( 1,g_YLine, 2.6f, fColDebug, false,"qqqtravelSpeed: atime: %f", travelSpeed );	
	//	g_YLine+=26.0f;
	SmoothCD(m_fDesiredMoveSpeedSmoothQTX, m_fDesiredMoveSpeedSmoothRateQTX, fDeltaTime, travelSpeed, 0.04f);
	pSkeletonAnim->SetDesiredMotionParam(eMotionParamID_TravelSpeed, m_fDesiredMoveSpeedSmoothQTX, fDeltaTime);
	pSkeletonAnim->SetDesiredMotionParam(eMotionParamID_TravelDist, travelDist, fDeltaTime);
	pSkeletonAnim->SetDesiredMotionParam(eMotionParamID_Scale, uniform_scale, fDeltaTime);
}
Exemple #8
0
//
// Extract the various modifiers out into their own function.
//
// Aim is to make the code easier to understand and modify, as 
// well as to ease the addition of new modifiers.
//
void CPlayerView::ViewFirstPerson(SViewParams &viewParams)
{
		//headbob
		Ang3 angOffset(0,0,0);
		Vec3 weaponOffset(0,0,0);
		Ang3 weaponAngleOffset(0,0,0);

		// jump/land spring effect. Adjust the eye and weapon pos as required.
		FirstPersonJump(viewParams,weaponOffset,weaponAngleOffset);

		//float standSpeed(GetStanceMaxSpeed(STANCE_STAND));

		Vec3 vSpeed(0,0,0);
		if (m_in.standSpeed>0.001f)
			vSpeed = (m_in.stats_velocity / m_in.standSpeed);

		float vSpeedLen(vSpeed.len());
		if (vSpeedLen>1.5f)
			vSpeed = vSpeed / vSpeedLen * 1.5f;

		float speedMul(0);
		if (m_in.standSpeed>0.001f)
			speedMul=(m_in.stats_flatSpeed / m_in.standSpeed * 1.1f);

		speedMul = min(1.5f,speedMul);

		bool crawling(m_in.stance==STANCE_PRONE /*&& m_in.stats_flatSpeed>0.1f*/ && m_in.stats_onGround>0.1f);
		bool weaponZoomed = false;
		bool weaponZomming = false;

		//Not crawling while in zoom mode
		IActor *owner = gEnv->pGame->GetIGameFramework()->GetIActorSystem()->GetActor(m_in.entityId);
		if(owner && owner->IsPlayer())
		{
			IItem *pItem = owner->GetCurrentItem();
			if(pItem)
			{
				CWeapon *pWeapon = static_cast<CWeapon*>(pItem->GetIWeapon());
				if(pWeapon)
				{
					weaponZoomed = pWeapon->IsZoomed();
					weaponZomming = pWeapon->IsZooming();
					if(weaponZoomed||weaponZomming||pWeapon->IsModifying())
						crawling = false;
				}
			}
		}
	
		// On the ground.
		if (m_in.stats_inAir < 0.1f /*&& m_in.stats_inWater < 0.1f*/)
		{
			//--- Bobbing.
			// bobCycle is a speed varying time step running (looping) from 0 to 1 
			// this feeds into a sin eqn creating a double horizontal figure of 8.
			// ( a lissajous figure with the vertical freq twice the horz freq ).

			// To tweak the total speed of the curve:

			// To tweak the effect speed has on the curve:
			float kSpeedToBobFactor=1.15f;//0.9f
			// To tweak the width of the bob:
			float kBobWidth=0.1f;
			// To tweak the height of the bob:
			float kBobHeight=0.05f;
			// To tweak the scale of strafing lag: (may need to manually adjust the strafing angle offsets as well.)
			const float kStrafeHorzScale=0.05f;

			kBobWidth = 0.15f;
			kBobHeight = 0.06f;

			m_io.stats_bobCycle += m_in.frameTime * kSpeedToBobFactor * speedMul;// * (m_in.bSprinting?1.25f:1.0f);

			//if player is standing set the bob to rest. (bobCycle reaches 1.0f within 1 second)
			if (speedMul < 0.1f)
				m_io.stats_bobCycle = min(m_io.stats_bobCycle + m_in.frameTime * 1.0f,1.0f);

			// bobCycle loops between 0 and 1
			if (m_io.stats_bobCycle>1.0f)
				m_io.stats_bobCycle = m_io.stats_bobCycle - 1.0f;

			if (crawling)
				kBobWidth *= 2.0f * speedMul;
			else if (m_in.bSprinting)
				kBobWidth *= 1.25f * speedMul;

			//set the bob offset
			Vec3 bobDir(cry_sinf(m_io.stats_bobCycle*gf_PI*2.0f)*kBobWidth*speedMul,0,cry_sinf(m_io.stats_bobCycle*gf_PI*4.0f)*kBobHeight*speedMul);
						
			//not the bob offset for the weapon
			bobDir *= 0.25f;
			//if player is strafing shift a bit the weapon on left/right
			if (speedMul > 0.01f)
			{
				// right vector dot speed vector
				float dot(m_io.viewQuatFinal.GetColumn0() * vSpeed);

				bobDir.x -= dot * kStrafeHorzScale;	// the faster we move right, the more the gun lags to the left and vice versa

				//tweak the right strafe for weapon laser
				if (dot>0.0f)
					weaponAngleOffset.z += dot * 1.5f;	// kStrafeHorzScale
				else
					weaponAngleOffset.z -= dot * 2.0f;	// kStrafeHorzScale

				weaponAngleOffset.y += dot * 5.0f;		// kStrafeHorzScale
			}
			//CryLogAlways("bobDir.z: %f", bobDir.z);
			if (bobDir.z < 0.0f)
			{
				bobDir.x *= 1.0f;
				bobDir.y *= 1.0f;
				bobDir.z *= 0.35f;
				speedMul *= 0.65f;
			}
			else
				bobDir.z *= 1.85f;

			//CryLogAlways("bobDir.z: %f after", bobDir.z);
			weaponOffset += m_io.viewQuatFinal * bobDir;
			weaponOffset -= m_io.baseQuat.GetColumn2() * 0.035f * speedMul;

			weaponAngleOffset.y += cry_sinf(m_io.stats_bobCycle*gf_PI*2.0f) * speedMul * -1.5f;
			if (crawling)
				weaponAngleOffset.y *= 3.0f;

			weaponAngleOffset.x += speedMul * 1.5f;
			if (crawling)
				weaponAngleOffset.z += cry_sinf(m_io.stats_bobCycle*gf_PI*2.0f) * speedMul * 3.0f;

			//FIXME: viewAngles must include all the view offsets, otherwise aiming wont be precise.
			angOffset.x += cry_sinf(m_io.stats_bobCycle*gf_PI*4.0f)*0.7f*speedMul;

			if (crawling)
			{
				angOffset.x *= 2.5f;
				angOffset.y += cry_sinf(m_io.stats_bobCycle*gf_PI*2.0f)*1.25f*speedMul;
				angOffset.z -= cry_sinf(m_io.stats_bobCycle*gf_PI*2.0f)*2.5f*speedMul;

			}
			else if (m_in.bSprinting)
			{
				angOffset.x *= 2.5f;
				angOffset.y += cry_sinf(m_io.stats_bobCycle*gf_PI*2.0f)*1.0f*speedMul;
				angOffset.z -= cry_sinf(m_io.stats_bobCycle*gf_PI*2.0f)*2.25f*speedMul;
			}
			else if(m_in.stance==STANCE_CROUCH && !weaponZoomed && !weaponZomming)
			{
				weaponOffset.z   += 0.035f;
				weaponOffset.y   -= m_io.viewQuatFinal.GetColumn1().y * 0.03f;
			}
			else if(m_in.stance==STANCE_CROUCH && weaponZomming)
			{
				weaponOffset.z	-= 0.07f;
				weaponOffset.y	+=  m_io.viewQuatFinal.GetColumn1().y * 0.06f;
			}
			else
			{
				//angOffset.x *= 2.25f;
				//angOffset.y += cry_sinf(m_io.stats_bobCycle*gf_PI*2.0f)*0.5f*speedMul;
				//angOffset.z -= cry_sinf(m_io.stats_bobCycle*gf_PI*2.0f)*1.125f*speedMul;
			}
		}
		else
		{
			m_io.stats_bobCycle = 0;

			//while flying offset a bit the weapon model by the player speed	
			if (m_in.stats_velocity.len2()>0.001f)
			{				
				float dotFwd(m_io.viewQuatFinal.GetColumn1() * vSpeed);
				float dotSide(m_io.viewQuatFinal.GetColumn0() * vSpeed);
				float dotUp(m_io.viewQuatFinal.GetColumn2() * vSpeed);

				weaponOffset += m_io.viewQuatFinal * Vec3(dotSide * -0.05f,dotFwd * -0.035f,dotUp * -0.05f);

				weaponAngleOffset.x += dotUp * 2.0f;
				weaponAngleOffset.y += dotSide * 5.0f;
				weaponAngleOffset.z -= dotSide * 2.0f;
			}
		}

		//add some inertia to weapon due view direction change.
		float deltaDotSide(m_io.vFPWeaponLastDirVec * m_io.viewQuatFinal.GetColumn0());
		float deltaDotUp(m_io.vFPWeaponLastDirVec * m_io.viewQuatFinal.GetColumn2());

		weaponOffset += m_io.viewQuatFinal * Vec3(deltaDotSide * 0.1f + m_in.stats_leanAmount * 0.05f,0,deltaDotUp * 0.1f - fabs(m_in.stats_leanAmount) * 0.05f) * m_in.params_weaponInertiaMultiplier;

		weaponAngleOffset.x -= deltaDotUp * 5.0f * m_in.params_weaponInertiaMultiplier;
		weaponAngleOffset.z += deltaDotSide * 5.0f * m_in.params_weaponInertiaMultiplier;
		weaponAngleOffset.y += deltaDotSide * 5.0f * m_in.params_weaponInertiaMultiplier;

		if(m_in.stats_leanAmount<0.0f)
			weaponAngleOffset.y += m_in.stats_leanAmount * 5.0f;

		//the weapon model tries to stay parallel to the terrain when the player is freefalling/parachuting

		if (m_in.stats_inWater > 0.0f)
			weaponOffset -= m_io.viewQuat.GetColumn2() * 0.15f;

		if (m_in.stats_inWater>0.1f && !m_in.stats_headUnderWater)
		{
			Ang3 offset(m_io.viewQuatFinal);
			offset.z = 0;
			if (offset.x<0.0f)
				offset.x = 0;

			weaponAngleOffset -= offset*(180.0f/gf_PI)*0.75f;
		}
		else if (m_io.stats_inFreefall)
		{
			Ang3 offset(m_io.viewQuatFinal);
			offset.z = 0;

			weaponAngleOffset -= offset*(180.0f/gf_PI)*0.5f;
		}
		//same thing with crawling
		else if (crawling)
		{
			//FIXME:to optimize, looks like a bit too expensive
			Vec3 forward(m_io.viewQuatFinal.GetColumn1());
			Vec3 up(m_io.baseQuat.GetColumn2());
			Vec3 right(-(up % forward));

			Matrix33 mat;
			mat.SetFromVectors(right,up%right,up);
			mat.OrthonormalizeFast();

			Ang3 offset(m_io.viewQuatFinal.GetInverted() * Quat(mat));

			weaponAngleOffset += offset*(180.0f/gf_PI)*0.5f;

			float lookDown(m_io.viewQuatFinal.GetColumn1() * m_io.baseQuat.GetColumn2());
			weaponOffset += m_io.baseQuat * Vec3(0,-0.5f*max(-lookDown,0.0f),-0.05f);

			float scale = 0.5f;;
			if(weaponAngleOffset.x>0.0f)
			{
				scale = min(0.5f,weaponAngleOffset.x/15.0f);
				weaponAngleOffset.x *= scale;
			}
			else
			{
				scale = min(0.5f,-weaponAngleOffset.x/20.0f);
				weaponAngleOffset *= (1.0f-scale);
				weaponOffset *= scale;
			}
			//if(vSpeedLen>0.1f)
				//weaponAngleOffset += Ang3(-8.0f,0,-12.5f);
			
		}
		else if (m_in.bSprinting && vSpeedLen>0.5f)
		{
			weaponAngleOffset += Ang3(-20.0f,0,10.0f);
			weaponOffset += m_io.viewQuatFinal * Vec3(0.0f, -.01f, .1f);
		}
		else if (m_in.bLookingAtFriendlyAI && !weaponZomming && !weaponZoomed)
		{
			weaponAngleOffset += Ang3(-15.0f,0,8.0f);
			weaponOffset += m_io.viewQuatFinal * Vec3(0.0f, -.01f, .05f);
		}

		//apply some multipliers
		weaponOffset *= m_in.params_weaponBobbingMultiplier;
		angOffset *= m_io.bobMul * 0.25f;
		if (m_io.bobMul*m_io.bobMul!=1.0f)
		{
			weaponOffset *= m_io.bobMul;
			weaponAngleOffset *= m_io.bobMul;
		}

		float bobSpeedMult(1.0f);
		if(m_in.stats_inWater>0.1)
			bobSpeedMult = 0.75f;
//		m_io.viewQuatForWeapon *= Quat::CreateRotationXYZ(Ang3(rx,ry,rz));
		
		Interpolate(m_io.vFPWeaponOffset,weaponOffset,3.95f*bobSpeedMult,m_in.frameTime);
		Interpolate(m_io.vFPWeaponAngleOffset,weaponAngleOffset,10.0f*bobSpeedMult,m_in.frameTime);
		Interpolate(m_io.vFPWeaponLastDirVec,m_io.viewQuatFinal.GetColumn1(),5.0f*bobSpeedMult,m_in.frameTime);

		Interpolate(m_io.angleOffset,angOffset,10.0f,m_in.frameTime,0.002f);
		if(weaponZomming)
		{
			m_io.vFPWeaponLastDirVec = m_io.viewQuatFinal.GetColumn1();
			m_io.vFPWeaponOffset.Set(0.0f,0.0f,0.0f);
			m_io.vFPWeaponAngleOffset.Set(0.0f,0.0f,0.0f);
			m_io.bobOffset.Set(0.0f,0.0f,0.0f);
		}

		if (m_in.bSprinting)
		{
			float headBobScale = (m_in.stats_flatSpeed / m_in.standSpeed);
			headBobScale = min(1.0f, headBobScale);

			m_io.bobOffset = m_io.vFPWeaponOffset * 2.5f * g_pGameCVars->cl_headBob * headBobScale;
			float bobLenSq = m_io.bobOffset.GetLengthSquared();
			float bobLenLimit = g_pGameCVars->cl_headBobLimit;
			if (bobLenSq > bobLenLimit*bobLenLimit)
			{
				float bobLen = sqrt_tpl(bobLenSq);
				m_io.bobOffset *= bobLenLimit/bobLen;
			}
			viewParams.position += m_io.bobOffset;
		}
}