// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once #include "../common/ray.h" #include "curve_intersector_precalculations.h" /* This file implements the intersection of a ray with a round linear curve segment. We define the geometry of such a round linear curve segment from point p0 with radius r0 to point p1 with radius r1 using the cone that touches spheres p0/r0 and p1/r1 tangentially plus the sphere p1/r1. We denote the tangentially touching cone from p0/r0 to p1/r1 with cone(p0,r0,p1,r1) and the cone plus the ending sphere with cone_sphere(p0,r0,p1,r1). For multiple connected round linear curve segments this construction yield a proper shape when viewed from the outside. Using the following CSG we can also handle the interior in most common cases: round_linear_curve(pl,rl,p0,r0,p1,r1,pr,rr) = cone_sphere(p0,r0,p1,r1) - cone(pl,rl,p0,r0) - cone(p1,r1,pr,rr) Thus by subtracting the neighboring cone geometries, we cut away parts of the center cone_sphere surface which lie inside the combined curve. This approach works as long as geometry of the current cone_sphere penetrates into direct neighbor segments only, and not into segments further away. To construct a cone that touches two spheres at p0 and p1 with r0 and r1, one has to increase the cone radius at r0 and r1 to obtain larger radii w0 and w1, such that the infinite cone properly touches the spheres. From the paper "Ray Tracing Generalized Tube Primitives: Method and Applications" (https://www.researchgate.net/publication/334378683_Ray_Tracing_Generalized_Tube_Primitives_Method_and_Applications) one can derive the following equations for these increased radii: sr = 1.0f / sqrt(1-sqr(dr)/sqr(p1-p0)) w0 = sr*r0 w1 = sr*r1 Further, we want the cone to start where it touches the sphere at p0 and to end where it touches sphere at p1. Therefore, we need to construct clipping locations y0 and y1 for the start and end of the cone. These start and end clipping location of the cone can get calculated as: Y0 = - r0 * (r1-r0) / length(p1-p0) Y1 = length(p1-p0) - r1 * (r1-r0) / length(p1-p0) Where the cone starts a distance Y0 and ends a distance Y1 away of point p0 along the cone center. The distance between Y1-Y0 can get calculated as: dY = length(p1-p0) - (r1-r0)^2 / length(p1-p0) In the code below, Y will always be scaled by length(p1-p0) to obtain y and you will find the terms r0*(r1-r0) and (p1-p0)^2-(r1-r0)^2. */ namespace embree { namespace isa { template<int M> struct RoundLineIntersectorHitM { … }; namespace __roundline_internal { template<int M> struct ConeGeometry { … }; template<int M> struct ConeGeometryIntersector : public ConeGeometry<M> { … }; template<int M, typename Epilog, typename ray_tfar_func> static __forceinline bool intersectConeSphere(const vbool<M>& valid_i, const Vec3vf<M>& ray_org_in, const Vec3vf<M>& ray_dir, const vfloat<M>& ray_tnear, const ray_tfar_func& ray_tfar, const Vec4vf<M>& v0, const Vec4vf<M>& v1, const Vec4vf<M>& vL, const Vec4vf<M>& vR, const Epilog& epilog) { … } } // end namespace __roundline_internal template<int M> struct RoundLinearCurveIntersector1 { … }; template<int M, int K> struct RoundLinearCurveIntersectorK { … }; } }