Beispiel #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 seg, out float scalar, out Vector3 p)
		{
			p = Vector3.Zero;
			scalar = float.NaN;

			Vector3 s, d;
			Vector3.Subtract(ref Center, ref seg.P1, out s);
			Vector3.Subtract(ref seg.P2, ref seg.P1, out d);
			float l2s = Vector3.Dot(s, s);
			float r2 = Radius * Radius;

			if (l2s <= r2)
			{
				p = seg.P1;
				scalar = 0f;
				return true;
			}

			float tc = Vector3.Dot(s, d) / Vector3.Dot(d, d);
			float l2h = (r2 - l2s) / d.LengthSquared() + tc * tc;
			if (l2h < 0f) return false;

			scalar = tc - (float)Math.Sqrt(l2h);
			Vector3.Multiply(ref d, scalar, out p);
			Vector3.Add(ref seg.P1, ref p, out p);

			return scalar >= 0f && scalar <= 1f;
		}
Beispiel #2
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)
		{
			p = Vector3.Zero;
			scalar = float.NaN;

			float a, d, e;
			Vector3 diff;
			Vector3.Subtract(ref segment.P2, ref segment.P1, out diff);
			Vector3.Dot(ref segment.P1, ref Normal, out a);
			Vector3.Dot(ref P, ref Normal, out d);
			Vector3.Dot(ref Normal, ref diff, out e);
			if (Math.Abs(e) <= Constants.Epsilon) return false;
			scalar = (d - a) / e;
			Vector3.Multiply(ref diff, scalar, out p);
			Vector3.Add(ref segment.P1, ref p, out p);
			return scalar >= 0f && scalar <= 1f;
		}
Beispiel #3
0
		/// <summary>
		/// Intersects two line segments.
		/// </summary>
		/// <param name="sa">The first line segment.</param>
		/// <param name="sb">The second line segment.</param>
		/// <param name="scalarA">Returns a value between 0 and 1 indicating the point of intersection on the first segment.</param>
		/// <param name="scalarB">Returns a value between 0 and 1 indicating the point of intersection on the second segment.</param>
		/// <param name="p">Returns the point of intersection, common to both segments.</param>
		/// <returns>Returns a value indicating whether there was an intersection.</returns>
		public static bool Intersect(ref Segment sa, ref Segment sb, out float scalarA, out float scalarB, out Vector3 p)
		{
			Vector3 pa;
			float dist;
			Segment.ClosestPoints(ref sa, ref sb, out scalarA, out pa, out scalarB, out p);
			Vector3.DistanceSquared(ref pa, ref p, out dist);
			return dist < Constants.Epsilon;
		}
Beispiel #4
0
		/// <summary>
		/// Transform the segment using the specified transformation.
		/// </summary>
		/// <param name="s">The segment to transform.</param>
		/// <param name="transform">the transform to apply.</param>
		/// <param name="output">Returns the transformed segment.</param>
		public static void Transform(ref Segment s, ref Transform transform, out Segment output)
		{
			Vector3.Transform(ref s.P1, ref transform.Combined, out output.P1);
			Vector3.Transform(ref s.P2, ref transform.Combined, out output.P2);
		}
Beispiel #5
0
		/// <summary>
		/// Gets the closest two points on two line segments.
		/// </summary>
		/// <remarks>
		/// If the line segments are parallel and overlap in their common direction, then the midpoint of the overlapped portion of line segments
		/// is returned.
		/// </remarks>
		/// <param name="sa">The first line segment.</param>
		/// <param name="sb">The second line segment.</param>
		/// <param name="scalarA">Returns a value between 0 and 1 indicating the position of the closest point on the first segment.</param>
		/// <param name="pa">Returns the closest point on the first segment.</param>
		/// <param name="scalarB">Returns a value between 0 and 1 indicating the position of the closest point on the second segment.</param>
		/// <param name="pb">Returns the closest point on the second segment.</param>
		public static void ClosestPoints(ref Segment sa, ref Segment sb,
			out float scalarA, out Vector3 pa, out float scalarB, out Vector3 pb)
		{
			Vector3 d1, d2, r;
			Vector3.Subtract(ref sa.P2, ref sa.P1, out d1);
			Vector3.Subtract(ref sb.P2, ref sb.P1, out d2);
			Vector3.Subtract(ref sa.P1, ref sb.P1, out r);
			float a, e, f;
			Vector3.Dot(ref d1, ref d1, out a);
			Vector3.Dot(ref d2, ref d2, out e);
			Vector3.Dot(ref d2, ref r, out f);

			if (a < Constants.Epsilon && e < Constants.Epsilon)
			{
				// segment a and b are both points
				scalarA = scalarB = 0f;
				pa = sa.P1;
				pb = sb.P1;
				return;
			}

			if (a < Constants.Epsilon)
			{
				// segment a is a point
				scalarA = 0f;
				scalarB = MathHelper.Clamp(f / e, 0f, 1f);
			}
			else
			{
				float c;
				Vector3.Dot(ref d1, ref r, out c);

				if (e < Constants.Epsilon)
				{
					// segment b is a point
					scalarB = 0f;
					scalarA = MathHelper.Clamp(-c / a, 0f, 1f);
				}
				else
				{
					float b;
					Vector3.Dot(ref d1, ref d2, out b);
					float denom = a * e - b * b;

					if (denom < Constants.Epsilon)
					{
						// segments are parallel
						float a1, a2, b1, b2;
						Vector3.Dot(ref d2, ref sa.P1, out a1);
						Vector3.Dot(ref d2, ref sa.P2, out a2);
						Vector3.Dot(ref d2, ref sb.P1, out b1);
						Vector3.Dot(ref d2, ref sb.P2, out b2);
						if (a1 <= b1 && a2 <= b1)
						{
							// segment A is completely "before" segment B
							scalarA = a2 > a1 ? 1f : 0f;
							scalarB = 0f;
						}
						else if (a1 >= b2 && a2 >= b2)
						{
							// segment B is completely "before" segment A
							scalarA = a2 > a1 ? 0f : 1f;
							scalarB = 1f;
						}
						else
						{
							// segments A and B overlap, use midpoint of shared length
							if (a1 > a2) { f = a1; a1 = a2; a2 = f; }
							f = (Math.Min(a2, b2) + Math.Max(a1, b1)) / 2f;
							scalarB = (f - b1) / e;
							Vector3.Multiply(ref d2, scalarB, out pb);
							Vector3.Add(ref sb.P1, ref pb, out pb);
							sa.ClosestPointTo(ref pb, out scalarA, out pa);
							return;
						}
					}
					else
					{
						// general case
						scalarA = MathHelper.Clamp((b * f - c * e) / denom, 0f, 1f);
						scalarB = (b * scalarA + f) / e;
						if (scalarB < 0f)
						{
							scalarB = 0f;
							scalarA = MathHelper.Clamp(-c / a, 0f, 1f);
						}
						else if (scalarB > 1f)
						{
							scalarB = 1f;
							scalarA = MathHelper.Clamp((b - c) / a, 0f, 1f);
						}
					}
				}
			}
			Vector3.Multiply(ref d1, scalarA, out d1);
			Vector3.Multiply(ref d2, scalarB, out d2);
			Vector3.Add(ref sa.P1, ref d1, out pa);
			Vector3.Add(ref sb.P1, ref d2, out pb);
		}
Beispiel #6
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)
		{
			Segment bodySeg;
			Segment.Transform(ref segment, ref TransformInverse, out bodySeg);

			AlignedBox box;
			AlignedBox.Fit(ref bodySeg.P1, ref bodySeg.P2, out box);

			var tf = Functor;
			tf.Segment = bodySeg;
			tf.Scalar = float.MaxValue;
			tf.Point = Vector3.Zero;
			tf.BoundingBox = box;

			_body.ProcessTriangles(tf);

			scalar = tf.Scalar;
			point = tf.Point;
			Vector3.Transform(ref point, ref Transform.Combined, out point);
			return scalar >= 0f && scalar <= 1f;
		}
Beispiel #7
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;
		}
		/// <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)
		{
			scalar = float.PositiveInfinity;
			point = Vector3.Zero;
			float scalar1;
			Vector3 point1;
			for (int i = 0; i < FaceCount; i++)
			{
				var face = Face(i);
				Vector3 p0;
				World(face[0], out p0);
				var plane = new Plane(p0, _faceNormals[i]);
				if (plane.Intersect(ref segment, out scalar1, out point1) &&
					scalar1 < scalar && IsPointOnFace(i, ref point1, true))
				{
					scalar = scalar1;
					point = point1;
				}
			}
			return !float.IsPositiveInfinity(scalar);
		}
Beispiel #9
0
		/// <summary>
		/// Gets the closest point on the triangle to the specified segment.
		/// </summary>
		/// <remarks>
		/// The result can either be any of the vertices, on one of the edges, or another point within the interior of the triangle.
		/// </remarks>
		/// <param name="seg">The segment against which to find the closest triangle point.</param>
		/// <param name="segPoint">Returns the point on the segment that is closest.</param>
		/// <param name="triPoint">Returns the point on the triangle that is closest.</param>
		/// <returns>Returns a value indicating whether the closest point is in the interior of the triangle (not on any vertex or edge).</returns>
		public bool ClosestPointTo(ref Segment seg, out float scalar, out Vector3 segPoint, out Vector3 triPoint)
		{
			// segment intersects triangle
			if (this.Intersect(ref seg, out scalar, out triPoint))
			{
				segPoint = triPoint;
				return true;
			}

			Vector3 v;
			float minDist = float.MaxValue, dtri;
			bool p1inside, p2inside;
			segPoint = Vector3.Zero;
			Vector3.Dot(ref Normal, ref V1, out dtri);

			p1inside = this.Contains(ref seg.P1);
			p2inside = this.Contains(ref seg.P2);

			// both points inside triangle
			if (p1inside && p2inside)
			{
				float d1, d2;
				Vector3.Dot(ref Normal, ref seg.P1, out d1);
				Vector3.Dot(ref Normal, ref seg.P2, out d2);
				d1 -= dtri;
				d2 -= dtri;
				if (Math.Abs(d2 - d1) < Constants.Epsilon)
				{
					// segment is parallel to triangle
					minDist = d1;
					Vector3.Add(ref seg.P1, ref seg.P2, out segPoint);
					Vector3.Multiply(ref segPoint, 0.5f, out segPoint);
				}
				else if (Math.Abs(d1) < Math.Abs(d2))
				{
					segPoint = seg.P1;
					minDist = d1;
					scalar = 0f;
				}
				else
				{
					segPoint = seg.P2;
					minDist = d2;
					scalar = 1f;
				}
				Vector3.Multiply(ref Normal, -minDist, out v);
				Vector3.Add(ref segPoint, ref v, out triPoint);

				return true;
			}
			else if (p1inside)
				segPoint = seg.P1;
			else if (p2inside)
				segPoint = seg.P2;

			// one point is inside triangle
			if (p1inside || p2inside)
			{
				Vector3.Dot(ref Normal, ref segPoint, out minDist);
				minDist -= dtri;
				Vector3.Multiply(ref Normal, -minDist, out v);
				Vector3.Add(ref segPoint, ref v, out triPoint);
				minDist = Math.Abs(minDist);
				minDist *= minDist;
				scalar = p1inside ? 0f : 1f;
			}

			float sa, sb, dist;
			Vector3 pa, pb;

			// test edge 1
			var edge = new Segment(V1, V2);
			Segment.ClosestPoints(ref seg, ref edge, out sa, out pa, out sb, out pb);
			Vector3.DistanceSquared(ref pa, ref pb, out dist);
			if (dist < minDist)
			{
				minDist = dist;
				scalar = sa;
				segPoint = pa;
				triPoint = pb;
			}

			// test edge 2
			edge.P1 = V2;
			edge.P2 = V3;
			Segment.ClosestPoints(ref seg, ref edge, out sa, out pa, out sb, out pb);
			Vector3.DistanceSquared(ref pa, ref pb, out dist);
			if (dist < minDist)
			{
				minDist = dist;
				scalar = sa;
				segPoint = pa;
				triPoint = pb;
			}

			// test edge 3
			edge.P1 = V3;
			edge.P2 = V1;
			Segment.ClosestPoints(ref seg, ref edge, out sa, out pa, out sb, out pb);
			Vector3.DistanceSquared(ref pa, ref pb, out dist);
			if (dist < minDist)
			{
				minDist = dist;
				scalar = sa;
				segPoint = pa;
				triPoint = pb;
			}

			return false;
		}
Beispiel #10
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 seg, out float scalar, out Vector3 p)
		{
			scalar = float.NaN;
			p = Vector3.Zero;
			bool switched = false;
			Segment backup = seg;

			Vector3 v12, v13, p21, v1p1, e, n;
			float d, t, v, w;
			Vector3.Subtract(ref V2, ref V1, out v12);
			Vector3.Subtract(ref V3, ref V1, out v13);
			Vector3.Subtract(ref seg.P1, ref seg.P2, out p21);
			Vector3.Cross(ref v12, ref v13, out n);

			Vector3.Dot(ref n, ref p21, out d);
			if (Math.Abs(d) < Constants.Epsilon)
				return false; // segment is parallel
			else if (d < 0f)
			{
				backup = seg;
				p = seg.P1;
				seg.P1 = seg.P2;
				seg.P2 = p;
				switched = true;
				Vector3.Subtract(ref seg.P1, ref seg.P2, out p21);
				d = -d;
			}

			Vector3.Subtract(ref seg.P1, ref V1, out v1p1);
			Vector3.Dot(ref n, ref v1p1, out t);
			Vector3.Cross(ref p21, ref v1p1, out e);
			Vector3.Dot(ref v13, ref e, out v);
			if (v < 0f || v > d)
				return false; // intersects outside triangle
			Vector3.Dot(ref v12, ref e, out w);
			w = -w;
			if (w < 0f || v + w > d)
				return false; // intersects outside triangle

			d = 1f / d;
			t *= d;
			v *= d;
			w *= d;
			scalar = t;

			// compute intersect point from barycentric coordinates
			Vector3.Multiply(ref v12, v, out v12);
			Vector3.Multiply(ref v13, w, out v13);
			Vector3.Add(ref V1, ref v12, out p);
			Vector3.Add(ref p, ref v13, out p);

			if (switched)
			{
				seg = backup;
				scalar = 1 - scalar;
			}
			return scalar >= 0f && scalar <= 1f;
		}
Beispiel #11
0
		/// <summary>
		/// Gets a triangle edge.
		/// </summary>
		/// <param name="index">The index of the triangle edge, or the first vertex that makes up the edge: 1, 2 or 3.</param>
		/// <param name="edge">Returns the edge line segment.</param>
		public void Edge(int index, out Segment edge)
		{
			switch (index)
			{
				case 1:
					edge.P1 = V1;
					edge.P2 = V2;
					break;
				case 2:
					edge.P1 = V2;
					edge.P2 = V3;
					break;
				case 3:
					edge.P1 = V3;
					edge.P2 = V1;
					break;
				default:
					throw new ArgumentException("Invalid triangle edge index.", "index");
			}
		}
Beispiel #12
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 Plane.Intersect(ref segment, out scalar, out point);
		}
Beispiel #13
0
        public Segment fireBullet()
        {
            canFire = false;
            this.bullets--;
            //calculate innacuracy offset
            Vector3 vOffset = new Vector3((float)random.NextDouble() - 0.5f, (float)random.NextDouble() - 0.5f, (float)random.NextDouble() - 0.5f);
            vOffset *= fAccuracyCoefficient;

            //calculate position bullet will be fired at
            vFireAt_Position = this.Position;
            vFireAt_Position += this.Forward * fBulletRange;
            vFireAt_Position += vOffset;

            drawBullet = true;

            m_Timer.AddTimer("Aircraft Fire Cooldown", fRateOfFire, resetFire, false);
            Segment Ray = new Segment(this.Position, vFireAt_Position);

            SoundManager.Get().PlaySoundCue("PlaneMachineGun");

            return Ray;
        }
Beispiel #14
0
		/// <summary>
		/// When overridden in a derived class, intersects a segment with the collision part, returning the intersection 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 abstract bool Intersect(ref Segment segment, out float scalar, out Vector3 point);
Beispiel #15
0
		/// <summary>
		/// Intersects a segment with all parts of the composition 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 any part of the composition.</returns>
		public bool Intersect(ref Segment s, out float scalar, out Vector3 point)
		{
			scalar = float.PositiveInfinity;
			point = Vector3.Zero;
			float scalar1;
			Vector3 point1;
			for (int i = 0; i < _parts.Count; i++)
			{
				if (_parts[i].Intersect(ref s, out scalar1, out point1) && scalar1 < scalar)
				{
					scalar = scalar1;
					point = point1;
				}
			}
			return !float.IsPositiveInfinity(scalar);
		}
Beispiel #16
0
        public Segment FireBullet()
        {
            canFire = false;
            drawBullet = true;

            //calculate innacuracy offset
            Vector3 vOffset = new Vector3((float)random.NextDouble() - 0.5f, (float)random.NextDouble() - 0.5f, (float)random.NextDouble() - 0.5f);
            vOffset *= fAccuracyCoefficient;
            vFireAt_Position = vTarget_Position + vOffset;

            m_Timer.AddTimer("EnemyBoat Fire Cooldown", fRateOfFire, resetFire, false);
            Segment Ray = new Segment(this.Position, vFireAt_Position);
            GameState.Get().ParticlesManager.effectFlakBurst(vFireAt_Position + GameState.Get().Aircraft.Forward * 15.0f);

            return Ray;
        }
Beispiel #17
0
		/// <summary>
		/// Attempts to encapsulate a cloud of points within a capsule. This may not produce an optimal or exact fit. The results
		/// are approximate.
		/// </summary>
		/// <param name="points">The list of points with which to build an enclosing capsule.</param>
		/// <param name="capsule">Returns the capsule containing all points.</param>
		public static void Fit(IList<Vector3> points, out Capsule capsule)
		{
			capsule = new Capsule();
			Vector3 axis, axisNeg;
			GeometryHelper.ComputeMaxSpreadAxis(points, out axis);
			Vector3.Negate(ref axis, out axisNeg);
			if (axis.LengthSquared() < Constants.Epsilon)
				return;
			GeometryHelper.ComputeExtremePoint(points, ref axis, out capsule.P2);
			GeometryHelper.ComputeExtremePoint(points, ref axisNeg, out capsule.P1);
			Segment s = new Segment(capsule.P1, capsule.P2);
			for (int i = 0; i < points.Count; i++)
			{
				var p = points[i];
				float x = s.DistanceSquaredTo(ref p);
				if (x > capsule.Radius)
				{
					capsule.Radius = x;
				}
			}
			capsule.Radius = (float)Math.Sqrt(capsule.Radius);
			Vector3.Multiply(ref axis, capsule.Radius, out axis);
			Vector3.Negate(ref axis, out axisNeg);
			Vector3.Add(ref capsule.P1, ref axis, out capsule.P1);
			Vector3.Add(ref capsule.P2, ref axisNeg, out capsule.P2);
		}
		/// <summary>
		/// Determines whether the specified point, when projected onto the face plane of the polyhedron, is within the face.
		/// </summary>
		/// <param name="faceIndex">The index of the face in which to check containment.</param>
		/// <param name="p">The point in world-space that is either inside or outside the face.</param>
		/// <param name="inclusive">Indicates whether points on the edge or vertices of a face should be considered within the face.</param>
		/// <returns>Returns a value indicating whether the point is contained within the face.</returns>
		public bool IsPointOnFace(int faceIndex, ref Vector3 p, bool inclusive)
		{
			int[] face = Face(faceIndex);
			int low = 0, high = face.Length;
			Vector3 normal;
			FaceNormal(faceIndex, out normal);
			Segment s;
			Vector3 p0;
			World(face[0], out p0);
			do
			{
				int mid = (low + high) / 2;
				Vector3 p1;
				World(face[mid], out p1);
				s = new Segment(p0, p1);
				if ((mid == face.Length - 1 || mid == 1) &&
					s.DistanceSquaredTo(ref p) < Constants.Epsilon)
				{
					return inclusive;
				}
				if (GeometryHelper.IsTriangleCcw(ref normal, ref s.P1, ref s.P2, ref p))
				{
					low = mid;
				}
				else
				{
					high = mid;
				}
			}
			while (low + 1 < high);
			if (low == 0 || high == face.Length) return false;
			World(face[low], out s.P1);
			World(face[high], out s.P2);
			return GeometryHelper.IsTriangleCcw(ref normal, ref s.P1, ref s.P2, ref p) ||
				(inclusive && s.DistanceSquaredTo(ref p) < Constants.Epsilon);
		}