Ejemplo n.º 1
0
  void BVH2Intersector<TriangleIntersector>::intersect(const Ray& ray, Hit& hit) const
  {
    AVX_ZERO_UPPER();
    STAT3(normal.travs,1,1,1);

    struct StackItem {
      Base* ptr;   //!< node pointer
      float dist;  //!< distance of node
    };

    /*! stack state */
    StackItem stack[1+BVH2::maxDepth];  //!< stack of nodes that still need to get traversed
    StackItem* stackPtr = stack;        //!< current stack pointer
    Base* cur = bvh->root;              //!< in cur we track the ID of the current node

    /*! precomputed shuffles, to switch lower and upper bounds depending on ray direction */
    const ssei identity = _mm_set_epi8(15, 14, 13, 12, 11, 10,  9,  8,  7,  6,  5,  4,  3,  2,  1, 0);
    const ssei swap     = _mm_set_epi8( 7,  6,  5,  4,  3,  2,  1,  0, 15, 14, 13, 12, 11, 10,  9, 8);
    const ssei shuffleX = ray.dir.x >= 0 ? identity : swap;
    const ssei shuffleY = ray.dir.y >= 0 ? identity : swap;
    const ssei shuffleZ = ray.dir.z >= 0 ? identity : swap;

    /*! load the ray into SIMD registers */
    const ssei pn = ssei(0x00000000,0x00000000,0x80000000,0x80000000);
    const sse3f norg(-ray.org.x,-ray.org.y,-ray.org.z);
    const sse3f rdir = sse3f(ssef(ray.rdir.x) ^ pn, ssef(ray.rdir.y) ^ pn, ssef(ray.rdir.z) ^ pn);
    ssef nearFar(ray.near, ray.near, -ray.far, -ray.far);
    hit.t = min(hit.t,ray.far);

    while (true)
    {
      /*! downtraversal loop */
      while (likely(cur->isNode()))
      {
        /*! single ray intersection with box of both children. */
        const Node* node = cur->node();
        const ssef tNearFarX = (shuffle8(node->lower_upper_x,shuffleX) + norg.x) * rdir.x;
        const ssef tNearFarY = (shuffle8(node->lower_upper_y,shuffleY) + norg.y) * rdir.y;
        const ssef tNearFarZ = (shuffle8(node->lower_upper_z,shuffleZ) + norg.z) * rdir.z;
        const ssef tNearFar = max(tNearFarX,tNearFarY,tNearFarZ,nearFar) ^ pn;
        const sseb lrhit = tNearFar <= shuffle8(tNearFar,swap);

        /*! if two children hit, push far node onto stack and continue with closer node */
        if (likely(lrhit[0] != 0 && lrhit[1] != 0)) {
          if (likely(tNearFar[0] < tNearFar[1])) { 
            stackPtr->ptr = node->child[1]; 
            stackPtr->dist = tNearFar[1]; 
            cur = node->child[0]; 
            stackPtr++; 
          }
          else { 
            stackPtr->ptr = node->child[0]; 
            stackPtr->dist = tNearFar[0]; 
            cur = node->child[1]; 
            stackPtr++; 
          }
        }

        /*! if one child hit, continue with that child */
        else {
          if      (likely(lrhit[0] != 0)) cur = node->child[0];
          else if (likely(lrhit[1] != 0)) cur = node->child[1];
          else goto pop_node;
        }
      }

      /*! leaf node, intersect all triangles */
      {
        STAT3(shadow.trav_leaves,1,1,1);
        size_t num; Triangle* tri = (Triangle*) cur->leaf(num);
        for (size_t i=0; i<num; i++)
          TriangleIntersector::intersect(ray,hit,tri[i],bvh->vertices);
        nearFar = shuffle<0,1,2,3>(nearFar,-hit.t);
      }

      /*! pop next node from stack */
pop_node:
      if (unlikely(stackPtr == stack)) break;
      --stackPtr;
      cur = stackPtr->ptr;
      if (unlikely(stackPtr->dist > hit.t)) goto pop_node;
    }
    AVX_ZERO_UPPER();
  }
Ejemplo n.º 2
0
  bool BVH2Traverser::occluded(const Ray& ray) const
  {
    /*! stack state */
    int stackPtr = 0;                         //!< current stack pointer
    int stack[1+BVH2<Triangle4>::maxDepth];   //!< stack of nodes that still need to get traversed
    int cur = bvh->root;                      //!< in cur we track the ID of the current node

    /*! precomputed shuffles, to switch lower and upper bounds depending on ray direction */
    const ssei identity = _mm_set_epi8(15, 14, 13, 12, 11, 10,  9,  8,  7,  6,  5,  4,  3,  2,  1, 0);
    const ssei swap     = _mm_set_epi8( 7,  6,  5,  4,  3,  2,  1,  0, 15, 14, 13, 12, 11, 10,  9, 8);
    const ssei shuffleX = ray.dir.x >= 0 ? identity : swap;
    const ssei shuffleY = ray.dir.y >= 0 ? identity : swap;
    const ssei shuffleZ = ray.dir.z >= 0 ? identity : swap;

    /*! load the ray into SIMD registers */
    const ssei pn = ssei(0x00000000,0x00000000,0x80000000,0x80000000);
    const sse3f norg(-ray.org.x,-ray.org.y,-ray.org.z);
    const sse3f rdir = sse3f(ssef(ray.rdir.x) ^ pn, ssef(ray.rdir.y) ^ pn, ssef(ray.rdir.z) ^ pn);
    ssef nearFar(ray.near, ray.near, -ray.far, -ray.far);
    BVH2<Triangle4>::Node* nodes = bvh->nodes;

    while (true)
    {
      /*! this is an inner node */
      while (__builtin_expect(cur >= 0, true))
      {
        /*! Single ray intersection with box of both children. See bvh2.h for node layout. */
        const BVH2<Triangle4>::Node& node = bvh->node(nodes,cur);
        const ssef tNearFarX = (shuffle8(node.lower_upper_x,shuffleX) + norg.x) * rdir.x;
        const ssef tNearFarY = (shuffle8(node.lower_upper_y,shuffleY) + norg.y) * rdir.y;
        const ssef tNearFarZ = (shuffle8(node.lower_upper_z,shuffleZ) + norg.z) * rdir.z;
        const ssef tNearFar = max(tNearFarX,tNearFarY,tNearFarZ,nearFar) ^ pn;
        const sseb lrhit = tNearFar <= shuffle8(tNearFar,swap);

        /*! if two children hit, push far node onto stack and continue with closer node */
        if (__builtin_expect(lrhit[0] != 0 && lrhit[1] != 0, true)) {
          if (tNearFar[0] < tNearFar[1]) { stack[stackPtr++] = node.child[1]; cur = node.child[0]; }
          else                           { stack[stackPtr++] = node.child[0]; cur = node.child[1]; }
        }

        /*! if one child hit, continue with that child */
        else {
          if      (lrhit[0] != 0) cur = node.child[0];
          else if (lrhit[1] != 0) cur = node.child[1];
          else goto pop_node;
        }
      }

      /*! leaf node, intersect all triangles */
      {
        cur ^= 0x80000000;
        const size_t ofs = size_t(cur) >> 5;
        const size_t num = size_t(cur) & 0x1F;
        for (size_t i=ofs; i<ofs+num; i++)
          if (bvh->triangles[i].occluded(ray))
            return true;
      }

      /*! pop next node from stack */
pop_node:
      if (__builtin_expect(stackPtr == 0, false)) break;
      cur = stack[--stackPtr];
    }
    return false;
  }
Ejemplo n.º 3
0
  bool BVH2Intersector<TriangleIntersector>::occluded(const Ray& ray) const
  {
    AVX_ZERO_UPPER();

    /*! stack state */
    Base* stack[1+BVH2::maxDepth];   //!< stack of nodes that still need to get traversed
    Base** stackPtr = stack;         //!< current stack pointer
    Base* cur = bvh->root;           //!< in cur we track the ID of the current node

    /*! precomputed shuffles, to switch lower and upper bounds depending on ray direction */
    const ssei identity = _mm_set_epi8(15, 14, 13, 12, 11, 10,  9,  8,  7,  6,  5,  4,  3,  2,  1, 0);
    const ssei swap     = _mm_set_epi8( 7,  6,  5,  4,  3,  2,  1,  0, 15, 14, 13, 12, 11, 10,  9, 8);
    const ssei shuffleX = ray.dir.x >= 0 ? identity : swap;
    const ssei shuffleY = ray.dir.y >= 0 ? identity : swap;
    const ssei shuffleZ = ray.dir.z >= 0 ? identity : swap;

    /*! load the ray into SIMD registers */
    const ssei pn = ssei(0x00000000,0x00000000,0x80000000,0x80000000);
    const sse3f norg(-ray.org.x,-ray.org.y,-ray.org.z);
    const sse3f rdir = sse3f(ssef(ray.rdir.x) ^ pn, ssef(ray.rdir.y) ^ pn, ssef(ray.rdir.z) ^ pn);
    ssef nearFar(ray.near, ray.near, -ray.far, -ray.far);

    while (true)
    {
      /*! this is an inner node */
      while (likely(cur->isNode()))
      {
        /*! Single ray intersection with box of both children. See bvh2i.h for node layout. */
        const Node* node = cur->node();
        const ssef tNearFarX = (shuffle8(node->lower_upper_x,shuffleX) + norg.x) * rdir.x;
        const ssef tNearFarY = (shuffle8(node->lower_upper_y,shuffleY) + norg.y) * rdir.y;
        const ssef tNearFarZ = (shuffle8(node->lower_upper_z,shuffleZ) + norg.z) * rdir.z;
        const ssef tNearFar = max(tNearFarX,tNearFarY,tNearFarZ,nearFar) ^ pn;
        const sseb lrhit = tNearFar <= shuffle8(tNearFar,swap);

        /*! if two children hit, push far node onto stack and continue with closer node */
        if (likely(lrhit[0] != 0 && lrhit[1] != 0)) {
          *stackPtr++ = node->child[0]; cur = node->child[1];
        }

        /*! if one child hit, continue with that child */
        else {
          if      (lrhit[0] != 0) cur = node->child[0];
          else if (lrhit[1] != 0) cur = node->child[1];
          else goto pop_node;
        }
      }

      /*! leaf node, intersect all triangles */
      {
        STAT3(shadow.trav_leaves,1,1,1);
        size_t num; Triangle* tri = (Triangle*) cur->leaf(num);
        for (size_t i=0; i<num; i++)
          if (TriangleIntersector::occluded(ray,tri[i],bvh->vertices)) {
            AVX_ZERO_UPPER();
            return true;
          }
      }

      /*! pop next node from stack */
pop_node:
      if (unlikely(stackPtr == stack)) break;
      cur = *(--stackPtr);
    }
    AVX_ZERO_UPPER();
    return false;
  }