Пример #1
0
//! - 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, &current);

        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;
}
Пример #2
0
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());
				}
			}
		}
	}
}