/// <summary>Draws a wire cube after being transformed the specified transformation</summary> public void DrawWireCube(GraphTransform tr, Bounds bounds, Color color) { var min = bounds.min; var max = bounds.max; DrawLine(tr.Transform(new Vector3(min.x, min.y, min.z)), tr.Transform(new Vector3(max.x, min.y, min.z)), color); DrawLine(tr.Transform(new Vector3(max.x, min.y, min.z)), tr.Transform(new Vector3(max.x, min.y, max.z)), color); DrawLine(tr.Transform(new Vector3(max.x, min.y, max.z)), tr.Transform(new Vector3(min.x, min.y, max.z)), color); DrawLine(tr.Transform(new Vector3(min.x, min.y, max.z)), tr.Transform(new Vector3(min.x, min.y, min.z)), color); DrawLine(tr.Transform(new Vector3(min.x, max.y, min.z)), tr.Transform(new Vector3(max.x, max.y, min.z)), color); DrawLine(tr.Transform(new Vector3(max.x, max.y, min.z)), tr.Transform(new Vector3(max.x, max.y, max.z)), color); DrawLine(tr.Transform(new Vector3(max.x, max.y, max.z)), tr.Transform(new Vector3(min.x, max.y, max.z)), color); DrawLine(tr.Transform(new Vector3(min.x, max.y, max.z)), tr.Transform(new Vector3(min.x, max.y, min.z)), color); DrawLine(tr.Transform(new Vector3(min.x, min.y, min.z)), tr.Transform(new Vector3(min.x, max.y, min.z)), color); DrawLine(tr.Transform(new Vector3(max.x, min.y, min.z)), tr.Transform(new Vector3(max.x, max.y, min.z)), color); DrawLine(tr.Transform(new Vector3(max.x, min.y, max.z)), tr.Transform(new Vector3(max.x, max.y, max.z)), color); DrawLine(tr.Transform(new Vector3(min.x, min.y, max.z)), tr.Transform(new Vector3(min.x, max.y, max.z)), color); }
// Token: 0x06002935 RID: 10549 RVA: 0x001BBE08 File Offset: 0x001BA008 public GraphTransform(Matrix4x4 matrix) { this.matrix = matrix; this.inverseMatrix = matrix.inverse; this.identity = matrix.isIdentity; this.onlyTranslational = GraphTransform.MatrixIsTranslational(matrix); this.up = matrix.MultiplyVector(Vector3.up).normalized; this.translation = matrix.MultiplyPoint3x4(Vector3.zero); this.i3translation = (Int3)this.translation; this.rotation = Quaternion.LookRotation(this.TransformVector(Vector3.forward), this.TransformVector(Vector3.up)); this.inverseRotation = Quaternion.Inverse(this.rotation); this.isXY = (this.rotation == Quaternion.Euler(-90f, 0f, 0f)); this.isXZ = (this.rotation == Quaternion.Euler(0f, 0f, 0f)); }
private static List <TileHandler.Cut> PrepareNavmeshCutsForCutting(List <NavmeshCut> navmeshCuts, GraphTransform transform, IntRect cutSpaceBounds, int perturbate, bool anyNavmeshAdds) { System.Random random = null; if (perturbate > 0) { random = new System.Random(); } List <List <Vector3> > list = ListPool <List <Vector3> > .Claim(); List <TileHandler.Cut> list2 = ListPool <TileHandler.Cut> .Claim(); for (int i = 0; i < navmeshCuts.Count; i++) { Int2 @int = new Int2(0, 0); if (perturbate > 0) { @int.x = random.Next() % 6 * perturbate - 3 * perturbate; if (@int.x >= 0) { @int.x++; } @int.y = random.Next() % 6 * perturbate - 3 * perturbate; if (@int.y >= 0) { @int.y++; } } list.Clear(); navmeshCuts[i].GetContour(list); int num = (int)(navmeshCuts[i].GetY(transform) * 1000f); for (int j = 0; j < list.Count; j++) { List <Vector3> list3 = list[j]; if (list3.Count == 0) { Debug.LogError("A NavmeshCut component had a zero length contour. Ignoring that contour."); } else { List <IntPoint> list4 = ListPool <IntPoint> .Claim(list3.Count); for (int k = 0; k < list3.Count; k++) { Int3 int2 = (Int3)transform.InverseTransform(list3[k]); if (perturbate > 0) { int2.x += @int.x; int2.z += @int.y; } list4.Add(new IntPoint((long)int2.x, (long)int2.z)); } IntRect bounds = new IntRect((int)list4[0].X, (int)list4[0].Y, (int)list4[0].X, (int)list4[0].Y); for (int l = 0; l < list4.Count; l++) { IntPoint intPoint = list4[l]; bounds = bounds.ExpandToContain((int)intPoint.X, (int)intPoint.Y); } TileHandler.Cut cut = new TileHandler.Cut(); int num2 = (int)(navmeshCuts[i].height * 0.5f * 1000f); cut.boundsY = new Int2(num - num2, num + num2); cut.bounds = bounds; cut.isDual = navmeshCuts[i].isDual; cut.cutsAddedGeom = navmeshCuts[i].cutsAddedGeom; cut.contour = list4; list2.Add(cut); } } } ListPool <List <Vector3> > .Release(list); return(list2); }
private TileHandler.CuttingResult CutPoly(Int3[] verts, int[] tris, Int3[] extraShape, GraphTransform graphTransform, IntRect tiles, TileHandler.CutMode mode = TileHandler.CutMode.CutAll | TileHandler.CutMode.CutDual, int perturbate = -1) { if (verts.Length == 0 || tris.Length == 0) { return(new TileHandler.CuttingResult { verts = ArrayPool <Int3> .Claim(0), tris = ArrayPool <int> .Claim(0) }); } if (perturbate > 10) { Debug.LogError("Too many perturbations aborting.\nThis may cause a tile in the navmesh to become empty. Try to see see if any of your NavmeshCut or NavmeshAdd components use invalid custom meshes."); return(new TileHandler.CuttingResult { verts = verts, tris = tris }); } List <IntPoint> list = null; if (extraShape == null && (mode & TileHandler.CutMode.CutExtra) != (TileHandler.CutMode) 0) { throw new Exception("extraShape is null and the CutMode specifies that it should be used. Cannot use null shape."); } Bounds tileBoundsInGraphSpace = this.graph.GetTileBoundsInGraphSpace(tiles); Vector3 min = tileBoundsInGraphSpace.min; GraphTransform graphTransform2 = graphTransform * Matrix4x4.TRS(min, Quaternion.identity, Vector3.one); Vector2 v = new Vector2(tileBoundsInGraphSpace.size.x, tileBoundsInGraphSpace.size.z); if ((mode & TileHandler.CutMode.CutExtra) != (TileHandler.CutMode) 0) { list = ListPool <IntPoint> .Claim(extraShape.Length); for (int i = 0; i < extraShape.Length; i++) { Int3 @int = graphTransform2.InverseTransform(extraShape[i]); list.Add(new IntPoint((long)@int.x, (long)@int.z)); } } IntRect cutSpaceBounds = new IntRect(verts[0].x, verts[0].z, verts[0].x, verts[0].z); for (int j = 0; j < verts.Length; j++) { cutSpaceBounds = cutSpaceBounds.ExpandToContain(verts[j].x, verts[j].z); } List <NavmeshCut> list2; if (mode == TileHandler.CutMode.CutExtra) { list2 = ListPool <NavmeshCut> .Claim(); } else { list2 = this.cuts.QueryRect <NavmeshCut>(tiles); } List <NavmeshAdd> list3 = this.cuts.QueryRect <NavmeshAdd>(tiles); List <int> list4 = ListPool <int> .Claim(); List <TileHandler.Cut> list5 = TileHandler.PrepareNavmeshCutsForCutting(list2, graphTransform2, cutSpaceBounds, perturbate, list3.Count > 0); List <Int3> list6 = ListPool <Int3> .Claim(verts.Length * 2); List <int> list7 = ListPool <int> .Claim(tris.Length); if (list2.Count == 0 && list3.Count == 0 && (mode & ~(TileHandler.CutMode.CutAll | TileHandler.CutMode.CutDual)) == (TileHandler.CutMode) 0 && (mode & TileHandler.CutMode.CutAll) != (TileHandler.CutMode) 0) { TileHandler.CopyMesh(verts, tris, list6, list7); } else { List <IntPoint> list8 = ListPool <IntPoint> .Claim(); Dictionary <TriangulationPoint, int> dictionary = new Dictionary <TriangulationPoint, int>(); List <PolygonPoint> list9 = ListPool <PolygonPoint> .Claim(); PolyTree polyTree = new PolyTree(); List <List <IntPoint> > list10 = ListPool <List <IntPoint> > .Claim(); Stack <Polygon> stack = StackPool <Polygon> .Claim(); this.clipper.StrictlySimple = (perturbate > -1); this.clipper.ReverseSolution = true; Int3[] array = null; Int3[] clipOut = null; Int2 size = default(Int2); if (list3.Count > 0) { array = new Int3[7]; clipOut = new Int3[7]; size = new Int2(((Int3)v).x, ((Int3)v).y); } Int3[] array2 = null; for (int k = -1; k < list3.Count; k++) { Int3[] array3; int[] array4; if (k == -1) { array3 = verts; array4 = tris; } else { list3[k].GetMesh(ref array2, out array4, graphTransform2); array3 = array2; } for (int l = 0; l < array4.Length; l += 3) { Int3 int2 = array3[array4[l]]; Int3 int3 = array3[array4[l + 1]]; Int3 int4 = array3[array4[l + 2]]; if (VectorMath.IsColinearXZ(int2, int3, int4)) { Debug.LogWarning("Skipping degenerate triangle."); } else { IntRect a = new IntRect(int2.x, int2.z, int2.x, int2.z); a = a.ExpandToContain(int3.x, int3.z); a = a.ExpandToContain(int4.x, int4.z); int num = Math.Min(int2.y, Math.Min(int3.y, int4.y)); int num2 = Math.Max(int2.y, Math.Max(int3.y, int4.y)); list4.Clear(); bool flag = false; for (int m = 0; m < list5.Count; m++) { int x = list5[m].boundsY.x; int y = list5[m].boundsY.y; if (IntRect.Intersects(a, list5[m].bounds) && y >= num && x <= num2 && (list5[m].cutsAddedGeom || k == -1)) { Int3 int5 = int2; int5.y = x; Int3 int6 = int2; int6.y = y; list4.Add(m); flag |= list5[m].isDual; } } if (list4.Count == 0 && (mode & TileHandler.CutMode.CutExtra) == (TileHandler.CutMode) 0 && (mode & TileHandler.CutMode.CutAll) != (TileHandler.CutMode) 0 && k == -1) { list7.Add(list6.Count); list7.Add(list6.Count + 1); list7.Add(list6.Count + 2); list6.Add(int2); list6.Add(int3); list6.Add(int4); } else { list8.Clear(); if (k == -1) { list8.Add(new IntPoint((long)int2.x, (long)int2.z)); list8.Add(new IntPoint((long)int3.x, (long)int3.z)); list8.Add(new IntPoint((long)int4.x, (long)int4.z)); } else { array[0] = int2; array[1] = int3; array[2] = int4; int num3 = this.ClipAgainstRectangle(array, clipOut, size); if (num3 == 0) { goto IL_9D3; } for (int n = 0; n < num3; n++) { list8.Add(new IntPoint((long)array[n].x, (long)array[n].z)); } } dictionary.Clear(); for (int num4 = 0; num4 < 16; num4++) { if ((mode >> (num4 & 31) & TileHandler.CutMode.CutAll) != (TileHandler.CutMode) 0) { if (1 << num4 == 1) { this.CutAll(list8, list4, list5, polyTree); } else if (1 << num4 == 2) { if (!flag) { goto IL_9C4; } this.CutDual(list8, list4, list5, flag, list10, polyTree); } else if (1 << num4 == 4) { this.CutExtra(list8, list, polyTree); } for (int num5 = 0; num5 < polyTree.ChildCount; num5++) { PolyNode polyNode = polyTree.Childs[num5]; List <IntPoint> contour = polyNode.Contour; List <PolyNode> childs = polyNode.Childs; if (childs.Count == 0 && contour.Count == 3 && k == -1) { for (int num6 = 0; num6 < 3; num6++) { Int3 int7 = new Int3((int)contour[num6].X, 0, (int)contour[num6].Y); int7.y = TileHandler.SampleYCoordinateInTriangle(int2, int3, int4, int7); list7.Add(list6.Count); list6.Add(int7); } } else { Polygon polygon = null; int num7 = -1; for (List <IntPoint> list11 = contour; list11 != null; list11 = ((num7 >= childs.Count) ? null : childs[num7].Contour)) { list9.Clear(); for (int num8 = 0; num8 < list11.Count; num8++) { PolygonPoint polygonPoint = new PolygonPoint((double)list11[num8].X, (double)list11[num8].Y); list9.Add(polygonPoint); Int3 int8 = new Int3((int)list11[num8].X, 0, (int)list11[num8].Y); int8.y = TileHandler.SampleYCoordinateInTriangle(int2, int3, int4, int8); dictionary[polygonPoint] = list6.Count; list6.Add(int8); } Polygon polygon2; if (stack.Count > 0) { polygon2 = stack.Pop(); polygon2.AddPoints(list9); } else { polygon2 = new Polygon(list9); } if (num7 == -1) { polygon = polygon2; } else { polygon.AddHole(polygon2); } num7++; } try { P2T.Triangulate(polygon); } catch (PointOnEdgeException) { Debug.LogWarning("PointOnEdgeException, perturbating vertices slightly.\nThis is usually fine. It happens sometimes because of rounding errors. Cutting will be retried a few more times."); return(this.CutPoly(verts, tris, extraShape, graphTransform, tiles, mode, perturbate + 1)); } try { for (int num9 = 0; num9 < polygon.Triangles.Count; num9++) { DelaunayTriangle delaunayTriangle = polygon.Triangles[num9]; list7.Add(dictionary[delaunayTriangle.Points._0]); list7.Add(dictionary[delaunayTriangle.Points._1]); list7.Add(dictionary[delaunayTriangle.Points._2]); } } catch (KeyNotFoundException) { Debug.LogWarning("KeyNotFoundException, perturbating vertices slightly.\nThis is usually fine. It happens sometimes because of rounding errors. Cutting will be retried a few more times."); return(this.CutPoly(verts, tris, extraShape, graphTransform, tiles, mode, perturbate + 1)); } TileHandler.PoolPolygon(polygon, stack); } } } IL_9C4 :; } } } IL_9D3 :; } } if (array2 != null) { ArrayPool <Int3> .Release(ref array2, false); } StackPool <Polygon> .Release(stack); ListPool <List <IntPoint> > .Release(list10); ListPool <IntPoint> .Release(list8); ListPool <PolygonPoint> .Release(list9); } TileHandler.CuttingResult result = default(TileHandler.CuttingResult); Polygon.CompressMesh(list6, list7, out result.verts, out result.tris); for (int num10 = 0; num10 < list2.Count; num10++) { list2[num10].UsedForCut(); } ListPool <Int3> .Release(list6); ListPool <int> .Release(list7); ListPool <int> .Release(list4); for (int num11 = 0; num11 < list5.Count; num11++) { ListPool <IntPoint> .Release(list5[num11].contour); } ListPool <TileHandler.Cut> .Release(list5); ListPool <NavmeshCut> .Release(list2); return(result); }
/// <summary>Y coordinate of the center of the bounding box in graph space</summary> internal float GetY(Pathfinding.Util.GraphTransform transform) { return(transform.InverseTransform(useRotationAndScale ? tr.TransformPoint(center) : tr.position + center).y); }