0

I am creating a quadtree for a 2D game in C# to make the rendering faster. Some of the objects (planets) are moving and that is why, I created a method called removeAndUpdate to update the tree by deleting and reinserting the specific object from the leaves (so not from the root) as I have already read in link. Unfortunately, I got System.OutOfMemoryException after some time at the reinsertion part. I am quite sure, that the removeAndUpdate method has some problems.

Maybe it is good to mention, that when a quad is subdivided (in case, when the quad's storing capacity is full), the content will not distributed among the subquads. I made this way to improve some performance. However, I don't think it has some connection with the problem above.

I guess, there is an infinite loop somewhere, which causes to run out of memory. If I insert new objects from the root, there is no problem.

I wrote a comment to the place where the exception occurs.

Here you can see the important parts of the QuadTree class:

public class QuadTree
{
    BoundingBox boundary;
    int capacity;
    List<WorldObject> leafContent;
    public QuadTree parent;
    bool divided;
    public List<QuadTree> childQuadTrees;

    public QuadTree(BoundingBox _boundary, int _capacity, QuadTree _parent)
    {
        this.boundary = _boundary;
        this.capacity = _capacity;
        this.leafContent = new List<WorldObject>();
        this.childQuadTrees = new List<QuadTree>();
        this.divided = false;
        this.parent = _parent;
    }

    // Subdividing the quad, if its storing capacity is full.
    public void subdivide()
    {
        // North-East
        this.childQuadTrees.Add(new QuadTree(new BoundingBox(new Vector3(boundary.Center.X, 0, boundary.Min.Z),
                                         new Vector3(boundary.Max.X, 0, boundary.Center.Z)), this.capacity, this));
        // North-West
        this.childQuadTrees.Add(new QuadTree(new BoundingBox(new Vector3(boundary.Min.X, 0, boundary.Min.Z),
                                        new Vector3(boundary.Center.X, 0, boundary.Center.Z)), this.capacity, this));
        // South-East
        this.childQuadTrees.Add(new QuadTree(new BoundingBox(boundary.Center, boundary.Max), this.capacity, this));
        // South-West
        this.childQuadTrees.Add(new QuadTree(new BoundingBox(new Vector3(boundary.Min.X, 0, boundary.Center.Z), new Vector3(boundary.Center.X, 0, boundary.Max.Z)), this.capacity, this));

        this.divided = true;
    }

    public void insert(WorldObject wO)
    {
        // Checking, whether the quad contains the box at all.
        if (!this.ContainOrOverlap(wO.BoundingBox))
        {
            return;
        }

        // If there is space, insert the box.
        if (this.leafContent.Count < this.capacity && this.divided == false)
        {



/*This is the instruction, where System.OutOfMemoryException occures*/
          this.leafContent.Add(wO); // <-------
          return;
        }

        // If not, subdivide the quad then insert the obj to the subquads.
        else
        {
            if (this.divided == false)
            {
                this.subdivide();
            }

            this.childQuadTrees[0].insert(wO);
            this.childQuadTrees[1].insert(wO);
            this.childQuadTrees[2].insert(wO);
            this.childQuadTrees[3].insert(wO);
        }
    }

    /* Here is the method to update the moving objects bounding volume.
    It first removes the element from the tree, updates the boundingbox, then reinsert the object from the leaves*/
    public void removeAndUpdate(WorldObject obj, Vector3 displacement)
    {
        if (!this.ContainOrOverlap(obj.BoundingBox))
        {
            return;
        }

        if (this.divided)
        {
            this.childQuadTrees[0].removeAndUpdate(obj, displacement);
            this.childQuadTrees[1].removeAndUpdate(obj, displacement);
            this.childQuadTrees[2].removeAndUpdate(obj, displacement);
            this.childQuadTrees[3].removeAndUpdate(obj, displacement);
        }

  /* if the obj is found, remove it, the try to reinsert it to its parent. If its parent does not contain it, move upwards in the hierarchy and try again to insert*/
        if (leafContent.Contains(obj))
        {
            this.leafContent.Remove(obj);
            QuadTree q = this.parent;
            while (q.ContainOrOverlap(obj.BoundingBox) == false)
            {
                q = q.parent;
            }
            obj.BoundingBox.Translate(displacement);
            q.insert(obj);
        }
    }

    public void query(BoundingBox range, List<WorldObject> resultList)
    {
        if (!this.ContainOrOverlap(range))
        {
            return;
        }

        if (this.divided)
        {

            this.childQuadTrees[0].query(range, resultList);
            this.childQuadTrees[1].query(range, resultList);
            this.childQuadTrees[2].query(range, resultList);
            this.childQuadTrees[3].query(range, resultList);
        }

        resultList.AddList(this.leafContent);
    }
}

Here is some info from the debug at the break of the exception:

enter image description here

Fox1942
  • 276
  • 2
  • 18
  • 2
    Have the debugger break once the exception is thrown and then you can see exactly what the cause is -- location, size. – MicroVirus Jun 09 '21 at 20:18
  • I guess there can be an infinite loop somewhere because I didn't see anything special in the debug, but I uploaded a screenshot. – Fox1942 Jun 09 '21 at 20:33
  • 1
    you should be looking at your memory usage in the debugger https://learn.microsoft.com/en-us/visualstudio/profiling/memory-usage-without-debugging2?view=vs-2019 – TJ Rockefeller Jun 09 '21 at 20:36
  • It is the size of the tree. It keeps adding elements until there is space in the memory. – Fox1942 Jun 09 '21 at 20:53
  • 1
    You'll have to make your tree smaller then, or if you want to experiment with a huge tree for a while then you can try to compile for 64 bit. – MicroVirus Jun 09 '21 at 21:34
  • I guess the problem is with the algorithm as, if I insert new objects from the root there is no problem. – Fox1942 Jun 10 '21 at 08:19

0 Answers0