public bool IsEqual(OrderedSlices other) { if (this.Count != other.Count || HashValue != other.HashValue) { return(false); } return(true); }
public void RunScan(Vector3 topOrigin, float heightPerGrade, float[] hRange, OrderedSlices slices) { float rayLen = hRange[1] - hRange[0]; int len = Physics.BoxCastNonAlloc(topOrigin, checkHalfExtent, Vector3.down, hitResultBuff, Quaternion.identity, 1.1f * rayLen); //floor for (int h = 0; h < len && h < SliceAccessor.MaxHeightSliceCount / 2; ++h) { RaycastHit hit = hitResultBuff[h]; if (Vector3.Dot(hit.normal, Vector3.up) < 0) { continue; } RawSlice rs = new RawSlice(); rs.height = hit.point.y; rs.flag = 0; slices.Add(rs); //Debug.Log(string.Format("u : {0}, v : {1}, height : {2}, flag : {3}", curXIdx, curZIdx, rs.height, rs.flag)); } slices.SortSlices(); if (slices.Count == 0) { slices.Add(infinitRoof); } //ceiling Vector3 down = topOrigin; down.y = slices[0].height + 2f * heightPerGrade; len = Physics.BoxCastNonAlloc(down, checkHalfExtent, Vector3.up, hitResultBuff, Quaternion.identity, 1.1f * rayLen); for (int h = 0; h < len && h < SliceAccessor.MaxHeightSliceCount / 2; ++h) { RaycastHit hit = hitResultBuff[h]; if (Vector3.Dot(hit.normal, Vector3.down) < 0) { continue; } RawSlice rs = new RawSlice(); rs.height = hit.point.y; rs.flag = 1; slices.Add(rs); //Debug.Log(string.Format("u : {0}, v : {1}, height : {2}, flag : {3}", curXIdx, curZIdx, rs.height, rs.flag)); } slices.Unify(hRange[0], heightPerGrade); }
//dynamically add pillars in //x ~ (0, setting.maxX * power(2, subdivision)), x ~ (0, setting.maxZ * power(2, subdivision)) public void AddPillar(int subdivision, int x, int z, OrderedSlices rawSlices) { //first grade int u = x >> subdivision; // x / power(2, subdivision); int v = z >> subdivision; int subx = x - u * (1 << subdivision); int subz = z - v * (1 << subdivision); --subdivision; int idx = (subx >> subdivision) * 2 + (subz >> subdivision); if (subdivision > 0) { if (Children[idx] is QuadTreeLeaf) { SubdividLeaf(idx); } QuadTreeNode node = (QuadTreeNode)Children[idx]; node.AddPillar(subdivision, subx, subz, rawSlices); } else { if (Children[idx] is QuadTreeNode) { MPLog.LogError("AddPillar leaf still a tree : " + subdivision); return; } QuadTreeLeaf leaf = (QuadTreeLeaf)Children[idx]; if (leaf.Slices != null) { HeightSlicePool.Push(leaf.Header, leaf.Slices); } leaf.Reset(rawSlices.Count, rawSlices.HashValue); for (int i = 0; i < rawSlices.Count; ++i) { leaf.Slices[i] = SliceAccessor.packVal(rawSlices[i].heightGrade, 0, 0, rawSlices[i].flag); } } }
//dynamic obstacles public void DynamicAddPillar(Vector3 pos, Bounds bnd) { Vector3 min = pos - bnd.extents; Vector3 max = pos + bnd.extents; int startU = 0, startV = 0, endU = mData.setting.maxX, endV = mData.setting.maxZ; TransformPos2UV(min, ref startU, ref startV); TransformPos2UV(max, ref endU, ref endV); Vector3 volumnMin = new Vector3(VolumeCenterX - 0.5f * mVolumeSizeX, VolumeFloor, VolumeCenterZ - 0.5f * mVolumeSizeZ); Vector3 checkHalfExtent = new Vector3(GridX / 2, VolumeHSliceT, GridZ / 2); mHeightScanner.Reset(checkHalfExtent); HashSet <uint> dirtyNodes = new HashSet <uint>(); OrderedSlices slices = new OrderedSlices(); int detailedSize = 1 << mData.setting.subdivision; for (int u = startU; u <= endU; ++u) { for (int v = startV; v <= endV; ++v) { int curXIdx = u >> mData.setting.subdivision; int curZIdx = v >> mData.setting.subdivision; QuadTreeBase subtree = mData.tree[curXIdx * mData.setting.maxZ + curZIdx]; QuadTreeNode node = null; if (subtree is QuadTreeLeaf) { QuadTreeLeaf leaf = (QuadTreeLeaf)subtree; node = QuadTreeNode.SubdivideLeaf(leaf); mData.tree[curXIdx * mData.setting.maxZ + curZIdx] = node; } else { node = (QuadTreeNode)subtree; } uint dirtyId = (uint)curXIdx; dirtyId = (dirtyId << 16) | (uint)curZIdx; if (!dirtyNodes.Contains(dirtyId)) { dirtyNodes.Add(dirtyId); } float fx = (float)(u + 0.5f) * mDetailGridX; float fz = (float)(v + 0.5f) * mDetailGridZ; Vector3 top = volumnMin + fx * Vector3.right + (VolumeCeiling + 10f * VolumeHSliceT) * Vector3.up + fz * Vector3.forward; slices.Clear(); mHeightScanner.RunScan(top, VolumeHSliceT, mData.setting.heightValRange, slices); node.AddPillar(mData.setting.subdivision, u, v, slices); } } //merge foreach (var dirtyId in dirtyNodes) { uint x = dirtyId >> 16; uint z = dirtyId & 0x0000ffff; int idx = (int)(x * mData.setting.maxZ + z); QuadTreeNode node = (QuadTreeNode)mData.tree[idx]; QuadTreeBase replaceLeaf = QuadTreeNode.CombineTree(node, 0.5f * GridX, 0.5f * GridZ, VolumeHSliceT, mData.setting.slopeErr); if (replaceLeaf != null) { mData.tree[idx] = replaceLeaf; } } }