//x ~ (0, setting.maxX * power(2, subdivision)), z ~ (0, setting.maxZ * power(2, subdivision)) public QuadTreeLeaf GetLeaf(int x, int z, ref float centerx, ref float centerz, ref int subdivision) { int u = x >> subdivision; // x / power(2, subdivision); int v = z >> subdivision; int idx = u * setting.maxZ + v; if (idx > tree.Length) { return(null); } QuadTreeBase subtree = tree[idx]; //center pos centerx = setting.sliceSize[0] * u; centerz = setting.sliceSize[1] * v; // if (subtree is QuadTreeLeaf) { centerx += setting.sliceSize[0] * 0.5f; centerz += setting.sliceSize[1] * 0.5f; return((QuadTreeLeaf)subtree); } else {//sub tree node int detail = 1 << subdivision; int subx = x - u * detail; int subz = z - v * detail; subdivision -= 1; QuadTreeNode node = (QuadTreeNode)subtree; return(node.GetLeaf(subx, subz, setting.sliceSize[0] * 0.5f, setting.sliceSize[1] * 0.5f, ref centerx, ref centerz, ref subdivision)); } }
public QuadTreeLeaf GetLeaf(int x, int z, float sizex, float sizez, ref float centerx, ref float centerz, ref int subdivision) { int u = x >> subdivision; // x / power(2, subdivision); int v = z >> subdivision; //center pos centerx += sizex * u; centerz += sizez * v; // int idx = u * 2 + v; QuadTreeBase subtree = Children[idx]; if (subtree is QuadTreeLeaf) { centerx += sizex * 0.5f; centerz += sizex * 0.5f; return((QuadTreeLeaf)subtree); } else {//sub tree node int detail = 1 << subdivision; int subx = x - u * detail; int subz = z - v * detail; subdivision -= 1; QuadTreeNode node = (QuadTreeNode)subtree; return(node.GetLeaf(subx, subz, sizex * 0.5f, sizez * 0.5f, ref centerx, ref centerz, ref subdivision)); } }
//display functions public void GetDisplaySlice(float startx, float startz, int x, int z, List <DisplaySlice> lSlices) { //first grade QuadTreeBase subtree = tree[x * setting.maxZ + z]; GetNodeDisplaySlice(subtree, startx, startz, x, z, setting.sliceSize[0], setting.sliceSize[1], lSlices); }
public override bool IsEqual(QuadTreeBase other) { if (Slices != null && other is QuadTreeLeaf) { QuadTreeLeaf otherLeaf = (QuadTreeLeaf)other; if (otherLeaf.Slices != null && HashVal == otherLeaf.HashVal) { return(true); } } return(false); }
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 bool SaveData(string path, PillarSetting setting, QuadTreeBase[] trees) { if (File.Exists(path)) { File.Delete(path); } FileStream stream = File.Open(path, FileMode.Create); byte[] stbuff = setting.ToArray(); stream.Write(stbuff, 0, stbuff.Length); //trees byte[] bRootLeafBuff = new byte[1] { 1 << 4 }; for (int x = 0; x < setting.maxX; ++x) { for (int z = 0; z < setting.maxZ; ++z) { QuadTreeBase subTree = trees[x * setting.maxZ + z]; if (subTree is QuadTreeLeafSerializable) { stream.Write(bRootLeafBuff, 0, 1); QuadTreeLeafSerializable leaf = (QuadTreeLeafSerializable)subTree; leaf.Serialize(stream); } else { QuadTreeNodeSerializable node = (QuadTreeNodeSerializable)subTree; node.Serialize(stream); } } } stream.Close(); MPLog.Log("create data successed!"); return(true); }
//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; } } }
public override bool IsEqual(QuadTreeBase other) { return(false); }
public abstract bool IsEqual(QuadTreeBase other);