// ======================================================================== // // Copyright 2009-2017 Intel Corporation // // // // Licensed under the Apache License, Version 2.0 (the "License"); // // you may not use this file except in compliance with the License. // // You may obtain a copy of the License at // // // // http://www.apache.org/licenses/LICENSE-2.0 // // // // Unless required by applicable law or agreed to in writing, software // // distributed under the License is distributed on an "AS IS" BASIS, // // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // // See the License for the specific language governing permissions and // // limitations under the License. // // ======================================================================== // #pragma once #include "../common/ray.h" #include "filter.h" namespace embree { namespace isa { template struct LineIntersectorHitM { __forceinline LineIntersectorHitM() {} __forceinline LineIntersectorHitM(const vfloat& u, const vfloat& v, const vfloat& t, const Vec3>& Ng) : vu(u), vv(v), vt(t), vNg(Ng) {} __forceinline void finalize() {} __forceinline Vec2f uv (const size_t i) const { return Vec2f(vu[i],vv[i]); } __forceinline float t (const size_t i) const { return vt[i]; } __forceinline Vec3fa Ng(const size_t i) const { return Vec3fa(vNg.x[i],vNg.y[i],vNg.z[i]); } public: vfloat vu; vfloat vv; vfloat vt; Vec3> vNg; }; template struct LineIntersector1 { typedef Vec3> Vec3vfM; typedef Vec4> Vec4vfM; struct Precalculations { __forceinline Precalculations() {} __forceinline Precalculations(const Ray& ray, const void* ptr) { const float s = rsqrt(dot(ray.dir,ray.dir)); depth_scale = s; ray_space = frame(s*ray.dir).transposed(); } vfloat depth_scale; LinearSpace3 ray_space; }; template static __forceinline bool intersect(const vbool& valid_i, Ray& ray, const Precalculations& pre, const Vec4vfM& v0, const Vec4vfM& v1, const Epilog& epilog) { /* transform end points into ray space */ vbool valid = valid_i; Vec4vfM p0(xfmVector(pre.ray_space,v0.xyz()-Vec3vfM(ray.org)), v0.w); Vec4vfM p1(xfmVector(pre.ray_space,v1.xyz()-Vec3vfM(ray.org)), v1.w); /* approximative intersection with cone */ const Vec4vfM v = p1-p0; const Vec4vfM w = -p0; const vfloat d0 = madd(w.x,v.x,w.y*v.y); const vfloat d1 = madd(v.x,v.x,v.y*v.y); const vfloat u = clamp(d0*rcp(d1),vfloat(zero),vfloat(one)); const Vec4vfM p = madd(u,v,p0); const vfloat t = p.z*pre.depth_scale; const vfloat d2 = madd(p.x,p.x,p.y*p.y); const vfloat r = p.w; const vfloat r2 = r*r; valid &= (d2 <= r2) & (vfloat(ray.tnear) < t) & (t < vfloat(ray.tfar)); if (unlikely(none(valid))) return false; /* ignore denormalized segments */ const Vec3vfM T = v1.xyz()-v0.xyz(); valid &= (T.x != vfloat(zero)) | (T.y != vfloat(zero)) | (T.z != vfloat(zero)); if (unlikely(none(valid))) return false; /* update hit information */ LineIntersectorHitM hit(u,zero,t,T); return epilog(valid,hit); } }; template struct LineIntersectorK { typedef Vec3> Vec3vfM; typedef Vec4> Vec4vfM; struct Precalculations { __forceinline Precalculations (const vbool& valid, const RayK& ray) { size_t mask = movemask(valid); depth_scale = rsqrt(dot(ray.dir,ray.dir)); while (mask) { size_t k = __bscf(mask); ray_space[k] = frame(depth_scale[k]*Vec3fa(ray.dir.x[k],ray.dir.y[k],ray.dir.z[k])).transposed(); } } vfloat depth_scale; LinearSpace3 ray_space[K]; }; template static __forceinline bool intersect(const vbool& valid_i, RayK& ray, size_t k, const Precalculations& pre, const Vec4vfM& v0, const Vec4vfM& v1, const Epilog& epilog) { /* transform end points into ray space */ vbool valid = valid_i; const Vec3vfM ray_org(ray.org.x[k],ray.org.y[k],ray.org.z[k]); const Vec3vfM ray_dir(ray.dir.x[k],ray.dir.y[k],ray.dir.z[k]); Vec4vfM p0(xfmVector(pre.ray_space[k],v0.xyz()-ray_org), v0.w); Vec4vfM p1(xfmVector(pre.ray_space[k],v1.xyz()-ray_org), v1.w); /* approximative intersection with cone */ const Vec4vfM v = p1-p0; const Vec4vfM w = -p0; const vfloat d0 = madd(w.x,v.x,w.y*v.y); const vfloat d1 = madd(v.x,v.x,v.y*v.y); const vfloat u = clamp(d0*rcp(d1),vfloat(zero),vfloat(one)); const Vec4vfM p = madd(u,v,p0); const vfloat t = p.z*pre.depth_scale[k]; const vfloat d2 = madd(p.x,p.x,p.y*p.y); const vfloat r = p.w; const vfloat r2 = r*r; valid &= (d2 <= r2) & (vfloat(ray.tnear[k]) < t) & (t < vfloat(ray.tfar[k])); if (unlikely(none(valid))) return false; /* ignore denormalized segments */ const Vec3vfM T = v1.xyz()-v0.xyz(); valid &= (T.x != vfloat(zero)) | (T.y != vfloat(zero)) | (T.z != vfloat(zero)); if (unlikely(none(valid))) return false; /* update hit information */ LineIntersectorHitM hit(u,zero,t,T); return epilog(valid,hit); } }; } }