HPC Magazine avril 2013 - L'Atelier CUDA - Listing 3.

Traversée itérative de l’arborescence avec traitement explicite de la pile de récursion.


__device__ void traverseIterative( 
  CollisionList& list,
  BVH& bvh, 
  AABB& queryAABB, 
  int queryObjectIdx)
{
  // Allocation d’une pile de traversee sur la memoire locale de la thread.
  NodePtr stack[64];
  NodePtr* stackPtr = stack;
  // Push sur la pile : il n’y a pas de noeud en attente de traitement.
  *stackPtr++ = NULL; 

  // Traversee des noeuds a partir de la racine.
  NodePtr node = bvh.getRoot();
  do {
    // Verifie le chevauchement de chaque descendant.
    NodePtr childL = bvh.getLeftChild(node);
    NodePtr childR = bvh.getRightChild(node);
    bool overlapL = ( checkOverlap(queryAABB, bvh.getAABB(childL)) );
    bool overlapR = ( checkOverlap(queryAABB, bvh.getAABB(childR)) );

    // Chevauchement d’un descendant final => collision.
    if (overlapL && bvh.isLeaf(childL))
      list.add(queryObjectIdx, bvh.getObjectIdx(childL));

    if (overlapR && bvh.isLeaf(childR))
      list.add(queryObjectIdx, bvh.getObjectIdx(childR));

    // Chevauchement d’un noeud intermediaire => traversee.
    bool traverseL = (overlapL && !bvh.isLeaf(childL));
    bool traverseR = (overlapR && !bvh.isLeaf(childR));

    if (!traverseL && !traverseR)
      node = *--stackPtr; // pop à partir de la pile.
    else {
      node = (traverseL) ? childL : childR;
      if (traverseL && traverseR)
        *stackPtr++ = childR; // push sur la pile.
    }
  }
  while (node != NULL);
}