Blender  V2.93
geom_motion_triangle_intersect.h
Go to the documentation of this file.
1 /*
2  * Copyright 2011-2016 Blender Foundation
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 /* Motion Triangle Primitive
18  *
19  * These are stored as regular triangles, plus extra positions and normals at
20  * times other than the frame center. Computing the triangle vertex positions
21  * or normals at a given ray time is a matter of interpolation of the two steps
22  * between which the ray time lies.
23  *
24  * The extra positions and normals are stored as ATTR_STD_MOTION_VERTEX_POSITION
25  * and ATTR_STD_MOTION_VERTEX_NORMAL mesh attributes.
26  */
27 
29 
30 /* Refine triangle intersection to more precise hit point. For rays that travel
31  * far the precision is often not so good, this reintersects the primitive from
32  * a closer distance.
33  */
34 
36  KernelGlobals *kg, ShaderData *sd, const Intersection *isect, const Ray *ray, float3 verts[3])
37 {
38  float3 P = ray->P;
39  float3 D = ray->D;
40  float t = isect->t;
41 
42 #ifdef __INTERSECTION_REFINE__
43  if (isect->object != OBJECT_NONE) {
44  if (UNLIKELY(t == 0.0f)) {
45  return P;
46  }
47 # ifdef __OBJECT_MOTION__
48  Transform tfm = sd->ob_itfm;
49 # else
51 # endif
52 
53  P = transform_point(&tfm, P);
54  D = transform_direction(&tfm, D * t);
55  D = normalize_len(D, &t);
56  }
57 
58  P = P + D * t;
59 
60  /* Compute refined intersection distance. */
61  const float3 e1 = verts[0] - verts[2];
62  const float3 e2 = verts[1] - verts[2];
63  const float3 s1 = cross(D, e2);
64 
65  const float invdivisor = 1.0f / dot(s1, e1);
66  const float3 d = P - verts[2];
67  const float3 s2 = cross(d, e1);
68  float rt = dot(e2, s2) * invdivisor;
69 
70  /* Compute refined position. */
71  P = P + D * rt;
72 
73  if (isect->object != OBJECT_NONE) {
74 # ifdef __OBJECT_MOTION__
75  Transform tfm = sd->ob_tfm;
76 # else
78 # endif
79 
80  P = transform_point(&tfm, P);
81  }
82 
83  return P;
84 #else
85  return P + D * t;
86 #endif
87 }
88 
89 /* Same as above, except that isect->t is assumed to be in object space
90  * for instancing.
91  */
92 
93 #ifdef __BVH_LOCAL__
94 # if defined(__KERNEL_CUDA__) && (defined(i386) || defined(_M_IX86))
96 # else
98 # endif
99  float3
100  motion_triangle_refine_local(KernelGlobals *kg,
101  ShaderData *sd,
102  const Intersection *isect,
103  const Ray *ray,
104  float3 verts[3])
105 {
106 # ifdef __KERNEL_OPTIX__
107  /* isect->t is always in world space with OptiX. */
108  return motion_triangle_refine(kg, sd, isect, ray, verts);
109 # else
110  float3 P = ray->P;
111  float3 D = ray->D;
112  float t = isect->t;
113 
114 # ifdef __INTERSECTION_REFINE__
115  if (isect->object != OBJECT_NONE) {
116 # ifdef __OBJECT_MOTION__
117  Transform tfm = sd->ob_itfm;
118 # else
120 # endif
121 
122  P = transform_point(&tfm, P);
123  D = transform_direction(&tfm, D);
124  D = normalize(D);
125  }
126 
127  P = P + D * t;
128 
129  /* compute refined intersection distance */
130  const float3 e1 = verts[0] - verts[2];
131  const float3 e2 = verts[1] - verts[2];
132  const float3 s1 = cross(D, e2);
133 
134  const float invdivisor = 1.0f / dot(s1, e1);
135  const float3 d = P - verts[2];
136  const float3 s2 = cross(d, e1);
137  float rt = dot(e2, s2) * invdivisor;
138 
139  P = P + D * rt;
140 
141  if (isect->object != OBJECT_NONE) {
142 # ifdef __OBJECT_MOTION__
143  Transform tfm = sd->ob_tfm;
144 # else
146 # endif
147 
148  P = transform_point(&tfm, P);
149  }
150 
151  return P;
152 # else /* __INTERSECTION_REFINE__ */
153  return P + D * t;
154 # endif /* __INTERSECTION_REFINE__ */
155 # endif
156 }
157 #endif /* __BVH_LOCAL__ */
158 
159 /* Ray intersection. We simply compute the vertex positions at the given ray
160  * time and do a ray intersection with the resulting triangle.
161  */
162 
164  Intersection *isect,
165  float3 P,
166  float3 dir,
167  float time,
168  uint visibility,
169  int object,
170  int prim_addr)
171 {
172  /* Primitive index for vertex location lookup. */
173  int prim = kernel_tex_fetch(__prim_index, prim_addr);
174  int fobject = (object == OBJECT_NONE) ? kernel_tex_fetch(__prim_object, prim_addr) : object;
175  /* Get vertex locations for intersection. */
176  float3 verts[3];
177  motion_triangle_vertices(kg, fobject, prim, time, verts);
178  /* Ray-triangle intersection, unoptimized. */
179  float t, u, v;
181  dir,
182  isect->t,
183 #if defined(__KERNEL_SSE2__) && defined(__KERNEL_SSE__)
184  (ssef *)verts,
185 #else
186  verts[0],
187  verts[1],
188  verts[2],
189 #endif
190  &u,
191  &v,
192  &t)) {
193 #ifdef __VISIBILITY_FLAG__
194  /* Visibility flag test. we do it here under the assumption
195  * that most triangles are culled by node flags.
196  */
197  if (kernel_tex_fetch(__prim_visibility, prim_addr) & visibility)
198 #endif
199  {
200  isect->t = t;
201  isect->u = u;
202  isect->v = v;
203  isect->prim = prim_addr;
204  isect->object = object;
206  return true;
207  }
208  }
209  return false;
210 }
211 
212 /* Special ray intersection routines for local intersections. In that case we
213  * only want to intersect with primitives in the same object, and if case of
214  * multiple hits we pick a single random primitive as the intersection point.
215  * Returns whether traversal should be stopped.
216  */
217 #ifdef __BVH_LOCAL__
218 ccl_device_inline bool motion_triangle_intersect_local(KernelGlobals *kg,
219  LocalIntersection *local_isect,
220  float3 P,
221  float3 dir,
222  float time,
223  int object,
224  int local_object,
225  int prim_addr,
226  float tmax,
227  uint *lcg_state,
228  int max_hits)
229 {
230  /* Only intersect with matching object, for instanced objects we
231  * already know we are only intersecting the right object. */
232  if (object == OBJECT_NONE) {
233  if (kernel_tex_fetch(__prim_object, prim_addr) != local_object) {
234  return false;
235  }
236  }
237 
238  /* Primitive index for vertex location lookup. */
239  int prim = kernel_tex_fetch(__prim_index, prim_addr);
240  /* Get vertex locations for intersection. */
241  float3 verts[3];
242  motion_triangle_vertices(kg, local_object, prim, time, verts);
243  /* Ray-triangle intersection, unoptimized. */
244  float t, u, v;
246  dir,
247  tmax,
248 # if defined(__KERNEL_SSE2__) && defined(__KERNEL_SSE__)
249  (ssef *)verts,
250 # else
251  verts[0],
252  verts[1],
253  verts[2],
254 # endif
255  &u,
256  &v,
257  &t)) {
258  return false;
259  }
260 
261  /* If no actual hit information is requested, just return here. */
262  if (max_hits == 0) {
263  return true;
264  }
265 
266  int hit;
267  if (lcg_state) {
268  /* Record up to max_hits intersections. */
269  for (int i = min(max_hits, local_isect->num_hits) - 1; i >= 0; --i) {
270  if (local_isect->hits[i].t == t) {
271  return false;
272  }
273  }
274 
275  local_isect->num_hits++;
276 
277  if (local_isect->num_hits <= max_hits) {
278  hit = local_isect->num_hits - 1;
279  }
280  else {
281  /* Reservoir sampling: if we are at the maximum number of
282  * hits, randomly replace element or skip it.
283  */
284  hit = lcg_step_uint(lcg_state) % local_isect->num_hits;
285 
286  if (hit >= max_hits)
287  return false;
288  }
289  }
290  else {
291  /* Record closest intersection only. */
292  if (local_isect->num_hits && t > local_isect->hits[0].t) {
293  return false;
294  }
295 
296  hit = 0;
297  local_isect->num_hits = 1;
298  }
299 
300  /* Record intersection. */
301  Intersection *isect = &local_isect->hits[hit];
302  isect->t = t;
303  isect->u = u;
304  isect->v = v;
305  isect->prim = prim_addr;
306  isect->object = object;
308 
309  /* Record geometric normal. */
310  local_isect->Ng[hit] = normalize(cross(verts[1] - verts[0], verts[2] - verts[0]));
311 
312  return false;
313 }
314 #endif /* __BVH_LOCAL__ */
315 
unsigned int uint
Definition: BLI_sys_types.h:83
#define UNLIKELY(x)
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei GLfloat GLfloat GLfloat GLfloat const GLubyte *bitmap _GL_VOID_RET _GL_VOID GLenum const void *lists _GL_VOID_RET _GL_VOID const GLdouble *equation _GL_VOID_RET _GL_VOID GLdouble GLdouble blue _GL_VOID_RET _GL_VOID GLfloat GLfloat blue _GL_VOID_RET _GL_VOID GLint GLint blue _GL_VOID_RET _GL_VOID GLshort GLshort blue _GL_VOID_RET _GL_VOID GLubyte GLubyte blue _GL_VOID_RET _GL_VOID GLuint GLuint blue _GL_VOID_RET _GL_VOID GLushort GLushort blue _GL_VOID_RET _GL_VOID GLbyte GLbyte GLbyte alpha _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble alpha _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat alpha _GL_VOID_RET _GL_VOID GLint GLint GLint alpha _GL_VOID_RET _GL_VOID GLshort GLshort GLshort alpha _GL_VOID_RET _GL_VOID GLubyte GLubyte GLubyte alpha _GL_VOID_RET _GL_VOID GLuint GLuint GLuint alpha _GL_VOID_RET _GL_VOID GLushort GLushort GLushort alpha _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLint GLsizei GLsizei GLenum type _GL_VOID_RET _GL_VOID GLsizei GLenum GLenum const void *pixels _GL_VOID_RET _GL_VOID const void *pointer _GL_VOID_RET _GL_VOID GLdouble v _GL_VOID_RET _GL_VOID GLfloat v _GL_VOID_RET _GL_VOID GLint GLint i2 _GL_VOID_RET _GL_VOID GLint j _GL_VOID_RET _GL_VOID GLfloat param _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble GLdouble GLdouble zFar _GL_VOID_RET _GL_UINT GLdouble *equation _GL_VOID_RET _GL_VOID GLenum GLint *params _GL_VOID_RET _GL_VOID GLenum GLfloat *v _GL_VOID_RET _GL_VOID GLenum GLfloat *params _GL_VOID_RET _GL_VOID GLfloat *values _GL_VOID_RET _GL_VOID GLushort *values _GL_VOID_RET _GL_VOID GLenum GLfloat *params _GL_VOID_RET _GL_VOID GLenum GLdouble *params _GL_VOID_RET _GL_VOID GLenum GLint *params _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_BOOL GLfloat param _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID GLenum GLfloat param _GL_VOID_RET _GL_VOID GLenum GLint param _GL_VOID_RET _GL_VOID GLushort pattern _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLint const GLdouble *points _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLint GLdouble GLdouble GLint GLint const GLdouble *points _GL_VOID_RET _GL_VOID GLdouble GLdouble u2 _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLdouble GLdouble v2 _GL_VOID_RET _GL_VOID GLenum GLfloat param _GL_VOID_RET _GL_VOID GLenum GLint param _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLdouble GLdouble nz _GL_VOID_RET _GL_VOID GLfloat GLfloat nz _GL_VOID_RET _GL_VOID GLint GLint nz _GL_VOID_RET _GL_VOID GLshort GLshort nz _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_VOID GLsizei const GLfloat *values _GL_VOID_RET _GL_VOID GLsizei const GLushort *values _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID const GLuint const GLclampf *priorities _GL_VOID_RET _GL_VOID GLdouble y _GL_VOID_RET _GL_VOID GLfloat y _GL_VOID_RET _GL_VOID GLint y _GL_VOID_RET _GL_VOID GLshort y _GL_VOID_RET _GL_VOID GLdouble GLdouble z _GL_VOID_RET _GL_VOID GLfloat GLfloat z _GL_VOID_RET _GL_VOID GLint GLint z _GL_VOID_RET _GL_VOID GLshort GLshort z _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble w _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat w _GL_VOID_RET _GL_VOID GLint GLint GLint w _GL_VOID_RET _GL_VOID GLshort GLshort GLshort w _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble y2 _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat y2 _GL_VOID_RET _GL_VOID GLint GLint GLint y2 _GL_VOID_RET _GL_VOID GLshort GLshort GLshort y2 _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble z _GL_VOID_RET _GL_VOID GLdouble GLdouble z _GL_VOID_RET _GL_VOID GLuint *buffer _GL_VOID_RET _GL_VOID GLdouble t _GL_VOID_RET _GL_VOID GLfloat t _GL_VOID_RET _GL_VOID GLint t _GL_VOID_RET _GL_VOID GLshort t _GL_VOID_RET _GL_VOID GLdouble t
ATTR_WARN_UNUSED_RESULT const BMVert * v
double time
static float verts[][3]
ccl_device_inline void motion_triangle_vertices(KernelGlobals *kg, int object, int prim, float time, float3 verts[3])
CCL_NAMESPACE_BEGIN ccl_device_inline float3 motion_triangle_refine(KernelGlobals *kg, ShaderData *sd, const Intersection *isect, const Ray *ray, float3 verts[3])
ccl_device_inline bool motion_triangle_intersect(KernelGlobals *kg, Intersection *isect, float3 P, float3 dir, float time, uint visibility, int object, int prim_addr)
@ OBJECT_INVERSE_TRANSFORM
Definition: geom_object.h:31
@ OBJECT_TRANSFORM
Definition: geom_object.h:30
ccl_device_inline Transform object_fetch_transform(KernelGlobals *kg, int object, enum ObjectTransform type)
Definition: geom_object.h:38
#define kernel_tex_fetch(tex, index)
#define ccl_device_inline
#define ccl_device_noinline
#define CCL_NAMESPACE_END
ccl_device uint lcg_step_uint(uint *rng)
@ PRIMITIVE_MOTION_TRIANGLE
Definition: kernel_types.h:687
#define OBJECT_NONE
Definition: kernel_types.h:59
ShaderData
static float P(float k)
Definition: math_interp.c:41
#define min(a, b)
Definition: sort.c:51
struct Intersection hits[LOCAL_MAX_HITS]
float3 Ng[LOCAL_MAX_HITS]
float3 P
Definition: kernel_types.h:647
float3 D
Definition: kernel_types.h:648
__forceinline avxf cross(const avxf &a, const avxf &b)
Definition: util_avxf.h:119
ccl_device_inline float2 normalize(const float2 &a)
ccl_device_inline float dot(const float2 &a, const float2 &b)
ccl_device_inline float2 normalize_len(const float2 &a, float *t)
ccl_device_forceinline bool ray_triangle_intersect(float3 ray_P, float3 ray_dir, float ray_t, const float3 tri_a, const float3 tri_b, const float3 tri_c, float *isect_u, float *isect_v, float *isect_t)
ccl_device_inline float3 transform_direction(const Transform *t, const float3 a)
ccl_device_inline float3 transform_point(const Transform *t, const float3 a)
BLI_INLINE float D(const float *data, const int res[3], int x, int y, int z)
Definition: voxel.c:29