public LoopIterator(MyPolygon poly, int loopBegin) { m_data = poly.m_vertices; m_begin = loopBegin; m_currentIndex = -1; m_current = new Vertex(); m_current.Next = m_begin; }
public BoundPair(MyPolygon parent, int left, int minimum, int right, bool rightHorizontal) { Debug.Assert(parent != null); Parent = parent; Left = left; Minimum = minimum; Right = right; RightIsPrecededByHorizontal = rightHorizontal; m_minimumCoordinate = 0; }
private void PrepareTransforms(MyPolygon polyA) { m_projectionPlane = polyA.PolygonPlane; Vector3 origin = -polyA.PolygonPlane.Normal * polyA.PolygonPlane.D; Vector3 forward = polyA.PolygonPlane.Normal; Vector3 right = Vector3.CalculatePerpendicularVector(forward); Vector3 up = Vector3.Cross(right, forward); m_invProjectionTransform = Matrix.CreateWorld(origin, forward, up); Matrix.Invert(ref m_invProjectionTransform, out m_projectionTransform); }
private void ProjectPoly(MyPolygon input, MyPolygon output, ref Matrix projection) { for (int i = 0; i < input.LoopCount; ++i) { m_tmpList.Clear(); var iterator = input.GetLoopIterator(i); while (iterator.MoveNext()) { Vector3 transformed = Vector3.Transform(iterator.Current, projection); m_tmpList.Add(transformed); } output.AddLoop(m_tmpList); } }
public MyPolygon Difference(MyPolygon polyA, MyPolygon polyB) { return PerformBooleanOperation(polyA, polyB, m_operationDifference); }
private MyPolygon PerformBooleanOperation(MyPolygon polyA, MyPolygon polyB, Operation operation) { Debug.Assert(polyA.PolygonPlane.Equals(polyB.PolygonPlane)); Clear(); PrepareTransforms(polyA); ProjectPoly(polyA, m_polyA, ref m_projectionTransform); ProjectPoly(polyB, m_polyB, ref m_projectionTransform); m_operation = operation; PerformInPlane(); m_operation = null; return UnprojectResult(); }
private static MatrixD DebugDrawBoundList(MatrixD drawMatrix, MyPolygon drawPoly, List<BoundPair> boundList) { foreach (var bound in boundList) { MyPolygon.Vertex v1, v2; Vector3 vec1 = default(Vector3); Vector3 vec2 = default(Vector3); int prev = bound.Left; drawPoly.GetVertex(prev, out v1); int current = v1.Prev; while (prev != bound.Minimum) { drawPoly.GetVertex(current, out v2); vec1 = Vector3.Transform(v1.Coord, drawMatrix); vec2 = Vector3.Transform(v2.Coord, drawMatrix); MyRenderProxy.DebugDrawLine3D(vec1, vec2, Color.Red, Color.Red, false); prev = current; v1 = v2; current = v1.Prev; } MatrixD minimum = drawMatrix; minimum.Translation = vec2; MyRenderProxy.DebugDrawAxis(minimum, 0.25f, false); MyRenderProxy.DebugDrawSphere(vec2, 0.03f, Color.Yellow, 1.0f, false); prev = bound.Minimum; drawPoly.GetVertex(prev, out v1); current = v1.Prev; while (prev != bound.Right) { drawPoly.GetVertex(current, out v2); vec1 = Vector3.Transform(v1.Coord, drawMatrix); vec2 = Vector3.Transform(v2.Coord, drawMatrix); MyRenderProxy.DebugDrawLine3D(vec1, vec2, Color.Green, Color.Green, false); prev = current; v1 = v2; current = v1.Prev; } if (bound.RightIsPrecededByHorizontal) { MyRenderProxy.DebugDrawSphere(vec2, 0.03f, Color.Red, 1.0f, false); } } return drawMatrix; }
public MyPolygon Union(MyPolygon polyA, MyPolygon polyB) { return PerformBooleanOperation(polyA, polyB, m_operationUnion); }
private MyPolygon UnprojectResult() { MyPolygon tmp = new MyPolygon(new Plane(Vector3.Forward, 0)); MyPolygon result = new MyPolygon(m_projectionPlane); foreach (var poly in m_results) { poly.Postprocess(); var loop = poly.GetLoop(); if (loop.Count == 0) continue; tmp.AddLoop(poly.GetLoop()); } ProjectPoly(tmp, result, ref m_invProjectionTransform); return result; }
private static int FindLoopLocalMaximum(MyPolygon poly, int loop) { int index, maxIndex; Vector3 localMax; MyPolygon.Vertex vertex, otherVertex; index = poly.GetLoopStart(loop); poly.GetVertex(index, out vertex); maxIndex = index; localMax = vertex.Coord; // Find local maximum while going to the previous vertices in the loop index = vertex.Prev; poly.GetVertex(index, out otherVertex); while (otherVertex.Coord.Y > localMax.Y || (otherVertex.Coord.Y == localMax.Y && otherVertex.Coord.X > localMax.X)) { maxIndex = index; localMax = otherVertex.Coord; index = otherVertex.Prev; poly.GetVertex(index, out otherVertex); } // Find local maximum while going to the next vertices in the loop index = vertex.Next; poly.GetVertex(index, out otherVertex); while (otherVertex.Coord.Y > localMax.Y || (otherVertex.Coord.Y == localMax.Y && otherVertex.Coord.X > localMax.X)) { maxIndex = index; localMax = otherVertex.Coord; index = otherVertex.Next; poly.GetVertex(index, out otherVertex); } return maxIndex; }
private static void ConstructBoundPairs(MyPolygon poly, List<BoundPair> boundList) { for (int l = 0; l < poly.LoopCount; ++l) { int start, current, prev; MyPolygon.Vertex vertex; start = FindLoopLocalMaximum(poly, l); poly.GetVertex(start, out vertex); current = start; MyPolygon.Vertex otherVertex; poly.GetVertex(vertex.Prev, out otherVertex); BoundPair bounds = new BoundPair(poly, -1, -1, start, otherVertex.Coord.Y == vertex.Coord.Y); bool right = true; int comparison, prevComparison; comparison = -1; do { Vector3 prevCoord = vertex.Coord; prev = current; current = vertex.Next; poly.GetVertex(current, out vertex); prevComparison = comparison; comparison = CompareCoords(vertex.Coord, prevCoord); Debug.Assert(comparison != 0, "Duplicate vertex in input polygon!"); if (right) { if (comparison > 0) { bounds.Minimum = prev; right = false; } } else { if (comparison < 0) { bounds.Left = prev; Debug.Assert(bounds.IsValid()); boundList.Add(bounds); bounds = new BoundPair(poly, -1, -1, prev, prevComparison == 0); right = true; } } } while (current != start); bounds.Left = current; Debug.Assert(right == false); Debug.Assert(bounds.IsValid()); boundList.Add(bounds); } }
private void RecalculateActiveEdge(ref Edge edge, ref MyPolygon.Vertex lowerVertex, ref MyPolygon.Vertex upperVertex, Side boundPairSide) { float Dy = upperVertex.Coord.Y - lowerVertex.Coord.Y; float Dx = upperVertex.Coord.X - lowerVertex.Coord.X; Debug.Assert(Dx != 0.0f || Dy != 0.0f, "Invalid polygon! Right point and minimum of a bound were the same point!"); edge.TopVertexIndex = boundPairSide == Side.LEFT ? lowerVertex.Next : lowerVertex.Prev; edge.BottomX = lowerVertex.Coord.X; edge.TopY = upperVertex.Coord.Y; edge.DXdy = Dy == 0 ? Dx : Dx / Dy; InsertScanBeamDivide(upperVertex.Coord.Y); }
private Edge PrepareActiveEdge(int boundPairIndex, ref MyPolygon.Vertex lowerVertex, ref MyPolygon.Vertex upperVertex, PolygonType polyType, Side side) { Edge newEdge = new Edge(); newEdge.BoundPairIndex = boundPairIndex; newEdge.BoundPairSide = side; newEdge.Kind = polyType; if (polyType == PolygonType.CLIP) { newEdge.OutputSide = m_operation.ClipInvert ? OtherSide(side) : side; } else { newEdge.OutputSide = m_operation.SubjectInvert ? OtherSide(side) : side; } RecalculateActiveEdge(ref newEdge, ref lowerVertex, ref upperVertex, side); return newEdge; }