void CPlayerRotation::ProcessNormal() { m_upVector = Vec3::CreateSlerp(m_upVector, m_stats.upVector, min(5.0f * m_frameTime, 1.0f)); //create a matrix perpendicular to the ground Vec3 up(m_upVector); //..or perpendicular to the linked object Z SLinkStats *pLinkStats = &m_player.m_linkStats; if (pLinkStats->linkID && pLinkStats->flags & LINKED_FREELOOK) { IEntity *pLinked = pLinkStats->GetLinked(); if (pLinked) { up = pLinked->GetRotation().GetColumn2(); } } Vec3 right(m_baseQuat.GetColumn0()); Vec3 forward((up % right).GetNormalized()); CHECKQNAN_VEC(up); CHECKQNAN_VEC(right); CHECKQNAN_VEC(forward); m_baseQuat = Quat(Matrix33::CreateFromVectors(forward % up, forward, up)); //CHECKQNAN_MAT33(m_baseMtx); m_baseQuat *= Quat::CreateRotationZ(m_deltaAngles.z); //m_baseQuat.Normalize(); m_viewQuat = m_baseQuat * Quat::CreateRotationX(GetLocalPitch() + m_deltaAngles.x) * Quat::CreateRotationY(m_viewRoll); //m_viewQuat.Normalize(); //CHECKQNAN_MAT33(m_viewMtx); }
void CPlayerRotation::ProcessFinalViewEffects( float minAngle, float maxAngle ) { if (!m_player.IsClient()) { m_viewQuatFinal = m_viewQuat; } else { Ang3 viewAngleOffset = m_frameViewAnglesOffset; float currentViewPitch = GetLocalPitch(); float newPitch = clamp_tpl(currentViewPitch + viewAngleOffset.x, minAngle, maxAngle); viewAngleOffset.x = newPitch - currentViewPitch; m_viewQuatFinal = m_viewQuat * Quat::CreateRotationXYZ(viewAngleOffset); } }
void CPlayerRotation::ClampAngles() { { //cap up/down looking float minAngle,maxAngle; GetStanceAngleLimits(minAngle,maxAngle); float currentViewPitch=GetLocalPitch(); float newPitch = currentViewPitch + m_deltaAngles.x; if(newPitch < minAngle) newPitch = minAngle; else if(newPitch > maxAngle) newPitch = maxAngle; m_deltaAngles.x = newPitch - currentViewPitch; } { //further limit the view if necessary float limitV = m_params.vLimitRangeV; float limitH = m_params.vLimitRangeH; Vec3 limitDir = m_params.vLimitDir; float limitVUp = m_params.vLimitRangeVUp; float limitVDown = m_params.vLimitRangeVDown; if(m_player.m_stats.isFrozen.Value()) { float clampMin = g_pGameCVars->cl_frozenAngleMin; float clampMax = g_pGameCVars->cl_frozenAngleMax; float frozenLimit = DEG2RAD(clampMin + (clampMax-clampMin)*(1.f-m_player.GetFrozenAmount(true))); if(limitV == 0 || limitV>frozenLimit) limitV = frozenLimit; if(limitH == 0 || limitH>frozenLimit) limitH = frozenLimit; if(g_pGameCVars->cl_debugFreezeShake) { static float color[] = {1,1,1,1}; gEnv->pRenderer->Draw2dLabel(100,200,1.5,color,false,"limit: %f", RAD2DEG(frozenLimit)); } } if(m_player.m_stats.isOnLadder) { limitDir = -m_player.m_stats.ladderOrientation; limitH = DEG2RAD(40.0f); } if((limitH+limitV+limitVUp+limitVDown) && limitDir.len2()>0.1f) { //A matrix is built around the view limit, and then the player view angles are checked with it. //Later, if necessary the upVector could be made customizable. Vec3 forward(limitDir); Vec3 up(m_baseQuat.GetColumn2()); Vec3 right(-(up % forward)); right.Normalize(); Matrix33 limitMtx; limitMtx.SetFromVectors(right,forward,right%forward); //gEnv->pRenderer->GetIRenderAuxGeom()->DrawLine(m_player.GetEntity()->GetWorldPos(), ColorB(0,0,255,255), m_player.GetEntity()->GetWorldPos() + limitMtx.GetColumn(0), ColorB(0,0,255,255)); //gEnv->pRenderer->GetIRenderAuxGeom()->DrawLine(m_player.GetEntity()->GetWorldPos(), ColorB(0,255,0,255), m_player.GetEntity()->GetWorldPos() + limitMtx.GetColumn(1), ColorB(0,255,0,255)); //gEnv->pRenderer->GetIRenderAuxGeom()->DrawLine(m_player.GetEntity()->GetWorldPos(), ColorB(255,0,0,255), m_player.GetEntity()->GetWorldPos() + limitMtx.GetColumn(2), ColorB(255,0,0,255)); limitMtx.Invert(); Vec3 localDir(limitMtx * m_viewQuat.GetColumn1()); // Vec3 localDir(limitMtx * m_player.GetEntity()->GetWorldRotation().GetColumn1()); Ang3 limit; if(limitV) { limit.x = asinf(localDir.z) + m_deltaAngles.x; float deltaX(limitV - fabs(limit.x)); if(deltaX < 0.0f) m_deltaAngles.x += deltaX*(limit.x>0.0f?1.0f:-1.0f); } if(limitVUp || limitVDown) { limit.x = asinf(localDir.z) + m_deltaAngles.x; if(limit.x>=limitVUp && limitVUp!=0) { float deltaXUp(limitVUp - limit.x); m_deltaAngles.x += deltaXUp; } if(limit.x<=limitVDown && limitVDown!=0) { float deltaXDown(limitVDown - limit.x); m_deltaAngles.x += deltaXDown; } } if(limitH) { limit.z = cry_atan2f(-localDir.x,localDir.y) + m_deltaAngles.z; float deltaZ(limitH - fabs(limit.z)); if(deltaZ < 0.0f) m_deltaAngles.z += deltaZ*(limit.z>0.0f?1.0f:-1.0f); } } } }
void CPlayerRotation::ClampAngles( float minAngle, float maxAngle ) { //Cap up/down looking { const float currentViewPitch = GetLocalPitch(); const float newPitch = clamp_tpl(currentViewPitch + m_deltaAngles.x, minAngle, maxAngle); m_deltaAngles.x = newPitch - currentViewPitch; } //Further limit the view if necessary { const SViewLimitParams& viewLimits = m_player.m_params.viewLimits; const Vec3 limitDir = viewLimits.GetViewLimitDir(); if (limitDir.len2() < 0.1f) return; const float limitV = viewLimits.GetViewLimitRangeV(); const float limitH = viewLimits.GetViewLimitRangeH(); const float limitVUp = viewLimits.GetViewLimitRangeVUp(); const float limitVDown = viewLimits.GetViewLimitRangeVDown(); if ((limitH+limitV+fabsf(limitVUp)+fabsf(limitVDown)) > 0.0f) { //A matrix is built around the view limit, and then the player view angles are checked with it. //Later, if necessary the upVector could be made customizable. const Vec3 forward(limitDir); const Vec3 up(m_baseQuat.GetColumn2()); const Vec3 right((-(up % forward)).GetNormalized()); Matrix33 limitMtx; limitMtx.SetFromVectors(right,forward,right%forward); limitMtx.Invert(); const Vec3 localDir(limitMtx * m_viewQuat.GetColumn1()); Ang3 limit; if (limitV) { limit.x = asinf(localDir.z) + m_deltaAngles.x; const float deltaX(limitV - fabs(limit.x)); m_deltaAngles.x = m_deltaAngles.x + (float)__fsel(deltaX, 0.0f, deltaX * (float)__fsel(limit.x, 1.0f, -1.0f)); } if (limitVUp || limitVDown) { limit.x = asinf(localDir.z) + m_deltaAngles.x; const float deltaXUp(limitVUp - limit.x); float fNewDeltaX = m_deltaAngles.x; const float fDeltaXUpIncrement = (float)__fsel( deltaXUp, 0.0f, deltaXUp); fNewDeltaX = fNewDeltaX + (float)__fsel(-fabsf(limitVUp), 0.0f, fDeltaXUpIncrement); const float deltaXDown(limitVDown - limit.x); const float fDeltaXDownIncrement = (float)__fsel( deltaXDown, deltaXDown, 0.0f); fNewDeltaX = fNewDeltaX + (float)__fsel(-fabsf(limitVDown), 0.0f, fDeltaXDownIncrement); m_deltaAngles.x = fNewDeltaX; } if (limitH) { limit.z = atan2_tpl(-localDir.x,localDir.y) + m_deltaAngles.z; const float deltaZ(limitH - fabs(limit.z)); m_deltaAngles.z = m_deltaAngles.z + (float)__fsel(deltaZ, 0.0f, deltaZ * (float)__fsel(limit.z, 1.0f, -1.0f)); } } } }
void CPlayerRotation::ProcessNormal() { m_upVector = Vec3::CreateSlerp(m_upVector,m_stats.upVector,min(5.0f*m_frameTime, 1.0f)); //create a matrix perpendicular to the ground Vec3 up(m_upVector); //..or perpendicular to the linked object Z SLinkStats *pLinkStats = &m_player.m_linkStats; if (pLinkStats->linkID && pLinkStats->flags & LINKED_FREELOOK) { IEntity *pLinked = pLinkStats->GetLinked(); if (pLinked) up = pLinked->GetRotation().GetColumn2(); } Vec3 right(m_baseQuat.GetColumn0()); Vec3 forward((up % right).GetNormalized()); CHECKQNAN_VEC(up); CHECKQNAN_VEC(right); CHECKQNAN_VEC(forward); m_baseQuat = Quat(Matrix33::CreateFromVectors(forward % up,forward,up)); //CHECKQNAN_MAT33(m_baseMtx); // todo: if this works apply the delta yaw from VR input as well... //CryLogAlways("Engine Delta yaw: %f", m_deltaAngles.z); m_baseQuat *= Quat::CreateRotationZ(m_deltaAngles.z); //m_baseQuat.Normalize(); m_viewQuat = m_baseQuat * Quat::CreateRotationX(GetLocalPitch() + m_deltaAngles.x) * Quat::CreateRotationY(m_viewRoll); // Apply view data from trackers, base matrix probably includes yaw orientation already... (not totally ok but for now) if (m_player.IsClient() && g_vr->initialized()) { // base engine yaw that new read deltas should be applied onto for all tracking devices float baseYaw = m_baseQuat.GetRotZ(); g_vr->update(baseYaw); Ang3 angle; g_vr->headOrientation(angle); // apply the tracked yaw delta m_baseQuat *= Quat::CreateRotationZ(angle.z - baseYaw); float baseYawAfter = m_baseQuat.GetRotZ(); m_viewQuat = m_baseQuat * Quat::CreateRotationX(angle.x) * Quat::CreateRotationY(angle.y); } //m_viewQuat.Normalize(); //CHECKQNAN_MAT33(m_viewMtx); }