typename BVHN<N>::NodeRef BVHN<N>::layoutLargeNodesRecursion(NodeRef& node, FastAllocator::ThreadLocal& allocator) { if (node.isBarrier()) { node.clearBarrier(); return node; } else if (node.isNode()) { Node* oldnode = node.node(); Node* newnode = (BVHN::Node*) allocator.malloc(sizeof(BVHN::Node),byteNodeAlignment); *newnode = *oldnode; for (size_t c=0; c<N; c++) newnode->child(c) = layoutLargeNodesRecursion(oldnode->child(c),allocator); return encodeNode(newnode); } else return node; }
BVH4::NodeRef BVH4::layoutLargeNodesRecursion(NodeRef& node) { if (node.isBarrier()) { node.clearBarrier(); return node; } else if (node.isNode()) { Node* oldnode = node.node(); Node* newnode = (BVH4::Node*) alloc.threadLocal2()->alloc0.malloc(sizeof(BVH4::Node)); // FIXME: optimize access to threadLocal2 *newnode = *oldnode; for (size_t c=0; c<BVH4::N; c++) newnode->child(c) = layoutLargeNodesRecursion(oldnode->child(c)); return encodeNode(newnode); } else return node; }
void BVHN<N>::layoutLargeNodes(size_t num) { struct NodeArea { __forceinline NodeArea() {} __forceinline NodeArea(NodeRef& node, const BBox3fa& bounds) : node(&node), A(node.isLeaf() ? float(neg_inf) : area(bounds)) {} __forceinline bool operator< (const NodeArea& other) const { return this->A < other.A; } NodeRef* node; float A; }; std::vector<NodeArea> lst; lst.reserve(num); lst.push_back(NodeArea(root,empty)); while (lst.size() < num) { std::pop_heap(lst.begin(), lst.end()); NodeArea n = lst.back(); lst.pop_back(); if (!n.node->isNode()) break; Node* node = n.node->node(); for (size_t i=0; i<N; i++) { if (node->child(i) == BVHN::emptyNode) continue; lst.push_back(NodeArea(node->child(i),node->bounds(i))); std::push_heap(lst.begin(), lst.end()); } } for (size_t i=0; i<lst.size(); i++) lst[i].node->setBarrier(); root = layoutLargeNodesRecursion(root,*alloc.threadLocal2()->alloc0); }