Path: blob/master/thirdparty/embree/kernels/geometry/disc_intersector.h
9905 views
// Copyright 2009-2021 Intel Corporation1// SPDX-License-Identifier: Apache-2.023#pragma once45#include "../common/ray.h"6#include "../common/scene_points.h"7#include "curve_intersector_precalculations.h"89namespace embree10{11namespace isa12{13template<int M>14struct DiscIntersectorHitM15{16__forceinline DiscIntersectorHitM() {}1718__forceinline DiscIntersectorHitM(const vfloat<M>& u, const vfloat<M>& v, const vfloat<M>& t, const Vec3vf<M>& Ng)19: vu(u), vv(v), vt(t), vNg(Ng)20{21}2223__forceinline void finalize() {}2425__forceinline Vec2f uv(const size_t i) const {26return Vec2f(vu[i], vv[i]);27}28__forceinline Vec2vf<M> uv() const {29return Vec2vf<M>(vu, vv);30}31__forceinline float t(const size_t i) const {32return vt[i];33}34__forceinline vfloat<M> t() const {35return vt;36}37__forceinline Vec3fa Ng(const size_t i) const {38return Vec3fa(vNg.x[i], vNg.y[i], vNg.z[i]);39}40__forceinline Vec3vf<M> Ng() const {41return vNg;42}4344public:45vfloat<M> vu;46vfloat<M> vv;47vfloat<M> vt;48Vec3vf<M> vNg;49};5051template<>52struct DiscIntersectorHitM<1>53{54__forceinline DiscIntersectorHitM() {}5556__forceinline DiscIntersectorHitM(const float& u, const float& v, const float& t, const Vec3fa& Ng)57: vu(u), vv(v), vt(t), vNg(Ng) {}5859__forceinline void finalize() {}6061__forceinline Vec2f uv() const {62return Vec2f(vu, vv);63}6465__forceinline float t() const {66return vt;67}6869__forceinline Vec3fa Ng() const {70return vNg;71}7273public:74float vu;75float vv;76float vt;77Vec3fa vNg;78};7980template<int M>81struct DiscIntersector182{83typedef CurvePrecalculations1 Precalculations;8485template<typename Ray, typename Epilog>86static __forceinline bool intersect(87const vbool<M>& valid_i,88Ray& ray,89RayQueryContext* context,90const Points* geom,91const Precalculations& pre,92const Vec4vf<M>& v0i,93const Epilog& epilog)94{95vbool<M> valid = valid_i;9697const Vec3vf<M> ray_org(ray.org.x, ray.org.y, ray.org.z);98const Vec3vf<M> ray_dir(ray.dir.x, ray.dir.y, ray.dir.z);99const vfloat<M> rd2 = rcp(dot(ray_dir, ray_dir));100101const Vec4vf<M> v0 = enlargeRadiusToMinWidth<M>(context,geom,ray_org,v0i);102const Vec3vf<M> center = v0.xyz();103const vfloat<M> radius = v0.w;104105/* compute ray distance projC0 to hit point with ray oriented plane */106const Vec3vf<M> c0 = center - ray_org;107const vfloat<M> projC0 = dot(c0, ray_dir) * rd2;108109valid &= (vfloat<M>(ray.tnear()) <= projC0) & (projC0 <= vfloat<M>(ray.tfar));110if (unlikely(none(valid)))111return false;112113/* check if hit point lies inside disc */114const Vec3vf<M> perp = c0 - projC0 * ray_dir;115const vfloat<M> l2 = dot(perp, perp);116const vfloat<M> r2 = radius * radius;117valid &= (l2 <= r2);118if (unlikely(none(valid)))119return false;120121/* We reject hits where the ray origin lies inside the ray122* oriented disc to avoid self intersections. */123#if defined(EMBREE_DISC_POINT_SELF_INTERSECTION_AVOIDANCE)124const vfloat<M> m2 = dot(c0, c0);125valid &= (m2 > r2);126if (unlikely(none(valid)))127return false;128#endif129130DiscIntersectorHitM<M> hit(zero, zero, projC0, -ray_dir);131return epilog(valid, hit);132}133134template<typename Ray, typename Epilog>135static __forceinline bool intersect(const vbool<M>& valid_i,136Ray& ray,137RayQueryContext* context,138const Points* geom,139const Precalculations& pre,140const Vec4vf<M>& v0i,141const Vec3vf<M>& normal,142const Epilog& epilog)143{144vbool<M> valid = valid_i;145const Vec3vf<M> ray_org(ray.org.x, ray.org.y, ray.org.z);146147const Vec4vf<M> v0 = enlargeRadiusToMinWidth<M>(context,geom,ray_org,v0i);148const Vec3vf<M> center = v0.xyz();149const vfloat<M> radius = v0.w;150151vfloat<M> divisor = dot(Vec3vf<M>((Vec3fa)ray.dir), normal);152const vbool<M> parallel = divisor == vfloat<M>(0.f);153valid &= !parallel;154divisor = select(parallel, 1.f, divisor); // prevent divide by zero155156vfloat<M> t = dot(center - Vec3vf<M>((Vec3fa)ray.org), Vec3vf<M>(normal)) / divisor;157158valid &= (vfloat<M>(ray.tnear()) <= t) & (t <= vfloat<M>(ray.tfar));159if (unlikely(none(valid)))160return false;161162Vec3vf<M> intersection = Vec3vf<M>((Vec3fa)ray.org) + Vec3vf<M>((Vec3fa)ray.dir) * t;163vfloat<M> dist2 = dot(intersection - center, intersection - center);164valid &= dist2 < radius * radius;165if (unlikely(none(valid)))166return false;167168DiscIntersectorHitM<M> hit(zero, zero, t, normal);169return epilog(valid, hit);170}171};172173template<int M, int K>174struct DiscIntersectorK175{176typedef CurvePrecalculationsK<K> Precalculations;177178template<typename Epilog>179static __forceinline bool intersect(const vbool<M>& valid_i,180RayK<K>& ray,181size_t k,182RayQueryContext* context,183const Points* geom,184const Precalculations& pre,185const Vec4vf<M>& v0i,186const Epilog& epilog)187{188vbool<M> valid = valid_i;189190const Vec3vf<M> ray_org(ray.org.x[k], ray.org.y[k], ray.org.z[k]);191const Vec3vf<M> ray_dir(ray.dir.x[k], ray.dir.y[k], ray.dir.z[k]);192const vfloat<M> rd2 = rcp(dot(ray_dir, ray_dir));193194const Vec4vf<M> v0 = enlargeRadiusToMinWidth<M>(context,geom,ray_org,v0i);195const Vec3vf<M> center = v0.xyz();196const vfloat<M> radius = v0.w;197198/* compute ray distance projC0 to hit point with ray oriented plane */199const Vec3vf<M> c0 = center - ray_org;200const vfloat<M> projC0 = dot(c0, ray_dir) * rd2;201202valid &= (vfloat<M>(ray.tnear()[k]) <= projC0) & (projC0 <= vfloat<M>(ray.tfar[k]));203if (unlikely(none(valid)))204return false;205206/* check if hit point lies inside disc */207const Vec3vf<M> perp = c0 - projC0 * ray_dir;208const vfloat<M> l2 = dot(perp, perp);209const vfloat<M> r2 = radius * radius;210valid &= (l2 <= r2);211if (unlikely(none(valid)))212return false;213214/* We reject hits where the ray origin lies inside the ray215* oriented disc to avoid self intersections. */216#if defined(EMBREE_DISC_POINT_SELF_INTERSECTION_AVOIDANCE)217const vfloat<M> m2 = dot(c0, c0);218valid &= (m2 > r2);219if (unlikely(none(valid)))220return false;221#endif222223DiscIntersectorHitM<M> hit(zero, zero, projC0, -ray_dir);224return epilog(valid, hit);225}226227template<typename Epilog>228static __forceinline bool intersect(const vbool<M>& valid_i,229RayK<K>& ray,230size_t k,231RayQueryContext* context,232const Points* geom,233const Precalculations& pre,234const Vec4vf<M>& v0i,235const Vec3vf<M>& normal,236const Epilog& epilog)237{238vbool<M> valid = valid_i;239const Vec3vf<M> ray_org(ray.org.x[k], ray.org.y[k], ray.org.z[k]);240const Vec3vf<M> ray_dir(ray.dir.x[k], ray.dir.y[k], ray.dir.z[k]);241242const Vec4vf<M> v0 = enlargeRadiusToMinWidth<M>(context,geom,ray_org,v0i);243const Vec3vf<M> center = v0.xyz();244const vfloat<M> radius = v0.w;245246vfloat<M> divisor = dot(Vec3vf<M>(ray_dir), normal);247const vbool<M> parallel = divisor == vfloat<M>(0.f);248valid &= !parallel;249divisor = select(parallel, 1.f, divisor); // prevent divide by zero250251vfloat<M> t = dot(center - Vec3vf<M>(ray_org), Vec3vf<M>(normal)) / divisor;252253valid &= (vfloat<M>(ray.tnear()[k]) <= t) & (t <= vfloat<M>(ray.tfar[k]));254if (unlikely(none(valid)))255return false;256257Vec3vf<M> intersection = Vec3vf<M>(ray_org) + Vec3vf<M>(ray_dir) * t;258vfloat<M> dist2 = dot(intersection - center, intersection - center);259valid &= dist2 < radius * radius;260if (unlikely(none(valid)))261return false;262263DiscIntersectorHitM<M> hit(zero, zero, t, normal);264return epilog(valid, hit);265}266};267} // namespace isa268} // namespace embree269270271