1// Copyright 2009-2021 Intel Corporation
2// SPDX-License-Identifier: Apache-2.0
3
4#pragma once
5
6#include "triangle.h"
7#include "triangle_intersector_moeller.h"
8
9namespace embree
10{
11 namespace isa
12 {
13 /*! Intersects M triangles with 1 ray */
14 template<int M, bool filter>
15 struct TriangleMIntersector1Moeller
16 {
17 typedef TriangleM<M> Primitive;
18 typedef MoellerTrumboreIntersector1<M> Precalculations;
19
20 /*! Intersect a ray with the M triangles and updates the hit. */
21 static __forceinline void intersect(const Precalculations& pre, RayHit& ray, IntersectContext* context, const TriangleM<M>& tri)
22 {
23 STAT3(normal.trav_prims,1,1,1);
24 pre.intersectEdge(ray,tri.v0,tri.e1,tri.e2,UVIdentity<M>(),Intersect1EpilogM<M,filter>(ray,context,tri.geomID(),tri.primID()));
25 }
26
27 /*! Test if the ray is occluded by one of M triangles. */
28 static __forceinline bool occluded(const Precalculations& pre, Ray& ray, IntersectContext* context, const TriangleM<M>& tri)
29 {
30 STAT3(shadow.trav_prims,1,1,1);
31 return pre.intersectEdge(ray,tri.v0,tri.e1,tri.e2,UVIdentity<M>(),Occluded1EpilogM<M,filter>(ray,context,tri.geomID(),tri.primID()));
32 }
33
34 static __forceinline bool pointQuery(PointQuery* query, PointQueryContext* context, const Primitive& tri)
35 {
36 return PrimitivePointQuery1<Primitive>::pointQuery(query, context, tri);
37 }
38
39 };
40
41 /*! Intersects M triangles with K rays. */
42 template<int M, int K, bool filter>
43 struct TriangleMIntersectorKMoeller
44 {
45 typedef TriangleM<M> Primitive;
46 typedef MoellerTrumboreIntersectorK<M,K> Precalculations;
47
48 /*! Intersects K rays with M triangles. */
49 static __forceinline void intersect(const vbool<K>& valid_i, Precalculations& pre, RayHitK<K>& ray, IntersectContext* context, const TriangleM<M>& tri)
50 {
51 STAT_USER(0,TriangleM<M>::max_size());
52 for (size_t i=0; i<TriangleM<M>::max_size(); i++)
53 {
54 if (!tri.valid(i)) break;
55 STAT3(normal.trav_prims,1,popcnt(valid_i),K);
56 const Vec3vf<K> p0 = broadcast<vfloat<K>>(tri.v0,i);
57 const Vec3vf<K> e1 = broadcast<vfloat<K>>(tri.e1,i);
58 const Vec3vf<K> e2 = broadcast<vfloat<K>>(tri.e2,i);
59 pre.intersectEdgeK(valid_i,ray,p0,e1,e2,UVIdentity<K>(),IntersectKEpilogM<M,K,filter>(ray,context,tri.geomID(),tri.primID(),i));
60 }
61 }
62
63 /*! Test for K rays if they are occluded by any of the M triangles. */
64 static __forceinline vbool<K> occluded(const vbool<K>& valid_i, Precalculations& pre, RayK<K>& ray, IntersectContext* context, const TriangleM<M>& tri)
65 {
66 vbool<K> valid0 = valid_i;
67
68 for (size_t i=0; i<TriangleM<M>::max_size(); i++)
69 {
70 if (!tri.valid(i)) break;
71 STAT3(shadow.trav_prims,1,popcnt(valid0),K);
72 const Vec3vf<K> p0 = broadcast<vfloat<K>>(tri.v0,i);
73 const Vec3vf<K> e1 = broadcast<vfloat<K>>(tri.e1,i);
74 const Vec3vf<K> e2 = broadcast<vfloat<K>>(tri.e2,i);
75 pre.intersectEdgeK(valid0,ray,p0,e1,e2,UVIdentity<K>(),OccludedKEpilogM<M,K,filter>(valid0,ray,context,tri.geomID(),tri.primID(),i));
76 if (none(valid0)) break;
77 }
78 return !valid0;
79 }
80
81 /*! Intersect a ray with M triangles and updates the hit. */
82 static __forceinline void intersect(Precalculations& pre, RayHitK<K>& ray, size_t k, IntersectContext* context, const TriangleM<M>& tri)
83 {
84 STAT3(normal.trav_prims,1,1,1);
85 pre.intersectEdge(ray,k,tri.v0,tri.e1,tri.e2,UVIdentity<M>(),Intersect1KEpilogM<M,K,filter>(ray,k,context,tri.geomID(),tri.primID()));
86 }
87
88 /*! Test if the ray is occluded by one of the M triangles. */
89 static __forceinline bool occluded(Precalculations& pre, RayK<K>& ray, size_t k, IntersectContext* context, const TriangleM<M>& tri)
90 {
91 STAT3(shadow.trav_prims,1,1,1);
92 return pre.intersectEdge(ray,k,tri.v0,tri.e1,tri.e2,UVIdentity<M>(),Occluded1KEpilogM<M,K,filter>(ray,k,context,tri.geomID(),tri.primID()));
93 }
94 };
95 }
96}
97