Beispiel #1
0
        // 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);
        }
Beispiel #2
0
        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));
        }
Beispiel #3
0
        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;
                }
            }
        }
Beispiel #4
0
        /// <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);
        }
Beispiel #5
0
        // 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;
        }
Beispiel #7
0
 /// <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);
 }
Beispiel #8
0
 // 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);
 }
Beispiel #9
0
        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");
        }