Ejemplo n.º 1
0
        private static void CalculateFaceFacePoints(CollisionFunctor cf, PolyhedronPart a, PolyhedronPart b, ref CollisionInfo ci)
        {
            int[] faceA = a.Face(ci.FeatureA.Index);
            int[] faceB = b.Face(ci.FeatureB.Index);

            Vector3 pa, pb, n;

            a.World(faceA[0], out pa);
            a.FaceNormal(ci.FeatureA.Index, out n);
            Plane planeA = new Plane(pa, n);

            b.World(faceB[0], out pb);
            Plane planeB = new Plane(pb, ci.Normal);

            // vertices of A contained in face of B
            for (int i = 0; i < faceA.Length; i++)
            {
                a.World(faceA[i], out pa);
                planeB.ClosestPointTo(ref pa, out pb);
                if (b.IsPointOnFace(ci.FeatureB.Index, ref pb, true))
                {
                    cf.WritePoint(ref pa, ref pb, ref ci.Normal);
                }
            }

            // vertices of B contained in face of A
            for (int i = 0; i < faceB.Length; i++)
            {
                b.World(faceB[i], out pb);
                planeA.ClosestPointTo(ref pb, out pa);
                if (a.IsPointOnFace(ci.FeatureA.Index, ref pa, true))
                {
                    cf.WritePoint(ref pa, ref pb, ref ci.Normal);
                }
            }

            // intersections of edges from both faces
            Segment ea, eb;

            for (int i = 0; i < faceA.Length; i++)
            {
                a.World(faceA[i == 0 ? faceA.Length - 1 : i - 1], out ea.P1);
                a.World(faceA[i], out ea.P2);

                for (int j = 0; j < faceB.Length; j++)
                {
                    b.World(faceB[j == 0 ? faceB.Length - 1 : j - 1], out eb.P1);
                    b.World(faceB[j], out eb.P2);

                    float sa, sb;
                    Segment.ClosestPoints(ref ea, ref eb, out sa, out pa, out sb, out pb);
                    if (sa > 0f && sa < 1f && sb > 0f && sb < 1f)
                    {
                        cf.WritePoint(ref pa, ref pb, ref ci.Normal);
                    }
                }
            }
        }
Ejemplo n.º 2
0
        public static bool DoOverlapTest(CollisionFunctor cf, SpherePart a, PolyhedronPart b, Vector3 offset)
        {
            Vector3 pa, pb, normal, v, center;
            float   depth, r2 = a.World.Radius * a.World.Radius;
            bool    foundAny = false;

            for (int i = 0; i < b.FaceCount; i++)
            {
                b.World(b.Face(i)[0], out v);
                b.FaceNormal(i, out normal);
                var plane = new Plane(v, normal);

                Vector3.Add(ref a.World.Center, ref offset, out center);
                Vector3.Subtract(ref center, ref v, out v);
                Vector3.Dot(ref normal, ref v, out depth);

                if (depth < 0f || depth - a.World.Radius >= Constants.Epsilon)
                {
                    continue;
                }

                plane.ClosestPointTo(ref center, out pb);
                if (b.IsPointOnFace(i, ref pb, true))
                {
                    Vector3.Subtract(ref pb, ref center, out v);
                    if (v.LengthSquared() - r2 < Constants.Epsilon)
                    {
                        Vector3.Multiply(ref normal, -a.World.Radius, out pa);
                        Vector3.Add(ref a.World.Center, ref pa, out pa);
                        cf.WritePoint(ref pa, ref pb, ref normal);
                        return(true);
                    }
                }
                else
                {
                    int[] face = b.Face(i);
                    for (int j = 0; j < face.Length; j++)
                    {
                        float   s;
                        Segment edge;
                        b.World(face[j == 0 ? face.Length - 1 : j - 1], out edge.P1);
                        b.World(face[j], out edge.P2);
                        edge.ClosestPointTo(ref center, out s, out pb);
                        Vector3.Subtract(ref center, ref pb, out normal);
                        if (normal.LengthSquared() - r2 < Constants.Epsilon)
                        {
                            normal.Normalize();
                            Vector3.Multiply(ref normal, -a.World.Radius, out pa);
                            Vector3.Add(ref a.World.Center, ref pa, out pa);
                            cf.WritePoint(ref pa, ref pb, ref normal);
                            foundAny = true;
                        }
                    }
                }
            }
            return(foundAny);
        }
Ejemplo n.º 3
0
		public static bool DoOverlapTest(CollisionFunctor cf, SpherePart a, PolyhedronPart b, Vector3 offset)
		{
			Vector3 pa, pb, normal, v, center;
			float depth, r2 = a.World.Radius * a.World.Radius;
			bool foundAny = false;

			for (int i = 0; i < b.FaceCount; i++)
			{
				b.World(b.Face(i)[0], out v);
				b.FaceNormal(i, out normal);
				var plane = new Plane(v, normal);

				Vector3.Add(ref a.World.Center, ref offset, out center);
				Vector3.Subtract(ref center, ref v, out v);
				Vector3.Dot(ref normal, ref v, out depth);

				if (depth < 0f || depth - a.World.Radius >= Constants.Epsilon)
					continue;

				plane.ClosestPointTo(ref center, out pb);
				if (b.IsPointOnFace(i, ref pb, true))
				{
					Vector3.Subtract(ref pb, ref center, out v);
					if (v.LengthSquared() - r2 < Constants.Epsilon)
					{
						Vector3.Multiply(ref normal, -a.World.Radius, out pa);
						Vector3.Add(ref a.World.Center, ref pa, out pa);
						cf.WritePoint(ref pa, ref pb, ref normal);
						return true;
					}
				}
				else
				{
					int[] face = b.Face(i);
					for (int j = 0; j < face.Length; j++)
					{
						float s;
						Segment edge;
						b.World(face[j == 0 ? face.Length - 1 : j - 1], out edge.P1);
						b.World(face[j], out edge.P2);
						edge.ClosestPointTo(ref center, out s, out pb);
						Vector3.Subtract(ref center, ref pb, out normal);
						if (normal.LengthSquared() - r2 < Constants.Epsilon)
						{
							normal.Normalize();
							Vector3.Multiply(ref normal, -a.World.Radius, out pa);
							Vector3.Add(ref a.World.Center, ref pa, out pa);
							cf.WritePoint(ref pa, ref pb, ref normal);
							foundAny = true;
						}
					}
				}
			}
			return foundAny;
		}
Ejemplo n.º 4
0
        private static void CalculateEdgeFacePoints(CollisionFunctor cf, PolyhedronPart a, PolyhedronPart b, ref CollisionInfo ci)
        {
            Vector3 pa, pb;
            Segment ea, eb, eab;

            int[] edgeA = a.Edge(ci.FeatureA.Index);
            a.World(edgeA[0], out ea.P1);
            a.World(edgeA[1], out ea.P2);
            int[] faceB = b.Face(ci.FeatureB.Index);
            b.World(faceB[0], out pb);
            var planeB = new Plane(pb, ci.Normal);

            planeB.ClosestPointTo(ref ea.P1, out eab.P1);
            planeB.ClosestPointTo(ref ea.P2, out eab.P2);

            int count = 0;

            if (b.IsPointOnFace(ci.FeatureB.Index, ref eab.P1, true))
            {
                count++;
                cf.WritePoint(ref ea.P1, ref eab.P1, ref ci.Normal);
            }
            if (b.IsPointOnFace(ci.FeatureB.Index, ref eab.P2, true))
            {
                count++;
                cf.WritePoint(ref ea.P2, ref eab.P2, ref ci.Normal);
            }

            for (int i = 0; i < faceB.Length && count < 2; i++)
            {
                b.World(faceB[i == 0 ? faceB.Length - 1 : i - 1], out eb.P1);
                b.World(faceB[i], out eb.P2);

                float sa, sb;
                Segment.ClosestPoints(ref ea, ref eb, out sa, out pa, out sb, out pb);
                if (sa > 0f && sa < 1f && sb > 0f && sb < 1f)
                {
                    count++;
                    cf.WritePoint(ref pa, ref pb, ref ci.Normal);
                }
            }
        }
Ejemplo n.º 5
0
        private static void CalculateFaceEdgePoints(CollisionFunctor cf, PolyhedronPart a, MeshPart b, ref Triangle tri, ref CollisionInfo ci)
        {
            Vector3 pa, pb;
            Segment ea, eba, eb;

            int[] faceA = a.Face(ci.FeatureA.Index);
            a.World(faceA[0], out pa);
            Plane planeA = new Plane(pa, ci.Normal);

            tri.Edge(ci.FeatureB.Index, out eb);
            planeA.ClosestPointTo(ref eb.P1, out eba.P1);
            planeA.ClosestPointTo(ref eb.P2, out eba.P2);

            int count = 0;

            if (a.IsPointOnFace(ci.FeatureA.Index, ref eba.P1, true))
            {
                count++;
                cf.WritePoint(ref eba.P1, ref eb.P1, ref ci.Normal);
            }
            if (a.IsPointOnFace(ci.FeatureA.Index, ref eba.P2, true))
            {
                count++;
                cf.WritePoint(ref eba.P2, ref eb.P2, ref ci.Normal);
            }

            for (int i = 0; i < faceA.Length && count < 2; i++)
            {
                a.World(faceA[i == 0 ? faceA.Length - 1 : i - 1], out ea.P1);
                a.World(faceA[i], out ea.P2);

                float sa, sb;
                Segment.ClosestPoints(ref ea, ref eb, out sa, out pa, out sb, out pb);
                if (sa > 0f && sa < 1f && sb > 0f && sb < 1f)
                {
                    count++;
                    cf.WritePoint(ref pa, ref pb, ref ci.Normal);
                }
            }
        }
Ejemplo n.º 6
0
        private static void CalculateFaceFacePoints(CollisionFunctor cf, PolyhedronPart a, MeshPart b, ref Triangle tri, ref CollisionInfo ci)
        {
            int[]   faceA = a.Face(ci.FeatureA.Index);
            Vector3 pa, pb, n;

            a.World(faceA[0], out pa);
            a.FaceNormal(ci.FeatureA.Index, out n);
            Plane planeA = new Plane(pa, n);
            Plane planeB = new Plane(tri.V1, tri.Normal);

            // vertices of A contained in face of B
            for (int i = 0; i < faceA.Length; i++)
            {
                a.World(faceA[i], out pa);
                planeB.ClosestPointTo(ref pa, out pb);
                if (tri.Contains(ref pb))
                {
                    cf.WritePoint(ref pa, ref pb, ref ci.Normal);
                }
            }

            for (int i = 1; i <= 3; i++)
            {
                tri.Vertex(i, out pb);
                planeA.ClosestPointTo(ref pb, out pa);
                if (a.IsPointOnFace(ci.FeatureA.Index, ref pa, true))
                {
                    cf.WritePoint(ref pa, ref pb, ref ci.Normal);
                }
            }

            // intersection of edges from both faces
            Segment ea, eb;

            for (int i = 0; i < faceA.Length; i++)
            {
                a.World(faceA[i == 0 ? faceA.Length - 1 : i - 1], out ea.P1);
                a.World(faceA[i], out ea.P2);

                for (int j = 1; j <= 3; j++)
                {
                    tri.Edge(j, out eb);

                    float sa, sb;
                    Segment.ClosestPoints(ref ea, ref eb, out sa, out pa, out sb, out pb);
                    if (sa > 0f && sa < 1f && sb > 0f && sb < 1f)
                    {
                        cf.WritePoint(ref pa, ref pb, ref ci.Normal);
                    }
                }
            }
        }
Ejemplo n.º 7
0
        private static void CalculateFaceFacePoints(CollisionFunctor cf, PolyhedronPart a, PolyhedronPart b, ref CollisionInfo ci)
        {
            int[] faceA = a.Face(ci.FeatureA.Index);
            int[] faceB = b.Face(ci.FeatureB.Index);

            Vector3 pa, pb, n;

            a.World(faceA[0], out pa);
            a.FaceNormal(ci.FeatureA.Index, out n);
            Plane planeA = new Plane(pa, n);
            b.World(faceB[0], out pb);
            Plane planeB = new Plane(pb, ci.Normal);

            // vertices of A contained in face of B
            for (int i = 0; i < faceA.Length; i++)
            {
                a.World(faceA[i], out pa);
                planeB.ClosestPointTo(ref pa, out pb);
                if(b.IsPointOnFace(ci.FeatureB.Index, ref pb, true))
                {
                    cf.WritePoint(ref pa, ref pb, ref ci.Normal);
                }
            }

            // vertices of B contained in face of A
            for (int i = 0; i < faceB.Length; i++)
            {
                b.World(faceB[i], out pb);
                planeA.ClosestPointTo(ref pb, out pa);
                if (a.IsPointOnFace(ci.FeatureA.Index, ref pa, true))
                {
                    cf.WritePoint(ref pa, ref pb, ref ci.Normal);
                }
            }

            // intersections of edges from both faces
            Segment ea, eb;
            for (int i = 0; i < faceA.Length; i++)
            {
                a.World(faceA[i == 0 ? faceA.Length - 1 : i - 1], out ea.P1);
                a.World(faceA[i], out ea.P2);

                for (int j = 0; j < faceB.Length; j++)
                {
                    b.World(faceB[j == 0 ? faceB.Length - 1 : j - 1], out eb.P1);
                    b.World(faceB[j], out eb.P2);

                    float sa, sb;
                    Segment.ClosestPoints(ref ea, ref eb, out sa, out pa, out sb, out pb);
                    if (sa > 0f && sa < 1f && sb > 0f && sb < 1f)
                    {
                        cf.WritePoint(ref pa, ref pb, ref ci.Normal);
                    }
                }
            }
        }
Ejemplo n.º 8
0
        private static void CalculateFaceEdgePoints(CollisionFunctor cf, PolyhedronPart a, PolyhedronPart b, ref CollisionInfo ci)
        {
            Vector3 pa, pb;
            Segment ea, eb, eba;
            int[] edgeB = b.Edge(ci.FeatureB.Index);
            b.World(edgeB[0], out eb.P1);
            b.World(edgeB[1], out eb.P2);
            int[] faceA = a.Face(ci.FeatureA.Index);
            a.World(faceA[0], out pa);
            var planeA = new Plane(pa, ci.Normal);
            planeA.ClosestPointTo(ref eb.P1, out eba.P1);
            planeA.ClosestPointTo(ref eb.P2, out eba.P2);

            int count = 0;
            if (a.IsPointOnFace(ci.FeatureA.Index, ref eba.P1, true))
            {
                count++;
                cf.WritePoint(ref eba.P1, ref eb.P1, ref ci.Normal);
            }
            if (a.IsPointOnFace(ci.FeatureA.Index, ref eba.P2, true))
            {
                count++;
                cf.WritePoint(ref eba.P2, ref eb.P2, ref ci.Normal);
            }

            for(int i = 0; i < faceA.Length && count < 2; i++)
            {
                a.World(faceA[i == 0 ? faceA.Length - 1 : i - 1], out ea.P1);
                a.World(faceA[i], out ea.P2);

                float sa, sb;
                Segment.ClosestPoints(ref ea, ref eb, out sa, out pa, out sb, out pb);
                if (sa > 0f && sa < 1f && sb > 0f && sb < 1f)
                {
                    count++;
                    cf.WritePoint(ref pa, ref pb, ref ci.Normal);
                }
            }
        }
Ejemplo n.º 9
0
        public static bool DoOverlapTest(CollisionFunctor cf, CapsulePart a, PolyhedronPart b, Vector3 offset)
        {
            Vector3 v, normal;
            float   ax1, ax2, bx, r2 = a.World.Radius * a.World.Radius;

            Segment capa;

            Vector3.Add(ref a.World.P1, ref offset, out capa.P1);
            Vector3.Add(ref a.World.P2, ref offset, out capa.P2);

            float curDepth, finalDepth = float.MaxValue;
            int   faceIdx = -1;

            // find the face with the least penetration depth along its normal
            for (int i = 0; i < b.FaceCount; i++)
            {
                b.World(b.Face(i)[0], out v);
                b.FaceNormal(i, out normal);
                Vector3.Dot(ref normal, ref v, out bx);
                Vector3.Dot(ref normal, ref capa.P1, out ax1);
                Vector3.Dot(ref normal, ref capa.P2, out ax2);
                bx      += a.World.Radius;
                curDepth = Math.Max(bx - ax1, bx - ax2);
                if (curDepth < 0f)
                {
                    return(false);
                }
                if (curDepth < finalDepth)
                {
                    faceIdx    = i;
                    finalDepth = curDepth;
                }
            }

            bool    got1 = false, got2 = false;
            Vector3 pa, pb, pa1, pa2, pb1, pb2;

            pa1 = pa2 = pb1 = pb2 = Vector3.Zero;
            var face = b.Face(faceIdx);

            b.World(face[0], out v);
            b.FaceNormal(faceIdx, out normal);

            var plane = new Plane(v, normal);

            Vector3.Dot(ref normal, ref v, out bx);
            bx += a.World.Radius;

            // determine if either capsule point is inside the face
            pa1 = capa.P1;
            plane.ClosestPointTo(ref pa1, out pb1);
            Vector3.Dot(ref normal, ref pa1, out ax1);
            got1 = ax1 - bx < Constants.Epsilon && b.IsPointOnFace(faceIdx, ref pb1, true);

            pa2 = capa.P2;
            plane.ClosestPointTo(ref pa2, out pb2);
            Vector3.Dot(ref normal, ref pa2, out ax1);
            if (ax1 - bx < Constants.Epsilon && b.IsPointOnFace(faceIdx, ref pb2, true))
            {
                if (got1)
                {
                    got2 = true;
                }
                else
                {
                    got1 = true;
                    pa1  = pa2;
                    pb1  = pb2;
                }
            }

            // if one capsule point is inside the face but one is not, try to generate a second point on an edge
            if (got1 ^ got2)
            {
                float sbPrev   = float.NaN;
                int   edgePrev = -1;
                for (int i = 0; i < face.Length; i++)
                {
                    float   dist, sa, sb;
                    Segment edge;
                    b.World(face[i == 0 ? face.Length - 1 : i - 1], out edge.P1);
                    b.World(face[i], out edge.P2);
                    Segment.ClosestPoints(ref capa, ref edge, out sa, out pa, out sb, out pb);
                    Vector3.DistanceSquared(ref pa, ref pb, out dist);
                    if (dist - r2 < Constants.Epsilon && sa >= Constants.Epsilon && sa < 1 - Constants.Epsilon)
                    {
                        if (i == face.Length - 1 && edgePrev == 0 && sb == 1f)
                        {
                            continue;
                        }
                        if (!got2 || (edgePrev == i - 1 && sbPrev == 1f))
                        {
                            pa2 = pa; pb2 = pb; got2 = true;
                        }
                        sbPrev   = sb;
                        edgePrev = i;
                    }
                }
            }
            else if (!got1 && !got2)
            {
                // neither point is inside the face, so try all edges
                float sbPrev = float.NaN, edgePrev = float.NaN;
                for (int i = 0; i < face.Length; i++)
                {
                    float   dist, sa, sb;
                    Segment edge;
                    b.World(face[i == 0 ? face.Length - 1 : i - 1], out edge.P1);
                    b.World(face[i], out edge.P2);
                    Segment.ClosestPoints(ref capa, ref edge, out sa, out pa, out sb, out pb);
                    Vector3.DistanceSquared(ref pa, ref pb, out dist);
                    if (dist - r2 < Constants.Epsilon && sb > Constants.Epsilon)
                    {
                        if (i == face.Length - 1 && edgePrev == 0 && sb == 1f)
                        {
                            continue;
                        }
                        if (!got1 || (edgePrev == i - 1 && sbPrev == 1f))
                        {
                            pa1 = pa; pb1 = pb; got1 = true;
                        }
                        else if (!got2)
                        {
                            pa2 = pa; pb2 = pb; got2 = true;
                        }
                        sbPrev   = sb;
                        edgePrev = i;
                    }
                }

                // if only one edge was crossed, create a new normal instead of using the face normal
                if (got1 ^ got2)
                {
                    Vector3.Subtract(ref pa1, ref pb1, out normal);
                    normal.Normalize();
                }
            }

            // write out points
            if (got1 || got2)
            {
                Vector3.Multiply(ref normal, -a.World.Radius, out v);

                if (got1)
                {
                    Vector3.Add(ref pa1, ref v, out pa1);
                    Vector3.Subtract(ref pa1, ref offset, out pa1);
                    cf.WritePoint(ref pa1, ref pb1, ref normal);
                }
                if (got2)
                {
                    Vector3.Add(ref pa2, ref v, out pa2);
                    Vector3.Subtract(ref pa2, ref offset, out pa2);
                    cf.WritePoint(ref pa2, ref pb2, ref normal);
                }
            }

            return(got1 || got2);
        }
Ejemplo n.º 10
0
		public static bool DoOverlapTest(CollisionFunctor cf, CapsulePart a, PolyhedronPart b, Vector3 offset)
		{
			Vector3 v, normal;
			float ax1, ax2, bx, r2 = a.World.Radius * a.World.Radius;

			Segment capa;
			Vector3.Add(ref a.World.P1, ref offset, out capa.P1);
			Vector3.Add(ref a.World.P2, ref offset, out capa.P2);

			float curDepth, finalDepth = float.MaxValue;
			int faceIdx = -1;

			// find the face with the least penetration depth along its normal
			for (int i = 0; i < b.FaceCount; i++)
			{
				b.World(b.Face(i)[0], out v);
				b.FaceNormal(i, out normal);
				Vector3.Dot(ref normal, ref v, out bx);
				Vector3.Dot(ref normal, ref capa.P1, out ax1);
				Vector3.Dot(ref normal, ref capa.P2, out ax2);
				bx += a.World.Radius;
				curDepth = Math.Max(bx - ax1, bx - ax2);
				if (curDepth < 0f)
					return false;
				if (curDepth < finalDepth)
				{
					faceIdx = i;
					finalDepth = curDepth;
				}
			}

			bool got1 = false, got2 = false;
			Vector3 pa, pb, pa1, pa2, pb1, pb2;
			pa1 = pa2 = pb1 = pb2 = Vector3.Zero;
			var face = b.Face(faceIdx);
			b.World(face[0], out v);
			b.FaceNormal(faceIdx, out normal);

			var plane = new Plane(v, normal);
			Vector3.Dot(ref normal, ref v, out bx);
			bx += a.World.Radius;

			// determine if either capsule point is inside the face
			pa1 = capa.P1;
			plane.ClosestPointTo(ref pa1, out pb1);
			Vector3.Dot(ref normal, ref pa1, out ax1);
			got1 = ax1 - bx < Constants.Epsilon && b.IsPointOnFace(faceIdx, ref pb1, true);

			pa2 = capa.P2;
			plane.ClosestPointTo(ref pa2, out pb2);
			Vector3.Dot(ref normal, ref pa2, out ax1);
			if (ax1 - bx < Constants.Epsilon && b.IsPointOnFace(faceIdx, ref pb2, true))
			{
				if (got1)
					got2 = true;
				else
				{
					got1 = true;
					pa1 = pa2;
					pb1 = pb2;
				}
			}

			// if one capsule point is inside the face but one is not, try to generate a second point on an edge
			if (got1 ^ got2)
			{
				float sbPrev = float.NaN;
				int edgePrev = -1;
				for (int i = 0; i < face.Length; i++)
				{
					float dist, sa, sb;
					Segment edge;
					b.World(face[i == 0 ? face.Length - 1 : i - 1], out edge.P1);
					b.World(face[i], out edge.P2);
					Segment.ClosestPoints(ref capa, ref edge, out sa, out pa, out sb, out pb);
					Vector3.DistanceSquared(ref pa, ref pb, out dist);
					if (dist - r2 < Constants.Epsilon && sa >= Constants.Epsilon && sa < 1 - Constants.Epsilon)
					{
						if (i == face.Length - 1 && edgePrev == 0 && sb == 1f) continue;
						if (!got2 || (edgePrev == i - 1 && sbPrev == 1f)) { pa2 = pa; pb2 = pb; got2 = true; }
						sbPrev = sb;
						edgePrev = i;
					}
				}
			}
			else if (!got1 && !got2)
			{
				// neither point is inside the face, so try all edges
				float sbPrev = float.NaN, edgePrev = float.NaN;
				for (int i = 0; i < face.Length; i++)
				{
					float dist, sa, sb;
					Segment edge;
					b.World(face[i == 0 ? face.Length - 1 : i - 1], out edge.P1);
					b.World(face[i], out edge.P2);
					Segment.ClosestPoints(ref capa, ref edge, out sa, out pa, out sb, out pb);
					Vector3.DistanceSquared(ref pa, ref pb, out dist);
					if (dist - r2 < Constants.Epsilon && sb > Constants.Epsilon)
					{
						if (i == face.Length - 1 && edgePrev == 0 && sb == 1f) continue;
						if (!got1 || (edgePrev == i - 1 && sbPrev == 1f)) { pa1 = pa; pb1 = pb; got1 = true; }
						else if (!got2) { pa2 = pa; pb2 = pb; got2 = true; }
						sbPrev = sb;
						edgePrev = i;
					}
				}

				// if only one edge was crossed, create a new normal instead of using the face normal
				if (got1 ^ got2)
				{
					Vector3.Subtract(ref pa1, ref pb1, out normal);
					normal.Normalize();
				}
			}

			// write out points
			if (got1 || got2)
			{
				Vector3.Multiply(ref normal, -a.World.Radius, out v);

				if (got1)
				{
					Vector3.Add(ref pa1, ref v, out pa1);
					Vector3.Subtract(ref pa1, ref offset, out pa1);
					cf.WritePoint(ref pa1, ref pb1, ref normal);
				}
				if (got2)
				{
					Vector3.Add(ref pa2, ref v, out pa2);
					Vector3.Subtract(ref pa2, ref offset, out pa2);
					cf.WritePoint(ref pa2, ref pb2, ref normal);
				}
			}

			return got1 || got2;
		}
Ejemplo n.º 11
0
		private static void CalculateFaceFacePoints(CollisionFunctor cf, PolyhedronPart a, MeshPart b, ref Triangle tri, ref CollisionInfo ci)
		{
			int[] faceA = a.Face(ci.FeatureA.Index);
			Vector3 pa, pb, n;

			a.World(faceA[0], out pa);
			a.FaceNormal(ci.FeatureA.Index, out n);
			Plane planeA = new Plane(pa, n);
			Plane planeB = new Plane(tri.V1, tri.Normal);

			// vertices of A contained in face of B
			for (int i = 0; i < faceA.Length; i++)
			{
				a.World(faceA[i], out pa);
				planeB.ClosestPointTo(ref pa, out pb);
				if (tri.Contains(ref pb))
				{
					cf.WritePoint(ref pa, ref pb, ref ci.Normal);
				}
			}

			for (int i = 1; i <= 3; i++)
			{
				tri.Vertex(i, out pb);
				planeA.ClosestPointTo(ref pb, out pa);
				if (a.IsPointOnFace(ci.FeatureA.Index, ref pa, true))
				{
					cf.WritePoint(ref pa, ref pb, ref ci.Normal);
				}
			}

			// intersection of edges from both faces
			Segment ea, eb;
			for (int i = 0; i < faceA.Length; i++)
			{
				a.World(faceA[i == 0 ? faceA.Length - 1 : i - 1], out ea.P1);
				a.World(faceA[i], out ea.P2);

				for (int j = 1; j <= 3; j++)
				{
					tri.Edge(j, out eb);

					float sa, sb;
					Segment.ClosestPoints(ref ea, ref eb, out sa, out pa, out sb, out pb);
					if (sa > 0f && sa < 1f && sb > 0f && sb < 1f)
					{
						cf.WritePoint(ref pa, ref pb, ref ci.Normal);
					}
				}
			}
		}