20#define CURVE_NUM_BEZIER_SUBDIVISIONS 3
21#define CURVE_NUM_BEZIER_SUBDIVISIONS_UNSTABLE (CURVE_NUM_BEZIER_SUBDIVISIONS + 1)
22#define CURVE_NUM_BEZIER_STEPS 2
23#define CURVE_NUM_JACOBIAN_ITERATIONS 5
33 const float s = 1.0f - u;
34 const float n0 = -t * s * s;
35 const float n1 = 2.0f + t * t * (3.0f * t - 5.0f);
36 const float n2 = 2.0f + s * s * (3.0f * s - 5.0f);
37 const float n3 = -s * t * t;
38 return 0.5f * (curve[0] * n0 + curve[1] * n1 + curve[2] * n2 + curve[3] * n3);
44 const float s = 1.0f - u;
45 const float n0 = -s * s + 2.0f * s * t;
46 const float n1 = 2.0f * t * (3.0f * t - 5.0f) + 3.0f * t * t;
47 const float n2 = 2.0f * s * (3.0f * t + 2.0f) - 3.0f * s * s;
48 const float n3 = -2.0f * s * t + t * t;
49 return 0.5f * (curve[0] * n0 + curve[1] * n1 + curve[2] * n2 + curve[3] * n3);
55 const float n0 = -3.0f * t + 2.0f;
56 const float n1 = 9.0f * t - 5.0f;
57 const float n2 = -9.0f * t + 4.0f;
58 const float n3 = 3.0f * t - 1.0f;
59 return (curve[0] * n0 + curve[1] * n1 + curve[2] * n2 + curve[3] * n3);
66 const float pp =
dot(p, p);
67 const float pdp =
dot(p, dp);
68 return (pp * dp - pdp * p) / (pp *
sqrtf(pp));
80 const float cylinder_radius,
89 const float rl = 1.0f /
len(cylinder_end - cylinder_start);
90 const float3 P0 = cylinder_start;
91 const float3 dP = (cylinder_end - cylinder_start) * rl;
95 const float dOdO =
dot(dO, dO);
96 const float OdO =
dot(dO, O);
97 const float OO =
dot(O, O);
98 const float dOz =
dot(dP, dO);
99 const float Oz =
dot(dP, O);
101 const float A = dOdO -
sqr(dOz);
102 const float B = 2.0f * (OdO - dOz * Oz);
103 const float C = OO -
sqr(Oz) -
sqr(cylinder_radius);
106 const float D =
B *
B - 4.0f *
A *
C;
125 const float rcp_2A = 1.0f / (2.0f *
A);
126 const float t0 = (-
B - Q) * rcp_2A;
127 const float t1 = (-
B + Q) * rcp_2A;
131 *u0_o = (t0 * dOz + Oz) * rl;
132 const float3 Pr = t0 * ray_D;
133 const float3 Pl = (*u0_o) * (cylinder_end - cylinder_start) + cylinder_start;
139 *u1_o = (t1 * dOz + Oz) * rl;
140 const float3 Pr = t1 * ray_D;
141 const float3 Pl = (*u1_o) * (cylinder_end - cylinder_start) + cylinder_start;
154 const float ON =
dot(O,
N);
155 const float DN =
dot(
D,
N);
156 const float min_rcp_input = 1e-18f;
157 const bool eps =
fabsf(DN) < min_rcp_input;
158 const float t = -ON / DN;
159 const float lower = (
eps || DN < 0.0f) ? -
FLT_MAX : t;
160 const float upper = (
eps || DN > 0.0f) ?
FLT_MAX : t;
165 const float ray_tmin,
171 const bool use_backfacing,
174 const float length_ray_D =
len(ray_D);
177 const float4 box_min =
min(
min(curve[0], curve[1]),
min(curve[2], curve[3]));
178 const float4 box_max =
max(
min(curve[0], curve[1]),
max(curve[2], curve[3]));
180 const float P_err = 16.0f * FLT_EPSILON *
182 const float radius_max = box_max.
w;
185 const float3 Q = ray_D * t;
186 const float3 dQdt = ray_D;
187 const float Q_err = 16.0f * FLT_EPSILON * length_ray_D * t;
189 const float4 P4 = catmull_rom_basis_eval(curve, u);
190 const float4 dPdu4 = catmull_rom_basis_derivative(curve, u);
194 const float radius = P4.
w;
195 const float dradiusdu = dPdu4.
w;
200 const float len_R =
len(
R);
201 const float R_err =
max(Q_err, P_err);
202 const float3 dRdu = -dPdu;
206 const float3 dTdu = dnormalize(dPdu, ddPdu);
207 const float cos_err = P_err /
len(dPdu);
209 const float f =
dot(
R,
T);
210 const float f_err = len_R * P_err + R_err + cos_err * (1.0f + len_R);
211 const float dfdu =
dot(dRdu,
T) +
dot(
R, dTdu);
212 const float dfdt =
dot(dRdt,
T);
215 const float dKdu = (
dot(
R, dRdu) - f * dfdu);
216 const float dKdt = (
dot(
R, dRdt) - f * dfdt);
219 const float g =
sqrtf(
K) - radius;
220 const float g_err = R_err + f_err + 16.0f * FLT_EPSILON * radius_max;
221 const float dgdu = dKdu * rsqrt_K - dradiusdu;
222 const float dgdt = dKdt * rsqrt_K;
224 const float invdet = 1.0f / (dfdu * dgdt - dgdu * dfdt);
225 u -= (dgdt * f - dfdt * g) * invdet;
226 t -= (-dgdu * f + dfdu * g) * invdet;
230 if (!(t >= ray_tmin && t <= *ray_tmax)) {
233 if (!(u >= 0.0f && u <= 1.0f)) {
239 const float3 U = dradiusdu *
R + dPdu;
242 if (!use_backfacing &&
dot(ray_D, Ng) > 0.0f) {
260 const float ray_tmin,
266 const float3 center =
make_float3(0.25f * (curve[0] + curve[1] + curve[2] + curve[3]));
267 const float dt =
dot(center - ray_P, ray_D) /
dot(ray_D, ray_D);
268 const float3 ref = ray_P + ray_D * dt;
275 const bool use_backfacing =
false;
295 const float step =
i * step_size;
298 const float dscale = (u1 - u0) * (1.0f / 3.0f) * step_size;
299 const float vu0 =
mix(u0, u1,
step);
300 const float vu1 =
mix(u0, u1,
step + step_size);
302 const float4 P0 = catmull_rom_basis_eval(curve, vu0);
303 const float4 dP0du = dscale * catmull_rom_basis_derivative(curve, vu0);
304 const float4 P3 = catmull_rom_basis_eval(curve, vu1);
305 const float4 dP3du = dscale * catmull_rom_basis_derivative(curve, vu1);
307 const float4 P1 = P0 + dP0du;
308 const float4 P2 = P3 - dP3du;
313 const float maxr12 =
sqrtf(
max(rr1, rr2));
314 const float one_plus_ulp = 1.0f + 2.0f * FLT_EPSILON;
315 const float one_minus_ulp = 1.0f - 2.0f * FLT_EPSILON;
316 float r_outer =
max(
max(P0.
w, P1.
w),
max(P2.
w, P3.
w)) + maxr12;
317 float r_inner =
min(
min(P0.
w, P1.
w),
min(P2.
w, P3.
w)) - maxr12;
318 r_outer = one_plus_ulp * r_outer;
319 r_inner =
max(0.0f, one_minus_ulp * r_inner);
348 valid = tp.
x <= tp.
y;
354 u_outer0 =
clamp(u_outer0, 0.0f, 1.0f);
355 u_outer1 =
clamp(u_outer1, 0.0f, 1.0f);
365 const bool valid_inner = cylinder_intersect(
make_float3(P0),
377 const bool unstable0 = (!valid_inner) |
379 const bool unstable1 = (!valid_inner) |
385 const bool unstable0 =
true;
386 const bool unstable1 =
true;
390 const float eps = 0.001f;
396 const bool valid0 = valid && ((tp0.
x - tp0.
y) <
eps);
397 const bool valid1 = valid && ((tp1.
x - tp1.
y) <
eps);
398 if (!(valid0 || valid1)) {
403 bool recurse =
false;
407 if (depth >= termDepth) {
408 found |= curve_intersect_iterative(
409 ray_D, ray_tmin, &ray_tmax, dt, curve, u_outer0, tp0.
x, use_backfacing, isect);
416 const float t1 = tp1.
x + dt;
417 if (valid1 && (t1 >= ray_tmin && t1 <= ray_tmax)) {
420 if (depth >= termDepth) {
421 found |= curve_intersect_iterative(
422 ray_D, ray_tmin, &ray_tmax, dt, curve, u_outer1, tp1.
y, use_backfacing, isect);
430 stack[depth].u0 = u0;
431 stack[depth].u1 = u1;
432 stack[depth].i =
i + 1;
443 u0 = stack[depth].u0;
444 u1 = stack[depth].u1;
460 const float2 dp = p2 - p1;
461 const float num = dp.
x * p1.
y - dp.
y * p1.
x;
462 const float den2 =
dot(dp, dp);
463 return num *
num <= r * r * den2;
473 const float ray_tmax,
485 const float3 va = quad_v0 - O;
486 const float3 vb = quad_v1 - O;
487 const float3 vc = quad_v2 - O;
488 const float3 vd = quad_v3 - O;
490 const float3 edb = vb - vd;
492 const float3 v0 = (WW <= 0.0f) ? va : vc;
493 const float3 v1 = (WW <= 0.0f) ? vb : vd;
494 const float3 v2 = (WW <= 0.0f) ? vd : vb;
498 const float3 e1 = v0 - v1;
503 if (!(
max(
U,
V) <= 0.0f)) {
509 const float den =
dot(Ng,
D);
510 const float rcpDen = 1.0f / den;
513 const float t = rcpDen *
dot(v0, Ng);
514 if (!(t >= ray_tmin && t <= ray_tmax)) {
519 if (!(den != 0.0f)) {
527 *u_o = (WW <= 0.0f) ? *u_o : 1.0f - *u_o;
528 *v_o = (WW <= 0.0f) ? *v_o : 1.0f - *v_o;
533 const float ray_D_invlen,
536 const float3 D = ray_D * ray_D_invlen;
541 ray_space[2] =
D * ray_D_invlen;
554 const float ray_tmin,
561 const float ray_D_invlen = 1.0f /
len(ray_D);
563 ribbon_ray_space(ray_D, ray_D_invlen, ray_space);
565 curve[0] = ribbon_to_ray_space(ray_space, ray_org, curve[0]);
566 curve[1] = ribbon_to_ray_space(ray_space, ray_org, curve[1]);
567 curve[2] = ribbon_to_ray_space(ray_space, ray_org, curve[2]);
568 curve[3] = ribbon_to_ray_space(ray_space, ray_org, curve[3]);
571 const float eps = 4.0f * FLT_EPSILON *
max(
max(mx.
x, mx.
y),
max(mx.
z, mx.
w));
572 const float step_size = 1.0f / (
float)
N;
575 float4 p0 = catmull_rom_basis_eval(curve, 0.0f);
578 const float4 p1 = catmull_rom_basis_eval(curve, step_size);
584 for (
int i = 0;
i <
N;
i++) {
585 const float u =
i * step_size;
586 const float4 p1 = catmull_rom_basis_eval(curve, u + step_size);
587 const bool valid = cylinder_culling_test(
606 bool valid0 = ribbon_intersect_quad(ray_tmin, ray_tmax, lp0, lp1, up1, up0, &vu, &vv, &vt);
610 const float avoidance_factor = 2.0f;
611 if (avoidance_factor != 0.0f) {
612 const float r =
mix(p0.
w, p1.
w, vu);
613 valid0 = vt > avoidance_factor * r * ray_D_invlen;
617 vv = 2.0f * vv - 1.0f;
622 isect->u = u + vu * step_size;
640 return mix(curve[1], curve[2], u);
645 return curve[2] - curve[1];
657 const float r0 = curve[1].
w;
658 const float r1 = curve[2].
w;
659 const float dr = r1 - r0;
660 const float r0dr = r0 * dr;
664 const float3 dP = P1 - P0;
668 const float dOdO =
dot(dO, dO);
669 const float OdO =
dot(dO, O);
670 const float OO =
dot(O, O);
671 const float dOz =
dot(dP, dO);
672 const float Oz =
dot(dP, O);
674 const float dPdP =
dot(dP, dP);
675 const float yp = Oz + r0dr;
676 const float g = dPdP -
sqr(dr);
678 const float A = g * dOdO -
sqr(dOz);
679 const float B = 2.0f * (g * OdO - dOz * yp);
680 const float C = g * OO -
sqr(Oz) -
sqr(r0) * dPdP - 2.0f * r0dr * Oz;
683 const float D =
B *
B - 4.0f *
A *
C;
690 const float eps = 1e-18f;
698 const float rcp_2A = 1.0f / (2.0f *
A);
699 const float t0 = (-
B - Q) * rcp_2A;
700 const float y0 = yp + t0 * dOz;
705 if ((y0 > -FLT_EPSILON) && (y0 <= g) && (g > 0.0f)) {
707 *u_o =
clamp(y0 / g, 0.0f, 1.0f);
708 const float3 Pr = O + t0 * dO;
709 const float3 Pl = (*u_o) * dP;
716 const float O1dO =
dot(O1, dO);
717 const float h2 =
sqr(O1dO) - dOdO * (
dot(O1, O1) -
sqr(r1));
719 const float rhs1 =
sqrt(h2);
722 const float t_sph1 = (-O1dO - rhs1) * (1.0f / dOdO);
724 const float r2 = curve[3].
w;
726 const float y2 =
dot((t_sph1 * dO) - P1, (P2 - P1));
727 const float cap2 = -(r1 * (r2 - r1));
729 if ((t_sph1 <= t) && (yp + t_sph1 * dOz) > g && !(y2 > cap2)) {
738 if (
isequal(curve[0], curve[1])) {
739 const float h2 =
sqr(OdO) - dOdO * (
dot(O, O) -
sqr(r0));
741 const float rhs1 =
sqrt(h2);
744 const float t_sph0 = (-OdO - rhs1) * (1.0f / dOdO);
746 if ((t_sph0 <= t) && (yp + t_sph0 * dOz) < 0) {
761 const float ray_tmin,
768 const float dt =
dot(center - ray_P, ray_D) /
dot(ray_D, ray_D);
769 const float3 ref = ray_P + ray_D * dt;
780 if (!cone_sphere_intersect(curve, ray_D, &t, &u, &Ng)) {
786 if (!(t >= ray_tmin && t <= ray_tmax)) {
814 const int k1 = k0 + 1;
826 motion_curve_keys(kg,
object, time, ka, k0, k1, kb, curve);
832 const int subdivisions =
kernel_data.bvh.curve_subdivisions;
833 if (ribbon_intersect(ray_P, ray_D, tmin, tmax, subdivisions, curve, isect)) {
835 isect->object = object;
842 if (curve_intersect_recursive(ray_P, ray_D, tmin, tmax, curve, isect)) {
844 isect->object = object;
851 if (linear_curve_intersect(ray_P, ray_D, tmin, tmax, curve, isect)) {
853 isect->object = object;
869 const int isect_prim)
882 const int k1 = k0 + 1;
895 motion_curve_keys(kg, sd->object, sd->time, ka, k0, k1, kb, P_curve);
901 linear_basis_derivative(P_curve, sd->u) :
902 catmull_rom_basis_derivative(P_curve, sd->u);
909 const float sine = sd->v;
916 const float dPdu_radius = dPdu4.
w;
918 P += sd->N * dPdu_radius;
929 make_float3(catmull_rom_basis_eval(P_curve, sd->u));
950 sd->dPdv =
cross(sd->dPdu, sd->Ng);
ATTR_WARN_UNUSED_RESULT const size_t num
ATTR_WARN_UNUSED_RESULT const BMVert * v2
reduce_max(value.rgb)") DEFINE_VALUE("REDUCE(lhs
dot(value.rgb, luminance_coefficients)") DEFINE_VALUE("REDUCE(lhs
#define CURVE_NUM_BEZIER_SUBDIVISIONS_UNSTABLE
#define CURVE_NUM_BEZIER_STEPS
#define CURVE_NUM_JACOBIAN_ITERATIONS
#define CURVE_NUM_BEZIER_SUBDIVISIONS
#define ccl_device_forceinline
#define kernel_data_fetch(name, index)
#define PRIMITIVE_UNPACK_SEGMENT(type)
const ThreadKernelGlobalsCPU * KernelGlobals
#define ccl_device_inline
#define CCL_NAMESPACE_END
VecBase< float, D > normalize(VecOp< float, D >) RET
VecBase< float, D > step(VecOp< float, D >, VecOp< float, D >) RET
VecBase< float, 3 > cross(VecOp< float, 3 >, VecOp< float, 3 >) RET
constexpr T clamp(T, U, U) RET
ccl_device_inline Transform object_get_inverse_transform(KernelGlobals kg, const ccl_private ShaderData *sd)
#define object_normal_transform_auto
#define object_position_transform_auto
#define object_dir_transform_auto
@ PRIMITIVE_CURVE_THICK_LINEAR
@ SD_OBJECT_TRANSFORM_APPLIED
ccl_device_inline float inversesqrtf(const float f)
ccl_device_inline float cos_from_sin(const float s)
ccl_device_inline float2 fabs(const float2 a)
ccl_device_inline bool isequal(const float2 a, const float2 b)
ccl_device_inline float3 safe_normalize_len(const float3 a, ccl_private float *t)
CCL_NAMESPACE_BEGIN struct Window V