// 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 :; } } }
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); } }