Beispiel #1
0
        // Trim Edges
        static void RefineEdges(ref NativeArray <int4> refinedEdges, ref NativeArray <int4> delaEdges, ref int delaEdgeCount, ref NativeArray <int4> voronoiEdges)
        {
            int origEdgeCount = delaEdgeCount;

            delaEdgeCount = 0;

            // Check Neighbour Triangles.
            for (int i = 0; i < origEdgeCount - 1; ++i)
            {
                var edge     = delaEdges[i];
                var neighbor = delaEdges[i + 1];
                if (edge.x == neighbor.x && edge.y == neighbor.y)
                {
                    // Found the Opposite Edge. i.e Nearby Triangle.
                    edge.w = neighbor.z;
                    ++i;
                }
                // Update new list.
                refinedEdges[delaEdgeCount++] = edge;
            }

            // Generate Voronoi Edges.
            for (int i = 0; i < delaEdgeCount; ++i)
            {
                var ti1 = refinedEdges[i].z;
                var ti2 = refinedEdges[i].w;

                // We only really care about Bounded Edges. This is simplification. Hoping this garbage works.
                if (ti1 != -1 && ti2 != -1)
                {
                    // Get Triangles
                    int4 e = new int4(ti2, ti1, i, 0);
                    voronoiEdges[i] = e;
                }
            }

            ModuleHandle.Copy(refinedEdges, delaEdges, delaEdgeCount);
        }
Beispiel #2
0
        public static float4 Tessellate(Allocator allocator, NativeArray <float2> points, NativeArray <int2> edges, ref NativeArray <float2> outVertices, ref int outVertexCount, ref NativeArray <int> outIndices, ref int outIndexCount, ref NativeArray <int2> outEdges, ref int outEdgeCount)
        {
            // Inputs are garbage, just early out.
            float4 ret = float4.zero;

            outEdgeCount = 0; outIndexCount = 0; outVertexCount = 0;
            if (points.Length < 3 || points.Length >= kMaxVertexCount)
            {
                return(ret);
            }

            // Ensure inputs form a proper PlanarGraph.
            bool validGraph = false, handleEdgeCase = false;
            int  pgEdgeCount = 0, pgPointCount = 0;
            NativeArray <int2>   pgEdges  = new NativeArray <int2>(kMaxEdgeCount, allocator);
            NativeArray <float2> pgPoints = new NativeArray <float2>(kMaxVertexCount, allocator);

            // Valid Edges and Paths, correct the Planar Graph. If invalid create a simple convex hull rect.
            if (0 != edges.Length)
            {
                validGraph = PlanarGraph.Validate(allocator, points, points.Length, edges, edges.Length, ref pgPoints, ref pgPointCount, ref pgEdges, ref pgEdgeCount);
            }


// Fallbacks are now handled by the Higher level packages. Enable if UTess needs to handle it.
// #if UTESS_QUAD_FALLBACK
//             if (!validGraph)
//             {
//                 pgPointCount = 0;
//                 handleEdgeCase = true;
//                 ModuleHandle.Copy(points, pgPoints, points.Length);
//                 GraphConditioner(points, ref pgPoints, ref pgPointCount, ref pgEdges, ref pgEdgeCount, false);
//             }
// #else

// If its not a valid Graph simply return back input Data without triangulation instead of going through UTess (pointless wasted cpu cycles).
            if (!validGraph)
            {
                outEdgeCount   = edges.Length;
                outVertexCount = points.Length;
                ModuleHandle.Copy(edges, outEdges, edges.Length);
                ModuleHandle.Copy(points, outVertices, points.Length);
            }

            // Do a proper Delaunay Triangulation if Inputs are valid.
            if (pgPointCount > 2 && pgEdgeCount > 2)
            {
                int tsIndexCount = 0, tsVertexCount = 0;
                NativeArray <int>    tsIndices = new NativeArray <int>(kMaxIndexCount, allocator);
                NativeArray <float2> tsVertices = new NativeArray <float2>(kMaxVertexCount, allocator);
                validGraph = Tessellator.Tessellate(allocator, pgPoints, pgPointCount, pgEdges, pgEdgeCount, ref tsVertices, ref tsVertexCount, ref tsIndices, ref tsIndexCount);
                if (validGraph)
                {
                    // Copy Out
                    TransferOutput(pgEdges, pgEdgeCount, ref outEdges, ref outEdgeCount, tsIndices, tsIndexCount, ref outIndices, ref outIndexCount, tsVertices, tsVertexCount, ref outVertices, ref outVertexCount);
                    if (handleEdgeCase == true)
                    {
                        outEdgeCount = 0;
                    }
                }
                tsVertices.Dispose();
                tsIndices.Dispose();
            }

            // Dispose Temp Memory.
            pgPoints.Dispose();
            pgEdges.Dispose();
            return(ret);
        }
Beispiel #3
0
        // Validate the Input Points ane Edges.
        internal static bool Validate(Allocator allocator, NativeArray <float2> inputPoints, int pointCount, NativeArray <int2> inputEdges, int edgeCount, ref NativeArray <float2> outputPoints, ref int outputPointCount, ref NativeArray <int2> outputEdges, ref int outputEdgeCount)
        {
            var protectLoop = edgeCount;
            var requiresFix = true;
            var validGraph  = false;

            // Processing Arrays.
            NativeArray <int2>    edges             = new NativeArray <int2>(ModuleHandle.kMaxEdgeCount, allocator);
            NativeArray <double2> points            = new NativeArray <double2>(ModuleHandle.kMaxVertexCount, allocator);
            NativeArray <int2>    tJunctions        = new NativeArray <int2>(ModuleHandle.kMaxEdgeCount, allocator);
            NativeArray <int2>    edgeIntersections = new NativeArray <int2>(ModuleHandle.kMaxEdgeCount, allocator);
            NativeArray <int>     duplicates        = new NativeArray <int>(ModuleHandle.kMaxVertexCount, allocator);
            NativeArray <double2> intersects        = new NativeArray <double2>(ModuleHandle.kMaxEdgeCount, allocator);

            // Initialize.
            for (int i = 0; i < pointCount; ++i)
            {
                points[i] = inputPoints[i];
            }
            ModuleHandle.Copy(inputEdges, edges, edgeCount);

            // Pre-clear duplicates, otherwise the following will simply fail.
            RemoveDuplicateEdges(ref edges, ref edgeCount, duplicates, 0);

            // While PSG is clean.
            while (requiresFix && --protectLoop > 0)
            {
                // Edge Edge Intersection.
                int intersectionCount = 0;
                validGraph = CalculateEdgeIntersections(edges, edgeCount, points, pointCount, ref edgeIntersections, ref intersects, ref intersectionCount);
                if (!validGraph)
                {
                    break;
                }

                // Edge Point Intersection. T-Junction.
                int tJunctionCount = 0;
                validGraph = CalculateTJunctions(edges, edgeCount, points, pointCount, tJunctions, ref tJunctionCount);
                if (!validGraph)
                {
                    break;
                }

                // Cut Overlapping Edges.
                validGraph = CutEdges(ref points, ref pointCount, ref edges, ref edgeCount, ref tJunctions, ref tJunctionCount, edgeIntersections, intersects, intersectionCount);
                if (!validGraph)
                {
                    break;
                }

                // Remove Duplicate Points.
                int duplicateCount = 0;
                RemoveDuplicatePoints(ref points, ref pointCount, ref duplicates, ref duplicateCount, allocator);
                RemoveDuplicateEdges(ref edges, ref edgeCount, duplicates, duplicateCount);

                requiresFix = intersectionCount != 0 || tJunctionCount != 0;
            }

            if (validGraph)
            {
                // Finalize Output.
                outputEdgeCount  = edgeCount;
                outputPointCount = pointCount;
                ModuleHandle.Copy(edges, outputEdges, edgeCount);
                for (int i = 0; i < pointCount; ++i)
                {
                    outputPoints[i] = new float2((float)points[i].x, (float)points[i].y);
                }
            }

            edges.Dispose();
            points.Dispose();
            intersects.Dispose();
            duplicates.Dispose();
            tJunctions.Dispose();
            edgeIntersections.Dispose();

            return(validGraph && protectLoop > 0);
        }