Blender V5.0
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 "kernel/globals.h"
14
16#include "kernel/geom/object.h"
17
19
20/* Evaluate a quantity at barycentric coordinates u, v, given the values at three triangle
21 * vertices. */
22template<typename T>
24triangle_interpolate(const float u, const float v, const T f0, const T f1, const T f2)
25{
26 return (1.0f - u - v) * f0 + u * f1 + v * f2;
27}
28
29/* Normal on triangle. */
31{
32 /* load triangle vertices */
33 const uint3 tri_vindex = kernel_data_fetch(tri_vindex, sd->prim);
34 const float3 v0 = kernel_data_fetch(tri_verts, tri_vindex.x);
35 const float3 v1 = kernel_data_fetch(tri_verts, tri_vindex.y);
36 const float3 v2 = kernel_data_fetch(tri_verts, tri_vindex.z);
37
38 /* return normal */
39 if (object_negative_scale_applied(sd->object_flag)) {
40 return normalize(cross(v2 - v0, v1 - v0));
41 }
42 return normalize(cross(v1 - v0, v2 - v0));
43}
44
45/* Point and normal on triangle. */
47 const int object,
48 const int prim,
49 const float u,
50 const float v,
53 ccl_private int *shader)
54{
55 /* load triangle vertices */
56 const uint3 tri_vindex = kernel_data_fetch(tri_vindex, prim);
57 const float3 v0 = kernel_data_fetch(tri_verts, tri_vindex.x);
58 const float3 v1 = kernel_data_fetch(tri_verts, tri_vindex.y);
59 const float3 v2 = kernel_data_fetch(tri_verts, tri_vindex.z);
60
61 /* compute point */
62 const float w = 1.0f - u - v;
63 *P = (w * v0 + u * v1 + v * v2);
64 /* get object flags */
65 const int object_flag = kernel_data_fetch(object_flag, object);
66 /* compute normal */
67 if (object_negative_scale_applied(object_flag)) {
68 *Ng = normalize(cross(v2 - v0, v1 - v0));
69 }
70 else {
71 *Ng = normalize(cross(v1 - v0, v2 - v0));
72 }
73 /* shader */
74 *shader = kernel_data_fetch(tri_shader, prim);
75}
76
77/* Triangle vertex locations */
78
80{
81 const uint3 tri_vindex = kernel_data_fetch(tri_vindex, prim);
82 P[0] = kernel_data_fetch(tri_verts, tri_vindex.x);
83 P[1] = kernel_data_fetch(tri_verts, tri_vindex.y);
84 P[2] = kernel_data_fetch(tri_verts, tri_vindex.z);
85}
86
87/* Triangle vertex locations and vertex normals */
88
90 const int prim,
91 float3 P[3],
92 float3 N[3])
93{
94 const uint3 tri_vindex = kernel_data_fetch(tri_vindex, prim);
95 P[0] = kernel_data_fetch(tri_verts, tri_vindex.x);
96 P[1] = kernel_data_fetch(tri_verts, tri_vindex.y);
97 P[2] = kernel_data_fetch(tri_verts, tri_vindex.z);
98
99 N[0] = kernel_data_fetch(tri_vnormal, tri_vindex.x);
100 N[1] = kernel_data_fetch(tri_vnormal, tri_vindex.y);
101 N[2] = kernel_data_fetch(tri_vnormal, tri_vindex.z);
102}
103
104/* Interpolate smooth vertex normal from vertices */
105
107triangle_smooth_normal(KernelGlobals kg, const float3 Ng, const int prim, const float u, float v)
108{
109 /* load triangle vertices */
110 const uint3 tri_vindex = kernel_data_fetch(tri_vindex, prim);
111
112 const float3 n0 = kernel_data_fetch(tri_vnormal, tri_vindex.x);
113 const float3 n1 = kernel_data_fetch(tri_vnormal, tri_vindex.y);
114 const float3 n2 = kernel_data_fetch(tri_vnormal, tri_vindex.z);
115
116 const float3 N = safe_normalize((1.0f - u - v) * n0 + u * n1 + v * n2);
117
118 return is_zero(N) ? Ng : N;
119}
120
121/* Compute triangle normals at the hit position, and offsetted positions in x and y direction for
122 * bump mapping. */
124 const float3 Ng,
125 const int prim,
126 const float u,
127 float v,
128 const differential du,
129 const differential dv,
130 ccl_private float3 &N_x,
131 ccl_private float3 &N_y)
132{
133 /* Load triangle vertices. */
134 const uint3 tri_vindex = kernel_data_fetch(tri_vindex, prim);
135
136 const float3 n0 = kernel_data_fetch(tri_vnormal, tri_vindex.x);
137 const float3 n1 = kernel_data_fetch(tri_vnormal, tri_vindex.y);
138 const float3 n2 = kernel_data_fetch(tri_vnormal, tri_vindex.z);
139
140 const float3 N = safe_normalize(triangle_interpolate(u, v, n0, n1, n2));
141 N_x = safe_normalize(triangle_interpolate(u + du.dx, v + dv.dx, n0, n1, n2));
142 N_y = safe_normalize(triangle_interpolate(u + du.dy, v + dv.dy, n0, n1, n2));
143
144 N_x = is_zero(N_x) ? Ng : N_x;
145 N_y = is_zero(N_y) ? Ng : N_y;
146 return is_zero(N) ? Ng : N;
147}
148
150 const ccl_private ShaderData *sd,
151 const float3 Ng,
152 const int prim,
153 const float u,
154 float v)
155{
156 /* load triangle vertices */
157 const uint3 tri_vindex = kernel_data_fetch(tri_vindex, prim);
158
159 float3 n0 = kernel_data_fetch(tri_vnormal, tri_vindex.x);
160 float3 n1 = kernel_data_fetch(tri_vnormal, tri_vindex.y);
161 float3 n2 = kernel_data_fetch(tri_vnormal, tri_vindex.z);
162
163 /* ensure that the normals are in object space */
164 if (sd->object_flag & SD_OBJECT_TRANSFORM_APPLIED) {
168 }
169
170 const float3 N = (1.0f - u - v) * n0 + u * n1 + v * n2;
171
172 return is_zero(N) ? Ng : N;
173}
174
175/* Ray differentials on triangle */
176
178 const int prim,
179 ccl_private float3 *dPdu,
180 ccl_private float3 *dPdv)
181{
182 /* fetch triangle vertex coordinates */
183 const uint3 tri_vindex = kernel_data_fetch(tri_vindex, prim);
184 const float3 p0 = kernel_data_fetch(tri_verts, tri_vindex.x);
185 const float3 p1 = kernel_data_fetch(tri_verts, tri_vindex.y);
186 const float3 p2 = kernel_data_fetch(tri_verts, tri_vindex.z);
187
188 /* compute derivatives of P w.r.t. uv */
189 *dPdu = (p1 - p0);
190 *dPdv = (p2 - p0);
191}
192
193/* Partial derivative of f w.r.t. x, namely ∂f/∂x.
194 * f is a function of barycentric coordinates u, v, given by
195 * f(u, v) = f1 * u + f2 * v + f0 * (1 - u - v),
196 * the derivatives are
197 * ∂f/∂u = (f1 - f0), ∂f/∂v = (f2 - f0).
198 * The partial derivative in x is
199 * ∂f/∂x = ∂f/∂u * ∂u/∂x + ∂f/∂v * ∂v/∂x
200 * = (f1 - f0) * du.dx + (f2 - f0) * dv.dx. */
201template<typename T>
203 const ccl_private differential &dv,
204 const ccl_private T &f0,
205 const ccl_private T &f1,
206 const ccl_private T &f2)
207{
208 return du.dx * f1 + dv.dx * f2 - (du.dx + dv.dx) * f0;
209}
210
211/* Partial derivative of f w.r.t. in x, namely ∂f/∂y, similarly computed as ∂f/∂x above. */
212template<typename T>
214 const ccl_private differential &dv,
215 const ccl_private T &f0,
216 const ccl_private T &f1,
217 const ccl_private T &f2)
218{
219 return du.dy * f1 + dv.dy * f2 - (du.dy + dv.dy) * f0;
220}
221
222/* Read attributes on various triangle elements, and compute the partial derivatives if requested.
223 */
224template<typename T>
226 const ccl_private ShaderData *sd,
227 const AttributeDescriptor desc,
228 const bool dx = false,
229 const bool dy = false)
230{
234 {
235 T f0;
236 T f1;
237 T f2;
238
240 const uint3 tri_vindex = kernel_data_fetch(tri_vindex, sd->prim);
241
242 f0 = attribute_data_fetch<T>(kg, desc.offset + tri_vindex.x);
243 f1 = attribute_data_fetch<T>(kg, desc.offset + tri_vindex.y);
244 f2 = attribute_data_fetch<T>(kg, desc.offset + tri_vindex.z);
245 }
246 else if (desc.element == ATTR_ELEMENT_CORNER_BYTE) {
247 const int tri = desc.offset + sd->prim * 3;
248 f0 = attribute_data_fetch_bytecolor<T>(kg, tri + 0);
249 f1 = attribute_data_fetch_bytecolor<T>(kg, tri + 1);
250 f2 = attribute_data_fetch_bytecolor<T>(kg, tri + 2);
251 }
252 else {
253 const int tri = desc.offset + sd->prim * 3;
254 f0 = attribute_data_fetch<T>(kg, tri + 0);
255 f1 = attribute_data_fetch<T>(kg, tri + 1);
256 f2 = attribute_data_fetch<T>(kg, tri + 2);
257 }
258
259#ifdef __RAY_DIFFERENTIALS__
260 if (dx) {
261 result.dx = triangle_attribute_dfdx(sd->du, sd->dv, f0, f1, f2);
262 }
263 if (dy) {
264 result.dy = triangle_attribute_dfdy(sd->du, sd->dv, f0, f1, f2);
265 }
266#endif
267
268 result.val = sd->u * f1 + sd->v * f2 + (1.0f - sd->u - sd->v) * f0;
269 return result;
270 }
271
272 if (desc.element == ATTR_ELEMENT_FACE) {
273 return dual<T>(attribute_data_fetch<T>(kg, desc.offset + sd->prim));
274 }
275 return make_zero<dual<T>>();
276}
277
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
#define kernel_data_fetch(name, index)
#define ccl_private
const ThreadKernelGlobalsCPU * KernelGlobals
#define ccl_device_inline
#define CCL_NAMESPACE_END
CCL_NAMESPACE_BEGIN ccl_device_inline T triangle_interpolate(const float u, const float v, const T f0, const T f1, const T f2)
ccl_device_inline float3 triangle_normal(KernelGlobals kg, ccl_private ShaderData *sd)
ccl_device_inline T triangle_attribute_dfdy(const ccl_private differential &du, const ccl_private differential &dv, const ccl_private T &f0, const ccl_private T &f1, const ccl_private T &f2)
ccl_device_inline T triangle_attribute_dfdx(const ccl_private differential &du, const ccl_private differential &dv, const ccl_private T &f0, const ccl_private T &f1, const ccl_private T &f2)
ccl_device dual< T > triangle_attribute(KernelGlobals kg, const ccl_private ShaderData *sd, const AttributeDescriptor desc, const bool dx=false, const bool dy=false)
ccl_device_inline void triangle_dPdudv(KernelGlobals kg, const int prim, ccl_private float3 *dPdu, ccl_private float3 *dPdv)
ccl_device_inline void triangle_vertices(KernelGlobals kg, const int prim, float3 P[3])
ccl_device_inline float3 triangle_smooth_normal(KernelGlobals kg, const float3 Ng, const int prim, const float u, float v)
ccl_device_inline void triangle_vertices_and_normals(KernelGlobals kg, const int prim, float3 P[3], float3 N[3])
ccl_device_inline void triangle_point_normal(KernelGlobals kg, const int object, const int prim, const float u, const float v, ccl_private float3 *P, ccl_private float3 *Ng, ccl_private int *shader)
ccl_device_inline float3 triangle_smooth_normal_unnormalized(KernelGlobals kg, const ccl_private ShaderData *sd, const float3 Ng, const int prim, const float u, float v)
VecBase< float, D > normalize(VecOp< float, D >) RET
VecBase< float, 3 > cross(VecOp< float, 3 >, VecOp< float, 3 >) RET
ccl_device_inline T attribute_data_fetch_bytecolor(KernelGlobals, int)
ccl_device_inline T attribute_data_fetch(KernelGlobals kg, int offset)
ccl_device_inline bool object_negative_scale_applied(const int object_flag)
ccl_device_inline void object_inverse_normal_transform(KernelGlobals kg, const ccl_private ShaderData *sd, ccl_private float3 *N)
@ SD_OBJECT_TRANSFORM_APPLIED
@ ATTR_ELEMENT_CORNER_BYTE
@ ATTR_ELEMENT_CORNER
@ ATTR_ELEMENT_VERTEX_MOTION
@ ATTR_ELEMENT_VERTEX
@ ATTR_ELEMENT_FACE
ccl_device_inline T make_zero()
Definition math_dual.h:17
ccl_device_inline bool is_zero(const float2 a)
ccl_device_inline float2 safe_normalize(const float2 a)
#define N
#define T
#define ccl_device
AttributeElement element
uint y
Definition types_uint3.h:13
uint z
Definition types_uint3.h:13
uint x
Definition types_uint3.h:13