public bool AddNode(OctreeLeaf leaf) { if (Branch == null) { Items.Add(leaf); if (Items.Count == 1) { AllTheSamePoint = true; FirstX = leaf.X; FirstY = leaf.Y; FirstZ = leaf.Z; } else { if (FirstX != leaf.X || FirstY != leaf.Y || FirstZ != leaf.Z) { AllTheSamePoint = false; } } if (Items.Count > MaxItems && !AllTheSamePoint) Split(); return true; } OctreeNode node = GetChild(leaf.X, leaf.Y, leaf.Z); return node != null && node.AddNode(leaf); }
public Octree(SplitPolicy splitPolicy, Vector3 position, float length, OctreeLeaf trace) { this.baseTrace = trace; this.position = position; _splitPolicy = splitPolicy; this.boxLength = length; }
public object RemoveNode(OctreeLeaf leaf) { if (Branch == null) { // This must be the node that has it... for (int i = 0; i < Items.Count; i++) { var qtl = (OctreeLeaf)Items[i]; if (leaf.LeafObject != qtl.LeafObject) { continue; } Items.RemoveAt(i); return(qtl.LeafObject); } } else { OctreeNode node = GetChild(leaf.X, leaf.Y, leaf.Z); if (node != null) { return(node.RemoveNode(leaf)); } } return(null); }
public bool AddNode(OctreeLeaf leaf) { if (Branch == null) { Items.Add(leaf); if (Items.Count == 1) { AllTheSamePoint = true; FirstX = leaf.X; FirstY = leaf.Y; FirstZ = leaf.Z; } else { if (FirstX != leaf.X || FirstY != leaf.Y || FirstZ != leaf.Z) { AllTheSamePoint = false; } } if (Items.Count > MaxItems && !AllTheSamePoint) { Split(); } return(true); } OctreeNode node = GetChild(leaf.X, leaf.Y, leaf.Z); return(node != null && node.AddNode(leaf)); }
/// <summary> /// Create a new Scene manager. /// </summary> public Scene() { objects = new Dictionary<int, List<GameObject>>(); rooms = new List<Room>(); //TODO: find root bounding box size octTreeRoot = new OctreeLeaf(new BoundingBox(new Vector3(-15000f), new Vector3(15000f)), 2, 0); octTreeRoot.setContainedObjects(new List<GameObject>()); }
private int AddLeaf(int parent, List <ItemEntry> items) { Debug.Assert(parent >= 0); Debug.Assert(parent % NodeSize == 0); Debug.Assert(parent < nodeCount * NodeSize); Debug.Assert(leafCount >= 0); Debug.Assert(leafCount <= leafs.Length); if (leafCount == leafs.Length) { // Grow the array to accomodate more leafs var newLeafs = new OctreeLeaf[leafs.Length * 2]; leafs.CopyTo(newLeafs, 0); leafs = newLeafs; } var cacheIndex = 0; var cacheSize = InitialNodeCapacity; while (cacheSize < items.Count) { cacheSize *= 2; cacheIndex++; } ItemEntry[] leafContent; var cache = ContentCache[cacheIndex]; if (cache.Count > 0) { // Extract the item container from the cache leafContent = cache[cache.Count - 1]; cache.RemoveAt(cache.Count - 1); } else { // Cache is empty, create a new container leafContent = new ItemEntry[cacheSize]; } for (var i = 0; i < items.Count; i++) { leafContent[i] = items[i]; } leafs[leafCount] = new OctreeLeaf(parent, leafContent, items.Count); leafCount++; return(-leafCount); // Leafs have negative indexing starting at -1 }
private void RemoveNode(int index) { Debug.Assert(index >= 0); Debug.Assert(index < nodeCount * NodeSize); Debug.Assert(index % NodeSize == 0); Debug.Assert(index != 0, "Can't remove root node"); nodeCount--; var lastIndex = nodeCount * NodeSize; if (index < lastIndex) { // Replace with the last node to prevent empty entries for (var i = 0; i < NodeSize; i++) { nodes[index + i] = nodes[lastIndex + i]; } // Update child reference of parent var parentIndex = nodes[index]; for (var i = ChildIndexOffset; i < NodeSize; i++) { if (nodes[parentIndex + i] == lastIndex) { // Update reference to the moved entry nodes[parentIndex + i] = index; break; } } // Update parent references of children for (var i = ChildIndexOffset; i < NodeSize; i++) { var child = nodes[index + i]; if (child > 0) { nodes[child] = index; } else if (child < 0) { var leafIndex = -(child + 1); var leaf = leafs[leafIndex]; leafs[leafIndex] = new OctreeLeaf(index, leaf.Content, leaf.Count); } } } }
private float[] FindVertices(GeometryShader shader) { List <float> verts = new List <float>(); FindSolidFacesDelegate <UInt16> solidCheck = (x => { var comp = BlockManager.Get(x).GetComponant <VisibilityBComponant>(); if (comp != null) { return(comp.SolidFaces); } return(Face.None); }); foreach (Octree <UInt16> octree in Chunk.Octrees) { var iter = (OctreeEnumerator <UInt16>)octree.GetEnumerator(); while (iter.MoveNext()) { OctreeLeaf <UInt16> leaf = iter.Current; BlockType type = BlockManager.Get(leaf.Value); var vis = type.GetComponant <VisibilityBComponant>(); if (vis == null || !vis.IsVisible) { continue; } var mdl = type.GetComponant <ModelBComponant>(); if (mdl == null) { continue; } int size = iter.Size; Vector3 offset = new Vector3(iter.X, iter.Y, iter.Z); verts.AddRange(mdl.Model.GenerateVertexData(offset, size, leaf.FindExposedFaces(solidCheck))); } } return(verts.ToArray()); }
private void SurfaceAdj(OctreeLeaf l, Dictionary <OctreeLeaf, Surface> nodesuf, int i, int j, int k) { OctreeNode n = l.getAdjacentNOde(i - 1, j - 1, k - 1); if (n != null) { Surface s; if (nodesuf.TryGetValue((OctreeLeaf)n, out s)) { if (s != null) { Render.GL_Draw.glLine(l.Sigma, n.Sigma, _g1, s.SurfColour); } else { Render.GL_Draw.glLine(l.Sigma, n.Sigma, _g1, Colour.Blue()); } } } }
private int AddLeaf(int parent, ItemEntry item) { Debug.Assert(parent >= 0); Debug.Assert(parent % NodeSize == 0); Debug.Assert(parent < nodeCount * NodeSize); Debug.Assert(leafCount >= 0); Debug.Assert(leafCount <= leafs.Length); if (leafCount == leafs.Length) { // Grow the array to accomodate more leafs var newLeafs = new OctreeLeaf[leafs.Length * 2]; leafs.CopyTo(newLeafs, 0); leafs = newLeafs; } ItemEntry[] leafContent; var cache = ContentCache[0]; if (cache.Count > 0) { // Extract the item container from the cache leafContent = cache[cache.Count - 1]; cache.RemoveAt(cache.Count - 1); } else { // Cache is empty, create a new container leafContent = new ItemEntry[DefaultLeafCapacity]; } leafContent[0] = item; leafs[leafCount] = new OctreeLeaf(parent, leafContent, 1); leafCount++; return(-leafCount); // Leafs have negative indexing starting at -1 }
/// <inheritdoc/> public bool Remove(T item, Vector3 position) { if (position.x < min.x || position.y < min.y || position.z < min.z || position.x > min.x + size.x || position.y > min.y + size.y || position.z > min.z + size.z) { return(false); } this.version++; var index = 0; var halfSize = size / 2f; var localMin = min; while (true) { var childIndex = 0; if (position.x > localMin.x + halfSize.x) { childIndex += 4; localMin.x += halfSize.x; } if (position.y > localMin.y + halfSize.y) { childIndex += 2; localMin.y += halfSize.y; } if (position.z > localMin.z + halfSize.z) { childIndex += 1; localMin.z += halfSize.z; } var nextIndex = nodes[index + childIndex + ChildIndexOffset]; if (nextIndex == 0) { return(false); } if (nextIndex > 0) { // Prepare for going one layer deeper halfSize /= 2f; // The node has a sub node for that area, restart search for that sub node index = nextIndex; continue; } // The node has a leaf for that area var leafIndex = -(nextIndex + 1); var leaf = leafs[leafIndex]; // Test if the item is in the leaf for (var i = 0; i < leaf.Count; i++) { if (leaf.Content[i].Position == position && Equals(leaf.Content[i].item, item)) { if (leaf.Count > 1) { if (i < leaf.Count - 1) { // If not last item, replace with last to prevent empty spots leaf.Content[i] = leaf.Content[leaf.Count - 1]; } leaf.Content[leaf.Count - 1] = default; leafs[leafIndex] = new OctreeLeaf(leaf.Parent, leaf.Content, leaf.Count - 1); } else { var content = leaf.Content; RemoveLeaf(leafIndex); CacheContentArray(content); nodes[index + childIndex + ChildIndexOffset] = 0; } // Remove the item from the item count of all containing nodes var removalIndex = index; nodes[removalIndex + 1]--; while (removalIndex != 0) { removalIndex = nodes[removalIndex]; nodes[removalIndex + 1]--; } if (nodes[index + 1] < NodeCollapseCount) { CollapseNode(index); } return(true); } } return(false); } }
//------------------------------------------------------------------------------ private void FlagSubset(out int [] contig, Surface Join) { List <int> res = new List <int>(); res.Add(0); int fmax = 0; int pmax = leafCount; int iq = 0, dq = 0; int joinid = -1; if (Join != null) { joinid = Join.ID; pmax += Join.leafCount; } List <OctreeLeaf> q = new List <OctreeLeaf>(pmax); for (int k = 0; k < pmax; k++) { q.Add(null); } Surface s = this; while (s != null) { List <OctreeLeaf> nl = s.Leafs; for (int i = 0; i < s.leafCount; i++) { OctreeLeaf l = nl[i]; if (l.Flag == 0) { //start new sub set flag it and enqueue fmax++; l.Flag = fmax; res.Add(1); iq = dq = 0; q[iq] = l; iq++; // deque nodes process adj while (dq < iq) { if (dq < q.Count) { l = q[dq]; for (int x = -1; x < 2; x++) { for (int y = -1; y < 2; y++) { for (int z = -1; z < 2; z++) { OctreeLeaf adj = (OctreeLeaf)l.getAdjacentNOde(x, y, z); if (adj != null) { if ((adj.SurfaceNum == ID) || (adj.SurfaceNum == joinid)) { if (adj.Flag == 0) { adj.Flag = fmax; res[fmax]++; if (iq < q.Count) { q[iq] = adj; } iq++; } } // surf } } // for z -1,0,1 } // for y -1,0,1 } // for x -1,0,1 } dq++; } //queque } // al unflagged nodes } // for all leafs if (s == this) { s = Join; } else { s = null; } }//while s!= null // find largest contiguous segment int mm = 0; for (int i = 0; i <= fmax; i++) { if (res[i] > mm) { mm = res[i]; res[0] = i; } } //contig contig = new int [res.Count]; for (int i = 0; i < res.Count; i++) { contig[i] = res[i]; } }
public override Octree <UInt16> Generate(int x, int y, int z, int size, int resolution = 1) { Octree <UInt16> octree = base.Generate(x, y, z, size, resolution); Random rand = new Random(Seed); UInt16 empty = BlockManager.GetID("Core_Empty"); UInt16[] sand = new UInt16[15]; UInt16[] rock = new UInt16[15]; for (int i = 0; i < 15; ++i) { sand[i] = BlockManager.GetID("MarsMiner_Sand", i); rock[i] = BlockManager.GetID("MarsMiner_Rock", i); } Face[] slopeFaces = new Face[] { Face.Front, Face.Left, Face.Back, Face.Right }; UInt16 boulder = BlockManager.GetID("MarsMiner_Boulder"); int min = System.Math.Min(myMinHilly, myMinPlains); int gradRange = 2; octree.SetCuboid(x, 0, z, size, System.Math.Min(myMinHilly, myMinPlains), size, rock[14]); if (y + size >= min) { int hillDiff = (myMaxHilly - myMinHilly) / 2; int hillMid = myMinHilly + hillDiff; int plainDiff = (myMinPlains - myMaxPlains) / 2; int plainMid = myMaxPlains + plainDiff; int maxCount = size / resolution; double hres = resolution / 2.0; int[,] heightmap = new int[maxCount + gradRange * 2, maxCount + gradRange * 2]; double[,] gradmap = new double[maxCount, maxCount]; for (int i = 0; i < maxCount + gradRange * 2; ++i) { double dx = (x + (i - gradRange) * resolution + hres) / 256.0; for (int j = 0; j < maxCount + gradRange * 2; ++j) { double dy = (z + (j - gradRange) * resolution + hres) / 256.0; double hillVal = Tools.Clamp(myHillyNoise.GetValue(dx, dy, 0.5) * hillDiff + hillMid, myMinHilly, myMaxHilly); double plainVal = Tools.Clamp(myHillyNoise.GetValue(dx, dy, 0.5) * plainDiff + plainMid, myMinPlains, myMaxPlains); double trans = Tools.Clamp((myTransNoise.GetValue(dx, dy, 0.5) + 1.0) / 2.0, 0.0, 1.0); //trans *= trans; int val = (int)System.Math.Floor(trans * hillVal + (1 - trans) * plainVal); heightmap[i, j] = val / resolution * resolution; } } for (int i = 0; i < maxCount; ++i) { for (int j = 0; j < maxCount; ++j) { double grad = 0; for (int gx = -gradRange; gx <= gradRange; ++gx) { for (int gy = -gradRange; gy <= gradRange; ++gy) { if (gx == 0 && gy == 0) { continue; } double dist = System.Math.Sqrt(gx * gx + gy * gy); int diff = heightmap[i + gradRange + gx, j + gradRange + gy] - heightmap[i + gradRange, j + gradRange]; grad += System.Math.Abs(diff) / dist; } } gradmap[i, j] = grad; } } Cuboid rcuboid = new Cuboid(0, 0, 0, resolution, 1, resolution); Cuboid scuboid = new Cuboid(0, 0, 0, 1, 1, 1); int[,] prev = null; for (int count = 1; count <= maxCount; count <<= 1) { int res = size / count; hres = res / 2.0; int[,] cur = new int[count, count]; int sca = res / resolution; rcuboid.Width = res; rcuboid.Depth = res; scuboid.Width = res; scuboid.Height = res; scuboid.Depth = res; for (int nx = 0; nx < count; ++nx) { int rx = x + nx * res; int px = nx >> 1; for (int nz = 0; nz < count; ++nz) { int rz = z + nz * res; int pz = nz >> 1; int realHeight = heightmap[nx * sca + gradRange, nz *sca + gradRange]; int height = realHeight / res * res; cur[nx, nz] = height; int prevHeight = (count == 1 ? 0 : prev[px, pz]); rcuboid.X = rx; rcuboid.Z = rz; rcuboid.Bottom = System.Math.Min(height, prevHeight); rcuboid.Top = System.Math.Max(height, prevHeight); if (height > prevHeight) { octree.SetCuboid(rcuboid, rock[14]); } else { octree.SetCuboid(rcuboid, empty); } if ((res == 1 || (resolution > 1 && height == realHeight)) && gradmap[nx, nz] <= 8.0 * res) { scuboid.X = rx; scuboid.Y = height - res; scuboid.Z = rz; octree.SetCuboid(scuboid, sand[14]); } } } prev = cur; } for (int colxi = 0; colxi < size / resolution; ++colxi) { int colx = colxi * resolution + x; for (int colzi = 0; colzi < size / resolution; ++colzi) { int colz = colzi * resolution + z; int height = heightmap[colxi + gradRange, colzi + gradRange]; OctreeLeaf <UInt16> curLeaf = octree.FindNode(colx, height - resolution, colz, resolution) as OctreeLeaf <UInt16>; if (curLeaf != null && curLeaf.Value != empty) { int[] ns = new int[] { heightmap[colxi + gradRange - 1, colzi + gradRange + 1], heightmap[colxi + gradRange + 0, colzi + gradRange + 1], heightmap[colxi + gradRange + 1, colzi + gradRange + 1], heightmap[colxi + gradRange - 1, colzi + gradRange + 0], heightmap[colxi + gradRange + 1, colzi + gradRange + 0], heightmap[colxi + gradRange - 1, colzi + gradRange - 1], heightmap[colxi + gradRange + 0, colzi + gradRange - 1], heightmap[colxi + gradRange + 1, colzi + gradRange - 1] }; bool[] bs = new bool[8]; for (int i = 0; i < 8; ++i) { bs[i] = ns[i] >= height; } int index = 0; if (bs[5] && (bs[3] && bs[6])) { index |= 1 << 0; } if (bs[7] && (bs[4] && bs[6])) { index |= 1 << 1; } if (bs[0] && (bs[1] && bs[3])) { index |= 1 << 2; } if (bs[2] && (bs[1] && bs[4])) { index |= 1 << 3; } if (index > 0) { octree.SetCuboid( colx, height - resolution, colz, resolution, resolution, resolution, (UInt16)(curLeaf.Value + index - 15)); } } } } } return(octree); }
/// <summary> /// Split this octree leaf into child leaves. /// </summary> protected void split() { Vector3 half = (containerBox.Max - containerBox.Min) / 2; Vector3 halfx = Vector3.UnitX * half; Vector3 halfy = Vector3.UnitY * half; Vector3 halfz = Vector3.UnitZ * half; BoundingBox[] boxes = { new BoundingBox(containerBox.Min, containerBox.Min + half), new BoundingBox(containerBox.Min + halfx, containerBox.Min + half + halfx), new BoundingBox(containerBox.Min + halfy, containerBox.Min + half + halfy), new BoundingBox(containerBox.Min + halfz, containerBox.Min + half + halfz), new BoundingBox(containerBox.Min + halfx + halfy, containerBox.Min + half + halfx + halfy), new BoundingBox(containerBox.Min + halfx + halfz, containerBox.Min + half + halfx + halfz), new BoundingBox(containerBox.Min + halfy + halfz, containerBox.Min + half + halfy + halfz), new BoundingBox(containerBox.Min + half, containerBox.Max) }; childLeaves.Clear(); foreach( BoundingBox tempBox in boxes) { OctreeLeaf tempLeaf = new OctreeLeaf(tempBox, maxDepth, currentDepth+1); foreach(GameObject obj in containedObjects){ BoundingSphere objSphere = new BoundingSphere(obj.position.pos(), obj.size); if (tempBox.Contains(objSphere) != ContainmentType.Disjoint || objSphere.Contains(tempBox) != ContainmentType.Disjoint) { tempLeaf.containedObjects.Add(obj); } } if (currentDepth < maxDepth && tempLeaf.containedObjects.Count != 0){ tempLeaf.split(); } childLeaves.Add(tempLeaf); } if (debugOctreeDepth) { Console.WriteLine("Current node depth: " + currentDepth + " Next depth: " + (currentDepth + 1)); } }
public object RemoveNode(OctreeLeaf leaf) { if (Branch == null) { // This must be the node that has it... for (int i = 0; i < Items.Count; i++) { var qtl = (OctreeLeaf)Items[i]; if (leaf.LeafObject != qtl.LeafObject) continue; Items.RemoveAt(i); return qtl.LeafObject; } } else { OctreeNode node = GetChild(leaf.X, leaf.Y, leaf.Z); if (node != null) { return node.RemoveNode(leaf); } } return null; }
//------------------------------------------------------------------------------ public void add(int id, OctreeLeaf lf) { _leafs.Add(lf); }
/// <summary> Remove a OctreeLeaf out of the tree at a location. /// /// </summary> /// <param name="leaf">object-location composite /// <returns> the object removed, null if the object not found. /// </returns> public object RemoveNode(OctreeLeaf leaf) { if (branch == null) { // This must be the node that has it... for (int i = 0; i < items.Count; i++) { OctreeLeaf qtl = (OctreeLeaf)items[i]; if (leaf.LeafObject == qtl.LeafObject) { items.RemoveAt(i); return qtl.LeafObject; } } } else { OctreeNode node = getChild(leaf.X, leaf.Y, leaf.Z); if (node != null) { return node.RemoveNode(leaf); } } return null; }
private void AddToNode(T item, Vector3 position, int index, int depth, Vector3 localMin, Vector3 halfSize, bool testForDuplicate) { while (true) { var childIndex = 0; if (position.x > localMin.x + halfSize.x) { childIndex += 4; localMin.x += halfSize.x; } if (position.y > localMin.y + halfSize.y) { childIndex += 2; localMin.y += halfSize.y; } if (position.z > localMin.z + halfSize.z) { childIndex += 1; localMin.z += halfSize.z; } var nextIndex = nodes[index + childIndex + ChildIndexOffset]; nodes[index + 1]++; // Increase the node child count if (nextIndex == 0) { // The node doesn't have a sub node or leaf for that area var newLeafIndex = AddLeaf(index, new ItemEntry(item, position)); nodes[index + childIndex + ChildIndexOffset] = newLeafIndex; break; } if (nextIndex > 0) { // Prepare for going one layer deeper halfSize /= 2f; depth++; // The node has a sub node for that area, restart search for that sub node index = nextIndex; continue; } // The node has a leaf for that area var leafIndex = -(nextIndex + 1); var leaf = leafs[leafIndex]; // Make sure the item isn't already part of the octree if (testForDuplicate) { for (var i = 0; i < leaf.Count; i++) { // If the item is already part of the tree, don't add again if (leaf.Content[i].Position == position && Equals(leaf.Content[i].item, item)) { // Revert the item count because the item wasn't actually added nodes[index + 1]--; while (index != 0) { index = nodes[index]; nodes[index + 1]--; } return; } } } // If the leaf has the capacity to store the item, just add it if (leaf.Count < leaf.Content.Length) { // Add the item to the leaf content and update the leaf count leaf.Content[leaf.Count] = new ItemEntry(item, position); leafs[leafIndex] = new OctreeLeaf(leaf.Parent, leaf.Content, leaf.Count + 1); break; } // If we can go deeper, replace the leaf with a node if (depth < MaxDepth) { // Prepare for going one layer deeper halfSize /= 2f; depth++; var content = leaf.Content; var cnt = leaf.Count; RemoveLeaf(leafIndex); // Remove the leaf nextIndex = AddNode(index); // Create a new node nodes[index + childIndex + ChildIndexOffset] = nextIndex; // Replace the leaf reference with the node reference index = nextIndex; // Continue with the current item for (var i = 0; i < cnt; i++) { AddToNode(content[i].item, content[i].Position, index, depth, localMin, halfSize, false); } CacheContentArray(content); } else { // The max depth has been reached, expand the leaf var newContent = ExpandContentArray(leaf.Content); newContent[leaf.Count] = new ItemEntry(item, position); leafs[leafIndex] = new OctreeLeaf(leaf.Parent, newContent, leaf.Count + 1); break; } } }
/// <summary> Add a OctreeLeaf into the tree at a location.</summary> /// <param name="leaf">object-location composite</param> /// <returns> true if the pution worked.</returns> public bool AddNode(OctreeLeaf leaf) { if (branch == null) { this.items.Add(leaf); if (this.items.Count == 1) { this.allTheSamePoint = true; this.firstX = leaf.X; this.firstY = leaf.Y; this.firstZ = leaf.Z; } else { if (this.firstX != leaf.X || this.firstY != leaf.Y || this.firstZ != leaf.Z) { this.allTheSamePoint = false; } } if (this.items.Count > maxItems && !this.allTheSamePoint) split(); return true; } else { OctreeNode node = getChild(leaf.X, leaf.Y, leaf.Z); if (node != null) { return node.AddNode(leaf); } } return false; }