public void TestSignedAngle() { { Vector3 v1 = Vector3.up; Vector2 v2 = Vector3.left; float angle = UnityVectorExtensions.SignedAngle(v1, v2, Vector3.forward); Assert.AreApproximatelyEqual(angle, 90f); float angle2 = Vector2.SignedAngle(v1, v2); Assert.AreApproximatelyEqual(angle, angle2); float angle3 = UnityVectorExtensions.SignedAngle(v1, v2, Vector3.back); Assert.AreApproximatelyEqual(angle, -angle3); } { Vector3 v1 = Vector3.up; Vector2 v2 = Vector3.right; float angle = UnityVectorExtensions.SignedAngle(v1, v2, Vector3.forward); Assert.AreApproximatelyEqual(angle, -90f); float angle2 = Vector2.SignedAngle(v1, v2); Assert.AreApproximatelyEqual(angle, angle2); float angle3 = UnityVectorExtensions.SignedAngle(v1, v2, Vector3.back); Assert.AreApproximatelyEqual(angle, -angle3); } { Vector3 v1 = Vector3.up; Vector2 v2 = new Vector3(-0.0001f, 1, 0); float angle = UnityVectorExtensions.SignedAngle(v1, v2, Vector3.forward); Assert.AreApproximatelyEqual(angle, 0.00572958f); float angle3 = UnityVectorExtensions.SignedAngle(v1, v2, Vector3.back); Assert.AreApproximatelyEqual(angle, -angle3); } { Vector3 v1 = Vector3.up; Vector2 v2 = new Vector3(0.0001f, 1, 0); float angle = UnityVectorExtensions.SignedAngle(v1, v2, Vector3.forward); Assert.AreApproximatelyEqual(angle, -0.00572958f); float angle3 = UnityVectorExtensions.SignedAngle(v1, v2, Vector3.back); Assert.AreApproximatelyEqual(angle, -angle3); } }
// Convert from screen coords to normalized FOV angular coords private Rect ScreenToFOV(Rect rScreen, float fov, float fovH, float aspect) { Rect r = new Rect(rScreen); Matrix4x4 persp = Matrix4x4.Perspective(fov, aspect, 0.0001f, 2f).inverse; Vector3 p = persp.MultiplyPoint(new Vector3(0, (r.yMin * 2f) - 1f, 0.5f)); p.z = -p.z; float angle = UnityVectorExtensions.SignedAngle(Vector3.forward, p, Vector3.left); r.yMin = ((fov / 2) + angle) / fov; p = persp.MultiplyPoint(new Vector3(0, (r.yMax * 2f) - 1f, 0.5f)); p.z = -p.z; angle = UnityVectorExtensions.SignedAngle(Vector3.forward, p, Vector3.left); r.yMax = ((fov / 2) + angle) / fov; p = persp.MultiplyPoint(new Vector3((r.xMin * 2f) - 1f, 0, 0.5f)); p.z = -p.z; angle = UnityVectorExtensions.SignedAngle(Vector3.forward, p, Vector3.up); r.xMin = ((fovH / 2) + angle) / fovH; p = persp.MultiplyPoint(new Vector3((r.xMax * 2f) - 1f, 0, 0.5f)); p.z = -p.z; angle = UnityVectorExtensions.SignedAngle(Vector3.forward, p, Vector3.up); r.xMax = ((fovH / 2) + angle) / fovH; return(r); }
private bool IsTargetOffscreen(CameraState state) { if (state.HasLookAt) { Vector3 dir = state.ReferenceLookAt - state.CorrectedPosition; dir = Quaternion.Inverse(state.CorrectedOrientation) * dir; if (state.Lens.Orthographic) { if (Mathf.Abs(dir.y) > state.Lens.OrthographicSize) { return(true); } if (Mathf.Abs(dir.x) > state.Lens.OrthographicSize * state.Lens.Aspect) { return(true); } } else { float fov = state.Lens.FieldOfView / 2; float angle = UnityVectorExtensions.Angle(dir.ProjectOntoPlane(Vector3.right), Vector3.forward); if (angle > fov) { return(true); } fov = Mathf.Rad2Deg * Mathf.Atan(Mathf.Tan(fov * Mathf.Deg2Rad) * state.Lens.Aspect); angle = UnityVectorExtensions.Angle(dir.ProjectOntoPlane(Vector3.up), Vector3.forward); if (angle > fov) { return(true); } } } return(false); }
private Rect ScreenToFOV(Rect rScreen, float fov, float fovH, float aspect) { Rect result = new Rect(rScreen); Matrix4x4 inverse = Matrix4x4.Perspective(fov, aspect, 0.01f, 10000f).inverse; Vector3 to = inverse.MultiplyPoint(new Vector3(0f, result.yMin * 2f - 1f, 0.1f)); to.z = -to.z; float num = UnityVectorExtensions.SignedAngle(Vector3.forward, to, Vector3.left); result.yMin = (fov / 2f + num) / fov; to = inverse.MultiplyPoint(new Vector3(0f, result.yMax * 2f - 1f, 0.1f)); to.z = -to.z; num = UnityVectorExtensions.SignedAngle(Vector3.forward, to, Vector3.left); result.yMax = (fov / 2f + num) / fov; to = inverse.MultiplyPoint(new Vector3(result.xMin * 2f - 1f, 0f, 0.1f)); to.z = -to.z; num = UnityVectorExtensions.SignedAngle(Vector3.forward, to, Vector3.up); result.xMin = (fovH / 2f + num) / fovH; to = inverse.MultiplyPoint(new Vector3(result.xMax * 2f - 1f, 0f, 0.1f)); to.z = -to.z; num = UnityVectorExtensions.SignedAngle(Vector3.forward, to, Vector3.up); result.xMax = (fovH / 2f + num) / fovH; return(result); }
/// <summary>Positions the virtual camera according to the transposer rules.</summary> /// <param name="deltaTime">Used for damping. If less than 0, no damping is done.</param> /// <param name="up">Current camera up</param> /// <param name="desiredCameraOffset">Where we want to put the camera relative to the follow target</param> /// <param name="outTargetPosition">Resulting camera position</param> /// <param name="outTargetOrient">Damped target orientation</param> protected void TrackTarget( float deltaTime, Vector3 up, Vector3 desiredCameraOffset, out Vector3 outTargetPosition, out Quaternion outTargetOrient) { var targetOrientation = GetReferenceOrientation(up); var dampedOrientation = targetOrientation; bool prevStateValid = deltaTime >= 0 && VirtualCamera.PreviousStateIsValid; if (prevStateValid) { if (m_AngularDampingMode == AngularDampingMode.Quaternion && m_BindingMode == BindingMode.LockToTarget) { float t = VirtualCamera.DetachedFollowTargetDamp(1, m_AngularDamping, deltaTime); dampedOrientation = Quaternion.Slerp( m_PreviousReferenceOrientation, targetOrientation, t); } else { var relative = (Quaternion.Inverse(m_PreviousReferenceOrientation) * targetOrientation).eulerAngles; for (int i = 0; i < 3; ++i) { if (Mathf.Abs(relative[i]) < 0.01f) // correct for precision drift { relative[i] = 0; } else if (relative[i] > 180) { relative[i] -= 360; } } relative = VirtualCamera.DetachedFollowTargetDamp(relative, AngularDamping, deltaTime); dampedOrientation = m_PreviousReferenceOrientation * Quaternion.Euler(relative); } } m_PreviousReferenceOrientation = dampedOrientation; var targetPosition = FollowTargetPosition; var currentPosition = m_PreviousTargetPosition; var previousOffset = prevStateValid ? m_PreviousOffset : desiredCameraOffset; var offsetDelta = desiredCameraOffset - previousOffset; if (offsetDelta.sqrMagnitude > 0.01f) { var q = UnityVectorExtensions.SafeFromToRotation( m_PreviousOffset.ProjectOntoPlane(up), desiredCameraOffset.ProjectOntoPlane(up), up); currentPosition = targetPosition + q * (m_PreviousTargetPosition - targetPosition); } m_PreviousOffset = desiredCameraOffset; // Adjust for damping, which is done in camera-offset-local coords var positionDelta = targetPosition - currentPosition; if (prevStateValid) { Quaternion dampingSpace; if (desiredCameraOffset.AlmostZero()) { dampingSpace = VcamState.RawOrientation; } else { dampingSpace = Quaternion.LookRotation(dampedOrientation * desiredCameraOffset, up); } var localDelta = Quaternion.Inverse(dampingSpace) * positionDelta; localDelta = VirtualCamera.DetachedFollowTargetDamp(localDelta, Damping, deltaTime); positionDelta = dampingSpace * localDelta; } currentPosition += positionDelta; outTargetPosition = m_PreviousTargetPosition = currentPosition; outTargetOrient = dampedOrientation; }
// Make sure this is calld only once per frame private float GetTargetHeading(float currentHeading, Quaternion targetOrientation) { if (m_BindingMode == BindingMode.SimpleFollowWithWorldUp) { return(0); } if (FollowTarget == null) { return(currentHeading); } var headingDef = m_Heading.m_Definition; if (headingDef == Heading.HeadingDefinition.Velocity && mTargetRigidBody == null) { headingDef = Heading.HeadingDefinition.PositionDelta; } Vector3 velocity = Vector3.zero; switch (headingDef) { case Heading.HeadingDefinition.PositionDelta: velocity = FollowTargetPosition - mLastTargetPosition; break; case Heading.HeadingDefinition.Velocity: velocity = mTargetRigidBody.velocity; break; case Heading.HeadingDefinition.TargetForward: velocity = FollowTargetRotation * Vector3.forward; break; default: case Heading.HeadingDefinition.WorldForward: return(0); } // Process the velocity and derive the heading from it. Vector3 up = targetOrientation * Vector3.up; velocity = velocity.ProjectOntoPlane(up); if (headingDef != Heading.HeadingDefinition.TargetForward) { int filterSize = m_Heading.m_VelocityFilterStrength * 5; if (mHeadingTracker == null || mHeadingTracker.FilterSize != filterSize) { mHeadingTracker = new HeadingTracker(filterSize); } mHeadingTracker.DecayHistory(); if (!velocity.AlmostZero()) { mHeadingTracker.Add(velocity); } velocity = mHeadingTracker.GetReliableHeading(); } if (!velocity.AlmostZero()) { return(UnityVectorExtensions.SignedAngle( targetOrientation * Vector3.forward, velocity, up)); } // If no reliable heading, then stay where we are. return(currentHeading); }
/// <summary>Positions the virtual camera according to the transposer rules.</summary> /// <param name="curState">The current camera state</param> /// <param name="deltaTime">Used for damping. If less than 0, no damping is done.</param> public override void MutateCameraState(ref CameraState curState, float deltaTime) { InitPrevFrameStateInfo(ref curState, deltaTime); // Update the heading if (FollowTarget != m_PreviousTarget) { m_PreviousTarget = FollowTarget; #if CINEMACHINE_PHYSICS m_TargetRigidBody = (m_PreviousTarget == null) ? null : m_PreviousTarget.GetComponent <Rigidbody>(); #endif m_LastTargetPosition = (m_PreviousTarget == null) ? Vector3.zero : m_PreviousTarget.position; mHeadingTracker = null; } m_LastHeading = HeadingUpdater(this, deltaTime, curState.ReferenceUp); float heading = m_LastHeading; if (IsValid) { // Calculate the heading if (m_BindingMode != BindingMode.SimpleFollowWithWorldUp) { heading += m_Heading.m_Bias; } Quaternion headingRot = Quaternion.AngleAxis(heading, Vector3.up); Vector3 rawOffset = EffectiveOffset; Vector3 offset = headingRot * rawOffset; // Track the target, with damping TrackTarget(deltaTime, curState.ReferenceUp, offset, out Vector3 pos, out Quaternion orient); // Place the camera offset = orient * offset; curState.ReferenceUp = orient * Vector3.up; // Respect minimum target distance on XZ plane var targetPosition = FollowTargetPosition; pos += GetOffsetForMinimumTargetDistance( pos, offset, curState.RawOrientation * Vector3.forward, curState.ReferenceUp, targetPosition); curState.RawPosition = pos + offset; if (deltaTime >= 0 && VirtualCamera.PreviousStateIsValid) { var lookAt = targetPosition; if (LookAtTarget != null) { lookAt = LookAtTargetPosition; } var dir0 = m_LastCameraPosition - lookAt; var dir1 = curState.RawPosition - lookAt; if (dir0.sqrMagnitude > 0.01f && dir1.sqrMagnitude > 0.01f) { curState.PositionDampingBypass = UnityVectorExtensions.SafeFromToRotation( dir0, dir1, curState.ReferenceUp).eulerAngles; } } m_LastTargetPosition = targetPosition; m_LastCameraPosition = curState.RawPosition; } }
// Make sure this is calld only once per frame private float GetTargetHeading( float currentHeading, Quaternion targetOrientation, float deltaTime) { if (m_BindingMode == BindingMode.SimpleFollowWithWorldUp) { return(0); } if (FollowTarget == null) { return(currentHeading); } if (m_Heading.m_HeadingDefinition == Heading.HeadingDefinition.Velocity && mTargetRigidBody == null) { Debug.Log(string.Format( "Attempted to use HeadingDerivationMode.Velocity to calculate heading for {0}. No RigidBody was present on '{1}'. Defaulting to position delta", GetFullName(VirtualCamera.VirtualCameraGameObject), FollowTarget)); m_Heading.m_HeadingDefinition = Heading.HeadingDefinition.PositionDelta; } Vector3 velocity = Vector3.zero; switch (m_Heading.m_HeadingDefinition) { case Heading.HeadingDefinition.PositionDelta: velocity = FollowTarget.position - mLastTargetPosition; break; case Heading.HeadingDefinition.Velocity: velocity = mTargetRigidBody.velocity; break; case Heading.HeadingDefinition.TargetForward: velocity = FollowTarget.forward; break; default: case Heading.HeadingDefinition.WorldForward: return(0); } // Process the velocity and derive the heading from it. int filterSize = m_Heading.m_VelocityFilterStrength * 5; if (mHeadingTracker == null || mHeadingTracker.FilterSize != filterSize) { mHeadingTracker = new HeadingTracker(filterSize); } mHeadingTracker.DecayHistory(); Vector3 up = targetOrientation * Vector3.up; velocity = velocity.ProjectOntoPlane(up); if (!velocity.AlmostZero()) { mHeadingTracker.Add(velocity); } velocity = mHeadingTracker.GetReliableHeading(); if (!velocity.AlmostZero()) { return(UnityVectorExtensions.SignedAngle(targetOrientation * Vector3.forward, velocity, up)); } // If no reliable heading, then stay where we are. return(currentHeading); }
private float GetTargetHeading(float currentHeading, Vector3 up, float deltaTime) { if (VirtualCamera.Follow == null) { return(currentHeading); } if (m_RecenterToTargetHeading.m_HeadingDefinition == Recentering.HeadingDerivationMode.Velocity && mTargetRigidBody == null) { Debug.Log(string.Format( "Attempted to use HeadingDerivationMode.Velocity to calculate heading for {0}. No RigidBody was present on '{1}'. Defaulting to position delta", GetFullName(VirtualCamera.VirtualCameraGameObject), VirtualCamera.Follow)); m_RecenterToTargetHeading.m_HeadingDefinition = Recentering.HeadingDerivationMode.PositionDelta; } Vector3 velocity = Vector3.zero; switch (m_RecenterToTargetHeading.m_HeadingDefinition) { case Recentering.HeadingDerivationMode.PositionDelta: velocity = VirtualCamera.Follow.position - mLastTargetPosition; break; case Recentering.HeadingDerivationMode.Velocity: velocity = mTargetRigidBody.velocity; break; default: case Recentering.HeadingDerivationMode.TargetForward: return(VirtualCamera.Follow.rotation.eulerAngles.y); case Recentering.HeadingDerivationMode.WorldForward: return(0); } // Process the velocity and derive the heading from it. int filterSize = m_RecenterToTargetHeading.m_VelocityFilterStrength * 5; if (mHeadingTracker == null || mHeadingTracker.FilterSize != filterSize) { mHeadingTracker = new HeadingTracker(filterSize); } mHeadingTracker.DecayHistory(); velocity = velocity.ProjectOntoPlane(up); if (!velocity.AlmostZero()) { mHeadingTracker.Add(velocity); } velocity = mHeadingTracker.GetReliableHeading(); if (!velocity.AlmostZero()) { Vector3 fwd = (-GetBackVector(up)).ProjectOntoPlane(up); return(UnityVectorExtensions.SignedAngle(fwd, velocity, up)); } // If no reliable heading, then stay where we are. return(currentHeading); }
Vector3 DoTracking(Vector3 currentPosition, Vector3 up, float deltaTime) { if (VirtualCamera.Follow == null) { return(currentPosition); } if (VirtualCamera.Follow != PreviousTarget) { PreviousTarget = VirtualCamera.Follow; mTargetRigidBody = VirtualCamera.Follow.GetComponent <Rigidbody>(); mLastTargetPosition = VirtualCamera.Follow.position; mHeadingTracker = null; } // Heading if (!m_HeadingIsSlave) { UpdateHeading(deltaTime, up, true); } mLastTargetPosition = VirtualCamera.Follow.position; // Where to put the camera Vector3 localTarget = EffectiveOffset(up); localTarget = Quaternion.AngleAxis(m_XAxis.Value + m_HeadingBias, up) * localTarget; // Adjust for damping, which is done in local coords if (deltaTime > 0) { if (m_DampingStyle == DampingStyle.Polar) { // Get the offset in polar Vector3 localCurrent = currentPosition - VirtualCamera.Follow.position; Vector3 currentOnPlane = localCurrent.ProjectOntoPlane(up); Vector3 currentPerpPlane = localCurrent - currentOnPlane; Vector3 targetOnPlane = localTarget.ProjectOntoPlane(up); Vector3 targetPerpPlane = localTarget - targetOnPlane; Vector3 delta = new Vector3( UnityVectorExtensions.SignedAngle(currentOnPlane, targetOnPlane, up), Vector3.Dot(targetPerpPlane - currentPerpPlane, up), (targetOnPlane.magnitude - currentOnPlane.magnitude)); // Apply damping Vector3 trackingSpeeds = TrackingSpeeds; for (int i = 0; i < 3; ++i) { delta[i] *= deltaTime / Mathf.Max(trackingSpeeds[i], deltaTime); } localTarget = currentOnPlane; localTarget += (localTarget.normalized * delta.z); localTarget += currentPerpPlane + (delta.y * up); localTarget = Quaternion.AngleAxis(delta.x, up) * localTarget; } else { Vector3 worldOffset = currentPosition - (VirtualCamera.Follow.position + localTarget); Quaternion localToWorldTransform = Quaternion.LookRotation( VirtualCamera.Follow.rotation * Vector3.forward, up); Vector3 localOffset = Quaternion.Inverse(localToWorldTransform) * worldOffset; Vector3 trackingSpeeds = TrackingSpeeds; for (int i = 0; i < 3; ++i) { localOffset[i] *= deltaTime / Mathf.Max(trackingSpeeds[i], deltaTime); } return(currentPosition - (localToWorldTransform * localOffset)); } } // Return the adjusted rig position return(VirtualCamera.Follow.position + localTarget); }
public void FindIntersectionTests() { { var l1_p1 = new Vector2(0, 1); var l1_p2 = new Vector2(0, -1); var l2_p1 = new Vector2(-1, 0); var l2_p2 = new Vector2(1, 0); int intersectionType = UnityVectorExtensions.FindIntersection(l1_p1, l1_p2, l2_p1, l2_p2, out Vector2 intersection); Assert.IsTrue(intersectionType == 2); Assert.IsTrue(AreApproximatelyEqual(intersection, Vector2.zero)); } { var l1_p1 = new Vector2(0, 1); var l1_p2 = new Vector2(0, 0); var l2_p1 = new Vector2(-1, 0); var l2_p2 = new Vector2(1, 0); int intersectionType = UnityVectorExtensions.FindIntersection(l1_p1, l1_p2, l2_p1, l2_p2, out Vector2 intersection); Assert.IsTrue(intersectionType == 2); Assert.IsTrue(AreApproximatelyEqual(intersection, Vector2.zero)); } { var l1_p1 = new Vector2(0, 2); var l1_p2 = new Vector2(0, 1); var l2_p1 = new Vector2(-1, 0); var l2_p2 = new Vector2(1, 0); int intersectionType = UnityVectorExtensions.FindIntersection(l1_p1, l1_p2, l2_p1, l2_p2, out Vector2 intersection); Assert.IsTrue(intersectionType == 1); Assert.IsTrue(AreApproximatelyEqual(intersection, Vector2.zero)); } { var l1_p1 = new Vector2(0, 2); var l1_p2 = new Vector2(0, 1); var l2_p1 = new Vector2(1, 2); var l2_p2 = new Vector2(1, 1); int intersectionType = UnityVectorExtensions.FindIntersection(l1_p1, l1_p2, l2_p1, l2_p2, out Vector2 intersection); Assert.IsTrue(intersectionType == 0); Assert.IsTrue(float.IsInfinity(intersection.x) && float.IsInfinity(intersection.y)); } { var l1_p1 = new Vector2(1, 2); var l1_p2 = new Vector2(1, 1); var l2_p1 = new Vector2(1, -2); var l2_p2 = new Vector2(1, -1); int intersectionType = UnityVectorExtensions.FindIntersection(l1_p1, l1_p2, l2_p1, l2_p2, out Vector2 intersection); Assert.IsTrue(intersectionType == 3); Assert.IsTrue(float.IsInfinity(intersection.x) && float.IsInfinity(intersection.y)); } { var l1_p1 = new Vector2(1, 2); var l1_p2 = new Vector2(1, -2); var l2_p1 = new Vector2(1, 3); var l2_p2 = new Vector2(1, 1); int intersectionType = UnityVectorExtensions.FindIntersection(l1_p1, l1_p2, l2_p1, l2_p2, out Vector2 intersection); Assert.IsTrue(intersectionType == 4); Assert.IsTrue(float.IsInfinity(intersection.x) && float.IsInfinity(intersection.y)); } { var l1_p1 = new Vector2(1, 2); var l1_p2 = new Vector2(1, -2); var l2_p1 = new Vector2(1, 2); var l2_p2 = new Vector2(1, -2); int intersectionType = UnityVectorExtensions.FindIntersection(l1_p1, l1_p2, l2_p1, l2_p2, out Vector2 intersection); Assert.IsTrue(intersectionType == 4); Assert.IsTrue(float.IsInfinity(intersection.x) && float.IsInfinity(intersection.y)); } { var l1_p1 = new Vector2(1, 2); var l1_p2 = new Vector2(1, -2); var l2_p1 = new Vector2(1, -2); var l2_p2 = new Vector2(1, 2); int intersectionType = UnityVectorExtensions.FindIntersection(l1_p1, l1_p2, l2_p1, l2_p2, out Vector2 intersection); Assert.IsTrue(intersectionType == 4); Assert.IsTrue(float.IsInfinity(intersection.x) && float.IsInfinity(intersection.y)); } { var l1_p1 = new Vector2(0, 1); var l1_p2 = new Vector2(0, 1); var l2_p1 = new Vector2(1, 0); var l2_p2 = new Vector2(1, 0); int intersectionType = UnityVectorExtensions.FindIntersection(l1_p1, l1_p2, l2_p1, l2_p2, out Vector2 intersection); Assert.IsTrue(intersectionType == 4); Assert.IsTrue(float.IsInfinity(intersection.x) && float.IsInfinity(intersection.y)); } { var l1_p1 = new Vector2(0, 0); var l1_p2 = new Vector2(2, 0); var l2_p1 = new Vector2(0, 1); var l2_p2 = new Vector2(1, 0); int intersectionType = UnityVectorExtensions.FindIntersection(l1_p1, l1_p2, l2_p1, l2_p2, out Vector2 intersection); Assert.IsTrue(intersectionType == 2); Assert.IsTrue(AreApproximatelyEqual(intersection, l2_p2)); } { var l1_p1 = new Vector2(0, 0); var l1_p2 = new Vector2(2, 0); var l2_p1 = new Vector2(1, 0); var l2_p2 = new Vector2(0, 1); int intersectionType = UnityVectorExtensions.FindIntersection(l1_p1, l1_p2, l2_p1, l2_p2, out Vector2 intersection); Assert.IsTrue(intersectionType == 2); Assert.IsTrue(AreApproximatelyEqual(intersection, l2_p1)); } // Parallel segments touching at one point { var l1_p1 = new Vector2(0, 3); var l1_p2 = new Vector2(0, 5); var l2_p1 = new Vector2(0, 5); var l2_p2 = new Vector2(0, 9); int intersectionType = UnityVectorExtensions.FindIntersection(l1_p1, l1_p2, l2_p1, l2_p2, out Vector2 intersection); Assert.IsTrue(intersectionType == 4); Assert.IsTrue(AreApproximatelyEqual(intersection, l2_p1)); } { var l1_p1 = new Vector2(0, 5); var l1_p2 = new Vector2(0, 3); var l2_p1 = new Vector2(0, 5); var l2_p2 = new Vector2(0, 9); int intersectionType = UnityVectorExtensions.FindIntersection(l1_p1, l1_p2, l2_p1, l2_p2, out Vector2 intersection); Assert.IsTrue(intersectionType == 4); Assert.IsTrue(AreApproximatelyEqual(intersection, l2_p1)); } { var l1_p1 = new Vector2(0, 3); var l1_p2 = new Vector2(0, 5); var l2_p1 = new Vector2(0, 9); var l2_p2 = new Vector2(0, 5); int intersectionType = UnityVectorExtensions.FindIntersection(l1_p1, l1_p2, l2_p1, l2_p2, out Vector2 intersection); Assert.IsTrue(intersectionType == 4); Assert.IsTrue(AreApproximatelyEqual(intersection, l2_p2)); } { var l1_p1 = new Vector2(0, 5); var l1_p2 = new Vector2(0, 3); var l2_p1 = new Vector2(0, 9); var l2_p2 = new Vector2(0, 5); int intersectionType = UnityVectorExtensions.FindIntersection(l1_p1, l1_p2, l2_p1, l2_p2, out Vector2 intersection); Assert.IsTrue(intersectionType == 4); Assert.IsTrue(AreApproximatelyEqual(intersection, l2_p2)); } }
public void FindIntersectionTests() { { var l1_p1 = new Vector2(0, 1); var l1_p2 = new Vector2(0, -1); var l2_p1 = new Vector2(-1, 0); var l2_p2 = new Vector2(1, 0); int intersectionType = UnityVectorExtensions.FindIntersection(l1_p1, l1_p2, l2_p1, l2_p2, out Vector2 intersection); Assert.IsTrue(intersectionType == 2); Assert.IsTrue(Mathf.Abs(intersection.x) < 1e-8f && Mathf.Abs(intersection.y) < 1e-8f); // intersection should be Vector2.zero } { var l1_p1 = new Vector2(0, 1); var l1_p2 = new Vector2(0, 0); var l2_p1 = new Vector2(-1, 0); var l2_p2 = new Vector2(1, 0); int intersectionType = UnityVectorExtensions.FindIntersection(l1_p1, l1_p2, l2_p1, l2_p2, out Vector2 intersection); Assert.IsTrue(intersectionType == 2); Assert.IsTrue(Mathf.Abs(intersection.x) < 1e-8f && Mathf.Abs(intersection.y) < 1e-8f); // intersection should be Vector2.zero } { var l1_p1 = new Vector2(0, 2); var l1_p2 = new Vector2(0, 1); var l2_p1 = new Vector2(-1, 0); var l2_p2 = new Vector2(1, 0); int intersectionType = UnityVectorExtensions.FindIntersection(l1_p1, l1_p2, l2_p1, l2_p2, out Vector2 intersection); Assert.IsTrue(intersectionType == 1); Assert.IsTrue(Mathf.Abs(intersection.x) < 1e-8f && Mathf.Abs(intersection.y) < 1e-8f); // intersection should be Vector2.zero } { var l1_p1 = new Vector2(0, 2); var l1_p2 = new Vector2(0, 1); var l2_p1 = new Vector2(1, 2); var l2_p2 = new Vector2(1, 1); int intersectionType = UnityVectorExtensions.FindIntersection(l1_p1, l1_p2, l2_p1, l2_p2, out Vector2 intersection); Assert.IsTrue(intersectionType == 0); } { var l1_p1 = new Vector2(0, 1); var l1_p2 = new Vector2(0, 1); var l2_p1 = new Vector2(1, 0); var l2_p2 = new Vector2(1, 0); int intersectionType = UnityVectorExtensions.FindIntersection(l1_p1, l1_p2, l2_p1, l2_p2, out Vector2 intersection); Assert.IsTrue(intersectionType == 0); } { var l1_p1 = new Vector2(0, 0); var l1_p2 = new Vector2(2, 0); var l2_p1 = new Vector2(0, 1); var l2_p2 = new Vector2(1, 0); int intersectionType = UnityVectorExtensions.FindIntersection(l1_p1, l1_p2, l2_p1, l2_p2, out Vector2 intersection); Assert.IsTrue(intersectionType == 1); Assert.IsTrue(intersection == l2_p2); } { var l1_p1 = new Vector2(0, 0); var l1_p2 = new Vector2(2, 0); var l2_p1 = new Vector2(1, 0); var l2_p2 = new Vector2(0, 1); int intersectionType = UnityVectorExtensions.FindIntersection(l1_p1, l1_p2, l2_p1, l2_p2, out Vector2 intersection); Assert.IsTrue(intersectionType == 2); Assert.IsTrue(intersection == l2_p1); } }