Terminology first: I refer to quadtree quads as "nodes" within the quadtree structure, and I refer to flat array elements as "cells".
Every individual quad, at each subdivision depth, should have it's own wireframe view component. You should also have a flat 2D array that represents all of the quadtree leaf (i.e. deepest level) nodes in your entire root node. We'll call this a presence array. Basically this array shows us which cells have objects in them. You should have one such array for the last frame/update, and one for the new frame. At the start of every frame/update, determine deltas from the presence arrays by comparing their cells at each respective [x, y]
location, and recording any differences into lists as follows:
enteredInto
holds corresponding leaf nodes for any cells that changed from not present in last
array -> present in new
array.
departedFrom
holds corresponding leaf nodes for any cells that changed from present in last
array -> not present in new
array.
I would keep each of these as List<T>
.
These sets can each hold multiple entries because your object may be sitting over an intersection of four (or more) leaf cells, and because the object may be larger than a single cell.
Using these sets, you can flag each leaf node with a boolean to either render or not in the current frame/update. As soon as a leaf node is turned on for rendering, all of its ancestors must be automatically turned on for rendering, as well, right up to the root. I would implement this in a set
ter method, such that as soon as you set any lower level node, it walks up its ancestor list, setting flags all the way to the root. Be sure to switch off "just departed" cells before switching on "just entered" cells.