예제 #1
0
		/// <summary>
		/// Intersects a line segment with the shape and returns the intersection point closest to the beginning of the segment.
		/// </summary>
		/// <param name="segment">The line segment to intersect.</param>
		/// <param name="scalar">A value between 0 and 1 indicating how far along the segment the intersection occurs.</param>
		/// <param name="p">The point of the intersection closest to the beginning of the line segment.</param>
		/// <returns>Returns a value indicating whether there is an intersection.</returns>
		public bool Intersect(ref Segment segment, out float scalar, out Vector3 p)
		{
			Vector3 d, m, n;
			float md, nd, dd;
			Vector3.Subtract(ref P2, ref P1, out d);
			Vector3.Subtract(ref segment.P1, ref P1, out m);
			Vector3.Subtract(ref segment.P2, ref segment.P1, out n);
			Vector3.Dot(ref d, ref m, out md);
			Vector3.Dot(ref d, ref n, out nd);
			Vector3.Dot(ref d, ref d, out dd);

			if (!(md < 0f && md + nd < 0f) &&
				!(md > dd && md + nd > dd))
			{
				float nn, mn, k;
				Vector3.Dot(ref n, ref n, out nn);
				Vector3.Dot(ref m, ref n, out mn);
				float a = dd * nn - nd * nd;
				Vector3.Dot(ref m, ref m, out k);
				k -= Radius * Radius;
				float c = dd * k - md * md;
				if (Math.Abs(a) >= Constants.Epsilon)
				{
					float b = dd * mn - nd * md;
					float discr = b * b - a * c;
					if (discr >= 0f)
					{
						float t = (-b - (float)Math.Sqrt(discr)) / a;
						if (t >= 0f && t <= 1f &&
							md + t * nd >= 0f &&
							md + t * nd <= dd)
						{
							scalar = t;
							Vector3.Multiply(ref n, t, out p);
							Vector3.Add(ref segment.P1, ref p, out p);
							return true;
						}
					}
				}
			}

			var cap = new Sphere(P1, Radius);
			float s;
			scalar = float.MaxValue;
			p = Vector3.Zero;

			Vector3 v;
			if (cap.Intersect(ref segment, out s, out v))
			{
				scalar = s;
				p = v;
			}
			cap.Center = P2;
			if (cap.Intersect(ref segment, out s, out v) && s < scalar)
			{
				scalar = s;
				p = v;
			}

			return scalar >= 0f && scalar <= 1f;
		}
예제 #2
0
파일: Capsule.cs 프로젝트: forestrf/Henge3D
        /// <summary>
        /// Intersects a line segment with the shape and returns the intersection point closest to the beginning of the segment.
        /// </summary>
        /// <param name="segment">The line segment to intersect.</param>
        /// <param name="scalar">A value between 0 and 1 indicating how far along the segment the intersection occurs.</param>
        /// <param name="p">The point of the intersection closest to the beginning of the line segment.</param>
        /// <returns>Returns a value indicating whether there is an intersection.</returns>
        public bool Intersect(ref Segment segment, out float scalar, out Vector3 p)
        {
            Vector3 d, m, n;
            float   md, nd, dd;

            Vector3.Subtract(ref P2, ref P1, out d);
            Vector3.Subtract(ref segment.P1, ref P1, out m);
            Vector3.Subtract(ref segment.P2, ref segment.P1, out n);
            Vector3.Dot(ref d, ref m, out md);
            Vector3.Dot(ref d, ref n, out nd);
            Vector3.Dot(ref d, ref d, out dd);

            if (!(md < 0f && md + nd < 0f) &&
                !(md > dd && md + nd > dd))
            {
                float nn, mn, k;
                Vector3.Dot(ref n, ref n, out nn);
                Vector3.Dot(ref m, ref n, out mn);
                float a = dd * nn - nd * nd;
                Vector3.Dot(ref m, ref m, out k);
                k -= Radius * Radius;
                float c = dd * k - md * md;
                if (Math.Abs(a) >= Constants.Epsilon)
                {
                    float b     = dd * mn - nd * md;
                    float discr = b * b - a * c;
                    if (discr >= 0f)
                    {
                        float t = (-b - (float)Math.Sqrt(discr)) / a;
                        if (t >= 0f && t <= 1f &&
                            md + t * nd >= 0f &&
                            md + t * nd <= dd)
                        {
                            scalar = t;
                            Vector3.Multiply(ref n, t, out p);
                            Vector3.Add(ref segment.P1, ref p, out p);
                            return(true);
                        }
                    }
                }
            }

            var   cap = new Sphere(P1, Radius);
            float s;

            scalar = float.MaxValue;
            p      = Vector3.Zero;

            Vector3 v;

            if (cap.Intersect(ref segment, out s, out v))
            {
                scalar = s;
                p      = v;
            }
            cap.Center = P2;
            if (cap.Intersect(ref segment, out s, out v) && s < scalar)
            {
                scalar = s;
                p      = v;
            }

            return(scalar >= 0f && scalar <= 1f);
        }
예제 #3
0
 /// <summary>
 /// Intersects a segment with this collision skin part and returns the intersection point that is nearest to the
 /// beginning of the segment.
 /// </summary>
 /// <param name="segment">The segment to intersect with.</param>
 /// <param name="scalar">Returns a value between 0 and 1 indicating where on the segment the first intersection occurs.</param>
 /// <param name="point">Returns the point of the first intersection.</param>
 /// <returns>Returns a value indicating whether the segment intersects with the part.</returns>
 public override bool Intersect(ref Segment segment, out float scalar, out Vector3 point)
 {
     return(World.Intersect(ref segment, out scalar, out point));
 }