Example #1
0
 typename BVHNStatistics<N>::Statistics BVHNStatistics<N>::statistics(NodeRef node, const double A, const BBox1f t0t1)
 {
   Statistics s;
   double dt = max(0.0f,t0t1.size());
   if (node.isAlignedNode())
   {
     AlignedNode* n = node.alignedNode();
     for (size_t i=0; i<N; i++) {
       if (n->child(i) == BVH::emptyNode) continue;
       s.statAlignedNodes.numChildren++;
       const double Ai = max(0.0f,halfArea(n->extend(i)));
       s = s + statistics(n->child(i),Ai,t0t1); 
     }
     s.statAlignedNodes.numNodes++;
     s.statAlignedNodes.nodeSAH += dt*A;
     s.depth++;
   }
   else if (node.isUnalignedNode())
   {
     UnalignedNode* n = node.unalignedNode();
     for (size_t i=0; i<N; i++) {
       if (n->child(i) == BVH::emptyNode) continue;
       s.statUnalignedNodes.numChildren++;
       const double Ai = max(0.0f,halfArea(n->extend(i)));
       s = s + statistics(n->child(i),Ai,t0t1); 
     }
     s.statUnalignedNodes.numNodes++;
     s.statUnalignedNodes.nodeSAH += dt*A;
     s.depth++;
   }
   else if (node.isAlignedNodeMB())
   {
     AlignedNodeMB* n = node.alignedNodeMB();
     for (size_t i=0; i<N; i++) {
       if (n->child(i) == BVH::emptyNode) continue;
       s.statAlignedNodesMB.numChildren++;
       const double Ai = max(0.0f,halfArea(n->extend0(i)));
       s = s + statistics(n->child(i),Ai,t0t1);
     }
     s.statAlignedNodesMB.numNodes++;
     s.statAlignedNodesMB.nodeSAH += dt*A;
     s.depth++;
   }
   else if (node.isUnalignedNodeMB())
   {
     UnalignedNodeMB* n = node.unalignedNodeMB();
     for (size_t i=0; i<N; i++) {
       if (n->child(i) == BVH::emptyNode) continue;
       s.statUnalignedNodesMB.numChildren++;
       const double Ai = max(0.0f,halfArea(n->extend0(i)));
       s = s + statistics(n->child(i),Ai,t0t1); 
     }
     s.statUnalignedNodesMB.numNodes++;
     s.statUnalignedNodesMB.nodeSAH += dt*A;
     s.depth++;
   }
   else if (node.isTransformNode())
   {
     s.statTransformNodes.numNodes++;
     s.statTransformNodes.nodeSAH += dt*A;
     s.depth++;
   }
   else if (node.isQuantizedNode())
   {
     QuantizedNode* n = node.quantizedNode();
     for (size_t i=0; i<N; i++) {
       if (n->child(i) == BVH::emptyNode) continue;
       s.statQuantizedNodes.numChildren++;
       const double Ai = max(0.0f,halfArea(n->extend(i)));
       s = s + statistics(n->child(i),Ai,t0t1); 
     }
     s.statQuantizedNodes.numNodes++;
     s.statQuantizedNodes.nodeSAH += dt*A;
     s.depth++;
   }
   else if (node.isLeaf())
   {
     size_t num; const char* tri = node.leaf(num);
     if (num)
     {
       for (size_t i=0; i<num; i++) {
         s.statLeaf.numPrims += bvh->primTy.size(tri+i*bvh->primTy.bytes);
       }
       s.statLeaf.numLeaves++;
       s.statLeaf.numPrimBlocks += num;
       s.statLeaf.leafSAH += dt*A*num;
       if (num-1 < Statistics::LeafStat::NHIST) {
         s.statLeaf.numPrimBlocksHistogram[num-1]++;
       }
     }
   }
   else {
     throw std::runtime_error("not supported node type in bvh_statistics");
   }
   return s;
 } 
Example #2
0
  void BVHNStatistics<N>::statistics(NodeRef node, const float A, size_t& depth)
  {
    if (node.isNode())
    {
      numAlignedNodes++;
      AlignedNode* n = node.node();
      bvhSAH += A*travCostAligned;
      depth = 0;
      for (size_t i=0; i<N; i++) {
        if (n->child(i) == BVH::emptyNode) continue;
        childrenAlignedNodes++;
        const float Ai = max(0.0f,halfArea(n->extend(i)));
        size_t cdepth; statistics(n->child(i),Ai,cdepth); 
        depth=max(depth,cdepth);
      }
      depth++;
    }
    else if (node.isUnalignedNode())
    {
      numUnalignedNodes++;
      UnalignedNode* n = node.unalignedNode();
      bvhSAH += A*travCostUnaligned;
      
      depth = 0;
      for (size_t i=0; i<N; i++) {
        if (n->child(i) == BVH::emptyNode) continue;
        childrenUnalignedNodes++;
        const float Ai = max(0.0f,halfArea(n->extend(i)));
        size_t cdepth; statistics(n->child(i),Ai,cdepth); 
        depth=max(depth,cdepth);
      }
      depth++;
    }
    else if (node.isNodeMB())
    {
      numAlignedNodesMB++;
      AlignedNodeMB* n = node.nodeMB();
      bvhSAH += A*travCostAligned;
      
      depth = 0;
      for (size_t i=0; i<N; i++) {
        if (n->child(i) == BVH::emptyNode) continue;
        childrenAlignedNodesMB++;
        const float Ai = max(0.0f,halfArea(n->extend0(i)));
        size_t cdepth; statistics(n->child(i),Ai,cdepth); 
        depth=max(depth,cdepth);
      }
      depth++;
    }
    else if (node.isUnalignedNodeMB())
    {
      numUnalignedNodesMB++;
      UnalignedNodeMB* n = node.unalignedNodeMB();
      bvhSAH += A*travCostUnaligned;
      
      depth = 0;
      for (size_t i=0; i<N; i++) {
        if (n->child(i) == BVH::emptyNode) continue;
        childrenUnalignedNodesMB++;
        const float Ai = max(0.0f,halfArea(n->extend0(i)));
        size_t cdepth; statistics(n->child(i),Ai,cdepth); 
        depth=max(depth,cdepth);
      }
      depth++;
    }
    else if (node.isTransformNode())
    {
      numTransformNodes++;
      TransformNode* n = node.transformNode();
      bvhSAH += A*travCostTransform;

      depth = 0;
      const BBox3fa worldBounds = xfmBounds(n->local2world,n->localBounds);
      const float Ai = max(0.0f,halfArea(worldBounds));
      //size_t cdepth; statistics(n->child,Ai,cdepth); 
      //depth=max(depth,cdepth)+1;
    }
    else
    {
      depth = 0;
      size_t num; const char* tri = node.leaf(num);
      if (!num) return;
      
      numLeaves++;
      numPrimBlocks += num;
      for (size_t i=0; i<num; i++)
        numPrims += bvh->primTy.size(tri+i*bvh->primTy.bytes);
      
      float sah = A * intCost * num;
      leafSAH += sah;
    }
  } 
Example #3
0
    void BVH4Intersector1<types,robust,PrimitiveIntersector>::occluded(const BVH4* bvh, Ray& ray)
    {
      /*! perform per ray precalculations required by the primitive intersector */
      Precalculations pre(ray);
      BVH4::UnalignedNodeMB::Precalculations pre1(ray);

      /*! stack state */
      NodeRef stack[stackSize];  //!< stack of nodes that still need to get traversed
      NodeRef* stackPtr = stack+1;        //!< current stack pointer
      NodeRef* stackEnd = stack+stackSize;
      stack[0] = bvh->root;
      
      /*! load the ray into SIMD registers */
      const Vec3fa ray_rdir = rcp_safe(ray.dir);
      const Vec3fa ray_org_rdir = ray.org*ray_rdir;
      const sse3f org(ray.org.x,ray.org.y,ray.org.z);
      const sse3f dir(ray.dir.x,ray.dir.y,ray.dir.z);
      const sse3f rdir(ray_rdir.x,ray_rdir.y,ray_rdir.z);
      const sse3f org_rdir(ray_org_rdir.x,ray_org_rdir.y,ray_org_rdir.z);
      const ssef  ray_near(ray.tnear);
      ssef ray_far(ray.tfar);

      /*! offsets to select the side that becomes the lower or upper bound */
      const size_t nearX = ray_rdir.x >= 0 ? 0*sizeof(ssef) : 1*sizeof(ssef);
      const size_t nearY = ray_rdir.y >= 0 ? 2*sizeof(ssef) : 3*sizeof(ssef);
      const size_t nearZ = ray_rdir.z >= 0 ? 4*sizeof(ssef) : 5*sizeof(ssef);      
      
      /* pop loop */
      while (true) pop:
      {
        /*! pop next node */
        if (unlikely(stackPtr == stack)) break;
        stackPtr--;
        NodeRef cur = (NodeRef) *stackPtr;
        
        /* downtraversal loop */
        while (true)
        {
	  size_t mask; 
	  ssef tNear;

	  /*! stop if we found a leaf node */
	  if (unlikely(cur.isLeaf(types))) break;
	  STAT3(shadow.trav_nodes,1,1,1);

	  /* process standard nodes */
          if (likely(cur.isNode(types)))
	    mask = cur.node()->intersect<robust>(nearX,nearY,nearZ,org,rdir,org_rdir,ray_near,ray_far,tNear); 

	  /* process motion blur nodes */
	  else if (likely(cur.isNodeMB(types)))
	    mask = cur.nodeMB()->intersect(nearX,nearY,nearZ,org,rdir,org_rdir,ray_near,ray_far,ray.time,tNear); 

	  /*! process nodes with unaligned bounds */
          else if (unlikely(cur.isUnalignedNode(types)))
            mask = cur.unalignedNode()->intersect(org,dir,ray_near,ray_far,tNear);

          /*! process nodes with unaligned bounds and motion blur */
          else if (unlikely(cur.isUnalignedNodeMB(types)))
            mask = cur.unalignedNodeMB()->intersect(pre1,org,dir,ray_near,ray_far,ray.time,tNear);
	  
          /*! if no child is hit, pop next node */
	  const BVH4::BaseNode* node = cur.baseNode(types);
          if (unlikely(mask == 0))
            goto pop;
	  
	  /*! one child is hit, continue with that child */
          size_t r = __bscf(mask);
          if (likely(mask == 0)) {
            cur = node->child(r); cur.prefetch(types); 
            assert(cur != BVH4::emptyNode);
            continue;
          }
          
          /*! two children are hit, push far child, and continue with closer child */
          NodeRef c0 = node->child(r); c0.prefetch(types); const unsigned int d0 = ((unsigned int*)&tNear)[r];
          r = __bscf(mask);
          NodeRef c1 = node->child(r); c1.prefetch(types); const unsigned int d1 = ((unsigned int*)&tNear)[r];
          assert(c0 != BVH4::emptyNode);
          assert(c1 != BVH4::emptyNode);
          if (likely(mask == 0)) {
            assert(stackPtr < stackEnd);
            if (d0 < d1) { *stackPtr = c1; stackPtr++; cur = c0; continue; }
            else         { *stackPtr = c0; stackPtr++; cur = c1; continue; }
          }
          assert(stackPtr < stackEnd);
          *stackPtr = c0; stackPtr++;
          assert(stackPtr < stackEnd);
          *stackPtr = c1; stackPtr++;
          
          /*! three children are hit */
          r = __bscf(mask);
          cur = node->child(r); cur.prefetch(types);
          assert(cur != BVH4::emptyNode);
          if (likely(mask == 0)) continue;
          assert(stackPtr < stackEnd);
          *stackPtr = cur; stackPtr++;
          
          /*! four children are hit */
          cur = node->child(3); cur.prefetch(types);
          assert(cur != BVH4::emptyNode);
        }
        
        /*! this is a leaf node */
	assert(cur != BVH4::emptyNode);
        STAT3(shadow.trav_leaves,1,1,1);
        size_t num; Primitive* prim = (Primitive*) cur.leaf(num);
        if (PrimitiveIntersector::occluded(pre,ray,prim,num,bvh->geometry)) {
          ray.geomID = 0;
          break;
        }
      }
      AVX_ZERO_UPPER();
    }
Example #4
0
    void BVH4Intersector1<types,robust,PrimitiveIntersector>::intersect(const BVH4* bvh, Ray& ray)
    {
      /*! perform per ray precalculations required by the primitive intersector */
      Precalculations pre(ray);
      BVH4::UnalignedNodeMB::Precalculations pre1(ray);

      /*! stack state */
      StackItemInt32<NodeRef> stack[stackSize];            //!< stack of nodes 
      StackItemInt32<NodeRef>* stackPtr = stack+1;        //!< current stack pointer
      StackItemInt32<NodeRef>* stackEnd = stack+stackSize;
      stack[0].ptr  = bvh->root;
      stack[0].dist = neg_inf;
            
      /*! load the ray into SIMD registers */
      const Vec3fa ray_rdir = rcp_safe(ray.dir);
      const Vec3fa ray_org_rdir = ray.org*ray_rdir;
      const sse3f org(ray.org.x,ray.org.y,ray.org.z);
      const sse3f dir(ray.dir.x,ray.dir.y,ray.dir.z);
      const sse3f rdir(ray_rdir.x,ray_rdir.y,ray_rdir.z);
      const sse3f org_rdir(ray_org_rdir.x,ray_org_rdir.y,ray_org_rdir.z);
      const ssef  ray_near(ray.tnear);
      ssef ray_far(ray.tfar);

      /*! offsets to select the side that becomes the lower or upper bound */
      const size_t nearX = ray_rdir.x >= 0.0f ? 0*sizeof(ssef) : 1*sizeof(ssef);
      const size_t nearY = ray_rdir.y >= 0.0f ? 2*sizeof(ssef) : 3*sizeof(ssef);
      const size_t nearZ = ray_rdir.z >= 0.0f ? 4*sizeof(ssef) : 5*sizeof(ssef);

      /* pop loop */
      while (true) pop:
      {
        /*! pop next node */
        if (unlikely(stackPtr == stack)) break;
        stackPtr--;
        NodeRef cur = NodeRef(stackPtr->ptr);
        
        /*! if popped node is too far, pop next one */
        if (unlikely(*(float*)&stackPtr->dist > ray.tfar))
          continue;
        
        /* downtraversal loop */
        while (true)
        {
	  size_t mask; 
	  ssef tNear;

	  /*! stop if we found a leaf node */
	  if (unlikely(cur.isLeaf(types))) break;
	  STAT3(normal.trav_nodes,1,1,1);

	  /* process standard nodes */
          if (likely(cur.isNode(types)))
	    mask = cur.node()->intersect<robust>(nearX,nearY,nearZ,org,rdir,org_rdir,ray_near,ray_far,tNear); 

	  /* process motion blur nodes */
	  else if (likely(cur.isNodeMB(types)))
	    mask = cur.nodeMB()->intersect(nearX,nearY,nearZ,org,rdir,org_rdir,ray_near,ray_far,ray.time,tNear); 

	  /*! process nodes with unaligned bounds */
          else if (unlikely(cur.isUnalignedNode(types)))
            mask = cur.unalignedNode()->intersect(org,dir,ray_near,ray_far,tNear);

          /*! process nodes with unaligned bounds and motion blur */
          else if (unlikely(cur.isUnalignedNodeMB(types)))
            mask = cur.unalignedNodeMB()->intersect(pre1,org,dir,ray_near,ray_far,ray.time,tNear);

          /*! if no child is hit, pop next node */
	  const BVH4::BaseNode* node = cur.baseNode(types);
          if (unlikely(mask == 0))
            goto pop;
          
          /*! one child is hit, continue with that child */
	  size_t r = __bscf(mask);
	  if (likely(mask == 0)) {
            cur = node->child(r); cur.prefetch(types);
            assert(cur != BVH4::emptyNode);
            continue;
          }
          
          /*! two children are hit, push far child, and continue with closer child */
          NodeRef c0 = node->child(r); c0.prefetch(types); const unsigned int d0 = ((unsigned int*)&tNear)[r];
          r = __bscf(mask);
          NodeRef c1 = node->child(r); c1.prefetch(types); const unsigned int d1 = ((unsigned int*)&tNear)[r];
          assert(c0 != BVH4::emptyNode);
          assert(c1 != BVH4::emptyNode);
          if (likely(mask == 0)) {
            assert(stackPtr < stackEnd); 
            if (d0 < d1) { stackPtr->ptr = c1; stackPtr->dist = d1; stackPtr++; cur = c0; continue; }
            else         { stackPtr->ptr = c0; stackPtr->dist = d0; stackPtr++; cur = c1; continue; }
          }
          
          /*! Here starts the slow path for 3 or 4 hit children. We push
           *  all nodes onto the stack to sort them there. */
          assert(stackPtr < stackEnd); 
          stackPtr->ptr = c0; stackPtr->dist = d0; stackPtr++;
          assert(stackPtr < stackEnd); 
          stackPtr->ptr = c1; stackPtr->dist = d1; stackPtr++;
          
          /*! three children are hit, push all onto stack and sort 3 stack items, continue with closest child */
          assert(stackPtr < stackEnd); 
          r = __bscf(mask);
          NodeRef c = node->child(r); c.prefetch(types); unsigned int d = ((unsigned int*)&tNear)[r]; stackPtr->ptr = c; stackPtr->dist = d; stackPtr++;
          assert(c != BVH4::emptyNode);
          if (likely(mask == 0)) {
            sort(stackPtr[-1],stackPtr[-2],stackPtr[-3]);
            cur = (NodeRef) stackPtr[-1].ptr; stackPtr--;
            continue;
          }
          
          /*! four children are hit, push all onto stack and sort 4 stack items, continue with closest child */
          assert(stackPtr < stackEnd); 
          r = __bscf(mask);
          c = node->child(r); c.prefetch(types); d = *(unsigned int*)&tNear[r]; stackPtr->ptr = c; stackPtr->dist = d; stackPtr++;
          assert(c != BVH4::emptyNode);
          sort(stackPtr[-1],stackPtr[-2],stackPtr[-3],stackPtr[-4]);
          cur = (NodeRef) stackPtr[-1].ptr; stackPtr--;
        }
        
        /*! this is a leaf node */
	assert(cur != BVH4::emptyNode);
        STAT3(normal.trav_leaves,1,1,1);
        size_t num; Primitive* prim = (Primitive*) cur.leaf(num);
        PrimitiveIntersector::intersect(pre,ray,prim,num,bvh->geometry);
        ray_far = ray.tfar;
      }
      AVX_ZERO_UPPER();
    }
Example #5
0
  void BVH4Statistics::statistics(NodeRef node, const float A, size_t& depth)
  {
    if (node.isNode())
      {
	hash += 0x1234;
	numAlignedNodes++;
	AlignedNode* n = node.node();
	bvhSAH += A*BVH4::travCostAligned;
	depth = 0;
	for (size_t i=0; i<BVH4::N; i++) {
	  if (n->child(i) == BVH4::emptyNode) continue;
	  childrenAlignedNodes++;
	  const float Ai = max(0.0f,halfArea(n->extend(i)));
	  size_t cdepth; statistics(n->child(i),Ai,cdepth); 
	  depth=max(depth,cdepth);
	}
	depth++;
	hash += 0x76767*depth;
      }
    else if (node.isUnalignedNode())
      {
	hash += 0x1232344;
	numUnalignedNodes++;
	UnalignedNode* n = node.unalignedNode();
	bvhSAH += A*BVH4::travCostUnaligned;

	depth = 0;
	for (size_t i=0; i<BVH4::N; i++) {
	  if (n->child(i) == BVH4::emptyNode) continue;
	  childrenUnalignedNodes++;
	  const float Ai = max(0.0f,halfArea(n->extend(i)));
	  size_t cdepth; statistics(n->child(i),Ai,cdepth); 
	  depth=max(depth,cdepth);
	}
	depth++;
	hash += 0x76767*depth;
      }
    else if (node.isNodeMB())
      {
	hash += 0xEF343;
	numAlignedNodesMB++;
	BVH4::NodeMB* n = node.nodeMB();
	bvhSAH += A*BVH4::travCostAligned;

	depth = 0;
	for (size_t i=0; i<BVH4::N; i++) {
	  if (n->child(i) == BVH4::emptyNode) continue;
	  childrenAlignedNodesMB++;
	  const float Ai = max(0.0f,halfArea(n->extend0(i)));
	  size_t cdepth; statistics(n->child(i),Ai,cdepth); 
	  depth=max(depth,cdepth);
	}
	depth++;
	hash += 0x76767*depth;
      }
    else if (node.isUnalignedNodeMB())
      {
	hash += 0x1EEF4;
	numUnalignedNodesMB++;
	BVH4::UnalignedNodeMB* n = node.unalignedNodeMB();
	bvhSAH += A*BVH4::travCostUnaligned;

	depth = 0;
	for (size_t i=0; i<BVH4::N; i++) {
	  if (n->child(i) == BVH4::emptyNode) continue;
	  childrenUnalignedNodesMB++;
	  const float Ai = max(0.0f,halfArea(n->extend0(i)));
	  size_t cdepth; statistics(n->child(i),Ai,cdepth); 
	  depth=max(depth,cdepth);
	}
	depth++;
	hash += 0x76767*depth;
      }
    else
      {
	depth = 0;
	size_t num; const char* tri = node.leaf(num);
	hash += 0xDD776*num+0x878;
	if (!num) return;

	hash += bvh->primTy.hash(tri,num);
      
	numLeaves++;
	numPrims += num;
	float sah = A * BVH4::intCost * num;
	bvhSAH += sah;
      }
  }