Exemplo n.º 1
0
        //Code almost completely ripped from Recast
        public void FilterLedges(uint voxelWalkableHeight, int voxelWalkableClimb, float cs, float ch, Vector3 min)
        {
            int wd = voxelArea.width * voxelArea.depth;

#if !ASTAR_RECAST_CLASS_BASED_LINKED_LIST
            LinkedVoxelSpan[] spans      = voxelArea.linkedSpans;
            int[]             DirectionX = voxelArea.DirectionX;
            int[]             DirectionZ = voxelArea.DirectionZ;
#endif
            int width = voxelArea.width;

            //Filter all ledges
            for (int z = 0, pz = 0; z < wd; z += width, pz++)
            {
                for (int x = 0; x < width; x++)
                {
#if !ASTAR_RECAST_CLASS_BASED_LINKED_LIST
                    if (spans[x + z].bottom == VoxelArea.InvalidSpanValue)
                    {
                        continue;
                    }

                    for (int s = x + z; s != -1; s = spans[s].next)
                    {
                        //Skip non-walkable spans
                        if (spans[s].area == UnwalkableArea)
                        {
                            continue;
                        }

                        int bottom = (int)spans[s].top;
                        int top    = spans[s].next != -1 ? (int)spans[spans[s].next].bottom : VoxelArea.MaxHeightInt;

                        int minHeight = VoxelArea.MaxHeightInt;

                        int aMinHeight = (int)spans[s].top;
                        int aMaxHeight = aMinHeight;

                        for (int d = 0; d < 4; d++)
                        {
                            int nx = x + DirectionX[d];
                            int nz = z + DirectionZ[d];

                            //Skip out-of-bounds points
                            if (nx < 0 || nz < 0 || nz >= wd || nx >= width)
                            {
                                spans[s].area = UnwalkableArea;
                                break;
                            }

                            int nsx = nx + nz;

                            int nbottom = -voxelWalkableClimb;

                            int ntop = spans[nsx].bottom != VoxelArea.InvalidSpanValue ? (int)spans[nsx].bottom : VoxelArea.MaxHeightInt;

                            if (System.Math.Min(top, ntop) - System.Math.Max(bottom, nbottom) > voxelWalkableHeight)
                            {
                                minHeight = System.Math.Min(minHeight, nbottom - bottom);
                            }

                            //Loop through spans
                            if (spans[nsx].bottom != VoxelArea.InvalidSpanValue)
                            {
                                for (int ns = nsx; ns != -1; ns = spans[ns].next)
                                {
                                    nbottom = (int)spans[ns].top;
                                    ntop    = spans[ns].next != -1 ? (int)spans[spans[ns].next].bottom : VoxelArea.MaxHeightInt;

                                    if (System.Math.Min(top, ntop) - System.Math.Max(bottom, nbottom) > voxelWalkableHeight)
                                    {
                                        minHeight = System.Math.Min(minHeight, nbottom - bottom);

                                        if (System.Math.Abs(nbottom - bottom) <= voxelWalkableClimb)
                                        {
                                            if (nbottom < aMinHeight)
                                            {
                                                aMinHeight = nbottom;
                                            }
                                            if (nbottom > aMaxHeight)
                                            {
                                                aMaxHeight = nbottom;
                                            }
                                        }
                                    }
                                }
                            }
                        }

                        if (minHeight < -voxelWalkableClimb || (aMaxHeight - aMinHeight) > voxelWalkableClimb)
                        {
                            spans[s].area = UnwalkableArea;
                        }
                    }
#else
                    for (VoxelSpan s = voxelArea.cells[z + x].firstSpan; s != null; s = s.next)
                    {
                        //Skip non-walkable spans
                        if (s.area == UnwalkableArea)
                        {
                            continue;
                        }

                        int bottom = (int)s.top;
                        int top    = s.next != null ? (int)s.next.bottom : VoxelArea.MaxHeightInt;

                        int minHeight = VoxelArea.MaxHeightInt;

                        int aMinHeight = (int)s.top;
                        int aMaxHeight = (int)s.top;

                        for (int d = 0; d < 4; d++)
                        {
                            int nx = x + voxelArea.DirectionX[d];
                            int nz = z + voxelArea.DirectionZ[d];

                            //Skip out-of-bounds points
                            if (nx < 0 || nz < 0 || nz >= wd || nx >= voxelArea.width)
                            {
                                s.area = UnwalkableArea;
                                break;
                            }

                            VoxelSpan nsx = voxelArea.cells[nx + nz].firstSpan;

                            int nbottom = -voxelWalkableClimb;

                            int ntop = nsx != null ? (int)nsx.bottom : VoxelArea.MaxHeightInt;

                            if (AstarMath.Min(top, ntop) - AstarMath.Max(bottom, nbottom) > voxelWalkableHeight)
                            {
                                minHeight = AstarMath.Min(minHeight, nbottom - bottom);
                            }

                            //Loop through spans
                            for (VoxelSpan ns = nsx; ns != null; ns = ns.next)
                            {
                                nbottom = (int)ns.top;
                                ntop    = ns.next != null ? (int)ns.next.bottom : VoxelArea.MaxHeightInt;

                                if (AstarMath.Min(top, ntop) - AstarMath.Max(bottom, nbottom) > voxelWalkableHeight)
                                {
                                    minHeight = AstarMath.Min(minHeight, nbottom - bottom);

                                    if (AstarMath.Abs(nbottom - bottom) <= voxelWalkableClimb)
                                    {
                                        if (nbottom < aMinHeight)
                                        {
                                            aMinHeight = nbottom;
                                        }
                                        if (nbottom > aMaxHeight)
                                        {
                                            aMaxHeight = nbottom;
                                        }
                                    }
                                }
                            }
                        }

                        if (minHeight < -voxelWalkableClimb || (aMaxHeight - aMinHeight) > voxelWalkableClimb)
                        {
                            s.area = UnwalkableArea;
                        }
                    }
#endif
                }
            }
        }
Exemplo n.º 2
0
        public void BuildVoxelConnections()
        {
            AstarProfiler.StartProfile("Build Voxel Connections");

            int wd = voxelArea.width * voxelArea.depth;

            CompactVoxelSpan[] spans = voxelArea.compactSpans;
            CompactVoxelCell[] cells = voxelArea.compactCells;

            //Build voxel connections
            for (int z = 0, pz = 0; z < wd; z += voxelArea.width, pz++)
            {
                //System.Threading.ManualResetEvent[] handles = new System.Threading.ManualResetEvent[voxelArea.depth];

                //This will run the loop in multiple threads (speedup by ? 40%)
                //Parallel.For (0, voxelArea.depth, delegate (int pz) {
                //System.Threading.WaitCallback del = delegate (System.Object _pz) {
                //int pz = (int)_pz;
                //int z = pz*voxelArea.width;

                for (int x = 0; x < voxelArea.width; x++)
                {
                    CompactVoxelCell c = cells[x + z];

                    for (int i = (int)c.index, ni = (int)(c.index + c.count); i < ni; i++)
                    {
                        CompactVoxelSpan s = spans[i];

                        spans[i].con = 0xFFFFFFFF;

                        for (int d = 0; d < 4; d++)
                        {
                            int nx = x + voxelArea.DirectionX[d];
                            int nz = z + voxelArea.DirectionZ[d];

                            if (nx < 0 || nz < 0 || nz >= wd || nx >= voxelArea.width)
                            {
                                continue;
                            }

                            CompactVoxelCell nc = cells[nx + nz];

                            for (int k = (int)nc.index, nk = (int)(nc.index + nc.count); k < nk; k++)
                            {
                                CompactVoxelSpan ns = spans[k];

                                int bottom = System.Math.Max(s.y, ns.y);

                                int top = AstarMath.Min((int)s.y + (int)s.h, (int)ns.y + (int)ns.h);

                                if ((top - bottom) >= voxelWalkableHeight && System.Math.Abs((int)ns.y - (int)s.y) <= voxelWalkableClimb)
                                {
                                    uint connIdx = (uint)k - nc.index;

                                    if (connIdx > MaxLayers)
                                    {
                                        Debug.LogError("Too many layers");
                                        continue;
                                    }

                                    spans[i].SetConnection(d, connIdx);
                                    break;
                                }
                            }
                        }
                    }
                }

                //handles[pz].Set ();
                //};
                //});
            }

            /*for (int z=0, pz = 0;z < wd;z += voxelArea.width, pz++) {
             *      handles[pz] = new System.Threading.ManualResetEvent(false);
             *      System.Threading.ThreadPool.QueueUserWorkItem (del, pz);
             * }
             *
             * System.Threading.WaitHandle.WaitAll (handles);*/

            AstarProfiler.EndProfile("Build Voxel Connections");
        }