| 598 | |
| 599 | template<int N, int K, int types, bool robust, typename PrimitiveIntersectorK, bool single> |
| 600 | void BVHNIntersectorKHybrid<N, K, types, robust, PrimitiveIntersectorK, single>::occluded(vint<K>* __restrict__ valid_i, |
| 601 | Accel::Intersectors* __restrict__ This, |
| 602 | RayK<K>& __restrict__ ray, |
| 603 | RayQueryContext* context) |
| 604 | { |
| 605 | BVH* __restrict__ bvh = (BVH*)This->ptr; |
| 606 | |
| 607 | /* we may traverse an empty BVH in case all geometry was invalid */ |
| 608 | if (bvh->root == BVH::emptyNode) |
| 609 | return; |
| 610 | |
| 611 | #if ENABLE_FAST_COHERENT_CODEPATHS == 1 |
| 612 | assert(context); |
| 613 | if (unlikely(types == BVH_AN1 && context->user && context->isCoherent())) |
| 614 | { |
| 615 | occludedCoherent(valid_i, This, ray, context); |
| 616 | return; |
| 617 | } |
| 618 | #endif |
| 619 | |
| 620 | /* filter out already occluded and invalid rays */ |
| 621 | vbool<K> valid = (*valid_i == -1) & (ray.tfar >= 0.0f); |
| 622 | #if defined(EMBREE_IGNORE_INVALID_RAYS) |
| 623 | valid &= ray.valid(); |
| 624 | #endif |
| 625 | |
| 626 | /* return if there are no valid rays */ |
| 627 | const size_t valid_bits = movemask(valid); |
| 628 | if (unlikely(valid_bits == 0)) return; |
| 629 | |
| 630 | /* verify correct input */ |
| 631 | assert(all(valid, ray.valid())); |
| 632 | assert(all(valid, ray.tnear() >= 0.0f)); |
| 633 | assert(!(types & BVH_MB) || all(valid, (ray.time() >= 0.0f) & (ray.time() <= 1.0f))); |
| 634 | Precalculations pre(valid, ray); |
| 635 | |
| 636 | /* load ray */ |
| 637 | TravRayK<K, robust> tray(ray.org, ray.dir, single ? N : 0); |
| 638 | const vfloat<K> org_ray_tnear = max(ray.tnear(), 0.0f); |
| 639 | const vfloat<K> org_ray_tfar = max(ray.tfar , 0.0f); |
| 640 | |
| 641 | tray.tnear = select(valid, org_ray_tnear, vfloat<K>(pos_inf)); |
| 642 | tray.tfar = select(valid, org_ray_tfar , vfloat<K>(neg_inf)); |
| 643 | |
| 644 | vbool<K> terminated = !valid; |
| 645 | const vfloat<K> inf = vfloat<K>(pos_inf); |
| 646 | |
| 647 | /* determine switch threshold based on flags */ |
| 648 | const size_t switchThreshold = (context->user && context->isCoherent()) ? 2 : switchThresholdIncoherent; |
| 649 | |
| 650 | /* allocate stack and push root node */ |
| 651 | vfloat<K> stack_near[stackSizeChunk]; |
| 652 | NodeRef stack_node[stackSizeChunk]; |
| 653 | stack_node[0] = BVH::invalidNode; |
| 654 | stack_near[0] = inf; |
| 655 | stack_node[1] = bvh->root; |
| 656 | stack_near[1] = tray.tnear; |
| 657 | NodeRef* stackEnd MAYBE_UNUSED = stack_node+stackSizeChunk; |
nothing calls this directly
no test coverage detected