//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); } } }
private void GetNodeDisplaySlice(QuadTreeBase subtree, float startx, float startz, int x, int z, float sizex, float sizez, List <DisplaySlice> lSlices) { //first grade if (subtree is QuadTreeLeaf) { QuadTreeLeaf leaf = (QuadTreeLeaf)subtree; GetLeafDisplaySlice(leaf.Slices, startx, startz, sizex, sizez, x, z, lSlices); } else {//sub tree node QuadTreeNode node = (QuadTreeNode)subtree; startx += sizex * x; startz += sizez * z; for (int i = 0; i < 4; ++i) { int subx = i >> 1; int subz = i & 0x00000001; GetNodeDisplaySlice(node.Children[i], startx, startz, subx, subz, sizex * 0.5f, sizez * 0.5f, lSlices); } } }
public static QuadTreeLeaf CombineTree(QuadTreeNode node, float dx, float dz, float sliceThickness, float slopeErr) { if (node == null) { return(null); } for (int i = 0; i < 4; ++i) { if (node.Children[i] is QuadTreeNode) { QuadTreeNode subNode = (QuadTreeNode)node.Children[i]; QuadTreeLeaf replacedLeaf = CombineTree(subNode, 0.5f * dx, 0.5f * dz, sliceThickness, slopeErr); if (replacedLeaf != null) { node.Children[i] = replacedLeaf; } } } if (node.isFullLeaf) { return(node.Combine(dx, dz, sliceThickness, slopeErr)); } return(null); }
//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; } } }