Blender V4.3
geom/triangle.h
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2011-2022 Blender Foundation
2 *
3 * SPDX-License-Identifier: Apache-2.0 */
4
5/* Triangle Primitive
6 *
7 * Basic triangle with 3 vertices is used to represent mesh surfaces. For BVH
8 * ray intersection we use a precomputed triangle storage to accelerate
9 * intersection at the cost of more memory usage */
10
11#pragma once
12
13#include "util/color.h"
14
16
17/* Normal on triangle. */
19{
20 /* load triangle vertices */
21 const uint3 tri_vindex = kernel_data_fetch(tri_vindex, sd->prim);
22 const float3 v0 = kernel_data_fetch(tri_verts, tri_vindex.x);
23 const float3 v1 = kernel_data_fetch(tri_verts, tri_vindex.y);
24 const float3 v2 = kernel_data_fetch(tri_verts, tri_vindex.z);
25
26 /* return normal */
27 if (object_negative_scale_applied(sd->object_flag)) {
28 return normalize(cross(v2 - v0, v1 - v0));
29 }
30 else {
31 return normalize(cross(v1 - v0, v2 - v0));
32 }
33}
34
35/* Point and normal on triangle. */
37 int object,
38 int prim,
39 float u,
40 float v,
43 ccl_private int *shader)
44{
45 /* load triangle vertices */
46 const uint3 tri_vindex = kernel_data_fetch(tri_vindex, prim);
47 float3 v0 = kernel_data_fetch(tri_verts, tri_vindex.x);
48 float3 v1 = kernel_data_fetch(tri_verts, tri_vindex.y);
49 float3 v2 = kernel_data_fetch(tri_verts, tri_vindex.z);
50
51 /* compute point */
52 float w = 1.0f - u - v;
53 *P = (w * v0 + u * v1 + v * v2);
54 /* get object flags */
55 int object_flag = kernel_data_fetch(object_flag, object);
56 /* compute normal */
57 if (object_negative_scale_applied(object_flag)) {
58 *Ng = normalize(cross(v2 - v0, v1 - v0));
59 }
60 else {
61 *Ng = normalize(cross(v1 - v0, v2 - v0));
62 }
63 /* shader`*/
64 *shader = kernel_data_fetch(tri_shader, prim);
65}
66
67/* Triangle vertex locations */
68
70{
71 const uint3 tri_vindex = kernel_data_fetch(tri_vindex, prim);
72 P[0] = kernel_data_fetch(tri_verts, tri_vindex.x);
73 P[1] = kernel_data_fetch(tri_verts, tri_vindex.y);
74 P[2] = kernel_data_fetch(tri_verts, tri_vindex.z);
75}
76
77/* Triangle vertex locations and vertex normals */
78
80 int prim,
81 float3 P[3],
82 float3 N[3])
83{
84 const uint3 tri_vindex = kernel_data_fetch(tri_vindex, prim);
85 P[0] = kernel_data_fetch(tri_verts, tri_vindex.x);
86 P[1] = kernel_data_fetch(tri_verts, tri_vindex.y);
87 P[2] = kernel_data_fetch(tri_verts, tri_vindex.z);
88
89 N[0] = kernel_data_fetch(tri_vnormal, tri_vindex.x);
90 N[1] = kernel_data_fetch(tri_vnormal, tri_vindex.y);
91 N[2] = kernel_data_fetch(tri_vnormal, tri_vindex.z);
92}
93
94/* Interpolate smooth vertex normal from vertices */
95
97triangle_smooth_normal(KernelGlobals kg, float3 Ng, int prim, float u, float v)
98{
99 /* load triangle vertices */
100 const uint3 tri_vindex = kernel_data_fetch(tri_vindex, prim);
101
102 float3 n0 = kernel_data_fetch(tri_vnormal, tri_vindex.x);
103 float3 n1 = kernel_data_fetch(tri_vnormal, tri_vindex.y);
104 float3 n2 = kernel_data_fetch(tri_vnormal, tri_vindex.z);
105
106 float3 N = safe_normalize((1.0f - u - v) * n0 + u * n1 + v * n2);
107
108 return is_zero(N) ? Ng : N;
109}
110
112 KernelGlobals kg, ccl_private const ShaderData *sd, float3 Ng, int prim, float u, float v)
113{
114 /* load triangle vertices */
115 const uint3 tri_vindex = kernel_data_fetch(tri_vindex, prim);
116
117 float3 n0 = kernel_data_fetch(tri_vnormal, tri_vindex.x);
118 float3 n1 = kernel_data_fetch(tri_vnormal, tri_vindex.y);
119 float3 n2 = kernel_data_fetch(tri_vnormal, tri_vindex.z);
120
121 /* ensure that the normals are in object space */
122 if (sd->object_flag & SD_OBJECT_TRANSFORM_APPLIED) {
126 }
127
128 float3 N = (1.0f - u - v) * n0 + u * n1 + v * n2;
129
130 return is_zero(N) ? Ng : N;
131}
132
133/* Ray differentials on triangle */
134
136 int prim,
137 ccl_private float3 *dPdu,
138 ccl_private float3 *dPdv)
139{
140 /* fetch triangle vertex coordinates */
141 const uint3 tri_vindex = kernel_data_fetch(tri_vindex, prim);
142 const float3 p0 = kernel_data_fetch(tri_verts, tri_vindex.x);
143 const float3 p1 = kernel_data_fetch(tri_verts, tri_vindex.y);
144 const float3 p2 = kernel_data_fetch(tri_verts, tri_vindex.z);
145
146 /* compute derivatives of P w.r.t. uv */
147 *dPdu = (p1 - p0);
148 *dPdv = (p2 - p0);
149}
150
151/* Reading attributes on various triangle elements */
152
154 ccl_private const ShaderData *sd,
155 const AttributeDescriptor desc,
156 ccl_private float *dx,
157 ccl_private float *dy)
158{
160 float f0, f1, f2;
161
163 const uint3 tri_vindex = kernel_data_fetch(tri_vindex, sd->prim);
164
165 f0 = kernel_data_fetch(attributes_float, desc.offset + tri_vindex.x);
166 f1 = kernel_data_fetch(attributes_float, desc.offset + tri_vindex.y);
167 f2 = kernel_data_fetch(attributes_float, desc.offset + tri_vindex.z);
168 }
169 else {
170 const int tri = desc.offset + sd->prim * 3;
171 f0 = kernel_data_fetch(attributes_float, tri + 0);
172 f1 = kernel_data_fetch(attributes_float, tri + 1);
173 f2 = kernel_data_fetch(attributes_float, tri + 2);
174 }
175
176#ifdef __RAY_DIFFERENTIALS__
177 if (dx)
178 *dx = sd->du.dx * f1 + sd->dv.dx * f2 - (sd->du.dx + sd->dv.dx) * f0;
179 if (dy)
180 *dy = sd->du.dy * f1 + sd->dv.dy * f2 - (sd->du.dy + sd->dv.dy) * f0;
181#endif
182
183 return sd->u * f1 + sd->v * f2 + (1.0f - sd->u - sd->v) * f0;
184 }
185 else {
186#ifdef __RAY_DIFFERENTIALS__
187 if (dx)
188 *dx = 0.0f;
189 if (dy)
190 *dy = 0.0f;
191#endif
192
194 const int offset = (desc.element == ATTR_ELEMENT_FACE) ? desc.offset + sd->prim :
195 desc.offset;
196 return kernel_data_fetch(attributes_float, offset);
197 }
198 else {
199 return 0.0f;
200 }
201 }
202}
203
205 ccl_private const ShaderData *sd,
206 const AttributeDescriptor desc,
209{
211 float2 f0, f1, f2;
212
214 const uint3 tri_vindex = kernel_data_fetch(tri_vindex, sd->prim);
215
216 f0 = kernel_data_fetch(attributes_float2, desc.offset + tri_vindex.x);
217 f1 = kernel_data_fetch(attributes_float2, desc.offset + tri_vindex.y);
218 f2 = kernel_data_fetch(attributes_float2, desc.offset + tri_vindex.z);
219 }
220 else {
221 const int tri = desc.offset + sd->prim * 3;
222 f0 = kernel_data_fetch(attributes_float2, tri + 0);
223 f1 = kernel_data_fetch(attributes_float2, tri + 1);
224 f2 = kernel_data_fetch(attributes_float2, tri + 2);
225 }
226
227#ifdef __RAY_DIFFERENTIALS__
228 if (dx)
229 *dx = sd->du.dx * f1 + sd->dv.dx * f2 - (sd->du.dx + sd->dv.dx) * f0;
230 if (dy)
231 *dy = sd->du.dy * f1 + sd->dv.dy * f2 - (sd->du.dy + sd->dv.dy) * f0;
232#endif
233
234 return sd->u * f1 + sd->v * f2 + (1.0f - sd->u - sd->v) * f0;
235 }
236 else {
237#ifdef __RAY_DIFFERENTIALS__
238 if (dx)
239 *dx = make_float2(0.0f, 0.0f);
240 if (dy)
241 *dy = make_float2(0.0f, 0.0f);
242#endif
243
245 const int offset = (desc.element == ATTR_ELEMENT_FACE) ? desc.offset + sd->prim :
246 desc.offset;
247 return kernel_data_fetch(attributes_float2, offset);
248 }
249 else {
250 return make_float2(0.0f, 0.0f);
251 }
252 }
253}
254
256 ccl_private const ShaderData *sd,
257 const AttributeDescriptor desc,
260{
262 float3 f0, f1, f2;
263
265 const uint3 tri_vindex = kernel_data_fetch(tri_vindex, sd->prim);
266
267 f0 = kernel_data_fetch(attributes_float3, desc.offset + tri_vindex.x);
268 f1 = kernel_data_fetch(attributes_float3, desc.offset + tri_vindex.y);
269 f2 = kernel_data_fetch(attributes_float3, desc.offset + tri_vindex.z);
270 }
271 else {
272 const int tri = desc.offset + sd->prim * 3;
273 f0 = kernel_data_fetch(attributes_float3, tri + 0);
274 f1 = kernel_data_fetch(attributes_float3, tri + 1);
275 f2 = kernel_data_fetch(attributes_float3, tri + 2);
276 }
277
278#ifdef __RAY_DIFFERENTIALS__
279 if (dx)
280 *dx = sd->du.dx * f1 + sd->dv.dx * f2 - (sd->du.dx + sd->dv.dx) * f0;
281 if (dy)
282 *dy = sd->du.dy * f1 + sd->dv.dy * f2 - (sd->du.dy + sd->dv.dy) * f0;
283#endif
284
285 return sd->u * f1 + sd->v * f2 + (1.0f - sd->u - sd->v) * f0;
286 }
287 else {
288#ifdef __RAY_DIFFERENTIALS__
289 if (dx)
290 *dx = make_float3(0.0f, 0.0f, 0.0f);
291 if (dy)
292 *dy = make_float3(0.0f, 0.0f, 0.0f);
293#endif
294
296 const int offset = (desc.element == ATTR_ELEMENT_FACE) ? desc.offset + sd->prim :
297 desc.offset;
298 return kernel_data_fetch(attributes_float3, offset);
299 }
300 else {
301 return make_float3(0.0f, 0.0f, 0.0f);
302 }
303 }
304}
305
307 ccl_private const ShaderData *sd,
308 const AttributeDescriptor desc,
309 ccl_private float4 *dx,
310 ccl_private float4 *dy)
311{
314 {
315 float4 f0, f1, f2;
316
318 const uint3 tri_vindex = kernel_data_fetch(tri_vindex, sd->prim);
319
320 f0 = kernel_data_fetch(attributes_float4, desc.offset + tri_vindex.x);
321 f1 = kernel_data_fetch(attributes_float4, desc.offset + tri_vindex.y);
322 f2 = kernel_data_fetch(attributes_float4, desc.offset + tri_vindex.z);
323 }
324 else {
325 const int tri = desc.offset + sd->prim * 3;
326 if (desc.element == ATTR_ELEMENT_CORNER) {
327 f0 = kernel_data_fetch(attributes_float4, tri + 0);
328 f1 = kernel_data_fetch(attributes_float4, tri + 1);
329 f2 = kernel_data_fetch(attributes_float4, tri + 2);
330 }
331 else {
333 color_uchar4_to_float4(kernel_data_fetch(attributes_uchar4, tri + 0)));
335 color_uchar4_to_float4(kernel_data_fetch(attributes_uchar4, tri + 1)));
337 color_uchar4_to_float4(kernel_data_fetch(attributes_uchar4, tri + 2)));
338 }
339 }
340
341#ifdef __RAY_DIFFERENTIALS__
342 if (dx)
343 *dx = sd->du.dx * f1 + sd->dv.dx * f2 - (sd->du.dx + sd->dv.dx) * f0;
344 if (dy)
345 *dy = sd->du.dy * f1 + sd->dv.dy * f2 - (sd->du.dy + sd->dv.dy) * f0;
346#endif
347
348 return sd->u * f1 + sd->v * f2 + (1.0f - sd->u - sd->v) * f0;
349 }
350 else {
351#ifdef __RAY_DIFFERENTIALS__
352 if (dx)
353 *dx = zero_float4();
354 if (dy)
355 *dy = zero_float4();
356#endif
357
359 const int offset = (desc.element == ATTR_ELEMENT_FACE) ? desc.offset + sd->prim :
360 desc.offset;
361 return kernel_data_fetch(attributes_float4, offset);
362 }
363 else {
364 return zero_float4();
365 }
366 }
367}
368
ATTR_WARN_UNUSED_RESULT const BMVert * v2
ATTR_WARN_UNUSED_RESULT const BMVert * v
SIMD_FORCE_INLINE const btScalar & w() const
Return the w value.
Definition btQuadWord.h:119
SIMD_FORCE_INLINE btVector3 & normalize()
Normalize this vector x^2 + y^2 + z^2 = 1.
Definition btVector3.h:303
const KernelGlobalsCPU *ccl_restrict KernelGlobals
#define kernel_data_fetch(name, index)
#define ccl_device
#define ccl_private
#define ccl_device_inline
#define CCL_NAMESPACE_END
ccl_device_forceinline float3 make_float3(const float x, const float y, const float z)
ccl_device_forceinline float2 make_float2(const float x, const float y)
ccl_device float triangle_attribute_float(KernelGlobals kg, ccl_private const ShaderData *sd, const AttributeDescriptor desc, ccl_private float *dx, ccl_private float *dy)
CCL_NAMESPACE_BEGIN ccl_device_inline float3 triangle_normal(KernelGlobals kg, ccl_private ShaderData *sd)
ccl_device float2 triangle_attribute_float2(KernelGlobals kg, ccl_private const ShaderData *sd, const AttributeDescriptor desc, ccl_private float2 *dx, ccl_private float2 *dy)
ccl_device float4 triangle_attribute_float4(KernelGlobals kg, ccl_private const ShaderData *sd, const AttributeDescriptor desc, ccl_private float4 *dx, ccl_private float4 *dy)
ccl_device_inline float3 triangle_smooth_normal(KernelGlobals kg, float3 Ng, int prim, float u, float v)
ccl_device_inline void triangle_point_normal(KernelGlobals kg, int object, int prim, float u, float v, ccl_private float3 *P, ccl_private float3 *Ng, ccl_private int *shader)
ccl_device_inline void triangle_vertices(KernelGlobals kg, int prim, float3 P[3])
ccl_device_inline void triangle_vertices_and_normals(KernelGlobals kg, int prim, float3 P[3], float3 N[3])
ccl_device_inline float3 triangle_smooth_normal_unnormalized(KernelGlobals kg, ccl_private const ShaderData *sd, float3 Ng, int prim, float u, float v)
ccl_device_inline void triangle_dPdudv(KernelGlobals kg, int prim, ccl_private float3 *dPdu, ccl_private float3 *dPdv)
ccl_device float3 triangle_attribute_float3(KernelGlobals kg, ccl_private const ShaderData *sd, const AttributeDescriptor desc, ccl_private float3 *dx, ccl_private float3 *dy)
ccl_device_inline bool object_negative_scale_applied(const int object_flag)
ccl_device_inline void object_inverse_normal_transform(KernelGlobals kg, ccl_private const ShaderData *sd, ccl_private float3 *N)
ShaderData
@ SD_OBJECT_TRANSFORM_APPLIED
@ ATTR_ELEMENT_CORNER_BYTE
@ ATTR_ELEMENT_CORNER
@ ATTR_ELEMENT_OBJECT
@ ATTR_ELEMENT_VERTEX_MOTION
@ ATTR_ELEMENT_VERTEX
@ ATTR_ELEMENT_FACE
@ ATTR_ELEMENT_MESH
ccl_device_inline bool is_zero(const float2 a)
ccl_device_inline float2 safe_normalize(const float2 a)
ccl_device_inline float cross(const float2 a, const float2 b)
CCL_NAMESPACE_BEGIN ccl_device_inline float4 zero_float4()
Definition math_float4.h:15
#define N
AttributeElement element
uint y
Definition types_uint3.h:15
uint z
Definition types_uint3.h:15
uint x
Definition types_uint3.h:15
ccl_device_inline float4 color_uchar4_to_float4(uchar4 c)
Definition util/color.h:56
ccl_device float4 color_srgb_to_linear_v4(float4 c)
Definition util/color.h:327