@@ -161,9 +161,10 @@ namespace embree
161161 (p0-p)^2 * (dP^2 - dr^2) - y^2 < dP^2 * r0^2 + 2.0f*r0*dr*y;
162162 */
163163
164- __forceinline vbool<M> isInsideCappedCone (const vbool<M>& valid_i, const Vec3vf <M>& p ) const
164+ __forceinline vbool<M> isInsideCappedCone (const vbool<M>& valid_i, const vfloat <M>& t ) const
165165 {
166- const Vec3vf<M> p0p = p - p0;
166+ Vec3vf<M> p0p = -p0;
167+ p0p.z += t;
167168 const vfloat<M> y = dot (p0p,dP);
168169 const vfloat<M> cap0 = vfloat<M>(ulp) - r0dr;
169170 const vfloat<M> cap1 = dPdP - r1*dr;
@@ -193,22 +194,20 @@ namespace embree
193194 struct ConeGeometryIntersector : public ConeGeometry <M>
194195 {
195196 using ConeGeometry<M>::p0;
196- using ConeGeometry<M>::p1;
197197 using ConeGeometry<M>::dP;
198- using ConeGeometry<M>::dPdP;
199198 using ConeGeometry<M>::r0;
200199 using ConeGeometry<M>::sqr_r0;
201- using ConeGeometry<M>::r1;
202200 using ConeGeometry<M>::dr;
203201 using ConeGeometry<M>::r0dr;
202+ using ConeGeometry<M>::drdr;
204203 using ConeGeometry<M>::g;
205204
206- ConeGeometryIntersector ( const Vec3vf<M>& ray_org, const Vec3vf<M>& ray_dir, const vfloat<M>& dOdO, const vfloat<M>& rcp_dOdO, const Vec4vf<M>& a, const Vec4vf<M>& b)
207- : ConeGeometry<M>(a,b), org(ray_org), P(p0-ray_org), dO(ray_dir), dOdO(dOdO), rcp_dOdO(rcp_dOdO), OdO(dot(dO,P)), dOdP(dot(dP,dO)), OdO_dOdO(OdO*rcp_dOdO), dOdP_dOdO(dOdP*rcp_dOdO) {
208- const Vec3vf<M> l = P - OdO_dOdO * dO; // more precise than dot(P,P ) - OdO^2/dOdO (catastrophic cancellation of squared terms)
209- G = sqr_r0 - sqr (l) ;
210- C = g - dOdP * dOdP_dOdO ;
211- F = r0dr - dot (dP,P) + dOdP * OdO_dOdO ;
205+ ConeGeometryIntersector ( const Vec4vf<M>& a, const Vec4vf<M>& b)
206+ : ConeGeometry<M>(a,b) {
207+ G = sqr_r0 - sqr (p0. x ) - sqr (p0. y );
208+ C = sqr (dP. x ) + sqr (dP. y ) - drdr ;
209+ E = sqr (dP. z ) + C ;
210+ F = r0dr - p0. x *dP. x - p0. y *dP. y ;
212211 }
213212
214213 /*
@@ -220,21 +219,21 @@ namespace embree
220219 __forceinline bool intersectConeU (vbool<M>& valid, vfloat<M>& u_front, vfloat<M>& u_back)
221220 {
222221 /* we miss the cone if determinant is smaller than zero */
223- const vfloat<M> D = (F*F + G*C) * rcp_dOdO * rcp (g );
222+ const vfloat<M> D = (F*F + G*C) * rcp (E );
224223 valid &= (D >= 0 .0f ) | (g <= 0 .0f ); // or inside a sphere end
225224
226225 if (unlikely (none (valid)))
227226 return false ;
228227
229- const vfloat<M> Q = dOdP * sqrt (D);
228+ const vfloat<M> Q = dP. z * sqrt (D);
230229 const vfloat<M> rcp_C = rcp (C);
231230 vfloat<M> u0 = (F + Q) * rcp_C;
232231 vfloat<M> u1 = (F - Q) * rcp_C;
233232 // flip negative caps to other side
234233 u0 = select (r0 + u0*dr < 0 .0f , 1 .0f -u0, u0);
235234 u1 = select (r0 + u1*dr < 0 .0f , 1 .0f -u1, u1);
236235 const vfloat<M> uend = select (dr >= 0 .0f , vfloat<M>(one), vfloat<M>(zero));
237- const vbool<M> swap = (dOdP >= 0.0 ) != (u1 > u0);
236+ const vbool<M> swap = (dP. z >= 0.0 ) != (u1 > u0);
238237 // already clamp for end sphere (always present)
239238 u_front = min (1 .0f , select (g > 0 .0f , select (swap, u1, u0), uend));
240239#if !defined (EMBREE_BACKFACE_CULLING_CURVES)
@@ -265,67 +264,77 @@ namespace embree
265264 This normal is valid for the cone as well for the end cap spheres.
266265
267266 Ng = h - (p0 + u*dP)
267+ h = (0,0,t)
268268 */
269269
270270 __forceinline Vec3vf<M> Ng (const vfloat<M>& u, const vfloat<M>& t) const
271271 {
272- return t*dO-P - u*dP;
272+ Vec3vf<M> n = -(p0 + u*dP);
273+ n.z += t;
274+ return n;
273275 }
274276
275277 private:
276- Vec3vf<M> org;
277- Vec3vf<M> P;
278- Vec3vf<M> dO;
279- vfloat<M> dOdO;
280- vfloat<M> rcp_dOdO;
281- vfloat<M> OdO;
282- vfloat<M> dOdP;
283- vfloat<M> OdO_dOdO;
284- vfloat<M> dOdP_dOdO;
285278 vfloat<M> C;
279+ vfloat<M> E;
286280 vfloat<M> F;
287281 vfloat<M> G;
288282 };
289283
290284 template <int M, typename Epilog, typename ray_tfar_func>
291285 static __forceinline bool intersectConeSphere (const vbool<M>& valid_i,
292- const Vec3vf<M>& ray_org, const Vec3vf<M>& ray_dir ,
286+ const Vec3vf<M>& ray_org, const Vec3vf<M>& ray_dir_in ,
293287 const vfloat<M>& ray_tnear, const ray_tfar_func& ray_tfar,
294- const Vec4vf<M>& v0 , const Vec4vf<M>& v1 ,
295- const Vec4vf<M>& vL , const Vec4vf<M>& vR ,
288+ const Vec4vf<M>& v0_in , const Vec4vf<M>& v1_in ,
289+ const Vec4vf<M>& vL_in , const Vec4vf<M>& vR_in ,
296290 const Epilog& epilog)
297291 {
298292 vbool<M> valid = valid_i;
299293
300- const vfloat<M> dOdO = sqr (ray_dir);
301- const vfloat<M> rcp_dOdO = rcp (dOdO);
294+ // normalize ray dir, keep length
295+ const vfloat<M> rcp_rd = rcp_length (ray_dir_in);
296+ const vfloat<M> rd = rcp (rcp_rd);
297+ const Vec3vf<M>& ray_dir = ray_dir_in*rcp_rd;
298+
299+ // transform into ray space
300+ const LinearSpace3vf<M> m = frame (ray_dir);
301+ const Vec4vf<M> v0 = Vec4vf<M>(m*(Vec3vf<M>(v0_in)-ray_org), v0_in.w );
302+ const Vec4vf<M> v1 = Vec4vf<M>(m*(Vec3vf<M>(v1_in)-ray_org), v1_in.w );
302303
303304 /* intersect with cone from v0 to v1 */
304- ConeGeometryIntersector<M> cone (ray_org, ray_dir, dOdO, rcp_dOdO, v0, v1);
305+ ConeGeometryIntersector<M> cone ( v0, v1);
305306 vfloat<M> u_front, u_back;
306307 if (unlikely (!cone.intersectConeU (valid, u_front, u_back)))
307308 return false ;
308309
309310 /* calculate front hit */
310- vbool<M> validFront = valid & ((u_front >= 0 .0f ) | (vL [0 ] == vfloat<M>(pos_inf)));
311+ vbool<M> validFront = valid & ((u_front >= 0 .0f ) | (vL_in [0 ] == vfloat<M>(pos_inf)));
311312 u_front = max (u_front, 0 .0f );
312313 vfloat<M> t_lower;
313314 cone.template intersectSphere <true >(validFront, u_front, t_lower);
314315
316+ // for normal
317+ Vec3vf<M> dP = v0_in.xyz () - v1_in.xyz ();
318+ Vec3vf<M> P = ray_org - v0_in.xyz ();
319+
315320#if !defined (EMBREE_BACKFACE_CULLING_CURVES)
316321 /* hits inside the neighboring capped cones are inside the geometry and thus ignored */
322+ const Vec4vf<M> vL = Vec4vf<M>(m*(Vec3vf<M>(vL_in)-ray_org), vL_in.w );
317323 const ConeGeometry<M> coneL (v0, vL);
324+ const Vec4vf<M> vR = Vec4vf<M>(m*(Vec3vf<M>(vR_in)-ray_org), vR_in.w );
318325 const ConeGeometry<M> coneR (v1, vR);
319- const Vec3vf<M> hit_lower = ray_org + t_lower*ray_dir;
320- validFront &= !coneL.isInsideCappedCone (validFront, hit_lower) & !coneR.isInsideCappedCone (validFront, hit_lower);
326+ validFront &= !coneL.isInsideCappedCone (validFront, t_lower) & !coneR.isInsideCappedCone (validFront, t_lower);
321327
322328 /* calculate back hit */
323- vbool<M> validBack = valid & ((u_back >= 0 .0f ) | (vL [0 ] == vfloat<M>(pos_inf)));
329+ vbool<M> validBack = valid & ((u_back >= 0 .0f ) | (vL_in [0 ] == vfloat<M>(pos_inf)));
324330 u_back = max (u_back, 0 .0f );
325331 vfloat<M> t_upper;
326332 cone.template intersectSphere <false >(validBack, u_back, t_upper);
327- const Vec3vf<M> hit_upper = ray_org + t_upper*ray_dir;
328- validBack &= !coneL.isInsideCappedCone (validBack, hit_upper) & !coneR.isInsideCappedCone (validBack, hit_upper);
333+ validBack &= !coneL.isInsideCappedCone (validBack, t_upper) & !coneR.isInsideCappedCone (validBack, t_upper);
334+
335+ // scale back
336+ t_lower *= rd;
337+ t_upper *= rd;
329338
330339 /* filter out hits that are not in tnear/tfar range */
331340 const vbool<M> valid_lower = validFront & ray_tnear <= t_lower & t_lower <= ray_tfar ();
@@ -341,7 +350,7 @@ namespace embree
341350 const vfloat<M> u_first = select (valid_lower, u_front, u_back);
342351
343352 /* invoke intersection filter for first hit */
344- RoundLineIntersectorHitM<M> hit (u_first,zero,t_first,cone. Ng (u_first, t_first) );
353+ RoundLineIntersectorHitM<M> hit (u_first,zero,t_first,t_first*ray_dir_in + P + u_first*dP );
345354 const bool is_hit_first = epilog (valid_first, hit);
346355
347356 /* check for possible second hits before potentially accepted hit */
@@ -350,11 +359,14 @@ namespace embree
350359 return is_hit_first;
351360
352361 /* invoke intersection filter for second hit */
353- hit = RoundLineIntersectorHitM<M>(u_back,zero,t_upper,cone. Ng (u_back, t_upper) );
362+ hit = RoundLineIntersectorHitM<M>(u_back,zero,t_upper,t_upper*ray_dir_in + P + u_back*dP );
354363 const bool is_hit_second = epilog (valid_second, hit);
355364
356365 return is_hit_first | is_hit_second;
357366#else
367+ // scale back
368+ t_lower *= rd;
369+
358370 /* filter out hits that are not in tnear/tfar range */
359371 const vbool<M> valid_lower = validFront & ray_tnear <= t_lower & t_lower <= ray_tfar ();
360372
@@ -363,7 +375,7 @@ namespace embree
363375 return false ;
364376
365377 /* construct first hit and invoke intersection filter for first hit */
366- RoundLineIntersectorHitM<M> hit (u_front,zero,t_lower,cone. Ng (u_front, t_lower) );
378+ RoundLineIntersectorHitM<M> hit (u_front,zero,t_lower,t_lower*ray_dir_in + P + u_front*dP );
367379 const bool is_hit_first = epilog (valid_lower, hit);
368380
369381 return is_hit_first;
0 commit comments