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; }
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); } }
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)); }
//-------------------------------------------------------------------------- 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); }
// // 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; } }