// Token: 0x06002696 RID: 9878 RVA: 0x001A8890 File Offset: 0x001A6A90 public void OnDrawGizmosSelected() { List <List <Vector3> > list = ListPool <List <Vector3> > .Claim(); this.GetContour(list); Color color = Color.Lerp(NavmeshCut.GizmoColor, Color.white, 0.5f); color.a *= 0.5f; Gizmos.color = color; NavmeshBase navmeshBase = (AstarPath.active != null) ? (AstarPath.active.data.recastGraph ?? AstarPath.active.data.navmesh) : null; GraphTransform graphTransform = (navmeshBase != null) ? navmeshBase.transform : GraphTransform.identityTransform; float y = this.GetY(graphTransform); float y2 = y - this.height * 0.5f; float y3 = y + this.height * 0.5f; for (int i = 0; i < list.Count; i++) { List <Vector3> list2 = list[i]; for (int j = 0; j < list2.Count; j++) { Vector3 vector = graphTransform.InverseTransform(list2[j]); Vector3 vector2 = graphTransform.InverseTransform(list2[(j + 1) % list2.Count]); Vector3 point = vector; Vector3 point2 = vector2; Vector3 point3 = vector; Vector3 point4 = vector2; point.y = (point2.y = y2); point3.y = (point4.y = y3); Gizmos.DrawLine(graphTransform.Transform(point), graphTransform.Transform(point2)); Gizmos.DrawLine(graphTransform.Transform(point3), graphTransform.Transform(point4)); Gizmos.DrawLine(graphTransform.Transform(point), graphTransform.Transform(point3)); } } ListPool <List <Vector3> > .Release(ref list); }
public static Bounds InverseTransform(this GraphTransform self, Bounds bounds) { if (self.onlyTranslational) { return(new Bounds(bounds.center - self.translation.ToUnityV3(), bounds.size)); } var corners = PF.ArrayPool <Vector3> .Claim(8); var extents = bounds.extents; corners[0] = self.InverseTransform(bounds.center + new Vector3(extents.x, extents.y, extents.z)); corners[1] = self.InverseTransform(bounds.center + new Vector3(extents.x, extents.y, -extents.z)); corners[2] = self.InverseTransform(bounds.center + new Vector3(extents.x, -extents.y, extents.z)); corners[3] = self.InverseTransform(bounds.center + new Vector3(extents.x, -extents.y, -extents.z)); corners[4] = self.InverseTransform(bounds.center + new Vector3(-extents.x, extents.y, extents.z)); corners[5] = self.InverseTransform(bounds.center + new Vector3(-extents.x, extents.y, -extents.z)); corners[6] = self.InverseTransform(bounds.center + new Vector3(-extents.x, -extents.y, extents.z)); corners[7] = self.InverseTransform(bounds.center + new Vector3(-extents.x, -extents.y, -extents.z)); var min = corners[0]; var max = corners[0]; for (int i = 1; i < 8; i++) { min = Vector3.Min(min, corners[i]); max = Vector3.Max(max, corners[i]); } PF.ArrayPool <Vector3> .Release(ref corners); return(new Bounds((min + max) * 0.5f, max - min)); }
public void GetMesh(ref Int3[] vbuffer, out int[] tbuffer, GraphTransform inverseTransform = null) { if (this.verts == null) { this.RebuildMesh(); } if (this.verts == null) { tbuffer = ArrayPool <int> .Claim(0); return; } if (vbuffer == null || vbuffer.Length < this.verts.Length) { if (vbuffer != null) { ArrayPool <Int3> .Release(ref vbuffer, false); } vbuffer = ArrayPool <Int3> .Claim(this.verts.Length); } tbuffer = this.tris; if (this.useRotationAndScale) { Matrix4x4 matrix4x = Matrix4x4.TRS(this.tr.position + this.center, this.tr.rotation, this.tr.localScale * this.meshScale); for (int i = 0; i < this.verts.Length; i++) { Vector3 vector = matrix4x.MultiplyPoint3x4(this.verts[i]); if (inverseTransform != null) { vector = inverseTransform.InverseTransform(vector); } vbuffer[i] = (Int3)vector; } } else { Vector3 a = this.tr.position + this.center; for (int j = 0; j < this.verts.Length; j++) { Vector3 vector2 = a + this.verts[j] * this.meshScale; if (inverseTransform != null) { vector2 = inverseTransform.InverseTransform(vector2); } vbuffer[j] = (Int3)vector2; } } }
/// <summary> /// Bounds in XZ space after transforming using the *inverse* transform of the inverseTransform parameter. /// The transformation will typically transform the vertices to graph space and this is used to /// figure out which tiles the cut intersects. /// </summary> public override Rect GetBounds(GraphTransform inverseTransform) { var buffers = ListPool <List <Vector3> > .Claim(); GetContour(buffers); Rect r = new Rect(); for (int i = 0; i < buffers.Count; i++) { var buffer = buffers[i]; for (int k = 0; k < buffer.Count; k++) { var p = inverseTransform.InverseTransform(buffer[k]); if (k == 0) { r = new Rect(p.x, p.z, 0, 0); } else { r.xMax = System.Math.Max(r.xMax, p.x); r.yMax = System.Math.Max(r.yMax, p.z); r.xMin = System.Math.Min(r.xMin, p.x); r.yMin = System.Math.Min(r.yMin, p.z); } } } ListPool <List <Vector3> > .Release(ref buffers); return(r); }
// Token: 0x06002691 RID: 9873 RVA: 0x001A83A8 File Offset: 0x001A65A8 internal override Rect GetBounds(GraphTransform inverseTranform) { List <List <Vector3> > list = ListPool <List <Vector3> > .Claim(); this.GetContour(list); Rect result = default(Rect); for (int i = 0; i < list.Count; i++) { List <Vector3> list2 = list[i]; for (int j = 0; j < list2.Count; j++) { Vector3 vector = inverseTranform.InverseTransform(list2[j]); if (j == 0) { result = new Rect(vector.x, vector.z, 0f, 0f); } else { result.xMax = Math.Max(result.xMax, vector.x); result.yMax = Math.Max(result.yMax, vector.z); result.xMin = Math.Min(result.xMin, vector.x); result.yMin = Math.Min(result.yMin, vector.z); } } } ListPool <List <Vector3> > .Release(ref list); return(result); }
public override void OnSceneGUI(NavGraph target) { Event e = Event.current; var graph = target as GridGraph; graph.UpdateTransform(); var currentTransform = graph.transform * Matrix4x4.Scale(new Vector3(graph.width, 1, graph.depth)); if (e.type == EventType.MouseDown) { isMouseDown = true; } else if (e.type == EventType.MouseUp) { isMouseDown = false; } if (!isMouseDown) { savedTransform = currentTransform; savedDimensions = new Vector2(graph.width, graph.depth); savedNodeSize = graph.nodeSize; } Handles.matrix = Matrix4x4.identity; Handles.color = AstarColor.BoundsHandles; #if UNITY_5_5_OR_NEWER Handles.CapFunction cap = Handles.CylinderHandleCap; #else Handles.DrawCapFunction cap = Handles.CylinderCap; #endif var center = currentTransform.Transform(new Vector3(0.5f, 0, 0.5f)); if (Tools.current == Tool.Scale) { const float HandleScale = 0.1f; Vector3 mn = Vector3.zero; Vector3 mx = Vector3.zero; EditorGUI.BeginChangeCheck(); for (int i = 0; i < handlePoints.Length; i++) { var ps = currentTransform.Transform(handlePoints[i]); Vector3 p = savedTransform.InverseTransform(Handles.Slider(ps, ps - center, HandleScale * HandleUtility.GetHandleSize(ps), cap, 0)); // Snap to increments of whole nodes p.x = Mathf.Round(p.x * savedDimensions.x) / savedDimensions.x; p.z = Mathf.Round(p.z * savedDimensions.y) / savedDimensions.y; if (i == 0) { mn = mx = p; } else { mn = Vector3.Min(mn, p); mx = Vector3.Max(mx, p); } } if (EditorGUI.EndChangeCheck()) { graph.center = savedTransform.Transform((mn + mx) * 0.5f); graph.unclampedSize = Vector2.Scale(new Vector2(mx.x - mn.x, mx.z - mn.z), savedDimensions) * savedNodeSize; } } else if (Tools.current == Tool.Move) { EditorGUI.BeginChangeCheck(); center = Handles.PositionHandle(graph.center, Tools.pivotRotation == PivotRotation.Global ? Quaternion.identity : Quaternion.Euler(graph.rotation)); if (EditorGUI.EndChangeCheck() && Tools.viewTool != ViewTool.Orbit) { graph.center = center; } } else if (Tools.current == Tool.Rotate) { EditorGUI.BeginChangeCheck(); var rot = Handles.RotationHandle(Quaternion.Euler(graph.rotation), graph.center); if (EditorGUI.EndChangeCheck() && Tools.viewTool != ViewTool.Orbit) { graph.rotation = rot.eulerAngles; } } Handles.matrix = Matrix4x4.identity; }
/// <summary>Y coordinate of the center of the bounding box in graph space</summary> internal float GetY(GraphTransform transform) { return(transform.InverseTransform(useRotationAndScale ? tr.TransformPoint(center) : tr.position + center).y); }
// Token: 0x06002695 RID: 9877 RVA: 0x001A884F File Offset: 0x001A6A4F internal float GetY(GraphTransform transform) { return(transform.InverseTransform(this.useRotationAndScale ? this.tr.TransformPoint(this.center) : (this.tr.position + this.center)).y); }
public void VoxelizeInput(GraphTransform graphTransform, Bounds graphSpaceBounds) { AstarProfiler.StartProfile("Build Navigation Mesh"); AstarProfiler.StartProfile("Voxelizing - Step 1"); // Transform from voxel space to graph space. // then scale from voxel space (one unit equals one voxel) // Finally add min PF.Matrix4x4 voxelMatrix = PF.Matrix4x4.TRS(graphSpaceBounds.min, PF.Quaternion.identity, Vector3.one) * PF.Matrix4x4.Scale(new PF.Vector3(cellSize, cellHeight, cellSize)); transformVoxel2Graph = new GraphTransform(voxelMatrix); // Transform from voxel space to world space // add half a voxel to fix rounding transform = graphTransform * voxelMatrix * PF.Matrix4x4.TRS(new Vector3(0.5f, 0, 0.5f), PF.Quaternion.identity, Vector3.one); int maximumVoxelYCoord = (int)(graphSpaceBounds.size.y / cellHeight); AstarProfiler.EndProfile("Voxelizing - Step 1"); AstarProfiler.StartProfile("Voxelizing - Step 2 - Init"); // Cosine of the slope limit in voxel space (some tweaks are needed because the voxel space might be stretched out along the y axis) float slopeLimit = Mathf.Cos(Mathf.Atan(Mathf.Tan(maxSlope * Mathf.Deg2Rad) * (cellSize / cellHeight))); // Temporary arrays used for rasterization float[] vTris = new float[3 * 3]; float[] vOut = new float[7 * 3]; float[] vRow = new float[7 * 3]; float[] vCellOut = new float[7 * 3]; float[] vCell = new float[7 * 3]; if (inputMeshes == null) { throw new System.NullReferenceException("inputMeshes not set"); } // Find the largest lengths of vertex arrays and check for meshes which can be skipped int maxVerts = 0; for (int m = 0; m < inputMeshes.Count; m++) { maxVerts = System.Math.Max(inputMeshes[m].vertices.Length, maxVerts); } // Create buffer, here vertices will be stored multiplied with the local-to-voxel-space matrix var verts = new Vector3[maxVerts]; AstarProfiler.EndProfile("Voxelizing - Step 2 - Init"); AstarProfiler.StartProfile("Voxelizing - Step 2"); // This loop is the hottest place in the whole rasterization process // it usually accounts for around 50% of the time for (int m = 0; m < inputMeshes.Count; m++) { RasterizationMesh mesh = inputMeshes[m]; var meshMatrix = mesh.matrix; // Flip the orientation of all faces if the mesh is scaled in such a way // that the face orientations would change // This happens for example if a mesh has a negative scale along an odd number of axes // e.g it happens for the scale (-1, 1, 1) but not for (-1, -1, 1) or (1,1,1) var flipOrientation = UnityHelper.ReversesFaceOrientations(meshMatrix); Vector3[] vs = mesh.vertices; int[] tris = mesh.triangles; int trisLength = mesh.numTriangles; // Transform vertices first to world space and then to voxel space for (int i = 0; i < vs.Length; i++) { verts[i] = transform.InverseTransform(meshMatrix.MultiplyPoint3x4(vs[i])); } int mesharea = mesh.area; for (int i = 0; i < trisLength; i += 3) { Vector3 p1 = verts[tris[i]]; Vector3 p2 = verts[tris[i + 1]]; Vector3 p3 = verts[tris[i + 2]]; if (flipOrientation) { var tmp = p1; p1 = p3; p3 = tmp; } int minX = (int)(Utility.Min(p1.x, p2.x, p3.x)); int minZ = (int)(Utility.Min(p1.z, p2.z, p3.z)); int maxX = (int)System.Math.Ceiling(Utility.Max(p1.x, p2.x, p3.x)); int maxZ = (int)System.Math.Ceiling(Utility.Max(p1.z, p2.z, p3.z)); minX = Mathf.Clamp(minX, 0, voxelArea.width - 1); maxX = Mathf.Clamp(maxX, 0, voxelArea.width - 1); minZ = Mathf.Clamp(minZ, 0, voxelArea.depth - 1); maxZ = Mathf.Clamp(maxZ, 0, voxelArea.depth - 1); // Check if the mesh is completely out of bounds if (minX >= voxelArea.width || minZ >= voxelArea.depth || maxX <= 0 || maxZ <= 0) { continue; } Vector3 normal; int area; //AstarProfiler.StartProfile ("Rasterize..."); normal = Vector3.Cross(p2 - p1, p3 - p1); float cosSlopeAngle = Vector3.Dot(normal.normalized, Vector3.up); if (cosSlopeAngle < slopeLimit) { area = UnwalkableArea; } else { area = 1 + mesharea; } Utility.CopyVector(vTris, 0, p1); Utility.CopyVector(vTris, 3, p2); Utility.CopyVector(vTris, 6, p3); for (int x = minX; x <= maxX; x++) { int nrow = clipper.ClipPolygon(vTris, 3, vOut, 1F, -x + 0.5F, 0); if (nrow < 3) { continue; } nrow = clipper.ClipPolygon(vOut, nrow, vRow, -1F, x + 0.5F, 0); if (nrow < 3) { continue; } float clampZ1 = vRow[2]; float clampZ2 = vRow[2]; for (int q = 1; q < nrow; q++) { float val = vRow[q * 3 + 2]; clampZ1 = System.Math.Min(clampZ1, val); clampZ2 = System.Math.Max(clampZ2, val); } int clampZ1I = Mathf.Clamp((int)System.Math.Round(clampZ1), 0, voxelArea.depth - 1); int clampZ2I = Mathf.Clamp((int)System.Math.Round(clampZ2), 0, voxelArea.depth - 1); for (int z = clampZ1I; z <= clampZ2I; z++) { //AstarProfiler.StartFastProfile(1); int ncell = clipper.ClipPolygon(vRow, nrow, vCellOut, 1F, -z + 0.5F, 2); if (ncell < 3) { //AstarProfiler.EndFastProfile(1); continue; } ncell = clipper.ClipPolygonY(vCellOut, ncell, vCell, -1F, z + 0.5F, 2); if (ncell < 3) { //AstarProfiler.EndFastProfile(1); continue; } //AstarProfiler.EndFastProfile(1); //AstarProfiler.StartFastProfile(2); float sMin = vCell[1]; float sMax = vCell[1]; for (int q = 1; q < ncell; q++) { float val = vCell[q * 3 + 1]; sMin = System.Math.Min(sMin, val); sMax = System.Math.Max(sMax, val); } //AstarProfiler.EndFastProfile(2); int maxi = (int)System.Math.Ceiling(sMax); // Skip span if below or above the bounding box if (maxi >= 0 && sMin <= maximumVoxelYCoord) { // Make sure mini >= 0 int mini = System.Math.Max(0, (int)sMin); // Make sure the span is at least 1 voxel high maxi = System.Math.Max(mini + 1, maxi); voxelArea.AddLinkedSpan(z * voxelArea.width + x, (uint)mini, (uint)maxi, area, voxelWalkableClimb); } } } } //AstarProfiler.EndFastProfile(0); //AstarProfiler.EndProfile ("Rasterize..."); } AstarProfiler.EndProfile("Voxelizing - Step 2"); }