Blender  V3.3
curve_intersect.h
Go to the documentation of this file.
1 /* SPDX-License-Identifier: Apache-2.0
2  * Copyright 2009-2020 Intel Corporation. Adapted from Embree with
3  * with modifications. */
4 
5 #pragma once
6 
8 
9 /* Curve primitive intersection functions.
10  *
11  * The code here was adapted from curve_intersector_sweep.h in Embree, to get
12  * an exact match between Embree CPU ray-tracing and our GPU ray-tracing. */
13 
14 #define CURVE_NUM_BEZIER_SUBDIVISIONS 3
15 #define CURVE_NUM_BEZIER_SUBDIVISIONS_UNSTABLE (CURVE_NUM_BEZIER_SUBDIVISIONS + 1)
16 #define CURVE_NUM_BEZIER_STEPS 2
17 #define CURVE_NUM_JACOBIAN_ITERATIONS 5
18 
19 #ifdef __HAIR__
20 
21 /* Catmull-rom curve evaluation. */
22 
23 ccl_device_inline float4 catmull_rom_basis_eval(const float4 curve[4], float u)
24 {
25  const float t = u;
26  const float s = 1.0f - u;
27  const float n0 = -t * s * s;
28  const float n1 = 2.0f + t * t * (3.0f * t - 5.0f);
29  const float n2 = 2.0f + s * s * (3.0f * s - 5.0f);
30  const float n3 = -s * t * t;
31  return 0.5f * (curve[0] * n0 + curve[1] * n1 + curve[2] * n2 + curve[3] * n3);
32 }
33 
34 ccl_device_inline float4 catmull_rom_basis_derivative(const float4 curve[4], float u)
35 {
36  const float t = u;
37  const float s = 1.0f - u;
38  const float n0 = -s * s + 2.0f * s * t;
39  const float n1 = 2.0f * t * (3.0f * t - 5.0f) + 3.0f * t * t;
40  const float n2 = 2.0f * s * (3.0f * t + 2.0f) - 3.0f * s * s;
41  const float n3 = -2.0f * s * t + t * t;
42  return 0.5f * (curve[0] * n0 + curve[1] * n1 + curve[2] * n2 + curve[3] * n3);
43 }
44 
45 ccl_device_inline float4 catmull_rom_basis_derivative2(const float4 curve[4], float u)
46 {
47 
48  const float t = u;
49  const float n0 = -3.0f * t + 2.0f;
50  const float n1 = 9.0f * t - 5.0f;
51  const float n2 = -9.0f * t + 4.0f;
52  const float n3 = 3.0f * t - 1.0f;
53  return (curve[0] * n0 + curve[1] * n1 + curve[2] * n2 + curve[3] * n3);
54 }
55 
56 /* Thick Curve */
57 
58 ccl_device_inline float3 dnormalize(const float3 p, const float3 dp)
59 {
60  const float pp = dot(p, p);
61  const float pdp = dot(p, dp);
62  return (pp * dp - pdp * p) / (pp * sqrtf(pp));
63 }
64 
65 ccl_device_inline float sqr_point_to_line_distance(const float3 PmQ0, const float3 Q1mQ0)
66 {
67  const float3 N = cross(PmQ0, Q1mQ0);
68  const float3 D = Q1mQ0;
69  return dot(N, N) / dot(D, D);
70 }
71 
72 ccl_device_inline bool cylinder_intersect(const float3 cylinder_start,
73  const float3 cylinder_end,
74  const float cylinder_radius,
75  const float3 ray_D,
76  ccl_private float2 *t_o,
77  ccl_private float *u0_o,
78  ccl_private float3 *Ng0_o,
79  ccl_private float *u1_o,
80  ccl_private float3 *Ng1_o)
81 {
82  /* Calculate quadratic equation to solve. */
83  const float rl = 1.0f / len(cylinder_end - cylinder_start);
84  const float3 P0 = cylinder_start, dP = (cylinder_end - cylinder_start) * rl;
85  const float3 O = -P0, dO = ray_D;
86 
87  const float dOdO = dot(dO, dO);
88  const float OdO = dot(dO, O);
89  const float OO = dot(O, O);
90  const float dOz = dot(dP, dO);
91  const float Oz = dot(dP, O);
92 
93  const float A = dOdO - sqr(dOz);
94  const float B = 2.0f * (OdO - dOz * Oz);
95  const float C = OO - sqr(Oz) - sqr(cylinder_radius);
96 
97  /* We miss the cylinder if determinant is smaller than zero. */
98  const float D = B * B - 4.0f * A * C;
99  if (!(D >= 0.0f)) {
100  *t_o = make_float2(FLT_MAX, -FLT_MAX);
101  return false;
102  }
103 
104  /* Special case for rays that are parallel to the cylinder. */
105  const float eps = 16.0f * FLT_EPSILON * max(fabsf(dOdO), fabsf(sqr(dOz)));
106  if (fabsf(A) < eps) {
107  if (C <= 0.0f) {
108  *t_o = make_float2(-FLT_MAX, FLT_MAX);
109  return true;
110  }
111  else {
112  *t_o = make_float2(-FLT_MAX, FLT_MAX);
113  return false;
114  }
115  }
116 
117  /* Standard case for rays that are not parallel to the cylinder. */
118  const float Q = sqrtf(D);
119  const float rcp_2A = 1.0f / (2.0f * A);
120  const float t0 = (-B - Q) * rcp_2A;
121  const float t1 = (-B + Q) * rcp_2A;
122 
123  /* Calculates u and Ng for near hit. */
124  {
125  *u0_o = (t0 * dOz + Oz) * rl;
126  const float3 Pr = t0 * ray_D;
127  const float3 Pl = (*u0_o) * (cylinder_end - cylinder_start) + cylinder_start;
128  *Ng0_o = Pr - Pl;
129  }
130 
131  /* Calculates u and Ng for far hit. */
132  {
133  *u1_o = (t1 * dOz + Oz) * rl;
134  const float3 Pr = t1 * ray_D;
135  const float3 Pl = (*u1_o) * (cylinder_end - cylinder_start) + cylinder_start;
136  *Ng1_o = Pr - Pl;
137  }
138 
139  *t_o = make_float2(t0, t1);
140 
141  return true;
142 }
143 
144 ccl_device_inline float2 half_plane_intersect(const float3 P, const float3 N, const float3 ray_D)
145 {
146  const float3 O = -P;
147  const float3 D = ray_D;
148  const float ON = dot(O, N);
149  const float DN = dot(D, N);
150  const float min_rcp_input = 1e-18f;
151  const bool eps = fabsf(DN) < min_rcp_input;
152  const float t = -ON / DN;
153  const float lower = (eps || DN < 0.0f) ? -FLT_MAX : t;
154  const float upper = (eps || DN > 0.0f) ? FLT_MAX : t;
155  return make_float2(lower, upper);
156 }
157 
158 ccl_device bool curve_intersect_iterative(const float3 ray_D,
159  const float ray_tmin,
160  ccl_private float *ray_tmax,
161  const float dt,
162  const float4 curve[4],
163  float u,
164  float t,
165  const bool use_backfacing,
166  ccl_private Intersection *isect)
167 {
168  const float length_ray_D = len(ray_D);
169 
170  /* Error of curve evaluations is proportional to largest coordinate. */
171  const float4 box_min = min(min(curve[0], curve[1]), min(curve[2], curve[3]));
172  const float4 box_max = max(min(curve[0], curve[1]), max(curve[2], curve[3]));
173  const float4 box_abs = max(fabs(box_min), fabs(box_max));
174  const float P_err = 16.0f * FLT_EPSILON *
175  max(box_abs.x, max(box_abs.y, max(box_abs.z, box_abs.w)));
176  const float radius_max = box_max.w;
177 
178  for (int i = 0; i < CURVE_NUM_JACOBIAN_ITERATIONS; i++) {
179  const float3 Q = ray_D * t;
180  const float3 dQdt = ray_D;
181  const float Q_err = 16.0f * FLT_EPSILON * length_ray_D * t;
182 
183  const float4 P4 = catmull_rom_basis_eval(curve, u);
184  const float4 dPdu4 = catmull_rom_basis_derivative(curve, u);
185 
186  const float3 P = float4_to_float3(P4);
187  const float3 dPdu = float4_to_float3(dPdu4);
188  const float radius = P4.w;
189  const float dradiusdu = dPdu4.w;
190 
191  const float3 ddPdu = float4_to_float3(catmull_rom_basis_derivative2(curve, u));
192 
193  const float3 R = Q - P;
194  const float len_R = len(R);
195  const float R_err = max(Q_err, P_err);
196  const float3 dRdu = -dPdu;
197  const float3 dRdt = dQdt;
198 
199  const float3 T = normalize(dPdu);
200  const float3 dTdu = dnormalize(dPdu, ddPdu);
201  const float cos_err = P_err / len(dPdu);
202 
203  const float f = dot(R, T);
204  const float f_err = len_R * P_err + R_err + cos_err * (1.0f + len_R);
205  const float dfdu = dot(dRdu, T) + dot(R, dTdu);
206  const float dfdt = dot(dRdt, T);
207 
208  const float K = dot(R, R) - sqr(f);
209  const float dKdu = (dot(R, dRdu) - f * dfdu);
210  const float dKdt = (dot(R, dRdt) - f * dfdt);
211  const float rsqrt_K = inversesqrtf(K);
212 
213  const float g = sqrtf(K) - radius;
214  const float g_err = R_err + f_err + 16.0f * FLT_EPSILON * radius_max;
215  const float dgdu = dKdu * rsqrt_K - dradiusdu;
216  const float dgdt = dKdt * rsqrt_K;
217 
218  const float invdet = 1.0f / (dfdu * dgdt - dgdu * dfdt);
219  u -= (dgdt * f - dfdt * g) * invdet;
220  t -= (-dgdu * f + dfdu * g) * invdet;
221 
222  if (fabsf(f) < f_err && fabsf(g) < g_err) {
223  t += dt;
224  if (!(t >= ray_tmin && t <= *ray_tmax)) {
225  return false; /* Rejects NaNs */
226  }
227  if (!(u >= 0.0f && u <= 1.0f)) {
228  return false; /* Rejects NaNs */
229  }
230 
231  /* Back-face culling. */
232  const float3 R = normalize(Q - P);
233  const float3 U = dradiusdu * R + dPdu;
234  const float3 V = cross(dPdu, R);
235  const float3 Ng = cross(V, U);
236  if (!use_backfacing && dot(ray_D, Ng) > 0.0f) {
237  return false;
238  }
239 
240  /* Record intersection. */
241  *ray_tmax = t;
242  isect->t = t;
243  isect->u = u;
244  isect->v = 0.0f;
245 
246  return true;
247  }
248  }
249  return false;
250 }
251 
252 ccl_device bool curve_intersect_recursive(const float3 ray_P,
253  const float3 ray_D,
254  const float ray_tmin,
255  float ray_tmax,
256  float4 curve[4],
257  ccl_private Intersection *isect)
258 {
259  /* Move ray closer to make intersection stable. */
260  const float3 center = float4_to_float3(0.25f * (curve[0] + curve[1] + curve[2] + curve[3]));
261  const float dt = dot(center - ray_P, ray_D) / dot(ray_D, ray_D);
262  const float3 ref = ray_P + ray_D * dt;
263  const float4 ref4 = make_float4(ref.x, ref.y, ref.z, 0.0f);
264  curve[0] -= ref4;
265  curve[1] -= ref4;
266  curve[2] -= ref4;
267  curve[3] -= ref4;
268 
269  const bool use_backfacing = false;
270  const float step_size = 1.0f / (float)(CURVE_NUM_BEZIER_STEPS);
271 
272  int depth = 0;
273 
274  /* todo: optimize stack for GPU somehow? Possibly some bitflags are enough, and
275  * u0/u1 can be derived from the depth. */
276  struct {
277  float u0, u1;
278  int i;
280 
281  bool found = false;
282 
283  float u0 = 0.0f;
284  float u1 = 1.0f;
285  int i = 0;
286 
287  while (1) {
288  for (; i < CURVE_NUM_BEZIER_STEPS; i++) {
289  const float step = i * step_size;
290 
291  /* Subdivide curve. */
292  const float dscale = (u1 - u0) * (1.0f / 3.0f) * step_size;
293  const float vu0 = mix(u0, u1, step);
294  const float vu1 = mix(u0, u1, step + step_size);
295 
296  const float4 P0 = catmull_rom_basis_eval(curve, vu0);
297  const float4 dP0du = dscale * catmull_rom_basis_derivative(curve, vu0);
298  const float4 P3 = catmull_rom_basis_eval(curve, vu1);
299  const float4 dP3du = dscale * catmull_rom_basis_derivative(curve, vu1);
300 
301  const float4 P1 = P0 + dP0du;
302  const float4 P2 = P3 - dP3du;
303 
304  /* Calculate bounding cylinders. */
305  const float rr1 = sqr_point_to_line_distance(float4_to_float3(dP0du),
306  float4_to_float3(P3 - P0));
307  const float rr2 = sqr_point_to_line_distance(float4_to_float3(dP3du),
308  float4_to_float3(P3 - P0));
309  const float maxr12 = sqrtf(max(rr1, rr2));
310  const float one_plus_ulp = 1.0f + 2.0f * FLT_EPSILON;
311  const float one_minus_ulp = 1.0f - 2.0f * FLT_EPSILON;
312  float r_outer = max(max(P0.w, P1.w), max(P2.w, P3.w)) + maxr12;
313  float r_inner = min(min(P0.w, P1.w), min(P2.w, P3.w)) - maxr12;
314  r_outer = one_plus_ulp * r_outer;
315  r_inner = max(0.0f, one_minus_ulp * r_inner);
316  bool valid = true;
317 
318  /* Intersect with outer cylinder. */
319  float2 tc_outer;
320  float u_outer0, u_outer1;
321  float3 Ng_outer0, Ng_outer1;
322  valid = cylinder_intersect(float4_to_float3(P0),
323  float4_to_float3(P3),
324  r_outer,
325  ray_D,
326  &tc_outer,
327  &u_outer0,
328  &Ng_outer0,
329  &u_outer1,
330  &Ng_outer1);
331  if (!valid) {
332  continue;
333  }
334 
335  /* Intersect with cap-planes. */
336  float2 tp = make_float2(ray_tmin - dt, ray_tmax - dt);
337  tp = make_float2(max(tp.x, tc_outer.x), min(tp.y, tc_outer.y));
338  const float2 h0 = half_plane_intersect(float4_to_float3(P0), float4_to_float3(dP0du), ray_D);
339  tp = make_float2(max(tp.x, h0.x), min(tp.y, h0.y));
340  const float2 h1 = half_plane_intersect(
341  float4_to_float3(P3), -float4_to_float3(dP3du), ray_D);
342  tp = make_float2(max(tp.x, h1.x), min(tp.y, h1.y));
343  valid = tp.x <= tp.y;
344  if (!valid) {
345  continue;
346  }
347 
348  /* Clamp and correct u parameter. */
349  u_outer0 = clamp(u_outer0, 0.0f, 1.0f);
350  u_outer1 = clamp(u_outer1, 0.0f, 1.0f);
351  u_outer0 = mix(u0, u1, (step + u_outer0) * (1.0f / (float)(CURVE_NUM_BEZIER_STEPS + 1)));
352  u_outer1 = mix(u0, u1, (step + u_outer1) * (1.0f / (float)(CURVE_NUM_BEZIER_STEPS + 1)));
353 
354  /* Intersect with inner cylinder. */
355  float2 tc_inner;
356  float u_inner0, u_inner1;
357  float3 Ng_inner0, Ng_inner1;
358  const bool valid_inner = cylinder_intersect(float4_to_float3(P0),
359  float4_to_float3(P3),
360  r_inner,
361  ray_D,
362  &tc_inner,
363  &u_inner0,
364  &Ng_inner0,
365  &u_inner1,
366  &Ng_inner1);
367 
368  /* At the unstable area we subdivide deeper. */
369 # if 0
370  const bool unstable0 = (!valid_inner) |
371  (fabsf(dot(normalize(ray_D), normalize(Ng_inner0))) < 0.3f);
372  const bool unstable1 = (!valid_inner) |
373  (fabsf(dot(normalize(ray_D), normalize(Ng_inner1))) < 0.3f);
374 # else
375  /* On the GPU appears to be a little faster if always enabled. */
376  (void)valid_inner;
377 
378  const bool unstable0 = true;
379  const bool unstable1 = true;
380 # endif
381 
382  /* Subtract the inner interval from the current hit interval. */
383  float2 tp0 = make_float2(tp.x, min(tp.y, tc_inner.x));
384  float2 tp1 = make_float2(max(tp.x, tc_inner.y), tp.y);
385  bool valid0 = valid && (tp0.x <= tp0.y);
386  bool valid1 = valid && (tp1.x <= tp1.y);
387  if (!(valid0 || valid1)) {
388  continue;
389  }
390 
391  /* Process one or two hits. */
392  bool recurse = false;
393  if (valid0) {
394  const int termDepth = unstable0 ? CURVE_NUM_BEZIER_SUBDIVISIONS_UNSTABLE :
396  if (depth >= termDepth) {
397  found |= curve_intersect_iterative(
398  ray_D, ray_tmin, &ray_tmax, dt, curve, u_outer0, tp0.x, use_backfacing, isect);
399  }
400  else {
401  recurse = true;
402  }
403  }
404 
405  const float t1 = tp1.x + dt;
406  if (valid1 && (t1 >= ray_tmin && t1 <= ray_tmax)) {
407  const int termDepth = unstable1 ? CURVE_NUM_BEZIER_SUBDIVISIONS_UNSTABLE :
409  if (depth >= termDepth) {
410  found |= curve_intersect_iterative(
411  ray_D, ray_tmin, &ray_tmax, dt, curve, u_outer1, tp1.y, use_backfacing, isect);
412  }
413  else {
414  recurse = true;
415  }
416  }
417 
418  if (recurse) {
419  stack[depth].u0 = u0;
420  stack[depth].u1 = u1;
421  stack[depth].i = i + 1;
422  depth++;
423 
424  u0 = vu0;
425  u1 = vu1;
426  i = -1;
427  }
428  }
429 
430  if (depth > 0) {
431  depth--;
432  u0 = stack[depth].u0;
433  u1 = stack[depth].u1;
434  i = stack[depth].i;
435  }
436  else {
437  break;
438  }
439  }
440 
441  return found;
442 }
443 
444 /* Ribbons */
445 
446 ccl_device_inline bool cylinder_culling_test(const float2 p1, const float2 p2, const float r)
447 {
448  /* Performs culling against a cylinder. */
449  const float2 dp = p2 - p1;
450  const float num = dp.x * p1.y - dp.y * p1.x;
451  const float den2 = dot(dp, dp);
452  return num * num <= r * r * den2;
453 }
454 
461 ccl_device_inline bool ribbon_intersect_quad(const float ray_tmin,
462  const float ray_tmax,
463  const float3 quad_v0,
464  const float3 quad_v1,
465  const float3 quad_v2,
466  const float3 quad_v3,
467  ccl_private float *u_o,
468  ccl_private float *v_o,
469  ccl_private float *t_o)
470 {
471  /* Calculate vertices relative to ray origin? */
472  const float3 O = make_float3(0.0f, 0.0f, 0.0f);
473  const float3 D = make_float3(0.0f, 0.0f, 1.0f);
474  const float3 va = quad_v0 - O;
475  const float3 vb = quad_v1 - O;
476  const float3 vc = quad_v2 - O;
477  const float3 vd = quad_v3 - O;
478 
479  const float3 edb = vb - vd;
480  const float WW = dot(cross(vd, edb), D);
481  const float3 v0 = (WW <= 0.0f) ? va : vc;
482  const float3 v1 = (WW <= 0.0f) ? vb : vd;
483  const float3 v2 = (WW <= 0.0f) ? vd : vb;
484 
485  /* Calculate edges? */
486  const float3 e0 = v2 - v0;
487  const float3 e1 = v0 - v1;
488 
489  /* perform edge tests */
490  const float U = dot(cross(v0, e0), D);
491  const float V = dot(cross(v1, e1), D);
492  if (!(max(U, V) <= 0.0f)) {
493  return false;
494  }
495 
496  /* Calculate geometry normal and denominator? */
497  const float3 Ng = cross(e1, e0);
498  const float den = dot(Ng, D);
499  const float rcpDen = 1.0f / den;
500 
501  /* Perform depth test? */
502  const float t = rcpDen * dot(v0, Ng);
503  if (!(t >= ray_tmin && t <= ray_tmax)) {
504  return false;
505  }
506 
507  /* Avoid division by 0? */
508  if (!(den != 0.0f)) {
509  return false;
510  }
511 
512  /* Update hit information? */
513  *t_o = t;
514  *u_o = U * rcpDen;
515  *v_o = V * rcpDen;
516  *u_o = (WW <= 0.0f) ? *u_o : 1.0f - *u_o;
517  *v_o = (WW <= 0.0f) ? *v_o : 1.0f - *v_o;
518  return true;
519 }
520 
521 ccl_device_inline void ribbon_ray_space(const float3 ray_D,
522  const float ray_D_invlen,
523  float3 ray_space[3])
524 {
525  const float3 D = ray_D * ray_D_invlen;
526  const float3 dx0 = make_float3(0, D.z, -D.y);
527  const float3 dx1 = make_float3(-D.z, 0, D.x);
528  ray_space[0] = normalize(dot(dx0, dx0) > dot(dx1, dx1) ? dx0 : dx1);
529  ray_space[1] = normalize(cross(D, ray_space[0]));
530  ray_space[2] = D * ray_D_invlen;
531 }
532 
533 ccl_device_inline float4 ribbon_to_ray_space(const float3 ray_space[3],
534  const float3 ray_org,
535  const float4 P4)
536 {
537  float3 P = float4_to_float3(P4) - ray_org;
538  return make_float4(dot(ray_space[0], P), dot(ray_space[1], P), dot(ray_space[2], P), P4.w);
539 }
540 
541 ccl_device_inline bool ribbon_intersect(const float3 ray_org,
542  const float3 ray_D,
543  const float ray_tmin,
544  float ray_tmax,
545  const int N,
546  float4 curve[4],
547  ccl_private Intersection *isect)
548 {
549  /* Transform control points into ray space. */
550  const float ray_D_invlen = 1.0f / len(ray_D);
551  float3 ray_space[3];
552  ribbon_ray_space(ray_D, ray_D_invlen, ray_space);
553 
554  curve[0] = ribbon_to_ray_space(ray_space, ray_org, curve[0]);
555  curve[1] = ribbon_to_ray_space(ray_space, ray_org, curve[1]);
556  curve[2] = ribbon_to_ray_space(ray_space, ray_org, curve[2]);
557  curve[3] = ribbon_to_ray_space(ray_space, ray_org, curve[3]);
558 
559  const float4 mx = max(max(fabs(curve[0]), fabs(curve[1])), max(fabs(curve[2]), fabs(curve[3])));
560  const float eps = 4.0f * FLT_EPSILON * max(max(mx.x, mx.y), max(mx.z, mx.w));
561  const float step_size = 1.0f / (float)N;
562 
563  /* Evaluate first point and radius scaled normal direction. */
564  float4 p0 = catmull_rom_basis_eval(curve, 0.0f);
565  float3 dp0dt = float4_to_float3(catmull_rom_basis_derivative(curve, 0.0f));
566  if (reduce_max(fabs(dp0dt)) < eps) {
567  const float4 p1 = catmull_rom_basis_eval(curve, step_size);
568  dp0dt = float4_to_float3(p1 - p0);
569  }
570  float3 wn0 = normalize(make_float3(dp0dt.y, -dp0dt.x, 0.0f)) * p0.w;
571 
572  /* Evaluate the bezier curve. */
573  for (int i = 0; i < N; i++) {
574  const float u = i * step_size;
575  const float4 p1 = catmull_rom_basis_eval(curve, u + step_size);
576  const bool valid = cylinder_culling_test(
577  make_float2(p0.x, p0.y), make_float2(p1.x, p1.y), max(p0.w, p1.w));
578 
579  /* Evaluate next point. */
580  float3 dp1dt = float4_to_float3(catmull_rom_basis_derivative(curve, u + step_size));
581  dp1dt = (reduce_max(fabs(dp1dt)) < eps) ? float4_to_float3(p1 - p0) : dp1dt;
582  const float3 wn1 = normalize(make_float3(dp1dt.y, -dp1dt.x, 0.0f)) * p1.w;
583 
584  if (valid) {
585  /* Construct quad coordinates. */
586  const float3 lp0 = float4_to_float3(p0) + wn0;
587  const float3 lp1 = float4_to_float3(p1) + wn1;
588  const float3 up0 = float4_to_float3(p0) - wn0;
589  const float3 up1 = float4_to_float3(p1) - wn1;
590 
591  /* Intersect quad. */
592  float vu, vv, vt;
593  bool valid0 = ribbon_intersect_quad(ray_tmin, ray_tmax, lp0, lp1, up1, up0, &vu, &vv, &vt);
594 
595  if (valid0) {
596  /* ignore self intersections */
597  const float avoidance_factor = 2.0f;
598  if (avoidance_factor != 0.0f) {
599  float r = mix(p0.w, p1.w, vu);
600  valid0 = vt > avoidance_factor * r * ray_D_invlen;
601  }
602 
603  if (valid0) {
604  vv = 2.0f * vv - 1.0f;
605 
606  /* Record intersection. */
607  ray_tmax = vt;
608  isect->t = vt;
609  isect->u = u + vu * step_size;
610  isect->v = vv;
611  return true;
612  }
613  }
614  }
615 
616  /* Store point for next step. */
617  p0 = p1;
618  wn0 = wn1;
619  }
620  return false;
621 }
622 
623 ccl_device_forceinline bool curve_intersect(KernelGlobals kg,
624  ccl_private Intersection *isect,
625  const float3 ray_P,
626  const float3 ray_D,
627  const float tmin,
628  const float tmax,
629  int object,
630  int prim,
631  float time,
632  int type)
633 {
634  const bool is_motion = (type & PRIMITIVE_MOTION);
635 
636  KernelCurve kcurve = kernel_data_fetch(curves, prim);
637 
638  int k0 = kcurve.first_key + PRIMITIVE_UNPACK_SEGMENT(type);
639  int k1 = k0 + 1;
640  int ka = max(k0 - 1, kcurve.first_key);
641  int kb = min(k1 + 1, kcurve.first_key + kcurve.num_keys - 1);
642 
643  float4 curve[4];
644  if (!is_motion) {
645  curve[0] = kernel_data_fetch(curve_keys, ka);
646  curve[1] = kernel_data_fetch(curve_keys, k0);
647  curve[2] = kernel_data_fetch(curve_keys, k1);
648  curve[3] = kernel_data_fetch(curve_keys, kb);
649  }
650  else {
651  motion_curve_keys(kg, object, prim, time, ka, k0, k1, kb, curve);
652  }
653 
655  /* todo: adaptive number of subdivisions could help performance here. */
656  const int subdivisions = kernel_data.bvh.curve_subdivisions;
657  if (ribbon_intersect(ray_P, ray_D, tmin, tmax, subdivisions, curve, isect)) {
658  isect->prim = prim;
659  isect->object = object;
660  isect->type = type;
661  return true;
662  }
663 
664  return false;
665  }
666  else {
667  if (curve_intersect_recursive(ray_P, ray_D, tmin, tmax, curve, isect)) {
668  isect->prim = prim;
669  isect->object = object;
670  isect->type = type;
671  return true;
672  }
673 
674  return false;
675  }
676 }
677 
678 ccl_device_inline void curve_shader_setup(KernelGlobals kg,
680  float3 P,
681  float3 D,
682  float t,
683  const int isect_object,
684  const int isect_prim)
685 {
686  if (!(sd->object_flag & SD_OBJECT_TRANSFORM_APPLIED)) {
687  const Transform tfm = object_get_inverse_transform(kg, sd);
688 
689  P = transform_point(&tfm, P);
690  D = transform_direction(&tfm, D * t);
691  D = safe_normalize_len(D, &t);
692  }
693 
694  KernelCurve kcurve = kernel_data_fetch(curves, isect_prim);
695 
696  int k0 = kcurve.first_key + PRIMITIVE_UNPACK_SEGMENT(sd->type);
697  int k1 = k0 + 1;
698  int ka = max(k0 - 1, kcurve.first_key);
699  int kb = min(k1 + 1, kcurve.first_key + kcurve.num_keys - 1);
700 
701  float4 P_curve[4];
702 
703  if (!(sd->type & PRIMITIVE_MOTION)) {
704  P_curve[0] = kernel_data_fetch(curve_keys, ka);
705  P_curve[1] = kernel_data_fetch(curve_keys, k0);
706  P_curve[2] = kernel_data_fetch(curve_keys, k1);
707  P_curve[3] = kernel_data_fetch(curve_keys, kb);
708  }
709  else {
710  motion_curve_keys(kg, sd->object, sd->prim, sd->time, ka, k0, k1, kb, P_curve);
711  }
712 
713  P = P + D * t;
714 
715  const float4 dPdu4 = catmull_rom_basis_derivative(P_curve, sd->u);
716  const float3 dPdu = float4_to_float3(dPdu4);
717 
718  if (sd->type & PRIMITIVE_CURVE_RIBBON) {
719  /* Rounded smooth normals for ribbons, to approximate thick curve shape. */
720  const float3 tangent = normalize(dPdu);
721  const float3 bitangent = normalize(cross(tangent, -D));
722  const float sine = sd->v;
723  const float cosine = safe_sqrtf(1.0f - sine * sine);
724 
725  sd->N = normalize(sine * bitangent - cosine * normalize(cross(tangent, bitangent)));
726 # if 0
727  /* This approximates the position and geometric normal of a thick curve too,
728  * but gives too many issues with wrong self intersections. */
729  const float dPdu_radius = dPdu4.w;
730  sd->Ng = sd->N;
731  P += sd->N * dPdu_radius;
732 # endif
733  }
734  else {
735  /* Thick curves, compute normal using direction from inside the curve.
736  * This could be optimized by recording the normal in the intersection,
737  * however for Optix this would go beyond the size of the payload. */
738  /* NOTE: It is possible that P will be the same as P_inside (precision issues, or very small
739  * radius). In this case use the view direction to approximate the normal. */
740  const float3 P_inside = float4_to_float3(catmull_rom_basis_eval(P_curve, sd->u));
741  const float3 N = (!isequal(P, P_inside)) ? normalize(P - P_inside) : -sd->I;
742 
743  sd->N = N;
744  sd->v = 0.0f;
745  }
746 
747 # ifdef __DPDU__
748  /* dPdu/dPdv */
749  sd->dPdu = dPdu;
750 # endif
751 
752  /* Convert to world space. */
753  if (!(sd->object_flag & SD_OBJECT_TRANSFORM_APPLIED)) {
755  object_normal_transform_auto(kg, sd, &sd->N);
756  object_dir_transform_auto(kg, sd, &sd->dPdu);
757  }
758 
759  sd->P = P;
760  sd->Ng = (sd->type & PRIMITIVE_CURVE_RIBBON) ? sd->I : sd->N;
761  sd->dPdv = cross(sd->dPdu, sd->Ng);
762  sd->shader = kernel_data_fetch(curves, sd->prim).shader_id;
763 }
764 
765 #endif
766 
typedef float(TangentPoint)[2]
MINLINE float safe_sqrtf(float a)
#define K(key)
NSNotificationCenter * center
_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 GLdouble r _GL_VOID_RET _GL_VOID GLfloat GLfloat r _GL_VOID_RET _GL_VOID GLint GLint r _GL_VOID_RET _GL_VOID GLshort GLshort r _GL_VOID_RET _GL_VOID GLdouble GLdouble r
_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 u1
_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 type
_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
_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 v1
float float4[4]
Group Output data from inside of a node group A color picker Mix two input colors RGB to Convert a color s luminance to a grayscale value Generate a normal vector and a dot product Bright Control the brightness and contrast of the input color Vector Map an input vectors to curves
#define C
Definition: RandGen.cpp:25
__forceinline int reduce_max(const avxi &v)
Definition: avxi.h:692
ATTR_WARN_UNUSED_RESULT const BMVert * v2
#define A
unsigned int U
Definition: btGjkEpa3.h:78
#define ccl_device_forceinline
Definition: cuda/compat.h:35
#define ccl_device
Definition: cuda/compat.h:32
#define ccl_private
Definition: cuda/compat.h:48
#define ccl_device_inline
Definition: cuda/compat.h:34
#define CCL_NAMESPACE_END
Definition: cuda/compat.h:9
#define CURVE_NUM_BEZIER_SUBDIVISIONS_UNSTABLE
#define CURVE_NUM_BEZIER_STEPS
#define CURVE_NUM_JACOBIAN_ITERATIONS
#define CURVE_NUM_BEZIER_SUBDIVISIONS
double time
Curve curve
#define kernel_data
const KernelGlobalsCPU *ccl_restrict KernelGlobals
#define kernel_data_fetch(name, index)
SyclQueue void void size_t num_bytes void
int len
Definition: draw_manager.c:108
#define mix(a, b, c)
Definition: hash.h:17
ccl_device_inline float3 transform_direction(ccl_private const Transform *t, const float3 a)
CCL_NAMESPACE_END CCL_NAMESPACE_BEGIN ccl_device_inline float3 transform_point(ccl_private const Transform *t, const float3 a)
#define object_normal_transform_auto
#define object_position_transform_auto
#define object_dir_transform_auto
ccl_device_inline Transform object_get_inverse_transform(KernelGlobals kg, ccl_private const ShaderData *sd)
@ PRIMITIVE_MOTION
Definition: kernel/types.h:558
@ PRIMITIVE_CURVE_RIBBON
Definition: kernel/types.h:553
#define PRIMITIVE_UNPACK_SEGMENT(type)
Definition: kernel/types.h:579
ShaderData
Definition: kernel/types.h:925
@ SD_OBJECT_TRANSFORM_APPLIED
Definition: kernel/types.h:808
ccl_device_inline float2 fabs(const float2 &a)
Definition: math_float2.h:222
ccl_device_inline bool isequal(const float3 a, const float3 b)
Definition: math_float3.h:524
ccl_device_inline float3 safe_normalize_len(const float3 a, ccl_private float *t)
Definition: math_float3.h:471
static float P(float k)
Definition: math_interp.c:25
#define N
#define T
#define B
#define R
#define make_float2(x, y)
Definition: metal/compat.h:203
#define make_float4(x, y, z, w)
Definition: metal/compat.h:205
#define fabsf(x)
Definition: metal/compat.h:219
#define sqrtf(x)
Definition: metal/compat.h:243
#define make_float3(x, y, z)
Definition: metal/compat.h:204
T dot(const vec_base< T, Size > &a, const vec_base< T, Size > &b)
vec_base< T, 3 > cross(const vec_base< T, 3 > &a, const vec_base< T, 3 > &b)
T clamp(const T &a, const T &min, const T &max)
vec_base< T, Size > normalize(const vec_base< T, Size > &v)
static const pxr::TfToken g("g", pxr::TfToken::Immortal)
const btScalar eps
Definition: poly34.cpp:11
#define min(a, b)
Definition: sort.c:35
float x
Definition: types_float2.h:15
float y
Definition: types_float2.h:15
float z
float y
float x
float max
ccl_device_inline float sqr(float a)
Definition: util/math.h:746
ccl_device_inline float inversesqrtf(float f)
Definition: util/math.h:682
ccl_device_inline float3 float4_to_float3(const float4 a)
Definition: util/math.h:500
BLI_INLINE float D(const float *data, const int res[3], int x, int y, int z)
Definition: voxel.c:13
CCL_NAMESPACE_BEGIN struct Window V