Path: blob/master/thirdparty/embree/kernels/geometry/cylinder.h
9905 views
// Copyright 2009-2021 Intel Corporation1// SPDX-License-Identifier: Apache-2.023#pragma once45#include "../common/ray.h"67namespace embree8{9namespace isa10{11struct Cylinder12{13const Vec3fa p0; //!< start location14const Vec3fa p1; //!< end position15const float rr; //!< squared radius of cylinder1617__forceinline Cylinder(const Vec3fa& p0, const Vec3fa& p1, const float r)18: p0(p0), p1(p1), rr(sqr(r)) {}1920__forceinline Cylinder(const Vec3fa& p0, const Vec3fa& p1, const float rr, bool)21: p0(p0), p1(p1), rr(rr) {}2223__forceinline bool intersect(const Vec3fa& org,24const Vec3fa& dir,25BBox1f& t_o,26float& u0_o, Vec3fa& Ng0_o,27float& u1_o, Vec3fa& Ng1_o) const28{29/* calculate quadratic equation to solve */30const float rl = rcp_length(p1-p0);31const Vec3fa P0 = p0, dP = (p1-p0)*rl;32const Vec3fa O = org-P0, dO = dir;3334const float dOdO = dot(dO,dO);35const float OdO = dot(dO,O);36const float OO = dot(O,O);37const float dOz = dot(dP,dO);38const float Oz = dot(dP,O);3940const float A = dOdO - sqr(dOz);41const float B = 2.0f * (OdO - dOz*Oz);42const float C = OO - sqr(Oz) - rr;4344/* we miss the cylinder if determinant is smaller than zero */45const float D = B*B - 4.0f*A*C;46if (D < 0.0f) {47t_o = BBox1f(pos_inf,neg_inf);48return false;49}5051/* special case for rays that are parallel to the cylinder */52const float eps = 16.0f*float(ulp)*max(abs(dOdO),abs(sqr(dOz)));53if (abs(A) < eps)54{55if (C <= 0.0f) {56t_o = BBox1f(neg_inf,pos_inf);57return true;58} else {59t_o = BBox1f(pos_inf,neg_inf);60return false;61}62}6364/* standard case for rays that are not parallel to the cylinder */65const float Q = sqrt(D);66const float rcp_2A = rcp(2.0f*A);67const float t0 = (-B-Q)*rcp_2A;68const float t1 = (-B+Q)*rcp_2A;6970/* calculates u and Ng for near hit */71{72u0_o = madd(t0,dOz,Oz)*rl;73const Vec3fa Pr = t0*dir;74const Vec3fa Pl = madd(u0_o,p1-p0,p0);75Ng0_o = Pr-Pl;76}7778/* calculates u and Ng for far hit */79{80u1_o = madd(t1,dOz,Oz)*rl;81const Vec3fa Pr = t1*dir;82const Vec3fa Pl = madd(u1_o,p1-p0,p0);83Ng1_o = Pr-Pl;84}8586t_o.lower = t0;87t_o.upper = t1;88return true;89}9091__forceinline bool intersect(const Vec3fa& org_i, const Vec3fa& dir, BBox1f& t_o) const92{93float u0_o; Vec3fa Ng0_o;94float u1_o; Vec3fa Ng1_o;95return intersect(org_i,dir,t_o,u0_o,Ng0_o,u1_o,Ng1_o);96}9798static bool verify(const size_t id, const Cylinder& cylinder, const RayHit& ray, bool shouldhit, const float t0, const float t1)99{100float eps = 0.001f;101BBox1f t; bool hit;102hit = cylinder.intersect(ray.org,ray.dir,t);103104bool failed = hit != shouldhit;105if (shouldhit) failed |= std::isinf(t0) ? t0 != t.lower : abs(t0-t.lower) > eps;106if (shouldhit) failed |= std::isinf(t1) ? t1 != t.upper : abs(t1-t.upper) > eps;107if (!failed) return true;108embree_cout << "Cylinder test " << id << " failed: cylinder = " << cylinder << ", ray = " << ray << ", hit = " << hit << ", t = " << t << embree_endl;109return false;110}111112/* verify cylinder class */113static bool verify()114{115bool passed = true;116const Cylinder cylinder(Vec3fa(0.0f,0.0f,0.0f),Vec3fa(1.0f,0.0f,0.0f),1.0f);117passed &= verify(0,cylinder,RayHit(Vec3fa(-2.0f,1.0f,0.0f),Vec3fa( 0.0f,-1.0f,+0.0f),0.0f,float(inf)),true,0.0f,2.0f);118passed &= verify(1,cylinder,RayHit(Vec3fa(+2.0f,1.0f,0.0f),Vec3fa( 0.0f,-1.0f,+0.0f),0.0f,float(inf)),true,0.0f,2.0f);119passed &= verify(2,cylinder,RayHit(Vec3fa(+2.0f,1.0f,2.0f),Vec3fa( 0.0f,-1.0f,+0.0f),0.0f,float(inf)),false,0.0f,0.0f);120passed &= verify(3,cylinder,RayHit(Vec3fa(+0.0f,0.0f,0.0f),Vec3fa( 1.0f, 0.0f,+0.0f),0.0f,float(inf)),true,neg_inf,pos_inf);121passed &= verify(4,cylinder,RayHit(Vec3fa(+0.0f,0.0f,0.0f),Vec3fa(-1.0f, 0.0f,+0.0f),0.0f,float(inf)),true,neg_inf,pos_inf);122passed &= verify(5,cylinder,RayHit(Vec3fa(+0.0f,2.0f,0.0f),Vec3fa( 1.0f, 0.0f,+0.0f),0.0f,float(inf)),false,pos_inf,neg_inf);123passed &= verify(6,cylinder,RayHit(Vec3fa(+0.0f,2.0f,0.0f),Vec3fa(-1.0f, 0.0f,+0.0f),0.0f,float(inf)),false,pos_inf,neg_inf);124return passed;125}126127/*! output operator */128friend __forceinline embree_ostream operator<<(embree_ostream cout, const Cylinder& c) {129return cout << "Cylinder { p0 = " << c.p0 << ", p1 = " << c.p1 << ", r = " << sqrtf(c.rr) << "}";130}131};132133template<int N>134struct CylinderN135{136const Vec3vf<N> p0; //!< start location137const Vec3vf<N> p1; //!< end position138const vfloat<N> rr; //!< squared radius of cylinder139140__forceinline CylinderN(const Vec3vf<N>& p0, const Vec3vf<N>& p1, const vfloat<N>& r)141: p0(p0), p1(p1), rr(sqr(r)) {}142143__forceinline CylinderN(const Vec3vf<N>& p0, const Vec3vf<N>& p1, const vfloat<N>& rr, bool)144: p0(p0), p1(p1), rr(rr) {}145146147__forceinline vbool<N> intersect(const Vec3fa& org, const Vec3fa& dir,148BBox<vfloat<N>>& t_o,149vfloat<N>& u0_o, Vec3vf<N>& Ng0_o,150vfloat<N>& u1_o, Vec3vf<N>& Ng1_o) const151{152/* calculate quadratic equation to solve */153const vfloat<N> rl = rcp_length(p1-p0);154const Vec3vf<N> P0 = p0, dP = (p1-p0)*rl;155const Vec3vf<N> O = Vec3vf<N>(org)-P0, dO = dir;156157const vfloat<N> dOdO = dot(dO,dO);158const vfloat<N> OdO = dot(dO,O);159const vfloat<N> OO = dot(O,O);160const vfloat<N> dOz = dot(dP,dO);161const vfloat<N> Oz = dot(dP,O);162163const vfloat<N> A = dOdO - sqr(dOz);164const vfloat<N> B = 2.0f * (OdO - dOz*Oz);165const vfloat<N> C = OO - sqr(Oz) - rr;166167/* we miss the cylinder if determinant is smaller than zero */168const vfloat<N> D = B*B - 4.0f*A*C;169vbool<N> valid = D >= 0.0f;170if (none(valid)) {171t_o = BBox<vfloat<N>>(empty);172return valid;173}174175/* standard case for rays that are not parallel to the cylinder */176const vfloat<N> Q = sqrt(D);177const vfloat<N> rcp_2A = rcp(2.0f*A);178const vfloat<N> t0 = (-B-Q)*rcp_2A;179const vfloat<N> t1 = (-B+Q)*rcp_2A;180181/* calculates u and Ng for near hit */182{183u0_o = madd(t0,dOz,Oz)*rl;184const Vec3vf<N> Pr = t0*Vec3vf<N>(dir);185const Vec3vf<N> Pl = madd(u0_o,p1-p0,p0);186Ng0_o = Pr-Pl;187}188189/* calculates u and Ng for far hit */190{191u1_o = madd(t1,dOz,Oz)*rl;192const Vec3vf<N> Pr = t1*Vec3vf<N>(dir);193const Vec3vf<N> Pl = madd(u1_o,p1-p0,p0);194Ng1_o = Pr-Pl;195}196197t_o.lower = select(valid, t0, vfloat<N>(pos_inf));198t_o.upper = select(valid, t1, vfloat<N>(neg_inf));199200/* special case for rays that are parallel to the cylinder */201const vfloat<N> eps = 16.0f*float(ulp)*max(abs(dOdO),abs(sqr(dOz)));202vbool<N> validt = valid & (abs(A) < eps);203if (unlikely(any(validt)))204{205vbool<N> inside = C <= 0.0f;206t_o.lower = select(validt,select(inside,vfloat<N>(neg_inf),vfloat<N>(pos_inf)),t_o.lower);207t_o.upper = select(validt,select(inside,vfloat<N>(pos_inf),vfloat<N>(neg_inf)),t_o.upper);208valid &= !validt | inside;209}210return valid;211}212213__forceinline vbool<N> intersect(const Vec3fa& org_i, const Vec3fa& dir, BBox<vfloat<N>>& t_o) const214{215vfloat<N> u0_o; Vec3vf<N> Ng0_o;216vfloat<N> u1_o; Vec3vf<N> Ng1_o;217return intersect(org_i,dir,t_o,u0_o,Ng0_o,u1_o,Ng1_o);218}219};220}221}222223224225