//! - Compute the nearest intersection of all objects within the tree. //! - Return true if hit was found, false otherwise. //! - In the case where we want to find out of there is _ANY_ intersection at all, //! set occlusion == true, in which case we exit on the first hit, rather //! than find the closest. bool BVH::getIntersection(const FastBVH::Ray& ray, FastBVH::IntersectionInfo* intersection, bool occlusion) const { intersection->t = 999999999.f; intersection->object = NULL; float bbhits[4]; int32_t closer, other; // Working set BVHTraversal todo[64]; int32_t stackptr = 0; // "Push" on the root node to the working set todo[stackptr].i = 0; todo[stackptr].mint = -9999999.f; while(stackptr>=0) { // Pop off the next node to work on. int ni = todo[stackptr].i; float near = todo[stackptr].mint; stackptr--; const BVHFlatNode &node(flatTree[ ni ]); // If this node is further than the closest found intersection, continue if(near > intersection->t) continue; // Is leaf -> Intersect if( node.rightOffset == 0 ) { for(uint32_t o=0;o<node.nPrims;++o) { FastBVH::IntersectionInfo current; const FastBVH::Object* obj = (*build_prims)[node.start+o]; bool hit = obj->getIntersection(ray, ¤t); if (hit) { // If we're only looking for occlusion, then any hit is good enough if(occlusion) { return true; } // Otherwise, keep the closest intersection only if(intersection->t <= 0 && current.t > 0) *intersection = current; if (current.t > 0 && current.t < intersection->t) { *intersection = current; } } } } else { // Not a leaf bool hitc0 = flatTree[ni+1].bbox.intersect(ray, bbhits, bbhits+1); bool hitc1 = flatTree[ni+node.rightOffset].bbox.intersect(ray, bbhits+2, bbhits+3); // Did we hit both nodes? if(hitc0 && hitc1) { // We assume that the left child is a closer hit... closer = ni+1; other = ni+node.rightOffset; // ... If the right child was actually closer, swap the relavent values. if(bbhits[2] < bbhits[0]) { std::swap(bbhits[0], bbhits[2]); std::swap(bbhits[1], bbhits[3]); std::swap(closer,other); } // It's possible that the nearest object is still in the other side, but we'll // check the further-awar node later... // Push the farther first todo[++stackptr] = BVHTraversal(other, bbhits[2]); // And now the closer (with overlap test) todo[++stackptr] = BVHTraversal(closer, bbhits[0]); } else if (hitc0) { todo[++stackptr] = BVHTraversal(ni+1, bbhits[0]); } else if(hitc1) { todo[++stackptr] = BVHTraversal(ni + node.rightOffset, bbhits[2]); } } } // If we hit something, if(intersection->object != NULL) intersection->hit = ray.o + ray.d * intersection->t; return intersection->object != NULL; }
void BVH::frustumCullingBox(Frustum& frustum, std::vector<int>& passedIdx) const { //Working set BVHTraversal todo[64]; int32_t stackptr = 0; // "Push" on the root node to the working set todo[stackptr].i = 0; //todo[stackptr].mint = -9999999.f; while(stackptr>=0) { // Pop off the next node to work on. int ni = todo[stackptr].i; float near = todo[stackptr].mint; stackptr--; const BVHFlatNode &node(flatTree[ ni ]); //added by sunf, if the node's bbox is not intersected by the ray, continue //float h1,h2; if ( frustum.ContainsBBox(flatTree[ni].bbox) == Out ) continue; // Is leaf -> Intersect if( node.rightOffset == 0 ) { for(uint32_t o=0;o<node.nPrims;++o) { const Object* obj = (*build_prims)[node.start+o]; Box* tri = (Box*)obj; if (frustum.ContainsBox(*tri) != Out) passedIdx.push_back(tri->getId()); } } else { // Not a leaf CullingResult hitc0 = frustum.ContainsBBox(flatTree[ni+1].bbox); CullingResult hitc1 = frustum.ContainsBBox(flatTree[ni+node.rightOffset].bbox); if (hitc0 == Intersect) todo[++stackptr] = BVHTraversal(ni+1, 0); else if(hitc0 == In) { //所有节点都输出 for(uint32_t o=0;o<flatTree[ni+1].nPrims;++o) { const Object* obj = (*build_prims)[flatTree[ni+1].start+o]; Box* tri = (Box*)obj; passedIdx.push_back(tri->getId()); } } if (hitc1 == Intersect) todo[++stackptr] = BVHTraversal(ni+node.rightOffset, 0); else if(hitc1 == In) { //所有节点都输出 for(uint32_t o=0;o<flatTree[ni+node.rightOffset].nPrims;++o) { const Object* obj = (*build_prims)[flatTree[ni+node.rightOffset].start+o]; Box* tri = (Box*)obj; passedIdx.push_back(tri->getId()); } } } } }