Esempio n. 1
0
            void Flip(NativeArray <float2> points, ref NativeArray <int> stack, ref int stackCount,
                      int a, int b, int x)
            {
                int y = OppositeOf(a, b);

                if (y < 0)
                {
                    return;
                }

                if (b < a)
                {
                    int tmp = a;
                    a   = b;
                    b   = tmp;
                    tmp = x;
                    x   = y;
                    y   = tmp;
                }

                if (FindConstraint(a, b) != -1)
                {
                    return;
                }

                if (TessUtils.IsInsideCircle(points[a], points[b], points[x], points[y]))
                {
                    stack[stackCount++] = a;
                    stack[stackCount++] = b;
                }
            }
Esempio n. 2
0
            static float FindSplit(TessHull hull, TessEvent edge)
            {
                float d = 0;

                if (hull.a.x < edge.a.x)
                {
                    d = TessUtils.OrientFast(hull.a, hull.b, edge.a);
                }
                else
                {
                    d = TessUtils.OrientFast(edge.b, edge.a, hull.a);
                }

                if (0 != d)
                {
                    return(d);
                }

                if (edge.b.x < hull.b.x)
                {
                    d = TessUtils.OrientFast(hull.a, hull.b, edge.b);
                }
                else
                {
                    d = TessUtils.OrientFast(edge.b, edge.a, hull.b);
                }

                if (0 != d)
                {
                    return(d);
                }

                return(hull.idx - edge.idx);
            }
Esempio n. 3
0
            public int Compare(TessEvent a, TessEvent b)
            {
                float f = (a.a.x - b.a.x);

                if (0 != f)
                {
                    return((f > 0) ? 1 : -1);
                }

                f = (a.a.y - b.a.y);
                if (0 != f)
                {
                    return((f > 0) ? 1 : -1);
                }

                int i = a.type - b.type;

                if (0 != i)
                {
                    return(i);
                }

                if (a.type != (int)TessEventType.EVENT_POINT)
                {
                    float o = TessUtils.OrientFast(a.a, a.b, b.b);
                    if (0 != o)
                    {
                        return((o > 0) ? 1 : -1);
                    }
                }

                return(a.idx - b.idx);
            }
Esempio n. 4
0
            void Prepare(NativeArray <TessEdge> edgesIn)
            {
                m_Stars = new NativeArray <TessStar>(edgesIn.Length, Allocator.Temp);

                for (int i = 0; i < edgesIn.Length; ++i)
                {
                    TessEdge e = edgesIn[i];
                    e.a        = (edgesIn[i].a < edgesIn[i].b) ? edgesIn[i].a : edgesIn[i].b;
                    e.b        = (edgesIn[i].a > edgesIn[i].b) ? edgesIn[i].a : edgesIn[i].b;
                    edgesIn[i] = e;
                    TessStar s = m_Stars[i];
                    s.points     = new ArraySlice <int>(m_SPArray, i * m_StarCount, m_StarCount);
                    s.pointCount = 0;
                    m_Stars[i]   = s;
                }

                unsafe
                {
                    TessUtils.InsertionSort <TessEdge, TessEdgeCompare>(
                        NativeArrayUnsafeUtility.GetUnsafeBufferPointerWithoutChecks(edgesIn), 0, edgesIn.Length - 1,
                        new TessEdgeCompare());
                }

                m_Edges = new NativeArray <TessEdge>(edgesIn.Length, Allocator.Temp);
                m_Edges.CopyFrom(edgesIn);

                // Fill stars.
                for (int i = 0; i < m_CellCount; ++i)
                {
                    int      a  = m_Cells[i].a;
                    int      b  = m_Cells[i].b;
                    int      c  = m_Cells[i].c;
                    TessStar sa = m_Stars[a];
                    TessStar sb = m_Stars[b];
                    TessStar sc = m_Stars[c];
                    sa.points[sa.pointCount++] = b;
                    sa.points[sa.pointCount++] = c;
                    sb.points[sb.pointCount++] = c;
                    sb.points[sb.pointCount++] = a;
                    sc.points[sc.pointCount++] = a;
                    sc.points[sc.pointCount++] = b;
                    m_Stars[a] = sa;
                    m_Stars[b] = sb;
                    m_Stars[c] = sc;
                }
            }
Esempio n. 5
0
            void AddPoint(NativeArray <TessHull> hulls, int hullCount, NativeArray <float2> points, float2 p,
                          int idx)
            {
                int l = GetLowerHullForVector(hulls, hullCount, p);
                int u = GetUpperHullForVector(hulls, hullCount, p);

                for (int i = l; i < u; ++i)
                {
                    TessHull hull = hulls[i];

                    int m = hull.ilcount;
                    while (m > 1 && TessUtils.OrientFast(points[hull.ilarray[m - 2]], points[hull.ilarray[m - 1]], p) >
                           0)
                    {
                        TessCell c = new TessCell();
                        c.a = hull.ilarray[m - 1];
                        c.b = hull.ilarray[m - 2];
                        c.c = idx;
                        m_Cells[m_CellCount++] = c;
                        m -= 1;
                    }

                    hull.ilcount    = m + 1;
                    hull.ilarray[m] = idx;

                    m = hull.iucount;
                    while (m > 1 && TessUtils.OrientFast(points[hull.iuarray[m - 2]], points[hull.iuarray[m - 1]], p) <
                           0)
                    {
                        TessCell c = new TessCell();
                        c.a = hull.iuarray[m - 2];
                        c.b = hull.iuarray[m - 1];
                        c.c = idx;
                        m_Cells[m_CellCount++] = c;
                        m -= 1;
                    }

                    hull.iucount    = m + 1;
                    hull.iuarray[m] = idx;

                    hulls[i] = hull;
                }
            }
Esempio n. 6
0
            internal void ApplyDelaunay(NativeArray <float2> points, NativeArray <TessEdge> edgesIn)
            {
                NativeArray <int> stack = new NativeArray <int>(m_NumPoints * (m_NumPoints + 1), Allocator.Temp);
                int stackCount          = 0;

                Prepare(edgesIn);
                for (int a = 0; a < m_NumPoints; ++a)
                {
                    TessStar star = m_Stars[a];
                    for (int j = 1; j < star.pointCount; j += 2)
                    {
                        int b = star.points[j];

                        if (b < a)
                        {
                            continue;
                        }

                        if (FindConstraint(a, b) >= 0)
                        {
                            continue;
                        }

                        int x = star.points[j - 1], y = -1;
                        for (int k = 1; k < star.pointCount; k += 2)
                        {
                            if (star.points[k - 1] == b)
                            {
                                y = star.points[k];
                                break;
                            }
                        }

                        if (y < 0)
                        {
                            continue;
                        }

                        if (TessUtils.IsInsideCircle(points[a], points[b], points[x], points[y]))
                        {
                            stack[stackCount++] = a;
                            stack[stackCount++] = b;
                        }
                    }
                }

                while (stackCount > 0)
                {
                    int b = stack[stackCount - 1];
                    stackCount--;
                    int a = stack[stackCount - 1];
                    stackCount--;

                    int      x = -1, y = -1;
                    TessStar star = m_Stars[a];
                    for (int i = 1; i < star.pointCount; i += 2)
                    {
                        int s = star.points[i - 1];
                        int t = star.points[i];
                        if (s == b)
                        {
                            y = t;
                        }
                        else if (t == b)
                        {
                            x = s;
                        }
                    }

                    if (x < 0 || y < 0)
                    {
                        continue;
                    }

                    if (!TessUtils.IsInsideCircle(points[a], points[b], points[x], points[y]))
                    {
                        continue;
                    }

                    EdgeFlip(a, b);

                    Flip(points, ref stack, ref stackCount, x, a, y);
                    Flip(points, ref stack, ref stackCount, a, y, x);
                    Flip(points, ref stack, ref stackCount, y, b, x);
                    Flip(points, ref stack, ref stackCount, b, x, y);
                }

                stack.Dispose();
            }
Esempio n. 7
0
            internal void Triangulate(NativeArray <float2> points, NativeArray <TessEdge> edgesIn)
            {
                int       numEdges   = edgesIn.Length;
                const int kStarEdges = 16;

                m_NumPoints = points.Length;
                m_StarCount = m_NumPoints > kStarEdges ? m_NumPoints : kStarEdges;
                m_StarCount = m_StarCount * 2;
                m_CellCount = 0;
                m_Cells     = new NativeArray <TessCell>(m_NumPoints * (m_NumPoints + 1), Allocator.Temp);
                m_ILArray   = new NativeArray <int>(m_NumPoints * (m_NumPoints + 1), Allocator.Temp); // Make room for -1 node.
                m_IUArray   = new NativeArray <int>(m_NumPoints * (m_NumPoints + 1), Allocator.Temp); // Make room for -1 node.
                m_SPArray   = new NativeArray <int>(m_NumPoints * (m_StarCount), Allocator.Temp);     // Make room for -1 node.

                NativeArray <TessHull> hulls = new NativeArray <TessHull>(m_NumPoints * 8, Allocator.Temp);
                int hullCount = 0;

                NativeArray <TessEvent> events = new NativeArray <TessEvent>(m_NumPoints + (numEdges * 2), Allocator.Temp);
                int eventCount = 0;

                for (int i = 0; i < m_NumPoints; ++i)
                {
                    TessEvent evt = new TessEvent();
                    evt.a                = points[i];
                    evt.b                = new float2();
                    evt.idx              = i;
                    evt.type             = (int)TessEventType.EVENT_POINT;
                    events[eventCount++] = evt;
                }

                for (int i = 0; i < numEdges; ++i)
                {
                    TessEdge e = edgesIn[i];
                    float2   a = points[e.a];
                    float2   b = points[e.b];
                    if (a.x < b.x)
                    {
                        TessEvent _s = new TessEvent();
                        _s.a    = a;
                        _s.b    = b;
                        _s.idx  = i;
                        _s.type = (int)TessEventType.EVENT_START;

                        TessEvent _e = new TessEvent();
                        _e.a    = b;
                        _e.b    = a;
                        _e.idx  = i;
                        _e.type = (int)TessEventType.EVENT_END;

                        events[eventCount++] = _s;
                        events[eventCount++] = _e;
                    }
                    else if (a.x > b.x)
                    {
                        TessEvent _s = new TessEvent();
                        _s.a    = b;
                        _s.b    = a;
                        _s.idx  = i;
                        _s.type = (int)TessEventType.EVENT_START;

                        TessEvent _e = new TessEvent();
                        _e.a    = a;
                        _e.b    = b;
                        _e.idx  = i;
                        _e.type = (int)TessEventType.EVENT_END;

                        events[eventCount++] = _s;
                        events[eventCount++] = _e;
                    }
                }

                unsafe
                {
                    TessUtils.InsertionSort <TessEvent, TessEventCompare>(
                        NativeArrayUnsafeUtility.GetUnsafeBufferPointerWithoutChecks(events), 0, eventCount - 1,
                        new TessEventCompare());
                    ;
                }

                float    minX = events[0].a.x - (1 + math.abs(events[0].a.x)) * math.pow(2.0f, -16.0f);
                TessHull hull;

                hull.a.x           = minX;
                hull.a.y           = 1;
                hull.b.x           = minX;
                hull.b.y           = 0;
                hull.idx           = -1;
                hull.ilarray       = new ArraySlice <int>(m_ILArray, m_NumPoints * m_NumPoints, m_NumPoints); // Last element
                hull.iuarray       = new ArraySlice <int>(m_IUArray, m_NumPoints * m_NumPoints, m_NumPoints);
                hull.ilcount       = 0;
                hull.iucount       = 0;
                hulls[hullCount++] = hull;

                for (int i = 0, numEvents = eventCount; i < numEvents; ++i)
                {
                    switch (events[i].type)
                    {
                    case (int)TessEventType.EVENT_POINT:
                    {
                        AddPoint(hulls, hullCount, points, events[i].a, events[i].idx);
                    }
                    break;

                    case (int)TessEventType.EVENT_START:
                    {
                        SplitHulls(hulls, ref hullCount, points, events[i]);
                    }
                    break;

                    default:
                    {
                        MergeHulls(hulls, ref hullCount, points, events[i]);
                    }
                    break;
                    }
                }

                hulls.Dispose();
                events.Dispose();
            }
Esempio n. 8
0
 static float TestPoint(TessHull hull, float2 point)
 {
     return(TessUtils.OrientFast(hull.a, hull.b, point));
 }
Esempio n. 9
0
            NativeArray <TessCell> Constrain(ref int count)
            {
                var cells = GetCells(ref count);
                int nc    = count;

                for (int i = 0; i < nc; ++i)
                {
                    TessCell c = cells[i];
                    int      x = c.a, y = c.b, z = c.c;
                    if (y < z)
                    {
                        if (y < x)
                        {
                            c.a = y;
                            c.b = z;
                            c.c = x;
                        }
                    }
                    else if (z < x)
                    {
                        c.a = z;
                        c.b = x;
                        c.c = y;
                    }

                    cells[i] = c;
                }

                unsafe
                {
                    TessUtils.InsertionSort <TessCell, TessCellCompare>(
                        NativeArrayUnsafeUtility.GetUnsafeBufferPointerWithoutChecks(cells), 0, m_CellCount - 1,
                        new TessCellCompare());
                }

                // Out
                m_Flags       = new NativeArray <int>(nc, Allocator.Temp);
                m_Neighbors   = new NativeArray <int>(nc * 3, Allocator.Temp);
                m_Constraints = new NativeArray <int>(nc * 3, Allocator.Temp);
                var next   = new NativeArray <int>(nc * 3, Allocator.Temp);
                var active = new NativeArray <int>(nc * 3, Allocator.Temp);

                int side = 1, nextCount = 0, activeCount = 0;

                for (int i = 0; i < nc; ++i)
                {
                    TessCell c = cells[i];
                    for (int j = 0; j < 3; ++j)
                    {
                        int x = j, y = (j + 1) % 3;
                        x = (x == 0) ? c.a : (j == 1) ? c.b : c.c;
                        y = (y == 0) ? c.a : (y == 1) ? c.b : c.c;

                        int o = OppositeOf(y, x);
                        int a = m_Neighbors[3 * i + j] = FindNeighbor(cells, count, y, x, o);
                        int b = m_Constraints[3 * i + j] = (-1 != FindConstraint(x, y)) ? 1 : 0;
                        if (a < 0)
                        {
                            if (0 != b)
                            {
                                next[nextCount++] = i;
                            }
                            else
                            {
                                active[activeCount++] = i;
                                m_Flags[i]            = 1;
                            }
                        }
                    }
                }

                while (activeCount > 0 || nextCount > 0)
                {
                    while (activeCount > 0)
                    {
                        int t = active[activeCount - 1];
                        activeCount--;
                        if (m_Flags[t] == -side)
                        {
                            continue;
                        }

                        m_Flags[t] = side;
                        TessCell c = cells[t];
                        for (int j = 0; j < 3; ++j)
                        {
                            int f = m_Neighbors[3 * t + j];
                            if (f >= 0 && m_Flags[f] == 0)
                            {
                                if (0 != m_Constraints[3 * t + j])
                                {
                                    next[nextCount++] = f;
                                }
                                else
                                {
                                    active[activeCount++] = f;
                                    m_Flags[f]            = side;
                                }
                            }
                        }
                    }

                    for (int e = 0; e < nextCount; e++)
                    {
                        active[e] = next[e];
                    }
                    activeCount = nextCount;
                    nextCount   = 0;
                    side        = -side;
                }

                active.Dispose();
                next.Dispose();
                return(cells);
            }