- internal static List<Single> getPolyDistanceToPlane(List<Vector3> poly, Vector4 plane)
- {
- List<Single> dists = new List<Single>();
- for (Int32 k = 0; k < poly.Count; k++)
- {
- Single dot = Vector3.Dot(poly[k], plane.Xyz) - plane.W;
- dists.Add(dot);
- }
- return dists;
- }
- internal static List<PlaneSide> getPolySideToPlane(List<Vector3> poly, Vector4 plane)
- {
- List<PlaneSide> sides = new List<PlaneSide>();
- List<Single> dists = getPolyDistanceToPlane(poly,plane);
- foreach (Single dot in dists)
- {
- if (dot > Single.Epsilon)
- {
- sides.Add(PlaneSide.front);
- }
- else if (-dot > Single.Epsilon)
- {
- sides.Add(PlaneSide.back);
- }
- else
- {
- sides.Add(PlaneSide.on);
- }
- }
- return sides;
- }
- internal static List<Vector3> intersectPolyByPlane(List<Vector3> poly, Vector4 plane)
- {
- List<PlaneSide> sides = getPolySideToPlane(poly, plane);
- List<Single> dists = getPolyDistanceToPlane(poly, plane);
- if ((from cc in sides where cc == PlaneSide.front select cc).Count() == 0 &&
- (from cc in sides where cc == PlaneSide.back select cc).Count() == 0)
- {
- return poly;
- }
- if ((from cc in sides where cc == PlaneSide.front select cc).Count() == 0)
- {
- return null;
- }
- if ((from cc in sides where cc == PlaneSide.back select cc).Count() == 0)
- {
- return poly;
- }
- List<Vector3> output = new List<Vector3>();
- for (Int32 i = 0; i < poly.Count; i++)
- {
- Vector3 p1 = poly[i];
- if (sides[i] == PlaneSide.on)
- {
- output.Add(p1);
- continue;
- }
- if (sides[i] == PlaneSide.front)
- {
- output.Add(p1);
- }
- if (sides[(i + 1) % sides.Count] == PlaneSide.on || sides[(i + 1) % sides.Count] == sides[i])
- {
- continue;
- }
- Vector3 p2 = poly[(i + 1) % poly.Count];
- Single dot = dists[i] / (dists[i] - dists[(i + 1) % dists.Count]);
- Vector3 mid = new Vector3(0, 0, 0);
- if (Math.Abs(plane.X - 1) < Single.Epsilon)
- {
- mid.X = plane.W;
- }
- else if (Math.Abs(plane.X + 1) < Single.Epsilon)
- {
- mid.X = -plane.W;
- }
- else
- {
- mid.X = p1.X + dot * (p2.X - p1.X);
- }
- if (Math.Abs(plane.Y - 1) < Single.Epsilon)
- {
- mid.Y = plane.W;
- }
- else if (Math.Abs(plane.Y + 1) < Single.Epsilon)
- {
- mid.Y = -plane.W;
- }
- else
- {
- mid.Y = p1.Y + dot * (p2.Y - p1.Y);
- }
- if (Math.Abs(plane.Z - 1) < Single.Epsilon)
- {
- mid.Z = plane.W;
- }
- else if (Math.Abs(plane.Z + 1) < Single.Epsilon)
- {
- mid.Z = -plane.W;
- }
- else
- {
- mid.Z = p1.Z + dot * (p2.Z - p1.Z);
- }
- output.Add(mid);
- }
- return output;
- }
- internal static List<Vector3> createPolyByPlane(Vector4 plane)
- {
- var max = Double.MinValue;
- var vup = new Vector3(0, 0, 0);
- if (Math.Abs(plane.X) > max)
- {
- max = Math.Abs(plane.X);
- vup.Z = 1;
- }
- if (Math.Abs(plane.Y) > max)
- {
- max = Math.Abs(plane.Y);
- vup.Z = 1;
- }
- if (Math.Abs(plane.Z) > max)
- {
- vup.X = 1;
- }
- vup = (plane.Xyz * -Vector3.Dot(vup, plane.Xyz)) + vup;
- vup.Normalize();
- Vector3 org = plane.Xyz * plane.W;
- Vector3 vright = Vector3.Cross(vup, plane.Xyz);
- vup *= 64000;
- vright *= 64000;
- return new List<Vector3>(new[] { org - vright + vup, org + vright + vup, org + vright - vup, org - vright - vup });
- }
- internal static List<Vector3> createPolyByPlaneAndVolume(Vector4 plane, List<Vector4> volumeData)
- {
- List<Vector3> winding = createPolyByPlane(plane);
- for (Int32 j = 0; j < volumeData.Count; j++)
- {
- if (volumeData[j].Equals(plane))
- {
- continue;
- }
- winding = intersectPolyByPlane(winding, volumeData[j]);
- if (winding == null)
- {
- break;
- }
- }
- if (winding != null)
- {
- if (winding.Count >= 3)
- {
- return winding;
- }
- }
- return null;
- }
- internal static List<Vector3> getVolumePoints(List<Vector4> volumeData)
- {
- List<Vector3> output = new List<Vector3>();
- for (Int32 i = 0; i < volumeData.Count; i++)
- {
- List<Vector3> vecs = createPolyByPlaneAndVolume(volumeData[i], volumeData);
- if (vecs != null)
- {
- if (vecs.Count >= 3)
- {
- output.AddRange(vecs);
- }
- }
- }
- return output;
- }