1// Copyright 2009-2021 Intel Corporation
2// SPDX-License-Identifier: Apache-2.0
3
4#pragma once
5
6#include "triangle.h"
7#include "intersector_epilog.h"
8
9namespace embree
10{
11 namespace isa
12 {
13 /*! Intersects M motion blur triangles with 1 ray */
14 template<int M, bool filter>
15 struct TriangleMvMBIntersector1Moeller
16 {
17 typedef TriangleMvMB<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 TriangleMvMB<M>& tri)
22 {
23 STAT3(normal.trav_prims,1,1,1);
24 const Vec3vf<M> time(ray.time());
25 const Vec3vf<M> v0 = madd(time,Vec3vf<M>(tri.dv0),Vec3vf<M>(tri.v0));
26 const Vec3vf<M> v1 = madd(time,Vec3vf<M>(tri.dv1),Vec3vf<M>(tri.v1));
27 const Vec3vf<M> v2 = madd(time,Vec3vf<M>(tri.dv2),Vec3vf<M>(tri.v2));
28 pre.intersect(ray,v0,v1,v2,Intersect1EpilogM<M,filter>(ray,context,tri.geomID(),tri.primID()));
29 }
30
31 /*! Test if the ray is occluded by one of M triangles. */
32 static __forceinline bool occluded(const Precalculations& pre, Ray& ray, IntersectContext* context, const TriangleMvMB<M>& tri)
33 {
34 STAT3(shadow.trav_prims,1,1,1);
35 const Vec3vf<M> time(ray.time());
36 const Vec3vf<M> v0 = madd(time,Vec3vf<M>(tri.dv0),Vec3vf<M>(tri.v0));
37 const Vec3vf<M> v1 = madd(time,Vec3vf<M>(tri.dv1),Vec3vf<M>(tri.v1));
38 const Vec3vf<M> v2 = madd(time,Vec3vf<M>(tri.dv2),Vec3vf<M>(tri.v2));
39 return pre.intersect(ray,v0,v1,v2,Occluded1EpilogM<M,filter>(ray,context,tri.geomID(),tri.primID()));
40 }
41
42 static __forceinline bool pointQuery(PointQuery* query, PointQueryContext* context, const Primitive& tri)
43 {
44 return PrimitivePointQuery1<Primitive>::pointQuery(query, context, tri);
45 }
46 };
47
48 /*! Intersects M motion blur triangles with K rays. */
49 template<int M, int K, bool filter>
50 struct TriangleMvMBIntersectorKMoeller
51 {
52 typedef TriangleMvMB<M> Primitive;
53 typedef MoellerTrumboreIntersectorK<M,K> Precalculations;
54
55 /*! Intersects K rays with M triangles. */
56 static __forceinline void intersect(const vbool<K>& valid_i, Precalculations& pre, RayHitK<K>& ray, IntersectContext* context, const TriangleMvMB<M>& tri)
57 {
58 for (size_t i=0; i<TriangleMvMB<M>::max_size(); i++)
59 {
60 if (!tri.valid(i)) break;
61 STAT3(normal.trav_prims,1,popcnt(valid_i),K);
62 const Vec3vf<K> time(ray.time());
63 const Vec3vf<K> v0 = madd(time,broadcast<vfloat<K>>(tri.dv0,i),broadcast<vfloat<K>>(tri.v0,i));
64 const Vec3vf<K> v1 = madd(time,broadcast<vfloat<K>>(tri.dv1,i),broadcast<vfloat<K>>(tri.v1,i));
65 const Vec3vf<K> v2 = madd(time,broadcast<vfloat<K>>(tri.dv2,i),broadcast<vfloat<K>>(tri.v2,i));
66 pre.intersectK(valid_i,ray,v0,v1,v2,IntersectKEpilogM<M,K,filter>(ray,context,tri.geomID(),tri.primID(),i));
67 }
68 }
69
70 /*! Test for K rays if they are occluded by any of the M triangles. */
71 static __forceinline vbool<K> occluded(const vbool<K>& valid_i, Precalculations& pre, RayK<K>& ray, IntersectContext* context, const TriangleMvMB<M>& tri)
72 {
73 vbool<K> valid0 = valid_i;
74
75 for (size_t i=0; i<TriangleMvMB<M>::max_size(); i++)
76 {
77 if (!tri.valid(i)) break;
78 STAT3(shadow.trav_prims,1,popcnt(valid0),K);
79 const Vec3vf<K> time(ray.time());
80 const Vec3vf<K> v0 = madd(time,broadcast<vfloat<K>>(tri.dv0,i),broadcast<vfloat<K>>(tri.v0,i));
81 const Vec3vf<K> v1 = madd(time,broadcast<vfloat<K>>(tri.dv1,i),broadcast<vfloat<K>>(tri.v1,i));
82 const Vec3vf<K> v2 = madd(time,broadcast<vfloat<K>>(tri.dv2,i),broadcast<vfloat<K>>(tri.v2,i));
83 pre.intersectK(valid0,ray,v0,v1,v2,OccludedKEpilogM<M,K,filter>(valid0,ray,context,tri.geomID(),tri.primID(),i));
84 if (none(valid0)) break;
85 }
86 return !valid0;
87 }
88
89 /*! Intersect a ray with M triangles and updates the hit. */
90 static __forceinline void intersect(Precalculations& pre, RayHitK<K>& ray, size_t k, IntersectContext* context, const TriangleMvMB<M>& tri)
91 {
92 STAT3(normal.trav_prims,1,1,1);
93 const Vec3vf<M> time(ray.time()[k]);
94 const Vec3vf<M> v0 = madd(time,Vec3vf<M>(tri.dv0),Vec3vf<M>(tri.v0));
95 const Vec3vf<M> v1 = madd(time,Vec3vf<M>(tri.dv1),Vec3vf<M>(tri.v1));
96 const Vec3vf<M> v2 = madd(time,Vec3vf<M>(tri.dv2),Vec3vf<M>(tri.v2));
97 pre.intersect(ray,k,v0,v1,v2,Intersect1KEpilogM<M,K,filter>(ray,k,context,tri.geomID(),tri.primID()));
98 }
99
100 /*! Test if the ray is occluded by one of the M triangles. */
101 static __forceinline bool occluded(Precalculations& pre, RayK<K>& ray, size_t k, IntersectContext* context, const TriangleMvMB<M>& tri)
102 {
103 STAT3(shadow.trav_prims,1,1,1);
104 const Vec3vf<M> time(ray.time()[k]);
105 const Vec3vf<M> v0 = madd(time,Vec3vf<M>(tri.dv0),Vec3vf<M>(tri.v0));
106 const Vec3vf<M> v1 = madd(time,Vec3vf<M>(tri.dv1),Vec3vf<M>(tri.v1));
107 const Vec3vf<M> v2 = madd(time,Vec3vf<M>(tri.dv2),Vec3vf<M>(tri.v2));
108 return pre.intersect(ray,k,v0,v1,v2,Occluded1KEpilogM<M,K,filter>(ray,k,context,tri.geomID(),tri.primID()));
109 }
110 };
111
112 /*! Intersects M motion blur triangles with 1 ray */
113 template<int M, bool filter>
114 struct TriangleMvMBIntersector1Pluecker
115 {
116 typedef TriangleMvMB<M> Primitive;
117 typedef PlueckerIntersector1<M> Precalculations;
118
119 /*! Intersect a ray with the M triangles and updates the hit. */
120 static __forceinline void intersect(const Precalculations& pre, RayHit& ray, IntersectContext* context, const TriangleMvMB<M>& tri)
121 {
122 STAT3(normal.trav_prims,1,1,1);
123 const Vec3vf<M> time(ray.time());
124 const Vec3vf<M> v0 = madd(time,Vec3vf<M>(tri.dv0),Vec3vf<M>(tri.v0));
125 const Vec3vf<M> v1 = madd(time,Vec3vf<M>(tri.dv1),Vec3vf<M>(tri.v1));
126 const Vec3vf<M> v2 = madd(time,Vec3vf<M>(tri.dv2),Vec3vf<M>(tri.v2));
127 pre.intersect(ray,v0,v1,v2,UVIdentity<M>(),Intersect1EpilogM<M,filter>(ray,context,tri.geomID(),tri.primID()));
128 }
129
130 /*! Test if the ray is occluded by one of M triangles. */
131 static __forceinline bool occluded(const Precalculations& pre, Ray& ray, IntersectContext* context, const TriangleMvMB<M>& tri)
132 {
133 STAT3(shadow.trav_prims,1,1,1);
134 const Vec3vf<M> time(ray.time());
135 const Vec3vf<M> v0 = madd(time,Vec3vf<M>(tri.dv0),Vec3vf<M>(tri.v0));
136 const Vec3vf<M> v1 = madd(time,Vec3vf<M>(tri.dv1),Vec3vf<M>(tri.v1));
137 const Vec3vf<M> v2 = madd(time,Vec3vf<M>(tri.dv2),Vec3vf<M>(tri.v2));
138 return pre.intersect(ray,v0,v1,v2,UVIdentity<M>(),Occluded1EpilogM<M,filter>(ray,context,tri.geomID(),tri.primID()));
139 }
140
141 static __forceinline bool pointQuery(PointQuery* query, PointQueryContext* context, const Primitive& tri)
142 {
143 return PrimitivePointQuery1<Primitive>::pointQuery(query, context, tri);
144 }
145 };
146
147 /*! Intersects M motion blur triangles with K rays. */
148 template<int M, int K, bool filter>
149 struct TriangleMvMBIntersectorKPluecker
150 {
151 typedef TriangleMvMB<M> Primitive;
152 typedef PlueckerIntersectorK<M,K> Precalculations;
153
154 /*! Intersects K rays with M triangles. */
155 static __forceinline void intersect(const vbool<K>& valid_i, Precalculations& pre, RayHitK<K>& ray, IntersectContext* context, const TriangleMvMB<M>& tri)
156 {
157 for (size_t i=0; i<TriangleMvMB<M>::max_size(); i++)
158 {
159 if (!tri.valid(i)) break;
160 STAT3(normal.trav_prims,1,popcnt(valid_i),K);
161 const Vec3vf<K> time(ray.time());
162 const Vec3vf<K> v0 = madd(time,broadcast<vfloat<K>>(tri.dv0,i),broadcast<vfloat<K>>(tri.v0,i));
163 const Vec3vf<K> v1 = madd(time,broadcast<vfloat<K>>(tri.dv1,i),broadcast<vfloat<K>>(tri.v1,i));
164 const Vec3vf<K> v2 = madd(time,broadcast<vfloat<K>>(tri.dv2,i),broadcast<vfloat<K>>(tri.v2,i));
165 pre.intersectK(valid_i,ray,v0,v1,v2,UVIdentity<K>(),IntersectKEpilogM<M,K,filter>(ray,context,tri.geomID(),tri.primID(),i));
166 }
167 }
168
169 /*! Test for K rays if they are occluded by any of the M triangles. */
170 static __forceinline vbool<K> occluded(const vbool<K>& valid_i, Precalculations& pre, RayK<K>& ray, IntersectContext* context, const TriangleMvMB<M>& tri)
171 {
172 vbool<K> valid0 = valid_i;
173
174 for (size_t i=0; i<TriangleMvMB<M>::max_size(); i++)
175 {
176 if (!tri.valid(i)) break;
177 STAT3(shadow.trav_prims,1,popcnt(valid0),K);
178 const Vec3vf<K> time(ray.time());
179 const Vec3vf<K> v0 = madd(time,broadcast<vfloat<K>>(tri.dv0,i),broadcast<vfloat<K>>(tri.v0,i));
180 const Vec3vf<K> v1 = madd(time,broadcast<vfloat<K>>(tri.dv1,i),broadcast<vfloat<K>>(tri.v1,i));
181 const Vec3vf<K> v2 = madd(time,broadcast<vfloat<K>>(tri.dv2,i),broadcast<vfloat<K>>(tri.v2,i));
182 pre.intersectK(valid0,ray,v0,v1,v2,UVIdentity<K>(),OccludedKEpilogM<M,K,filter>(valid0,ray,context,tri.geomID(),tri.primID(),i));
183 if (none(valid0)) break;
184 }
185 return !valid0;
186 }
187
188 /*! Intersect a ray with M triangles and updates the hit. */
189 static __forceinline void intersect(Precalculations& pre, RayHitK<K>& ray, size_t k, IntersectContext* context, const TriangleMvMB<M>& tri)
190 {
191 STAT3(normal.trav_prims,1,1,1);
192 const Vec3vf<M> time(ray.time()[k]);
193 const Vec3vf<M> v0 = madd(time,Vec3vf<M>(tri.dv0),Vec3vf<M>(tri.v0));
194 const Vec3vf<M> v1 = madd(time,Vec3vf<M>(tri.dv1),Vec3vf<M>(tri.v1));
195 const Vec3vf<M> v2 = madd(time,Vec3vf<M>(tri.dv2),Vec3vf<M>(tri.v2));
196 pre.intersect(ray,k,v0,v1,v2,UVIdentity<M>(),Intersect1KEpilogM<M,K,filter>(ray,k,context,tri.geomID(),tri.primID()));
197 }
198
199 /*! Test if the ray is occluded by one of the M triangles. */
200 static __forceinline bool occluded(Precalculations& pre, RayK<K>& ray, size_t k, IntersectContext* context, const TriangleMvMB<M>& tri)
201 {
202 STAT3(shadow.trav_prims,1,1,1);
203 const Vec3vf<M> time(ray.time()[k]);
204 const Vec3vf<M> v0 = madd(time,Vec3vf<M>(tri.dv0),Vec3vf<M>(tri.v0));
205 const Vec3vf<M> v1 = madd(time,Vec3vf<M>(tri.dv1),Vec3vf<M>(tri.v1));
206 const Vec3vf<M> v2 = madd(time,Vec3vf<M>(tri.dv2),Vec3vf<M>(tri.v2));
207 return pre.intersect(ray,k,v0,v1,v2,UVIdentity<M>(),Occluded1KEpilogM<M,K,filter>(ray,k,context,tri.geomID(),tri.primID()));
208 }
209 };
210 }
211}
212