コード例 #1
0
ファイル: Plane.cs プロジェクト: Blecki/GemgineCore
 public Plane(Plane inPlane)
 {
     A = inPlane.A;
     B = inPlane.B;
     C = inPlane.C;
     D = inPlane.D;
 }
コード例 #2
0
ファイル: CSGMesh.cs プロジェクト: Blecki/GemgineCore
 public CSGMesh(Plane[] planes, List<Polygon> polygons, List<HalfEdge> edges, List<Vector3> vertices, AABB bounds)
 {
     this.Planes = planes;
     this.Polygons = polygons;
     this.Edges = edges;
     this.Vertices = vertices;
     this.Bounds.Set(bounds);
 }
コード例 #3
0
ファイル: CSGMesh.cs プロジェクト: Blecki/GemgineCore
        // Note: This method is not optimized! Code is simplified for clarity!
        //          for example: Plane.Distance / Plane.OnSide should be inlined manually and shouldn't use enums, but floating point values directly!
        public PolygonSplitResult PolygonSplit(Plane cuttingPlane, Vector3 translation, ref Polygon inputPolygon, out Polygon outsidePolygon)
        {
            HalfEdge prev		= Edges[inputPolygon.FirstIndex];
            HalfEdge current	= Edges[prev.NextIndex];
            HalfEdge next		= Edges[current.NextIndex];
            HalfEdge last		= next;
            HalfEdge enterEdge	= null;
            HalfEdge exitEdge	= null;

            var prevVertex			= Vertices[prev.VertexIndex];
            var prevDistance		= cuttingPlane.Distance(prevVertex);		// distance to previous vertex
            var prevSide			= Plane.OnSide(prevDistance);				// side of plane of previous vertex

            var currentVertex		= Vertices[current.VertexIndex];
            var currentDistance		= cuttingPlane.Distance(currentVertex);		// distance to current vertex
            var currentSide			= Plane.OnSide(currentDistance);			// side of plane of current vertex

            do
            {
                var nextVertex		= Vertices[next.VertexIndex];
                var nextDistance	= cuttingPlane.Distance(nextVertex);		// distance to next vertex
                var nextSide		= Plane.OnSide(nextDistance);				// side of plane of next vertex

                if (prevSide != currentSide)							// check if edge crossed the plane ...
                {
                    if (currentSide != PlaneSideResult.Intersects)		// prev:inside/outside - current:inside/outside - next:??
                    {
                        if (prevSide != PlaneSideResult.Intersects)		// prev:inside/outside - current:outside        - next:??
                        {
                            // Calculate intersection of edge with plane split the edge into two, inserting the new vertex
                            var newVertex	= Plane.Intersection(prevVertex, currentVertex, prevDistance, currentDistance);
                            var newEdge		= EdgeSplit(current, newVertex);

                            if (prevSide == PlaneSideResult.Inside)		// prev:inside         - current:outside        - next:??
                            {
                                //edge01 exits:
                                //
                                //      outside
                                //         1
                                //         *
                                // ......./........ intersect
                                //       /
                                //      0
                                //      inside

                                exitEdge		= current;
                            } else
                            if (prevSide == PlaneSideResult.Outside)		// prev:outside - current:inside - next:??
                            {
                                //edge01 enters:
                                //
                                //      outside
                                //      0
                                //       \
                                // .......\........ intersect
                                //         *
                                //         1
                                //      inside

                                enterEdge		= current;
                            }

                            prevDistance	= 0;
                            prev			= Edges[prev.NextIndex];
                            prevSide		= PlaneSideResult.Intersects;

                            if (exitEdge != null &&
                                enterEdge != null)
                                break;

                            current			= Edges[prev.NextIndex];
                            currentVertex	= Vertices[current.VertexIndex];

                            next			= Edges[current.NextIndex];
                            nextVertex		= Vertices[next.VertexIndex];
                        }
                    } else												// prev:??                - current:intersects - next:??
                    {
                        if (prevSide == PlaneSideResult.Intersects ||	// prev:intersects        - current:intersects - next:??
                            nextSide == PlaneSideResult.Intersects ||	// prev:??                - current:intersects - next:intersects
                            prevSide == nextSide)						// prev:inside/outde      - current:intersects - next:inside/outde
                        {
                            if (prevSide == PlaneSideResult.Inside ||	// prev:inside            - current:intersects - next:intersects/inside
                                nextSide == PlaneSideResult.Inside)		// prev:intersects/inside - current:intersects - next:inside
                            {
                                //      outside
                                // 0       1
                                // --------*....... intersect
                                //          \
                                //           2
                                //       inside
                                //
                                //      outside
                                //         1      2
                                // ........*------- intersect
                                //        /
                                //       0
                                //      inside
                                //
                                //     outside
                                //        1
                                //........*....... intersect
                                //       / \
                                //      0   2
                                //      inside
                                //

                                prevSide = PlaneSideResult.Inside;
                                enterEdge = exitEdge = null;
                                break;
                            } else
                            if (prevSide == PlaneSideResult.Outside ||		// prev:outside            - current:intersects - next:intersects/outside
                                nextSide == PlaneSideResult.Outside)		// prev:intersects/outside - current:intersects - next:outside
                            {
                                //     outside
                                //          2
                                //         /
                                //..------*....... intersect
                                //  0     1
                                //     inside
                                //
                                //     outside
                                //      0
                                //       \
                                //........*------- intersect
                                //        1      2
                                //     inside
                                //
                                //     outside
                                //      0   2
                                //       \ /
                                //........*....... intersect
                                //        1
                                //     inside
                                //

                                prevSide = PlaneSideResult.Outside;
                                enterEdge = exitEdge = null;
                                break;
                            }
                        } else											// prev:inside/outside - current:intersects - next:inside/outside
                        {
                            if (prevSide == PlaneSideResult.Inside)		// prev:inside         - current:intersects - next:outside
                            {
                                //find exit edge:
                                //
                                //      outside
                                //           2
                                //        1 /
                                // ........*....... intersect
                                //        /
                                //       0
                                //       inside

                                exitEdge = current;
                                if (enterEdge != null)
                                    break;
                            } else										// prev:outside        - current:intersects - next:inside
                            {
                                //find enter edge:
                                //
                                //      outside
                                //       0
                                //        \ 1
                                // ........*....... intersect
                                //          \
                                //           2
                                //       inside

                                enterEdge = current;
                                if (exitEdge != null)
                                    break;
                            }
                        }
                    }
                }

                prev	= current;
                current = next;
                next	= Edges[next.NextIndex];

                prevDistance	= currentDistance;
                currentDistance = nextDistance;
                prevSide		= currentSide;
                currentSide		= nextSide;
                prevVertex		= currentVertex;
                currentVertex	= nextVertex;
            } while (next != last);

            // We should never have only one edge crossing the plane ..
            //Debug.Assert((enterEdge == null) == (exitEdge == null));

            // Check if we have an edge that exits and an edge that enters the plane and split the polygon into two if we do
            if (enterEdge != null && exitEdge != null)
            {
                //enter   .
                //        .
                //  =====>*----->
                //        .
                //
                //outside . inside
                //        .
                //  <-----*<=====
                //        .
                //        .  exit

                outsidePolygon = new Polygon();
                var outsidePolygonIndex = (short)this.Polygons.Count;
                this.Polygons.Add(outsidePolygon);

                var outsideEdge			= new HalfEdge();
                var outsideEdgeIndex	= (short)Edges.Count;

                var insideEdge			= new HalfEdge();
                var insideEdgeIndex		= (short)(outsideEdgeIndex + 1);

                outsideEdge.TwinIndex		= insideEdgeIndex;
                insideEdge.TwinIndex		= outsideEdgeIndex;

                //insideEdge.PolygonIndex	= inputPolygonIndex;// index does not change
                outsideEdge.PolygonIndex	= outsidePolygonIndex;

                outsideEdge.VertexIndex		= exitEdge.VertexIndex;
                insideEdge.VertexIndex		= enterEdge.VertexIndex;

                outsideEdge.NextIndex		= exitEdge.NextIndex;
                insideEdge.NextIndex		= enterEdge.NextIndex;

                exitEdge.NextIndex			= insideEdgeIndex;
                enterEdge.NextIndex			= outsideEdgeIndex;

                outsidePolygon.FirstIndex	= outsideEdgeIndex;
                inputPolygon.FirstIndex		= insideEdgeIndex;

                outsidePolygon.Visible		= inputPolygon.Visible;
                outsidePolygon.Category		= inputPolygon.Category;
                outsidePolygon.PlaneIndex	= inputPolygon.PlaneIndex;

                Edges.Add(outsideEdge);
                Edges.Add(insideEdge);

                // calculate the bounds of the polygons
                outsidePolygon.Bounds.Clear();
                var first = Edges[outsidePolygon.FirstIndex];
                var iterator = first;
                do
                {
                    outsidePolygon.Bounds.Add(Vertices[iterator.VertexIndex]);
                    iterator.PolygonIndex = outsidePolygonIndex;
                    iterator = Edges[iterator.NextIndex];
                } while (iterator != first);

                inputPolygon.Bounds.Clear();
                first = Edges[inputPolygon.FirstIndex];
                iterator = first;
                do
                {
                    inputPolygon.Bounds.Add(Vertices[iterator.VertexIndex]);
                    iterator = Edges[iterator.NextIndex];
                } while (iterator != first);

                return PolygonSplitResult.Split;
            } else
            {
                outsidePolygon = null;
                switch (prevSide)
                {
                    case PlaneSideResult.Inside:	return PolygonSplitResult.CompletelyInside;
                    case PlaneSideResult.Outside:	return PolygonSplitResult.CompletelyOutside;
                    default:
                    case PlaneSideResult.Intersects:
                    {
                        var polygonPlane = Planes[inputPolygon.PlaneIndex];
                        var result = Vector3.DotProduct(polygonPlane.Normal, cuttingPlane.Normal);
                        if (result > 0)
                            return PolygonSplitResult.PlaneAligned;
                        else
                            return PolygonSplitResult.PlaneOppositeAligned;
                    }
                }
            }
        }
コード例 #4
0
ファイル: CSGMesh.cs プロジェクト: Blecki/GemgineCore
        public void Intersect(AABB		cuttingNodeBounds,
							  Plane[]	cuttingNodePlanes,
							  Vector3	cuttingNodeTranslation,
							  Vector3	inputPolygonTranslation,

							  List<Polygon> inputPolygons,

							  List<Polygon> inside,
							  List<Polygon> aligned,
							  List<Polygon> revAligned,
							  List<Polygon> outside)
        {
            var categories			= new PolygonSplitResult[cuttingNodePlanes.Length];
            var translatedPlanes	= new Plane[cuttingNodePlanes.Length];
            var translation			= Vector3.Subtract(cuttingNodeTranslation, inputPolygonTranslation);

            // translate the planes we cut our polygons with so that they're located at the same
            // relative distance from the polygons as the brushes are from each other.
            for (int i = 0; i < cuttingNodePlanes.Length; i++)
                translatedPlanes[i] = Plane.Translated(cuttingNodePlanes[i], translation);

            var vertices = this.Vertices;
            var edges = this.Edges;
            var planes = this.Planes;
            for (int i = inputPolygons.Count - 1; i >= 0; i--)
            {
                var inputPolygon = inputPolygons[i];
                if (inputPolygon.FirstIndex == -1)
                    continue;

                var bounds		= inputPolygon.Bounds;
                var finalResult = PolygonSplitResult.CompletelyInside;

                // A quick check if the polygon lies outside the planes we're cutting our polygons with.
                if (!AABB.IsOutside(cuttingNodeBounds, translation, bounds))
                {
                    PolygonSplitResult	intermediateResult;
                    Polygon				outsidePolygon = null;
                    for (int otherIndex = 0; otherIndex < translatedPlanes.Length; otherIndex++)
                    {
                        var translatedCuttingPlane = translatedPlanes[otherIndex];

                        var side = cuttingNodePlanes[otherIndex].OnSide(bounds, translation.Negated());
                        if (side == PlaneSideResult.Outside)
                        {
                            finalResult = PolygonSplitResult.CompletelyOutside;
                            break;	// nothing left to process, so we exit
                        } else
                        if (side == PlaneSideResult.Inside)
                            continue;

                        var polygon = inputPolygon;
                        intermediateResult = PolygonSplit(translatedCuttingPlane, inputPolygonTranslation, ref polygon, out outsidePolygon);
                        inputPolygon = polygon;

                        if (intermediateResult == PolygonSplitResult.CompletelyOutside)
                        {
                            finalResult = PolygonSplitResult.CompletelyOutside;
                            break;	// nothing left to process, so we exit
                        } else
                        if (intermediateResult == PolygonSplitResult.Split)
                        {
                            if (outside != null)
                                outside.Add(outsidePolygon);
                            // Note: left over is still completely inside,
                            //		 or plane (opposite) aligned
                        } else
                        if (intermediateResult != PolygonSplitResult.CompletelyInside)
                            finalResult = intermediateResult;
                    }
                } else
                    finalResult = PolygonSplitResult.CompletelyOutside;

                switch (finalResult)
                {
                    case PolygonSplitResult.CompletelyInside:		inside .Add(inputPolygon); break;
                    case PolygonSplitResult.CompletelyOutside:		outside.Add(inputPolygon); break;

                    // The polygon can only be visible if it's part of the last brush that shares it's surface area,
                    // otherwise we'd get overlapping polygons if two brushes overlap.
                    // When the (final) polygon is aligned with one of the cutting planes, we know it lies on the surface of
                    // the CSG node we're cutting the polygons with. We also know that this node is not the node this polygon belongs to
                    // because we've done that check earlier on. So we flag this polygon as being invisible.
                    case PolygonSplitResult.PlaneAligned:			inputPolygon.Visible = false; aligned   .Add(inputPolygon); break;
                    case PolygonSplitResult.PlaneOppositeAligned:	inputPolygon.Visible = false; revAligned.Add(inputPolygon); break;
                }
            }
        }
コード例 #5
0
ファイル: CSGMesh.cs プロジェクト: Blecki/GemgineCore
        public CSGMesh Clone()
        {
            var newPlanes = new Plane[Planes.Length];
            for (int i = 0; i < Planes.Length; i++)
            {
                var plane = Planes[i];
                newPlanes[i] = new Plane(plane.A, plane.B, plane.C, plane.D);
            }
            var newPolygons = new List<Polygon>(Polygons.Count);
            foreach (var polygon in Polygons)
            {
                var newPolygon = new Polygon();
                newPolygon.FirstIndex = polygon.FirstIndex;
                newPolygon.Visible = polygon.Visible;
                newPolygon.Category = polygon.Category;
                newPolygon.PlaneIndex = polygon.PlaneIndex;
                newPolygon.Bounds.Set(polygon.Bounds);

                newPolygons.Add(newPolygon);
            }

            var newEdges = new List<HalfEdge>(Edges.Count);
            foreach (var edge in Edges)
            {
                var newEdge = new HalfEdge();
                newEdge.NextIndex = edge.NextIndex;
                newEdge.PolygonIndex = edge.PolygonIndex;
                newEdge.TwinIndex = edge.TwinIndex;
                newEdge.VertexIndex = edge.VertexIndex;
                newEdges.Add(newEdge);
            }

            var newVertices = new List<Vector3>(Vertices.Count);
            foreach (var vertex in Vertices)
            {
                var newVertex = new Vector3(vertex.X, vertex.Y, vertex.Z);
                newVertices.Add(newVertex);
            }

            var newBounds = new AABB(Bounds);
            var newMesh = new CSGMesh(
                newPlanes,
                newPolygons,
                newEdges,
                newVertices,
                newBounds);

            return newMesh;
        }
コード例 #6
0
ファイル: CSGMesh.cs プロジェクト: Blecki/GemgineCore
        public static CSGMesh CreateFromPlanes(Plane[] brushPlanes)
        {
            var planes = new Plane[brushPlanes.Length];
            for (int i = 0; i < brushPlanes.Length; i++)
            {
                var plane = brushPlanes[i];
                planes[i] = new Plane(plane.A, plane.B, plane.C, plane.D);
            }

            var pointIntersections = new List<PointIntersection>(planes.Length * planes.Length);
            var intersectingPlanes = new List<short>();
            var vertices = new List<Vector3>();
            var edges = new List<HalfEdge>();

            // Find all point intersections where 3 (or more planes) intersect
            for (short planeIndex1 = 0; planeIndex1 < planes.Length - 2; planeIndex1++)
            {
                var plane1 = planes[planeIndex1];
                for (short planeIndex2 = (short)(planeIndex1 + 1); planeIndex2 < planes.Length - 1; planeIndex2++)
                {
                    var plane2 = planes[planeIndex2];
                    for (short planeIndex3 = (short)(planeIndex2 + 1); planeIndex3 < planes.Length; planeIndex3++)
                    {
                        var plane3 = planes[planeIndex3];

                        // Calculate the intersection
                        var vertex = Plane.Intersection(plane1, plane2, plane3);

                        // Check if the intersection is valid
                        if (float.IsNaN(vertex.X) || float.IsNaN(vertex.Y) || float.IsNaN(vertex.Z) ||
                            float.IsInfinity(vertex.X) || float.IsInfinity(vertex.Y) || float.IsInfinity(vertex.Z))
                            continue;

                        intersectingPlanes.Clear();
                        intersectingPlanes.Add(planeIndex1);
                        intersectingPlanes.Add(planeIndex2);
                        intersectingPlanes.Add(planeIndex3);

                        for (short planeIndex4 = 0; planeIndex4 < planes.Length; planeIndex4++)
                        {
                            if (planeIndex4 == planeIndex1 ||
                                planeIndex4 == planeIndex2 ||
                                planeIndex4 == planeIndex3)
                                continue;

                            var plane4 = planes[planeIndex4];
                            var side = plane4.OnSide(vertex);
                            if (side == PlaneSideResult.Intersects)
                            {
                                if (planeIndex4 < planeIndex3)
                                    // Already found this vertex
                                    goto SkipIntersection;

                                // We've found another plane which goes trough our found intersection point
                                intersectingPlanes.Add(planeIndex4);
                            }
                            else
                                if (side == PlaneSideResult.Outside)
                                    // Intersection is outside of brush
                                    goto SkipIntersection;
                        }

                        var vertexIndex = (short)vertices.Count;
                        vertices.Add(vertex);

                        // Add intersection point to our list
                        pointIntersections.Add(new PointIntersection(vertexIndex, intersectingPlanes));

                    SkipIntersection:
                        ;
                    }
                }
            }

            var foundPlanes = new short[2];
            // Find all our intersection edges which are formed by a pair of planes
            // (this could probably be done inside the previous loop)
            for (int i = 0; i < pointIntersections.Count; i++)
            {
                var pointIntersectionA = pointIntersections[i];
                for (int j = i + 1; j < pointIntersections.Count; j++)
                {
                    var pointIntersectionB = pointIntersections[j];
                    var planesIndicesA = pointIntersectionA.PlaneIndices;
                    var planesIndicesB = pointIntersectionB.PlaneIndices;

                    short foundPlaneIndex = 0;
                    foreach (var currentPlaneIndex in planesIndicesA)
                    {
                        if (!planesIndicesB.Contains(currentPlaneIndex))
                            continue;

                        foundPlanes[foundPlaneIndex] = currentPlaneIndex;
                        foundPlaneIndex++;

                        if (foundPlaneIndex == 2)
                            break;
                    }

                    // If foundPlaneIndex is 0 or 1 then either this combination does not exist,
                    // or only goes trough one point
                    if (foundPlaneIndex < 2)
                        continue;

                    // Create our found intersection edge
                    var halfEdgeA = new HalfEdge();
                    var halfEdgeAIndex = (short)edges.Count;
                    edges.Add(halfEdgeA);

                    var halfEdgeB = new HalfEdge();
                    var halfEdgeBIndex = (short)edges.Count;
                    edges.Add(halfEdgeB);

                    halfEdgeA.TwinIndex = halfEdgeBIndex;
                    halfEdgeB.TwinIndex = halfEdgeAIndex;

                    halfEdgeA.VertexIndex = pointIntersectionA.VertexIndex;
                    halfEdgeB.VertexIndex = pointIntersectionB.VertexIndex;

                    // Add it to our points
                    pointIntersectionA.Edges.Add(new EdgeIntersection(
                                                        halfEdgeA,
                                                        foundPlanes[0],
                                                        foundPlanes[1]));
                    pointIntersectionB.Edges.Add(new EdgeIntersection(
                                                        halfEdgeB,
                                                        foundPlanes[0],
                                                        foundPlanes[1]));
                }
            }

            var polygons = new List<Polygon>();
            for (short i = 0; i < (short)planes.Length; i++)
            {
                var polygon = new Polygon();
                polygon.PlaneIndex = i;
                polygons.Add(polygon);
            }

            var bounds = new AABB();
            var direction = new Vector3();
            for (int i = pointIntersections.Count - 1; i >= 0; i--)
            {
                var pointIntersection = pointIntersections[i];
                var pointEdges = pointIntersection.Edges;

                // Make sure that we have at least 2 edges ...
                // This may happen when a plane only intersects at a single edge.
                if (pointEdges.Count <= 2)
                {
                    pointIntersections.RemoveAt(i);
                    continue;
                }

                var vertexIndex = pointIntersection.VertexIndex;
                var vertex = vertices[vertexIndex];

                for (int j = 0; j < pointEdges.Count - 1; j++)
                {
                    var edge1 = pointEdges[j];
                    for (int k = j + 1; k < pointEdges.Count; k++)
                    {
                        var edge2 = pointEdges[k];

                        int planeIndex1 = -1;
                        int planeIndex2 = -1;

                        // Determine if and which of our 2 planes are identical
                        if (edge1.PlaneIndices[0] == edge2.PlaneIndices[0]) { planeIndex1 = 0; planeIndex2 = 0; }
                        else
                            if (edge1.PlaneIndices[0] == edge2.PlaneIndices[1]) { planeIndex1 = 0; planeIndex2 = 1; }
                            else
                                if (edge1.PlaneIndices[1] == edge2.PlaneIndices[0]) { planeIndex1 = 1; planeIndex2 = 0; }
                                else
                                    if (edge1.PlaneIndices[1] == edge2.PlaneIndices[1]) { planeIndex1 = 1; planeIndex2 = 1; }
                                    else
                                        continue;

                        HalfEdge ingoing;
                        HalfEdge outgoing;
                        short outgoingIndex;

                        var shared_plane = planes[edge1.PlaneIndices[planeIndex1]];
                        var edge1_plane = planes[edge1.PlaneIndices[1 - planeIndex1]];
                        var edge2_plane = planes[edge2.PlaneIndices[1 - planeIndex2]];

                        direction = Vector3.CrossProduct(shared_plane.Normal, edge1_plane.Normal);

                        // Determine the orientation of our two edges to determine
                        // which edge is in-going, and which one is out-going
                        if (Vector3.DotProduct(direction, edge2_plane.Normal) < 0)
                        {
                            ingoing = edge2.Edge;
                            outgoingIndex = edge1.Edge.TwinIndex;
                            outgoing = edges[outgoingIndex];
                        }
                        else
                        {
                            ingoing = edge1.Edge;
                            outgoingIndex = edge2.Edge.TwinIndex;
                            outgoing = edges[outgoingIndex];
                        }

                        // Link the out-going half-edge to the in-going half-edge
                        ingoing.NextIndex = outgoingIndex;

                        // Add reference to polygon to half-edge, and make sure our
                        // polygon has a reference to a half-edge
                        // Since a half-edge, in this case, serves as a circular
                        // linked list this just works.
                        var polygonIndex = edge1.PlaneIndices[planeIndex1];

                        ingoing.PolygonIndex = polygonIndex;
                        outgoing.PolygonIndex = polygonIndex;

                        var polygon = polygons[polygonIndex];
                        polygon.FirstIndex = outgoingIndex;
                        polygon.Bounds.Add(vertex);
                    }
                }

                // Add the intersection point to the area of our bounding box
                bounds.Add(vertex);
            }

            return new CSGMesh(planes, polygons, edges, vertices, bounds);
        }
コード例 #7
0
ファイル: Plane.cs プロジェクト: Blecki/GemgineCore
 public bool Equals(Plane other)
 {
     if (Object.ReferenceEquals(this, other))
         return true;
     if (Object.ReferenceEquals(other, null))
         return false;
     return D == other.D &&
             A == other.A &&
             B == other.B &&
             C == other.C;
 }
コード例 #8
0
ファイル: Plane.cs プロジェクト: Blecki/GemgineCore
 public bool EpsilonEquals(Plane other)
 {
     var epsilon = 0.001f;
     return D > other.D - epsilon && D < other.D + epsilon &&
         A > other.A - epsilon && A < other.A + epsilon &&
         B > other.B - epsilon && B < other.B + epsilon &&
         C > other.C - epsilon && C < other.C + epsilon;
 }
コード例 #9
0
ファイル: Plane.cs プロジェクト: Blecki/GemgineCore
 public static Plane Translated(Plane plane, float translateX, float translateY, float translateZ)
 {
     return new Plane(plane.A, plane.B, plane.C,
         // translated offset = plane.Normal.Dotproduct(translation)
         // normal = A,B,C
                      plane.D + (plane.A * translateX) +
                                (plane.B * translateY) +
                                (plane.C * translateZ));
 }
コード例 #10
0
ファイル: Plane.cs プロジェクト: Blecki/GemgineCore
 public static Plane Translated(Plane plane, Vector3 translation)
 {
     return new Plane(plane.A, plane.B, plane.C,
         // translated offset = plane.Normal.Dotproduct(translation)
         // normal = A,B,C
                      plane.D + (plane.A * translation.X) +
                                (plane.B * translation.Y) +
                                (plane.C * translation.Z));
 }
コード例 #11
0
ファイル: Plane.cs プロジェクト: Blecki/GemgineCore
        public static Vector3 Intersection(Plane inPlane1,
										   Plane inPlane2,
										   Plane inPlane3)
        {
            // intersection point with 3 planes
            //  {
            //      x = -( c2*b1*d3-c2*b3*d1+b3*c1*d2+c3*b2*d1-b1*c3*d2-c1*b2*d3)/
            //           (-c2*b3*a1+c3*b2*a1-b1*c3*a2-c1*b2*a3+b3*c1*a2+c2*b1*a3),
            //      y =  ( c3*a2*d1-c3*a1*d2-c2*a3*d1+d2*c1*a3-a2*c1*d3+c2*d3*a1)/
            //           (-c2*b3*a1+c3*b2*a1-b1*c3*a2-c1*b2*a3+b3*c1*a2+c2*b1*a3),
            //      z = -(-a2*b1*d3+a2*b3*d1-a3*b2*d1+d3*b2*a1-d2*b3*a1+d2*b1*a3)/
            //           (-c2*b3*a1+c3*b2*a1-b1*c3*a2-c1*b2*a3+b3*c1*a2+c2*b1*a3)
            //  }

            double bc1 = (inPlane1.B * inPlane3.C) - (inPlane3.B * inPlane1.C);
            double bc2 = (inPlane2.B * inPlane1.C) - (inPlane1.B * inPlane2.C);
            double bc3 = (inPlane3.B * inPlane2.C) - (inPlane2.B * inPlane3.C);

            double ad1 = (inPlane1.A * inPlane3.D) - (inPlane3.A * inPlane1.D);
            double ad2 = (inPlane2.A * inPlane1.D) - (inPlane1.A * inPlane2.D);
            double ad3 = (inPlane3.A * inPlane2.D) - (inPlane2.A * inPlane3.D);

            double x = -((inPlane1.D * bc3) + (inPlane2.D * bc1) + (inPlane3.D * bc2));
            double y = -((inPlane1.C * ad3) + (inPlane2.C * ad1) + (inPlane3.C * ad2));
            double z = +((inPlane1.B * ad3) + (inPlane2.B * ad1) + (inPlane3.B * ad2));
            double w = -((inPlane1.A * bc3) + (inPlane2.A * bc1) + (inPlane3.A * bc2));

            // better to have detectable invalid values than to have reaaaaaaally big values
            if (w > -Constants.NormalEpsilon && w < Constants.NormalEpsilon)
            {
                return new Vector3(float.NaN,
                                   float.NaN,
                                   float.NaN);
            }
            else
                return new Vector3((float)(x / w),
                                   (float)(y / w),
                                   (float)(z / w));
        }
コード例 #12
0
ファイル: BrushGenerator.cs プロジェクト: Blecki/GemgineCore
 public StaticBrushGenerator(Plane[] planes)
 {
     this.Planes = planes;
 }