예제 #1
0
        // Token: 0x060005E3 RID: 1507 RVA: 0x00037424 File Offset: 0x00035824
        private void DelaunayRefinement(Int3[] verts, int[] tris, ref int vCount, ref int tCount, bool delaunay, bool colinear, Int3 worldOffset)
        {
            if (tCount % 3 != 0)
            {
                throw new Exception("Triangle array length must be a multiple of 3");
            }
            Dictionary <Int2, int> dictionary = this.cached_Int2_int_dict;

            dictionary.Clear();
            for (int i = 0; i < tCount; i += 3)
            {
                if (!Polygon.IsClockwise(verts[tris[i]], verts[tris[i + 1]], verts[tris[i + 2]]))
                {
                    int num = tris[i];
                    tris[i]     = tris[i + 2];
                    tris[i + 2] = num;
                }
                dictionary[new Int2(tris[i], tris[i + 1])]     = i + 2;
                dictionary[new Int2(tris[i + 1], tris[i + 2])] = i;
                dictionary[new Int2(tris[i + 2], tris[i])]     = i + 1;
            }
            int num2 = 9;

            for (int j = 0; j < tCount; j += 3)
            {
                for (int k = 0; k < 3; k++)
                {
                    int num3;
                    if (dictionary.TryGetValue(new Int2(tris[j + (k + 1) % 3], tris[j + k % 3]), out num3))
                    {
                        Int3 @int = verts[tris[j + (k + 2) % 3]];
                        Int3 int2 = verts[tris[j + (k + 1) % 3]];
                        Int3 int3 = verts[tris[j + (k + 3) % 3]];
                        Int3 int4 = verts[tris[num3]];
                        @int.y = 0;
                        int2.y = 0;
                        int3.y = 0;
                        int4.y = 0;
                        bool flag = false;
                        if (!Polygon.Left(@int, int3, int4) || Polygon.LeftNotColinear(@int, int2, int4))
                        {
                            if (!colinear)
                            {
                                goto IL_439;
                            }
                            flag = true;
                        }
                        if (colinear && AstarMath.DistancePointSegment(@int, int4, int2) < (float)num2 && !dictionary.ContainsKey(new Int2(tris[j + (k + 2) % 3], tris[j + (k + 1) % 3])) && !dictionary.ContainsKey(new Int2(tris[j + (k + 1) % 3], tris[num3])))
                        {
                            tCount -= 3;
                            int num4 = num3 / 3 * 3;
                            tris[j + (k + 1) % 3] = tris[num3];
                            if (num4 != tCount)
                            {
                                tris[num4]     = tris[tCount];
                                tris[num4 + 1] = tris[tCount + 1];
                                tris[num4 + 2] = tris[tCount + 2];
                                dictionary[new Int2(tris[num4], tris[num4 + 1])]     = num4 + 2;
                                dictionary[new Int2(tris[num4 + 1], tris[num4 + 2])] = num4;
                                dictionary[new Int2(tris[num4 + 2], tris[num4])]     = num4 + 1;
                                tris[tCount]     = 0;
                                tris[tCount + 1] = 0;
                                tris[tCount + 2] = 0;
                            }
                            else
                            {
                                tCount += 3;
                            }
                            dictionary[new Int2(tris[j], tris[j + 1])]     = j + 2;
                            dictionary[new Int2(tris[j + 1], tris[j + 2])] = j;
                            dictionary[new Int2(tris[j + 2], tris[j])]     = j + 1;
                        }
                        else if (delaunay && !flag)
                        {
                            float num5 = Int3.Angle(int2 - @int, int3 - @int);
                            float num6 = Int3.Angle(int2 - int4, int3 - int4);
                            if (num6 > 6.28318548f - 2f * num5)
                            {
                                tris[j + (k + 1) % 3] = tris[num3];
                                int num7 = num3 / 3 * 3;
                                int num8 = num3 - num7;
                                tris[num7 + (num8 - 1 + 3) % 3]                      = tris[j + (k + 2) % 3];
                                dictionary[new Int2(tris[j], tris[j + 1])]           = j + 2;
                                dictionary[new Int2(tris[j + 1], tris[j + 2])]       = j;
                                dictionary[new Int2(tris[j + 2], tris[j])]           = j + 1;
                                dictionary[new Int2(tris[num7], tris[num7 + 1])]     = num7 + 2;
                                dictionary[new Int2(tris[num7 + 1], tris[num7 + 2])] = num7;
                                dictionary[new Int2(tris[num7 + 2], tris[num7])]     = num7 + 1;
                            }
                        }
                    }
                    IL_439 :;
                }
            }
        }
예제 #2
0
        public void SimplifyContour(List <int> verts, List <int> simplified, float maxError, int maxEdgeLenght, int buildFlags)
        {
            // Add initial points.
            bool hasConnections = false;

            for (int i = 0; i < verts.Count; i += 4)
            {
                if ((verts[i + 3] & ContourRegMask) != 0)
                {
                    hasConnections = true;
                    break;
                }
            }

            if (hasConnections)
            {
                // The contour has some portals to other regions.
                // Add a new point to every location where the region changes.
                for (int i = 0, ni = verts.Count / 4; i < ni; i++)
                {
                    int  ii            = (i + 1) % ni;
                    bool differentRegs = (verts[i * 4 + 3] & ContourRegMask) != (verts[ii * 4 + 3] & ContourRegMask);
                    bool areaBorders   = (verts[i * 4 + 3] & RC_AREA_BORDER) != (verts[ii * 4 + 3] & RC_AREA_BORDER);

                    if (differentRegs || areaBorders)
                    {
                        simplified.Add(verts[i * 4 + 0]);
                        simplified.Add(verts[i * 4 + 1]);
                        simplified.Add(verts[i * 4 + 2]);
                        simplified.Add(i);
                    }
                }
            }


            if (simplified.Count == 0)
            {
                // If there is no connections at all,
                // create some initial points for the simplification process.
                // Find lower-left and upper-right vertices of the contour.
                int llx = verts[0];
                int lly = verts[1];
                int llz = verts[2];
                int lli = 0;
                int urx = verts[0];
                int ury = verts[1];
                int urz = verts[2];
                int uri = 0;

                for (int i = 0; i < verts.Count; i += 4)
                {
                    int x = verts[i + 0];
                    int y = verts[i + 1];
                    int z = verts[i + 2];
                    if (x < llx || (x == llx && z < llz))
                    {
                        llx = x;
                        lly = y;
                        llz = z;
                        lli = i / 4;
                    }
                    if (x > urx || (x == urx && z > urz))
                    {
                        urx = x;
                        ury = y;
                        urz = z;
                        uri = i / 4;
                    }
                }

                simplified.Add(llx);
                simplified.Add(lly);
                simplified.Add(llz);
                simplified.Add(lli);

                simplified.Add(urx);
                simplified.Add(ury);
                simplified.Add(urz);
                simplified.Add(uri);
            }

            // Add points until all raw points are within
            // error tolerance to the simplified shape.
            int pn = verts.Count / 4;

            //Use the max squared error instead
            maxError *= maxError;

            for (int i = 0; i < simplified.Count / 4;)
            {
                int ii = (i + 1) % (simplified.Count / 4);

                int ax = simplified[i * 4 + 0];
                int az = simplified[i * 4 + 2];
                int ai = simplified[i * 4 + 3];

                int bx = simplified[ii * 4 + 0];
                int bz = simplified[ii * 4 + 2];
                int bi = simplified[ii * 4 + 3];

                // Find maximum deviation from the segment.
                float maxd = 0;
                int   maxi = -1;
                int   ci, cinc, endi;

                // Traverse the segment in lexilogical order so that the
                // max deviation is calculated similarly when traversing
                // opposite segments.
                if (bx > ax || (bx == ax && bz > az))
                {
                    cinc = 1;
                    ci   = (ai + cinc) % pn;
                    endi = bi;
                }
                else
                {
                    cinc = pn - 1;
                    ci   = (bi + cinc) % pn;
                    endi = ai;
                }

                // Tessellate only outer edges or edges between areas.
                if ((verts[ci * 4 + 3] & ContourRegMask) == 0 ||
                    (verts[ci * 4 + 3] & RC_AREA_BORDER) == RC_AREA_BORDER)
                {
                    while (ci != endi)
                    {
                        float d2 = AstarMath.DistancePointSegment(verts[ci * 4 + 0], verts[ci * 4 + 2] / voxelArea.width, ax, az / voxelArea.width, bx, bz / voxelArea.width);
                        //float d2 = Mathfx.DistancePointSegment2 (verts[ci*4+0], verts[ci*4+2]/voxelArea.width, ax, az/voxelArea.width, bx, bz/voxelArea.width);

                        //if (Mathf.Abs (d2-d3) > 0.5F) {
                        //	Debug.Log (d2+" "+d3);
                        //}

                        if (d2 > maxd)
                        {
                            maxd = d2;
                            maxi = ci;
                        }
                        ci = (ci + cinc) % pn;
                    }
                }

                // If the max deviation is larger than accepted error,
                // add new point, else continue to next segment.
                if (maxi != -1 && maxd > maxError)
                {
                    // Add space for the new point.
                    //simplified.resize(simplified.size()+4);
                    simplified.Add(0);
                    simplified.Add(0);
                    simplified.Add(0);
                    simplified.Add(0);

                    int n = simplified.Count / 4;

                    for (int j = n - 1; j > i; --j)
                    {
                        simplified[j * 4 + 0] = simplified[(j - 1) * 4 + 0];
                        simplified[j * 4 + 1] = simplified[(j - 1) * 4 + 1];
                        simplified[j * 4 + 2] = simplified[(j - 1) * 4 + 2];
                        simplified[j * 4 + 3] = simplified[(j - 1) * 4 + 3];
                    }
                    // Add the point.
                    simplified[(i + 1) * 4 + 0] = verts[maxi * 4 + 0];
                    simplified[(i + 1) * 4 + 1] = verts[maxi * 4 + 1];
                    simplified[(i + 1) * 4 + 2] = verts[maxi * 4 + 2];
                    simplified[(i + 1) * 4 + 3] = maxi;
                }
                else
                {
                    i++;
                }
            }



            //Split too long edges

            float maxEdgeLen = maxEdgeLength / cellSize;

            if (maxEdgeLen > 0 && (buildFlags & (RC_CONTOUR_TESS_WALL_EDGES | RC_CONTOUR_TESS_AREA_EDGES)) != 0)
            {
                for (int i = 0; i < simplified.Count / 4;)
                {
                    if (simplified.Count / 4 > 200)
                    {
                        break;
                    }

                    int ii = (i + 1) % (simplified.Count / 4);

                    int ax = simplified[i * 4 + 0];
                    int az = simplified[i * 4 + 2];
                    int ai = simplified[i * 4 + 3];

                    int bx = simplified[ii * 4 + 0];
                    int bz = simplified[ii * 4 + 2];
                    int bi = simplified[ii * 4 + 3];

                    // Find maximum deviation from the segment.
                    int maxi = -1;
                    int ci   = (ai + 1) % pn;

                    // Tessellate only outer edges or edges between areas.
                    bool tess = false;

                    // Wall edges.
                    if ((buildFlags & RC_CONTOUR_TESS_WALL_EDGES) == 1 && (verts[ci * 4 + 3] & ContourRegMask) == 0)
                    {
                        tess = true;
                    }
                    // Edges between areas.
                    if ((buildFlags & RC_CONTOUR_TESS_AREA_EDGES) == 1 && (verts[ci * 4 + 3] & RC_AREA_BORDER) == 1)
                    {
                        tess = true;
                    }

                    if (tess)
                    {
                        int dx = bx - ax;
                        int dz = (bz / voxelArea.width) - (az / voxelArea.width);
                        if (dx * dx + dz * dz > maxEdgeLen * maxEdgeLen)
                        {
                            // Round based on the segments in lexilogical order so that the
                            // max tesselation is consistent regardles in which direction
                            // segments are traversed.
                            if (bx > ax || (bx == ax && bz > az))
                            {
                                int n = bi < ai ? (bi + pn - ai) : (bi - ai);
                                maxi = (ai + n / 2) % pn;
                            }
                            else
                            {
                                int n = bi < ai ? (bi + pn - ai) : (bi - ai);
                                maxi = (ai + (n + 1) / 2) % pn;
                            }
                        }
                    }

                    // If the max deviation is larger than accepted error,
                    // add new point, else continue to next segment.
                    if (maxi != -1)
                    {
                        // Add space for the new point.
                        //simplified.resize(simplified.size()+4);
                        simplified.AddRange(new int[4]);

                        int n = simplified.Count / 4;
                        for (int j = n - 1; j > i; --j)
                        {
                            simplified[j * 4 + 0] = simplified[(j - 1) * 4 + 0];
                            simplified[j * 4 + 1] = simplified[(j - 1) * 4 + 1];
                            simplified[j * 4 + 2] = simplified[(j - 1) * 4 + 2];
                            simplified[j * 4 + 3] = simplified[(j - 1) * 4 + 3];
                        }
                        // Add the point.
                        simplified[(i + 1) * 4 + 0] = verts[maxi * 4 + 0];
                        simplified[(i + 1) * 4 + 1] = verts[maxi * 4 + 1];
                        simplified[(i + 1) * 4 + 2] = verts[maxi * 4 + 2];
                        simplified[(i + 1) * 4 + 3] = maxi;
                    }
                    else
                    {
                        ++i;
                    }
                }
            }

            for (int i = 0; i < simplified.Count / 4; i++)
            {
                // The edge vertex flag is take from the current raw point,
                // and the neighbour region is take from the next raw point.
                int ai = (simplified[i * 4 + 3] + 1) % pn;
                int bi = simplified[i * 4 + 3];
                simplified[i * 4 + 3] = (verts[ai * 4 + 3] & ContourRegMask) | (verts[bi * 4 + 3] & RC_BORDER_VERTEX);
            }
        }