Example #1
0
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));
			}
		}
	}
}
Example #2
0
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);
			}
		}
	}
}
Example #3
0
/**
 * @brief Get all possible collisions with another line
 * @param aCompare Line to check
 * @param aOutput Output circle
 * @return If circle is found or not
 */
bool Line::GetCollisions(Line const &aCompare, Circle &aOutput)
{
  Vector3 d = aCompare.position - position;
  float dist = d.length();
  float longer = length >= aCompare.length ? length : aCompare.length;
  float shorter = length >= aCompare.length ? aCompare.length : length;

  print_line(*this);
  print_line(aCompare);

  // If they're in the exact same location that would be a problem
  if (position == aCompare.position)
  {
    // IS THIS THE SAME EXACT SPHERE?!
    if (length == aCompare.length)
    {
      aOutput.position = position;
      aOutput.radius = length;
      aOutput.up = Vector3(0, 1, 0);
      aOutput.right = Vector3(0, 0, 1);
      DebugLogPrint("Same exact sphere, gonna return false\n\n");
    }
    else
    {
      DebugLogPrint("One sphere is inside of another, WAT\n");
      DebugLogPrint("Therefore, cannot touch, gonna return false\n\n");
    }
    print_circle(aOutput);
    DebugLogPrint("\n\n");
    return false;
  }

  // > is an early out
  if (dist < length + aCompare.length && dist != longer - shorter)
  {
    // THE IDEA: Find one point, rotate about arbitrary axis between spheres
    // Reduce the problem to solving a circle
    Vector3 axis = d.normalize();
    float xylength = sqrt(axis.x * axis.x + axis.y * axis.y);
    float xyzlength = axis.length();
    // Don't want to divide by zero
    float templength = xylength > 0.0f ? xylength : 1.0f;
    // Our matrices
    // First, go to xz plane
    float xzvalues[3][3] =
    {
    { axis.x / templength, axis.y / templength, 0 },
    { -axis.y / templength, axis.x / templength, 0 },
    { 0, 0, 1 } };
    // Then, only to z axis
    float zvalues[3][3] =
    {
    { axis.z / xyzlength, 0, -xylength / xyzlength },
    { 0, 1, 0 },
    { xylength / xyzlength, 0, axis.z / xyzlength } };

    // Create identity matrix if we're already on the z plane
    if (xylength <= 0.0f)
    {
      xzvalues[0][0] = 1.0f;
      xzvalues[1][1] = 1.0f;
      xzvalues[1][0] = 0.0f;
      xzvalues[0][1] = 0.0f;
    }

    // Create our matrices and invert them
    Matrix33 xztrans(xzvalues);
    Matrix33 ztrans(zvalues);
    Matrix33 toZAxis = ztrans * xztrans;
    Matrix33 toZAxisInverse = toZAxis.Invert();

    Vector3 comparePos = toZAxis * d;
    dist = comparePos.length();

    // Circle collision function
    float z = ((dist * dist) - (aCompare.length * aCompare.length)
        + (length * length)) / (2.0f * dist);
    float y = sqrt((length * length) - (z * z));

    // Create our circle
    aOutput.position = Vector3(0, 0, z);
    aOutput.up = Vector3(0, 1, 0);
    aOutput.right = Vector3(0, 0, 1);
    aOutput.radius = y;

    aOutput.position = toZAxisInverse * aOutput.position;
    aOutput.position += position;
    aOutput.up = toZAxisInverse * aOutput.up;
    aOutput.right = toZAxisInverse * aOutput.right;
  }
  else if (dist == length + aCompare.length)
  {
    // They barely touch, from the outside
    Vector3 largerPos =
        length >= aCompare.length ? position : aCompare.position;
    Vector3 smallerPos =
        length >= aCompare.length ? aCompare.position : position;
    float smallerLen = length >= aCompare.length ? aCompare.length : length;
    d = smallerPos - largerPos;

    DebugLogPrint("The radii barely touch, will still return true, but radius is zero\n");
    aOutput.position = smallerPos - (d.normalize() * smallerLen);
    aOutput.radius = 0;
    aOutput.up = Vector3(0, 1, 0);
    aOutput.right = Vector3(0, 0, 1);
  }
  else if (dist == longer - shorter)
  {
    // They barely touch, from the inside
    Vector3 largerPos =
        length >= aCompare.length ? position : aCompare.position;
    Vector3 smallerPos =
        length >= aCompare.length ? aCompare.position : position;
    float smallerLen = length >= aCompare.length ? aCompare.length : length;
    d = smallerPos - largerPos;

    DebugLogPrint("The radii barely touch, will still return true, but radius is zero\n");
    aOutput.position = smallerPos + (d.normalize() * smallerLen);
    aOutput.radius = 0;
    aOutput.up = Vector3(0, 1, 0);
    aOutput.right = Vector3(0, 0, 1);
  }
  else
  {
    DebugLogPrint("These LineSegments can never touch. Returning false.\n\n");
    return false;
  }

  print_circle(aOutput);
  DebugLogPrint("\n\n");
  return true;
}