Exemple #1
0
        public static float4 Subdivide(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, float areaFactor, float targetArea, int refineIterations, int smoothenIterations)
        {
            // Inputs are garbage, just early out.
            float4 ret = float4.zero;

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

            // Do a proper Delaunay Triangulation.
            int tsIndexCount = 0, tsVertexCount = 0;
            NativeArray <int>    tsIndices  = new NativeArray <int>(kMaxIndexCount, allocator);
            NativeArray <float2> tsVertices = new NativeArray <float2>(kMaxVertexCount, allocator);
            var validGraph = Tessellator.Tessellate(allocator, points, points.Length, edges, edges.Length, ref tsVertices, ref tsVertexCount, ref tsIndices, ref tsIndexCount);

            // Refinement and Smoothing.
            bool refined            = false;
            bool refinementRequired = (targetArea != 0 || areaFactor != 0);

            if (validGraph && refinementRequired)
            {
                // Do Refinement until success.
                float maxArea = 0;
                float incArea = 0;
                int   rfEdgeCount = 0, rfPointCount = 0, rfIndexCount = 0, rfVertexCount = 0;
                NativeArray <int2>   rfEdges    = new NativeArray <int2>(kMaxEdgeCount, allocator);
                NativeArray <float2> rfPoints   = new NativeArray <float2>(kMaxVertexCount, allocator);
                NativeArray <int>    rfIndices  = new NativeArray <int>(kMaxIndexCount, allocator);
                NativeArray <float2> rfVertices = new NativeArray <float2>(kMaxVertexCount, allocator);
                ret.x            = 0;
                refineIterations = Math.Min(refineIterations, kMaxRefineIterations);

                if (targetArea != 0)
                {
                    // Increment for Iterations.
                    incArea = (targetArea / 10);

                    while (targetArea < kMaxArea && refineIterations > 0)
                    {
                        // Do Mesh Refinement.
                        CopyGraph(points, points.Length, ref rfPoints, ref rfPointCount, edges, edges.Length, ref rfEdges, ref rfEdgeCount);
                        CopyGeometry(tsIndices, tsIndexCount, ref rfIndices, ref rfIndexCount, tsVertices, tsVertexCount, ref rfVertices, ref rfVertexCount);
                        refined = Refinery.Condition(allocator, areaFactor, targetArea, ref rfPoints, ref rfPointCount, ref rfEdges, ref rfEdgeCount, ref rfVertices, ref rfVertexCount, ref rfIndices, ref rfIndexCount, ref maxArea);

                        if (refined && rfIndexCount > rfPointCount)
                        {
                            // Copy Out
                            ret.x = areaFactor;
                            TransferOutput(rfEdges, rfEdgeCount, ref outEdges, ref outEdgeCount, rfIndices, rfIndexCount, ref outIndices, ref outIndexCount, rfVertices, rfVertexCount, ref outVertices, ref outVertexCount);
                            break;
                        }

                        refined    = false;
                        targetArea = targetArea + incArea;
                        refineIterations--;
                    }
                }
                else if (areaFactor != 0)
                {
                    // Increment for Iterations.
                    areaFactor = math.lerp(0.1f, 0.54f, (areaFactor - 0.05f) / 0.45f); // Specific to Animation.
                    incArea    = (areaFactor / 10);

                    while (areaFactor < 0.8f && refineIterations > 0)
                    {
                        // Do Mesh Refinement.
                        CopyGraph(points, points.Length, ref rfPoints, ref rfPointCount, edges, edges.Length, ref rfEdges, ref rfEdgeCount);
                        CopyGeometry(tsIndices, tsIndexCount, ref rfIndices, ref rfIndexCount, tsVertices, tsVertexCount, ref rfVertices, ref rfVertexCount);
                        refined = Refinery.Condition(allocator, areaFactor, targetArea, ref rfPoints, ref rfPointCount, ref rfEdges, ref rfEdgeCount, ref rfVertices, ref rfVertexCount, ref rfIndices, ref rfIndexCount, ref maxArea);

                        if (refined && rfIndexCount > rfPointCount)
                        {
                            // Copy Out
                            ret.x = areaFactor;
                            TransferOutput(rfEdges, rfEdgeCount, ref outEdges, ref outEdgeCount, rfIndices, rfIndexCount, ref outIndices, ref outIndexCount, rfVertices, rfVertexCount, ref outVertices, ref outVertexCount);
                            break;
                        }

                        refined    = false;
                        areaFactor = areaFactor + incArea;
                        refineIterations--;
                    }
                }

                if (refined)
                {
                    // Sanitize generated geometry data.
                    var preSmoothen = outVertexCount;
                    if (ret.x != 0)
                    {
                        VertexCleanupConditioner(tsVertexCount, ref rfIndices, ref rfIndexCount, ref rfVertices, ref rfVertexCount);
                    }

                    // Smoothen. At this point only vertex relocation is allowed, not vertex addition/removal.
                    // Note: Only refined mesh contains Steiner points and we only smoothen these points.
                    ret.y = 0;
                    smoothenIterations = math.clamp(smoothenIterations, 0, kMaxSmoothenIterations);
                    while (smoothenIterations > 0)
                    {
                        var smoothen = Smoothen.Condition(allocator, ref rfPoints, rfPointCount, rfEdges, rfEdgeCount, ref rfVertices, ref rfVertexCount, ref rfIndices, ref rfIndexCount);
                        if (!smoothen)
                        {
                            break;
                        }
                        // Copy Out
                        ret.y = (float)(smoothenIterations);
                        TransferOutput(rfEdges, rfEdgeCount, ref outEdges, ref outEdgeCount, rfIndices, rfIndexCount, ref outIndices, ref outIndexCount, rfVertices, rfVertexCount, ref outVertices, ref outVertexCount);
                        smoothenIterations--;
                    }

                    // Sanitize generated geometry data.
                    var postSmoothen = outVertexCount;
                    if (ret.y != 0)
                    {
                        VertexCleanupConditioner(tsVertexCount, ref outIndices, ref outIndexCount, ref outVertices, ref outVertexCount);
                    }
                }

                rfVertices.Dispose();
                rfIndices.Dispose();
                rfPoints.Dispose();
                rfEdges.Dispose();
            }

            // Refinement failed but Graph succeeded.
            if (validGraph && !refined)
            {
                // Copy Out
                TransferOutput(edges, edges.Length, ref outEdges, ref outEdgeCount, tsIndices, tsIndexCount, ref outIndices, ref outIndexCount, tsVertices, tsVertexCount, ref outVertices, ref outVertexCount);
            }

            // Dispose Temp Memory.
            tsVertices.Dispose();
            tsIndices.Dispose();
            return(ret);
        }
        public static float4 Subdivide(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, float areaFactor, float targetArea, int smoothenCount)
        {
            // Inputs are garbage, just early out.
            outEdgeCount = 0; outIndexCount = 0; outVertexCount = 0;
            if (points.Length == 0)
            {
                return(float4.zero);
            }

            // Do a proper Delaunay Triangulation.
            float4               ret = float4.zero;
            int                  tsIndexCount = 0, tsVertexCount = 0;
            NativeArray <int>    tsIndices  = new NativeArray <int>(kMaxIndexCount, allocator);
            NativeArray <float2> tsVertices = new NativeArray <float2>(kMaxVertexCount, allocator);
            var                  validGraph = Tessellator.Tessellate(allocator, points, points.Length, edges, edges.Length, ref tsVertices, ref tsVertexCount, ref tsIndices, ref tsIndexCount);

            // Refinement and Smoothing.
            bool refined            = false;
            bool refinementRequired = (targetArea != 0 || areaFactor != 0);

            if (validGraph && refinementRequired)
            {
                // Do Refinement until success.
                float maxArea = 0;
                int   rfEdgeCount = 0, rfPointCount = 0, rfIndexCount = 0, rfVertexCount = 0;
                NativeArray <int2>   rfEdges    = new NativeArray <int2>(kMaxEdgeCount, allocator);
                NativeArray <float2> rfPoints   = new NativeArray <float2>(kMaxVertexCount, allocator);
                NativeArray <int>    rfIndices  = new NativeArray <int>(kMaxIndexCount, allocator);
                NativeArray <float2> rfVertices = new NativeArray <float2>(kMaxVertexCount, allocator);

                if (targetArea != 0)
                {
                    while (targetArea < kMaxArea)
                    {
                        // Do Mesh Refinement.
                        CopyGraph(points, points.Length, ref rfPoints, ref rfPointCount, edges, edges.Length, ref rfEdges, ref rfEdgeCount);
                        CopyGeometry(tsIndices, tsIndexCount, ref rfIndices, ref rfIndexCount, tsVertices, tsVertexCount, ref rfVertices, ref rfVertexCount);
                        refined = Refinery.Condition(allocator, areaFactor, targetArea, ref rfPoints, ref rfPointCount, ref rfEdges, ref rfEdgeCount, ref rfVertices, ref rfVertexCount, ref rfIndices, ref rfIndexCount, ref maxArea);

                        if (refined && rfIndexCount > rfPointCount)
                        {
                            // Copy Out
                            ret.x = areaFactor;
                            TransferOutput(rfEdges, rfEdgeCount, ref outEdges, ref outEdgeCount, rfIndices, rfIndexCount, ref outIndices, ref outIndexCount, rfVertices, rfVertexCount, ref outVertices, ref outVertexCount);
                            break;
                        }

                        refined    = false;
                        targetArea = targetArea * 2.0f;
                    }
                }
                else if (areaFactor != 0)
                {
                    while (areaFactor < 0.8f)
                    {
                        // Do Mesh Refinement.
                        CopyGraph(points, points.Length, ref rfPoints, ref rfPointCount, edges, edges.Length, ref rfEdges, ref rfEdgeCount);
                        CopyGeometry(tsIndices, tsIndexCount, ref rfIndices, ref rfIndexCount, tsVertices, tsVertexCount, ref rfVertices, ref rfVertexCount);
                        refined = Refinery.Condition(allocator, areaFactor, targetArea, ref rfPoints, ref rfPointCount, ref rfEdges, ref rfEdgeCount, ref rfVertices, ref rfVertexCount, ref rfIndices, ref rfIndexCount, ref maxArea);

                        if (refined && rfIndexCount > rfPointCount)
                        {
                            // Copy Out
                            ret.x = areaFactor;
                            TransferOutput(rfEdges, rfEdgeCount, ref outEdges, ref outEdgeCount, rfIndices, rfIndexCount, ref outIndices, ref outIndexCount, rfVertices, rfVertexCount, ref outVertices, ref outVertexCount);
                            break;
                        }

                        refined    = false;
                        areaFactor = areaFactor * 2.0f;
                    }
                }

                if (refined)
                {
                    // Smoothen. At this point only vertex relocation is allowed, not vertex addition/removal.
                    // Note: Only refined mesh contains Steiner points and we only smoothen these points.
                    smoothenCount = math.clamp(smoothenCount, 0, kMaxSmoothenIterations);
                    while (smoothenCount > 0)
                    {
                        var smoothen = Smoothen.Condition(allocator, ref rfPoints, rfPointCount, rfEdges, rfEdgeCount, ref rfVertices, ref rfVertexCount, ref rfIndices, ref rfIndexCount);
                        if (!smoothen)
                        {
                            break;
                        }
                        // Copy Out
                        ret.y = (float)(smoothenCount);
                        TransferOutput(rfEdges, rfEdgeCount, ref outEdges, ref outEdgeCount, rfIndices, rfIndexCount, ref outIndices, ref outIndexCount, rfVertices, rfVertexCount, ref outVertices, ref outVertexCount);
                        smoothenCount--;
                    }
                }

                rfVertices.Dispose();
                rfIndices.Dispose();
                rfPoints.Dispose();
                rfEdges.Dispose();
            }

            // Refinement failed but Graph succeeded.
            if (validGraph && !refined)
            {
                // Copy Out
                TransferOutput(edges, edges.Length, ref outEdges, ref outEdgeCount, tsIndices, tsIndexCount, ref outIndices, ref outIndexCount, tsVertices, tsVertexCount, ref outVertices, ref outVertexCount);
            }

            // Dispose Temp Memory.
            tsVertices.Dispose();
            tsIndices.Dispose();
            return(ret);
        }