Ejemplo n.º 1
0
    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);
    }
Ejemplo n.º 2
0
 public Octree(SplitPolicy splitPolicy, Vector3 position, float length, OctreeLeaf trace)
 {
     this.baseTrace = trace;
     this.position  = position;
     _splitPolicy   = splitPolicy;
     this.boxLength = length;
 }
Ejemplo n.º 3
0
 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);
 }
Ejemplo n.º 4
0
    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));
    }
Ejemplo n.º 5
0
 /// <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>());
 }
Ejemplo n.º 6
0
        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
        }
Ejemplo n.º 7
0
        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);
                    }
                }
            }
        }
Ejemplo n.º 8
0
        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());
        }
Ejemplo n.º 9
0
        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());
                    }
                }
            }
        }
Ejemplo n.º 10
0
        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
        }
Ejemplo n.º 11
0
        /// <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);
            }
        }
Ejemplo n.º 12
0
        //------------------------------------------------------------------------------
        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];
            }
        }
Ejemplo n.º 13
0
        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);
        }
Ejemplo n.º 14
0
    /// <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));
        }
    }
Ejemplo n.º 15
0
 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;
 }
Ejemplo n.º 16
0
 //------------------------------------------------------------------------------
 public void add(int id, OctreeLeaf lf)
 {
     _leafs.Add(lf);
 }
Ejemplo n.º 17
0
 /// <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;
 }
Ejemplo n.º 18
0
        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;
                }
            }
        }
Ejemplo n.º 19
0
        /// <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;
        }