Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'intern/cycles/kernel/geom/curve_intersect.h')
-rw-r--r--intern/cycles/kernel/geom/curve_intersect.h133
1 files changed, 71 insertions, 62 deletions
diff --git a/intern/cycles/kernel/geom/curve_intersect.h b/intern/cycles/kernel/geom/curve_intersect.h
index e1a1f9c02c5..97644aacaa8 100644
--- a/intern/cycles/kernel/geom/curve_intersect.h
+++ b/intern/cycles/kernel/geom/curve_intersect.h
@@ -72,7 +72,7 @@ ccl_device_inline float sqr_point_to_line_distance(const float3 PmQ0, const floa
ccl_device_inline bool cylinder_intersect(const float3 cylinder_start,
const float3 cylinder_end,
const float cylinder_radius,
- const float3 ray_dir,
+ const float3 ray_D,
ccl_private float2 *t_o,
ccl_private float *u0_o,
ccl_private float3 *Ng0_o,
@@ -82,7 +82,7 @@ ccl_device_inline bool cylinder_intersect(const float3 cylinder_start,
/* Calculate quadratic equation to solve. */
const float rl = 1.0f / len(cylinder_end - cylinder_start);
const float3 P0 = cylinder_start, dP = (cylinder_end - cylinder_start) * rl;
- const float3 O = -P0, dO = ray_dir;
+ const float3 O = -P0, dO = ray_D;
const float dOdO = dot(dO, dO);
const float OdO = dot(dO, O);
@@ -123,7 +123,7 @@ ccl_device_inline bool cylinder_intersect(const float3 cylinder_start,
/* Calculates u and Ng for near hit. */
{
*u0_o = (t0 * dOz + Oz) * rl;
- const float3 Pr = t0 * ray_dir;
+ const float3 Pr = t0 * ray_D;
const float3 Pl = (*u0_o) * (cylinder_end - cylinder_start) + cylinder_start;
*Ng0_o = Pr - Pl;
}
@@ -131,7 +131,7 @@ ccl_device_inline bool cylinder_intersect(const float3 cylinder_start,
/* Calculates u and Ng for far hit. */
{
*u1_o = (t1 * dOz + Oz) * rl;
- const float3 Pr = t1 * ray_dir;
+ const float3 Pr = t1 * ray_D;
const float3 Pl = (*u1_o) * (cylinder_end - cylinder_start) + cylinder_start;
*Ng1_o = Pr - Pl;
}
@@ -141,10 +141,10 @@ ccl_device_inline bool cylinder_intersect(const float3 cylinder_start,
return true;
}
-ccl_device_inline float2 half_plane_intersect(const float3 P, const float3 N, const float3 ray_dir)
+ccl_device_inline float2 half_plane_intersect(const float3 P, const float3 N, const float3 ray_D)
{
const float3 O = -P;
- const float3 D = ray_dir;
+ const float3 D = ray_D;
const float ON = dot(O, N);
const float DN = dot(D, N);
const float min_rcp_input = 1e-18f;
@@ -155,8 +155,9 @@ ccl_device_inline float2 half_plane_intersect(const float3 P, const float3 N, co
return make_float2(lower, upper);
}
-ccl_device bool curve_intersect_iterative(const float3 ray_dir,
- ccl_private float *ray_tfar,
+ccl_device bool curve_intersect_iterative(const float3 ray_D,
+ const float ray_tmin,
+ ccl_private float *ray_tmax,
const float dt,
const float4 curve[4],
float u,
@@ -164,7 +165,7 @@ ccl_device bool curve_intersect_iterative(const float3 ray_dir,
const bool use_backfacing,
ccl_private Intersection *isect)
{
- const float length_ray_dir = len(ray_dir);
+ const float length_ray_D = len(ray_D);
/* Error of curve evaluations is proportional to largest coordinate. */
const float4 box_min = min(min(curve[0], curve[1]), min(curve[2], curve[3]));
@@ -175,9 +176,9 @@ ccl_device bool curve_intersect_iterative(const float3 ray_dir,
const float radius_max = box_max.w;
for (int i = 0; i < CURVE_NUM_JACOBIAN_ITERATIONS; i++) {
- const float3 Q = ray_dir * t;
- const float3 dQdt = ray_dir;
- const float Q_err = 16.0f * FLT_EPSILON * length_ray_dir * t;
+ const float3 Q = ray_D * t;
+ const float3 dQdt = ray_D;
+ const float Q_err = 16.0f * FLT_EPSILON * length_ray_D * t;
const float4 P4 = catmull_rom_basis_eval(curve, u);
const float4 dPdu4 = catmull_rom_basis_derivative(curve, u);
@@ -220,7 +221,7 @@ ccl_device bool curve_intersect_iterative(const float3 ray_dir,
if (fabsf(f) < f_err && fabsf(g) < g_err) {
t += dt;
- if (!(0.0f <= t && t <= *ray_tfar)) {
+ if (!(t >= ray_tmin && t <= *ray_tmax)) {
return false; /* Rejects NaNs */
}
if (!(u >= 0.0f && u <= 1.0f)) {
@@ -232,12 +233,12 @@ ccl_device bool curve_intersect_iterative(const float3 ray_dir,
const float3 U = dradiusdu * R + dPdu;
const float3 V = cross(dPdu, R);
const float3 Ng = cross(V, U);
- if (!use_backfacing && dot(ray_dir, Ng) > 0.0f) {
+ if (!use_backfacing && dot(ray_D, Ng) > 0.0f) {
return false;
}
/* Record intersection. */
- *ray_tfar = t;
+ *ray_tmax = t;
isect->t = t;
isect->u = u;
isect->v = 0.0f;
@@ -248,16 +249,17 @@ ccl_device bool curve_intersect_iterative(const float3 ray_dir,
return false;
}
-ccl_device bool curve_intersect_recursive(const float3 ray_orig,
- const float3 ray_dir,
- float ray_tfar,
+ccl_device bool curve_intersect_recursive(const float3 ray_P,
+ const float3 ray_D,
+ const float ray_tmin,
+ float ray_tmax,
float4 curve[4],
ccl_private Intersection *isect)
{
/* Move ray closer to make intersection stable. */
const float3 center = float4_to_float3(0.25f * (curve[0] + curve[1] + curve[2] + curve[3]));
- const float dt = dot(center - ray_orig, ray_dir) / dot(ray_dir, ray_dir);
- const float3 ref = ray_orig + ray_dir * dt;
+ const float dt = dot(center - ray_P, ray_D) / dot(ray_D, ray_D);
+ const float3 ref = ray_P + ray_D * dt;
const float4 ref4 = make_float4(ref.x, ref.y, ref.z, 0.0f);
curve[0] -= ref4;
curve[1] -= ref4;
@@ -320,7 +322,7 @@ ccl_device bool curve_intersect_recursive(const float3 ray_orig,
valid = cylinder_intersect(float4_to_float3(P0),
float4_to_float3(P3),
r_outer,
- ray_dir,
+ ray_D,
&tc_outer,
&u_outer0,
&Ng_outer0,
@@ -331,13 +333,12 @@ ccl_device bool curve_intersect_recursive(const float3 ray_orig,
}
/* Intersect with cap-planes. */
- float2 tp = make_float2(-dt, ray_tfar - dt);
+ float2 tp = make_float2(ray_tmin - dt, ray_tmax - dt);
tp = make_float2(max(tp.x, tc_outer.x), min(tp.y, tc_outer.y));
- const float2 h0 = half_plane_intersect(
- float4_to_float3(P0), float4_to_float3(dP0du), ray_dir);
+ const float2 h0 = half_plane_intersect(float4_to_float3(P0), float4_to_float3(dP0du), ray_D);
tp = make_float2(max(tp.x, h0.x), min(tp.y, h0.y));
const float2 h1 = half_plane_intersect(
- float4_to_float3(P3), -float4_to_float3(dP3du), ray_dir);
+ float4_to_float3(P3), -float4_to_float3(dP3du), ray_D);
tp = make_float2(max(tp.x, h1.x), min(tp.y, h1.y));
valid = tp.x <= tp.y;
if (!valid) {
@@ -357,7 +358,7 @@ ccl_device bool curve_intersect_recursive(const float3 ray_orig,
const bool valid_inner = cylinder_intersect(float4_to_float3(P0),
float4_to_float3(P3),
r_inner,
- ray_dir,
+ ray_D,
&tc_inner,
&u_inner0,
&Ng_inner0,
@@ -367,9 +368,9 @@ ccl_device bool curve_intersect_recursive(const float3 ray_orig,
/* At the unstable area we subdivide deeper. */
# if 0
const bool unstable0 = (!valid_inner) |
- (fabsf(dot(normalize(ray_dir), normalize(Ng_inner0))) < 0.3f);
+ (fabsf(dot(normalize(ray_D), normalize(Ng_inner0))) < 0.3f);
const bool unstable1 = (!valid_inner) |
- (fabsf(dot(normalize(ray_dir), normalize(Ng_inner1))) < 0.3f);
+ (fabsf(dot(normalize(ray_D), normalize(Ng_inner1))) < 0.3f);
# else
/* On the GPU appears to be a little faster if always enabled. */
(void)valid_inner;
@@ -394,19 +395,20 @@ ccl_device bool curve_intersect_recursive(const float3 ray_orig,
CURVE_NUM_BEZIER_SUBDIVISIONS;
if (depth >= termDepth) {
found |= curve_intersect_iterative(
- ray_dir, &ray_tfar, dt, curve, u_outer0, tp0.x, use_backfacing, isect);
+ ray_D, ray_tmin, &ray_tmax, dt, curve, u_outer0, tp0.x, use_backfacing, isect);
}
else {
recurse = true;
}
}
- if (valid1 && (tp1.x + dt <= ray_tfar)) {
+ const float t1 = tp1.x + dt;
+ if (valid1 && (t1 >= ray_tmin && t1 <= ray_tmax)) {
const int termDepth = unstable1 ? CURVE_NUM_BEZIER_SUBDIVISIONS_UNSTABLE :
CURVE_NUM_BEZIER_SUBDIVISIONS;
if (depth >= termDepth) {
found |= curve_intersect_iterative(
- ray_dir, &ray_tfar, dt, curve, u_outer1, tp1.y, use_backfacing, isect);
+ ray_D, ray_tmin, &ray_tmax, dt, curve, u_outer1, tp1.y, use_backfacing, isect);
}
else {
recurse = true;
@@ -456,7 +458,8 @@ ccl_device_inline bool cylinder_culling_test(const float2 p1, const float2 p2, c
* v0,v1,v3 and v2,v3,v1. The edge v1,v2 decides which of the two
* triangles gets intersected.
*/
-ccl_device_inline bool ribbon_intersect_quad(const float ray_tfar,
+ccl_device_inline bool ribbon_intersect_quad(const float ray_tmin,
+ const float ray_tmax,
const float3 quad_v0,
const float3 quad_v1,
const float3 quad_v2,
@@ -497,7 +500,7 @@ ccl_device_inline bool ribbon_intersect_quad(const float ray_tfar,
/* Perform depth test? */
const float t = rcpDen * dot(v0, Ng);
- if (!(0.0f <= t && t <= ray_tfar)) {
+ if (!(t >= ray_tmin && t <= ray_tmax)) {
return false;
}
@@ -515,13 +518,16 @@ ccl_device_inline bool ribbon_intersect_quad(const float ray_tfar,
return true;
}
-ccl_device_inline void ribbon_ray_space(const float3 ray_dir, float3 ray_space[3])
+ccl_device_inline void ribbon_ray_space(const float3 ray_D,
+ const float ray_D_invlen,
+ float3 ray_space[3])
{
- const float3 dx0 = make_float3(0, ray_dir.z, -ray_dir.y);
- const float3 dx1 = make_float3(-ray_dir.z, 0, ray_dir.x);
+ const float3 D = ray_D * ray_D_invlen;
+ const float3 dx0 = make_float3(0, D.z, -D.y);
+ const float3 dx1 = make_float3(-D.z, 0, D.x);
ray_space[0] = normalize(dot(dx0, dx0) > dot(dx1, dx1) ? dx0 : dx1);
- ray_space[1] = normalize(cross(ray_dir, ray_space[0]));
- ray_space[2] = ray_dir;
+ ray_space[1] = normalize(cross(D, ray_space[0]));
+ ray_space[2] = D * ray_D_invlen;
}
ccl_device_inline float4 ribbon_to_ray_space(const float3 ray_space[3],
@@ -533,15 +539,17 @@ ccl_device_inline float4 ribbon_to_ray_space(const float3 ray_space[3],
}
ccl_device_inline bool ribbon_intersect(const float3 ray_org,
- const float3 ray_dir,
- float ray_tfar,
+ const float3 ray_D,
+ const float ray_tmin,
+ float ray_tmax,
const int N,
float4 curve[4],
ccl_private Intersection *isect)
{
/* Transform control points into ray space. */
+ const float ray_D_invlen = 1.0f / len(ray_D);
float3 ray_space[3];
- ribbon_ray_space(ray_dir, ray_space);
+ ribbon_ray_space(ray_D, ray_D_invlen, ray_space);
curve[0] = ribbon_to_ray_space(ray_space, ray_org, curve[0]);
curve[1] = ribbon_to_ray_space(ray_space, ray_org, curve[1]);
@@ -555,7 +563,7 @@ ccl_device_inline bool ribbon_intersect(const float3 ray_org,
/* Evaluate first point and radius scaled normal direction. */
float4 p0 = catmull_rom_basis_eval(curve, 0.0f);
float3 dp0dt = float4_to_float3(catmull_rom_basis_derivative(curve, 0.0f));
- if (max3(fabs(dp0dt)) < eps) {
+ if (reduce_max(fabs(dp0dt)) < eps) {
const float4 p1 = catmull_rom_basis_eval(curve, step_size);
dp0dt = float4_to_float3(p1 - p0);
}
@@ -570,7 +578,7 @@ ccl_device_inline bool ribbon_intersect(const float3 ray_org,
/* Evaluate next point. */
float3 dp1dt = float4_to_float3(catmull_rom_basis_derivative(curve, u + step_size));
- dp1dt = (max3(fabs(dp1dt)) < eps) ? float4_to_float3(p1 - p0) : dp1dt;
+ dp1dt = (reduce_max(fabs(dp1dt)) < eps) ? float4_to_float3(p1 - p0) : dp1dt;
const float3 wn1 = normalize(make_float3(dp1dt.y, -dp1dt.x, 0.0f)) * p1.w;
if (valid) {
@@ -582,21 +590,21 @@ ccl_device_inline bool ribbon_intersect(const float3 ray_org,
/* Intersect quad. */
float vu, vv, vt;
- bool valid0 = ribbon_intersect_quad(ray_tfar, lp0, lp1, up1, up0, &vu, &vv, &vt);
+ bool valid0 = ribbon_intersect_quad(ray_tmin, ray_tmax, lp0, lp1, up1, up0, &vu, &vv, &vt);
if (valid0) {
/* ignore self intersections */
const float avoidance_factor = 2.0f;
if (avoidance_factor != 0.0f) {
float r = mix(p0.w, p1.w, vu);
- valid0 = vt > avoidance_factor * r;
+ valid0 = vt > avoidance_factor * r * ray_D_invlen;
}
if (valid0) {
vv = 2.0f * vv - 1.0f;
/* Record intersection. */
- ray_tfar = vt;
+ ray_tmax = vt;
isect->t = vt;
isect->u = u + vu * step_size;
isect->v = vv;
@@ -614,8 +622,9 @@ ccl_device_inline bool ribbon_intersect(const float3 ray_org,
ccl_device_forceinline bool curve_intersect(KernelGlobals kg,
ccl_private Intersection *isect,
- const float3 P,
- const float3 dir,
+ const float3 ray_P,
+ const float3 ray_D,
+ const float tmin,
const float tmax,
int object,
int prim,
@@ -624,7 +633,7 @@ ccl_device_forceinline bool curve_intersect(KernelGlobals kg,
{
const bool is_motion = (type & PRIMITIVE_MOTION);
- KernelCurve kcurve = kernel_tex_fetch(__curves, prim);
+ KernelCurve kcurve = kernel_data_fetch(curves, prim);
int k0 = kcurve.first_key + PRIMITIVE_UNPACK_SEGMENT(type);
int k1 = k0 + 1;
@@ -633,10 +642,10 @@ ccl_device_forceinline bool curve_intersect(KernelGlobals kg,
float4 curve[4];
if (!is_motion) {
- curve[0] = kernel_tex_fetch(__curve_keys, ka);
- curve[1] = kernel_tex_fetch(__curve_keys, k0);
- curve[2] = kernel_tex_fetch(__curve_keys, k1);
- curve[3] = kernel_tex_fetch(__curve_keys, kb);
+ curve[0] = kernel_data_fetch(curve_keys, ka);
+ curve[1] = kernel_data_fetch(curve_keys, k0);
+ curve[2] = kernel_data_fetch(curve_keys, k1);
+ curve[3] = kernel_data_fetch(curve_keys, kb);
}
else {
motion_curve_keys(kg, object, prim, time, ka, k0, k1, kb, curve);
@@ -645,7 +654,7 @@ ccl_device_forceinline bool curve_intersect(KernelGlobals kg,
if (type & PRIMITIVE_CURVE_RIBBON) {
/* todo: adaptive number of subdivisions could help performance here. */
const int subdivisions = kernel_data.bvh.curve_subdivisions;
- if (ribbon_intersect(P, dir, tmax, subdivisions, curve, isect)) {
+ if (ribbon_intersect(ray_P, ray_D, tmin, tmax, subdivisions, curve, isect)) {
isect->prim = prim;
isect->object = object;
isect->type = type;
@@ -655,7 +664,7 @@ ccl_device_forceinline bool curve_intersect(KernelGlobals kg,
return false;
}
else {
- if (curve_intersect_recursive(P, dir, tmax, curve, isect)) {
+ if (curve_intersect_recursive(ray_P, ray_D, tmin, tmax, curve, isect)) {
isect->prim = prim;
isect->object = object;
isect->type = type;
@@ -682,7 +691,7 @@ ccl_device_inline void curve_shader_setup(KernelGlobals kg,
D = safe_normalize_len(D, &t);
}
- KernelCurve kcurve = kernel_tex_fetch(__curves, isect_prim);
+ KernelCurve kcurve = kernel_data_fetch(curves, isect_prim);
int k0 = kcurve.first_key + PRIMITIVE_UNPACK_SEGMENT(sd->type);
int k1 = k0 + 1;
@@ -692,10 +701,10 @@ ccl_device_inline void curve_shader_setup(KernelGlobals kg,
float4 P_curve[4];
if (!(sd->type & PRIMITIVE_MOTION)) {
- P_curve[0] = kernel_tex_fetch(__curve_keys, ka);
- P_curve[1] = kernel_tex_fetch(__curve_keys, k0);
- P_curve[2] = kernel_tex_fetch(__curve_keys, k1);
- P_curve[3] = kernel_tex_fetch(__curve_keys, kb);
+ P_curve[0] = kernel_data_fetch(curve_keys, ka);
+ P_curve[1] = kernel_data_fetch(curve_keys, k0);
+ P_curve[2] = kernel_data_fetch(curve_keys, k1);
+ P_curve[3] = kernel_data_fetch(curve_keys, kb);
}
else {
motion_curve_keys(kg, sd->object, sd->prim, sd->time, ka, k0, k1, kb, P_curve);
@@ -729,7 +738,7 @@ ccl_device_inline void curve_shader_setup(KernelGlobals kg,
/* NOTE: It is possible that P will be the same as P_inside (precision issues, or very small
* radius). In this case use the view direction to approximate the normal. */
const float3 P_inside = float4_to_float3(catmull_rom_basis_eval(P_curve, sd->u));
- const float3 N = (!isequal_float3(P, P_inside)) ? normalize(P - P_inside) : -sd->I;
+ const float3 N = (!isequal(P, P_inside)) ? normalize(P - P_inside) : -sd->I;
sd->N = N;
sd->v = 0.0f;
@@ -750,7 +759,7 @@ ccl_device_inline void curve_shader_setup(KernelGlobals kg,
sd->P = P;
sd->Ng = (sd->type & PRIMITIVE_CURVE_RIBBON) ? sd->I : sd->N;
sd->dPdv = cross(sd->dPdu, sd->Ng);
- sd->shader = kernel_tex_fetch(__curves, sd->prim).shader_id;
+ sd->shader = kernel_data_fetch(curves, sd->prim).shader_id;
}
#endif