Tree Traversal
A common way i've seen of storing transforms is giving each node a pointer to it's parent, and a list of children. For example:
struct Transform {
Transform parent;
Transform children[];
Vector position;
Quaternion rotation;
Vector scale;
}
It's easy to do bredth first traversal with this layout, you can either do it recursivley or by utilizing a stack. Both require some allocation for traversal, and the children array requires an allocation as well. We could use a different data structure, a "First Child, Next Sibling" tree which allows for efficient depth first traversal without any additional memory or allocation. Let's explore how.
Instead of storing a parent reference and a list of children, we will store a parent, first child, and next sibling reference.
struct Transform {
Transform parent;
Transform firstChild;
Transform nextSibling;
Vector position;
Quaternion rotation;
Vector scale;
}
With this representation, traversal becomes:
void DepthFirstTraversal(Node root, NodeVisitorFnPtr callback) {
Node itr = root;
bool traversing = true;
while (traversing) {
callback(itr);
if (itr->children) {
itr = itr->firstChild;
}
else {
while (itr->nextSibling == null) {
if (itr == root) {
traversing = false;
break;
}
itr = itr->parent;
}
if (itr == root) { // Prevent stepping to the roots sibling
traversing = false;
break;
}
itr = itr->nextSibling;
}
}
}
Or, you can structure the code to be an interative function:
class Scene {
Node root
// Pass NULL to start from root.
// Or pass the result of the last call to DepthFirst
// Returns the next node, or NULL on exit
Node DepthFirst(Node iter = null) {
if (iter == null) {
return root;
}
if (iter->firstChild) {
iter = iter->firstChild;
}
else {
while (iter->nextSibling == null) {
if (iter == root) {
return null;
}
iter = iter->parent;
}
if (iter == root) {
return null;
}
iter = iter->nextSibling;
}
return iter;
}
}
Now traversal becomes:
for (Node* iter = scene.DepthFirst(); iter != null; iter = scene.DepthFirst(iter)) {
// Do something
}