public void GetPathNeighbours(MPPathNode current, int maxX, int maxZ, MPNeigbours neighbours) { ulong[] curSlices = HeightSlicePool.GetSlices(current.SliceHeader); if (curSlices == null) { return; } //get current ceiling, where I can't go across ushort maxH = ushort.MaxValue; if (current.HIdx < curSlices.Length - 1) { ulong higherSlice = curSlices[current.HIdx + 1]; ushort higherf = SliceAccessor.flag(higherSlice); ushort higherheight = SliceAccessor.heightGrade(higherSlice); if ((higherf & SliceAccessor.SliceCeiling) > 0) { maxH = higherheight; } } for (int u = current.BoundaryXMin; u <= current.BoundaryXMax; ++u) { if (u < 0 || u >= maxX) { continue; } if (current.BoundaryZMin >= 0 && current.BoundaryZMin < maxZ) { GetPathNeighbour(current.HeightGrade, maxH, u, current.BoundaryZMin, neighbours); } if (current.BoundaryZMax >= 0 && current.BoundaryZMax < maxZ) { GetPathNeighbour(current.HeightGrade, maxH, u, current.BoundaryZMax, neighbours); } } for (int v = current.BoundaryZMin; v <= current.BoundaryZMax; ++v) { if (v < 0 || v >= maxZ) { continue; } if (current.BoundaryXMin >= 0 && current.BoundaryXMin < maxX) { GetPathNeighbour(current.HeightGrade, maxH, current.BoundaryXMin, v, neighbours); } if (current.BoundaryXMax >= 0 && current.BoundaryXMax < maxX) { GetPathNeighbour(current.HeightGrade, maxH, current.BoundaryXMax, v, neighbours); } } }
// public MPAStarPath(PillarData data) { mData = data; mDetail = 1 << data.setting.subdivision; mMaxDeatailX = data.setting.maxX * mDetail; mMaxDeatailZ = data.setting.maxZ * mDetail; mVolumeSizeX = data.setting.maxX * GridX; mVolumeSizeZ = data.setting.maxZ * GridZ; mDetailGridX = GridX / mDetail; mDetailGridZ = GridZ / mDetail; //each pillar height slice max to 64 mNeighbourCache = new MPNeigbours((mDetail + 1) * 4 * SliceAccessor.MaxHeightSliceCount); MPPathNodePool.AllocatePool(128); }
private void GetPathNeighbour(ushort curH, ushort maxH, int u, int v, MPNeigbours neighbours) { float centerx = 0; float centerz = 0; int subdivision = setting.subdivision; QuadTreeLeaf leaf = GetLeaf(u, v, ref centerx, ref centerz, ref subdivision); if (leaf == null || leaf.Slices == null) { return; } //bigger subdivision may has the same slice structure, add only one if (neighbours.Contains(leaf.Header)) { return; } //each height slice could be a neighbour if (leaf.Slices.Length == 1) { ulong floorSlice = leaf.Slices[0]; ushort height = SliceAccessor.heightGrade(floorSlice); byte flag = SliceAccessor.flag(floorSlice); if (CanMove2Neighbour(setting, curH, maxH, height, ushort.MaxValue)) { neighbours.Add(leaf.Header, u, v, 0, subdivision, setting.subdivision, centerx, centerz, floorSlice); } } else { for (uint i = 0; i < leaf.Slices.Length - 1; ++i) { ulong currentSlice = leaf.Slices[i]; byte currentf = SliceAccessor.flag(currentSlice); ushort currentheight = SliceAccessor.heightGrade(currentSlice); ulong higherSlice = leaf.Slices[i + 1]; byte higherf = SliceAccessor.flag(higherSlice); ushort higherheight = SliceAccessor.heightGrade(higherSlice); if (i == leaf.Slices.Length - 2 && (higherf & SliceAccessor.SliceCeiling) == 0) {//pillar roof if (CanMove2Neighbour(setting, curH, maxH, higherheight, ushort.MaxValue)) { neighbours.Add(leaf.Header, u, v, i + 1, subdivision, setting.subdivision, centerx, centerz, higherSlice); } break; } if ((currentf & SliceAccessor.SliceCeiling) > 0) { continue; } ushort currentMaxH = ushort.MaxValue; if ((higherf & SliceAccessor.SliceCeiling) > 0) {//check standable float holeHeight = (higherheight - currentheight) * setting.heightPerGrade; if (holeHeight < setting.boundHeight) { continue; } currentMaxH = higherheight; } if (CanMove2Neighbour(setting, curH, maxH, currentheight, currentMaxH)) { neighbours.Add(leaf.Header, u, v, i, subdivision, setting.subdivision, centerx, centerz, currentSlice); } } } }