From 767e374dced69b45db0afb30ca2ccf0bbbeef672 Mon Sep 17 00:00:00 2001 From: jfons Date: Thu, 20 May 2021 12:49:33 +0200 Subject: Upgrade Embree to the latest official release. Since Embree v3.13.0 supports AARCH64, switch back to the official repo instead of using Embree-aarch64. `thirdparty/embree/patches/godot-changes.patch` should now contain an accurate diff of the changes done to the library. --- .../geometry/triangle_intersector_pluecker.h | 407 +++++++++++++++++++++ 1 file changed, 407 insertions(+) create mode 100644 thirdparty/embree/kernels/geometry/triangle_intersector_pluecker.h (limited to 'thirdparty/embree/kernels/geometry/triangle_intersector_pluecker.h') diff --git a/thirdparty/embree/kernels/geometry/triangle_intersector_pluecker.h b/thirdparty/embree/kernels/geometry/triangle_intersector_pluecker.h new file mode 100644 index 0000000000..8fbefcea88 --- /dev/null +++ b/thirdparty/embree/kernels/geometry/triangle_intersector_pluecker.h @@ -0,0 +1,407 @@ +// Copyright 2009-2021 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 + +#pragma once + +#include "triangle.h" +#include "trianglev.h" +#include "trianglev_mb.h" +#include "intersector_epilog.h" + +/*! Modified Pluecker ray/triangle intersector. The test first shifts + * the ray origin into the origin of the coordinate system and then + * uses Pluecker coordinates for the intersection. Due to the shift, + * the Pluecker coordinate calculation simplifies and the tests get + * numerically stable. The edge equations are watertight along the + * edge for neighboring triangles. */ + +namespace embree +{ + namespace isa + { + template + struct PlueckerHitM + { + __forceinline PlueckerHitM(const UVMapper& mapUV) : mapUV(mapUV) {} + + __forceinline PlueckerHitM(const vbool& valid, const vfloat& U, const vfloat& V, const vfloat& UVW, const vfloat& t, const Vec3vf& Ng, const UVMapper& mapUV) + : U(U), V(V), UVW(UVW), mapUV(mapUV), valid(valid), vt(t), vNg(Ng) {} + + __forceinline void finalize() + { + const vbool invalid = abs(UVW) < min_rcp_input; + const vfloat rcpUVW = select(invalid,vfloat(0.0f),rcp(UVW)); + vu = min(U * rcpUVW,1.0f); + vv = min(V * rcpUVW,1.0f); + mapUV(vu,vv,vNg); + } + + __forceinline Vec2vf uv() const { return Vec2vf(vu,vv); } + __forceinline vfloat t () const { return vt; } + __forceinline Vec3vf Ng() const { return vNg; } + + __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 U; + vfloat V; + vfloat UVW; + const UVMapper& mapUV; + + public: + vbool valid; + vfloat vu; + vfloat vv; + vfloat vt; + Vec3vf vNg; + }; + + template + struct PlueckerIntersector1 + { + __forceinline PlueckerIntersector1() {} + + __forceinline PlueckerIntersector1(const Ray& ray, const void* ptr) {} + + template + __forceinline bool intersect(const vbool& valid0, + Ray& ray, + const Vec3vf& tri_v0, + const Vec3vf& tri_v1, + const Vec3vf& tri_v2, + const UVMapper& mapUV, + PlueckerHitM& hit) const + { + vbool valid = valid0; + + /* calculate vertices relative to ray origin */ + const Vec3vf O = Vec3vf((Vec3fa)ray.org); + const Vec3vf D = Vec3vf((Vec3fa)ray.dir); + const Vec3vf v0 = tri_v0-O; + const Vec3vf v1 = tri_v1-O; + const Vec3vf v2 = tri_v2-O; + + /* calculate triangle edges */ + const Vec3vf e0 = v2-v0; + const Vec3vf e1 = v0-v1; + const Vec3vf e2 = v1-v2; + + /* perform edge tests */ + const vfloat U = dot(cross(e0,v2+v0),D); + const vfloat V = dot(cross(e1,v0+v1),D); + const vfloat W = dot(cross(e2,v1+v2),D); + const vfloat UVW = U+V+W; + const vfloat eps = float(ulp)*abs(UVW); +#if defined(EMBREE_BACKFACE_CULLING) + valid &= max(U,V,W) <= eps; +#else + valid &= (min(U,V,W) >= -eps) | (max(U,V,W) <= eps); +#endif + if (unlikely(early_out && none(valid))) return false; + + /* calculate geometry normal and denominator */ + const Vec3vf Ng = stable_triangle_normal(e0,e1,e2); + const vfloat den = twice(dot(Ng,D)); + + /* perform depth test */ + const vfloat T = twice(dot(v0,Ng)); + const vfloat t = rcp(den)*T; + valid &= vfloat(ray.tnear()) <= t & t <= vfloat(ray.tfar); + valid &= den != vfloat(zero); + if (unlikely(early_out && none(valid))) return false; + + /* update hit information */ + new (&hit) PlueckerHitM(valid,U,V,UVW,t,Ng,mapUV); + return true; + } + + template + __forceinline bool intersectEdge(const vbool& valid, + Ray& ray, + const Vec3vf& tri_v0, + const Vec3vf& tri_v1, + const Vec3vf& tri_v2, + const UVMapper& mapUV, + PlueckerHitM& hit) const + { + return intersect(valid,ray,tri_v0,tri_v1,tri_v2,mapUV,hit); + } + + template + __forceinline bool intersectEdge(Ray& ray, + const Vec3vf& tri_v0, + const Vec3vf& tri_v1, + const Vec3vf& tri_v2, + const UVMapper& mapUV, + PlueckerHitM& hit) const + { + vbool valid = true; + return intersect(valid,ray,tri_v0,tri_v1,tri_v2,mapUV,hit); + } + + template + __forceinline bool intersect(Ray& ray, + const Vec3vf& tri_v0, + const Vec3vf& tri_v1, + const Vec3vf& tri_v2, + const UVMapper& mapUV, + PlueckerHitM& hit) const + { + return intersectEdge(ray,tri_v0,tri_v1,tri_v2,mapUV,hit); + } + + template + __forceinline bool intersectEdge(Ray& ray, + const Vec3vf& v0, + const Vec3vf& e1, + const Vec3vf& e2, + const UVMapper& mapUV, + const Epilog& epilog) const + { + PlueckerHitM hit(mapUV); + if (likely(intersectEdge(ray,v0,e1,e2,mapUV,hit))) return epilog(hit.valid,hit); + return false; + } + + template + __forceinline bool intersect(Ray& ray, + const Vec3vf& v0, + const Vec3vf& v1, + const Vec3vf& v2, + const UVMapper& mapUV, + const Epilog& epilog) const + { + PlueckerHitM hit(mapUV); + if (likely(intersect(ray,v0,v1,v2,mapUV,hit))) return epilog(hit.valid,hit); + return false; + } + + template + __forceinline bool intersect(Ray& ray, + const Vec3vf& v0, + const Vec3vf& v1, + const Vec3vf& v2, + const Epilog& epilog) const + { + auto mapUV = UVIdentity(); + PlueckerHitM> hit(mapUV); + if (likely(intersect(ray,v0,v1,v2,mapUV,hit))) return epilog(hit.valid,hit); + return false; + } + + template + __forceinline bool intersect(const vbool& valid, + Ray& ray, + const Vec3vf& v0, + const Vec3vf& v1, + const Vec3vf& v2, + const UVMapper& mapUV, + const Epilog& epilog) const + { + PlueckerHitM hit(mapUV); + if (likely(intersect(valid,ray,v0,v1,v2,mapUV,hit))) return epilog(hit.valid,hit); + return false; + } + + }; + + template + struct PlueckerHitK + { + __forceinline PlueckerHitK(const UVMapper& mapUV) : mapUV(mapUV) {} + + __forceinline PlueckerHitK(const vfloat& U, const vfloat& V, const vfloat& UVW, const vfloat& t, const Vec3vf& Ng, const UVMapper& mapUV) + : U(U), V(V), UVW(UVW), t(t), Ng(Ng), mapUV(mapUV) {} + + __forceinline std::tuple,vfloat,vfloat,Vec3vf> operator() () const + { + const vbool invalid = abs(UVW) < min_rcp_input; + const vfloat rcpUVW = select(invalid,vfloat(0.0f),rcp(UVW)); + vfloat u = min(U * rcpUVW,1.0f); + vfloat v = min(V * rcpUVW,1.0f); + Vec3vf vNg = Ng; + mapUV(u,v,vNg); + return std::make_tuple(u,v,t,vNg); + } + vfloat U; + vfloat V; + const vfloat UVW; + const vfloat t; + const Vec3vf Ng; + const UVMapper& mapUV; + }; + + template + struct PlueckerIntersectorK + { + __forceinline PlueckerIntersectorK() {} + __forceinline PlueckerIntersectorK(const vbool& valid, const RayK& ray) {} + + /*! Intersects K rays with one of M triangles. */ + template + __forceinline vbool intersectK(const vbool& valid0, + RayK& ray, + const Vec3vf& tri_v0, + const Vec3vf& tri_v1, + const Vec3vf& tri_v2, + const UVMapper& mapUV, + PlueckerHitK &hit) const + { + /* calculate vertices relative to ray origin */ + vbool valid = valid0; + const Vec3vf O = ray.org; + const Vec3vf D = ray.dir; + const Vec3vf v0 = tri_v0-O; + const Vec3vf v1 = tri_v1-O; + const Vec3vf v2 = tri_v2-O; + + /* calculate triangle edges */ + const Vec3vf e0 = v2-v0; + const Vec3vf e1 = v0-v1; + const Vec3vf e2 = v1-v2; + + /* perform edge tests */ + const vfloat U = dot(Vec3vf(cross(e0,v2+v0)),D); + const vfloat V = dot(Vec3vf(cross(e1,v0+v1)),D); + const vfloat W = dot(Vec3vf(cross(e2,v1+v2)),D); + const vfloat UVW = U+V+W; + const vfloat eps = float(ulp)*abs(UVW); +#if defined(EMBREE_BACKFACE_CULLING) + valid &= max(U,V,W) <= eps; +#else + valid &= (min(U,V,W) >= -eps) | (max(U,V,W) <= eps); +#endif + if (unlikely(none(valid))) return valid; + + /* calculate geometry normal and denominator */ + const Vec3vf Ng = stable_triangle_normal(e0,e1,e2); + const vfloat den = twice(dot(Vec3vf(Ng),D)); + + /* perform depth test */ + const vfloat T = twice(dot(v0,Vec3vf(Ng))); + const vfloat t = rcp(den)*T; + valid &= ray.tnear() <= t & t <= ray.tfar; + valid &= den != vfloat(zero); + if (unlikely(none(valid))) return valid; + + /* calculate hit information */ + new (&hit) PlueckerHitK(U,V,UVW,t,Ng,mapUV); + return valid; + } + + template + __forceinline vbool intersectK(const vbool& valid0, + RayK& ray, + const Vec3vf& tri_v0, + const Vec3vf& tri_v1, + const Vec3vf& tri_v2, + const Epilog& epilog) const + { + UVIdentity mapUV; + PlueckerHitK> hit(mapUV); + const vbool valid = intersectK(valid0,ray,tri_v0,tri_v1,tri_v2,mapUV,hit); + return epilog(valid,hit); + } + + template + __forceinline vbool intersectK(const vbool& valid0, + RayK& ray, + const Vec3vf& tri_v0, + const Vec3vf& tri_v1, + const Vec3vf& tri_v2, + const UVMapper& mapUV, + const Epilog& epilog) const + { + PlueckerHitK hit(mapUV); + const vbool valid = intersectK(valid0,ray,tri_v0,tri_v1,tri_v2,mapUV,hit); + return epilog(valid,hit); + } + + /*! Intersect k'th ray from ray packet of size K with M triangles. */ + template + __forceinline bool intersect(RayK& ray, size_t k, + const Vec3vf& tri_v0, + const Vec3vf& tri_v1, + const Vec3vf& tri_v2, + const UVMapper& mapUV, + PlueckerHitM &hit) const + { + /* calculate vertices relative to ray origin */ + const Vec3vf O = broadcast>(ray.org,k); + const Vec3vf D = broadcast>(ray.dir,k); + const Vec3vf v0 = tri_v0-O; + const Vec3vf v1 = tri_v1-O; + const Vec3vf v2 = tri_v2-O; + + /* calculate triangle edges */ + const Vec3vf e0 = v2-v0; + const Vec3vf e1 = v0-v1; + const Vec3vf e2 = v1-v2; + + + /* perform edge tests */ + const vfloat U = dot(cross(e0,v2+v0),D); + const vfloat V = dot(cross(e1,v0+v1),D); + const vfloat W = dot(cross(e2,v1+v2),D); + + const vfloat UVW = U+V+W; + const vfloat eps = float(ulp)*abs(UVW); +#if defined(EMBREE_BACKFACE_CULLING) + vbool valid = max(U,V,W) <= eps; +#else + vbool valid = (min(U,V,W) >= -eps) | (max(U,V,W) <= eps); +#endif + if (unlikely(none(valid))) return false; + + /* calculate geometry normal and denominator */ + const Vec3vf Ng = stable_triangle_normal(e0,e1,e2); + const vfloat den = twice(dot(Ng,D)); + + /* perform depth test */ + const vfloat T = twice(dot(v0,Ng)); + const vfloat t = rcp(den)*T; + valid &= vfloat(ray.tnear()[k]) <= t & t <= vfloat(ray.tfar[k]); + if (unlikely(none(valid))) return false; + + /* avoid division by 0 */ + valid &= den != vfloat(zero); + if (unlikely(none(valid))) return false; + + /* update hit information */ + new (&hit) PlueckerHitM(valid,U,V,UVW,t,Ng,mapUV); + return true; + } + + template + __forceinline bool intersect(RayK& ray, size_t k, + const Vec3vf& tri_v0, + const Vec3vf& tri_v1, + const Vec3vf& tri_v2, + const UVMapper& mapUV, + const Epilog& epilog) const + { + PlueckerHitM hit(mapUV); + if (intersect(ray,k,tri_v0,tri_v1,tri_v2,mapUV,hit)) + return epilog(hit.valid,hit); + return false; + } + + template + __forceinline bool intersect(RayK& ray, size_t k, + const Vec3vf& tri_v0, + const Vec3vf& tri_v1, + const Vec3vf& tri_v2, + const Epilog& epilog) const + { + UVIdentity mapUV; + PlueckerHitM> hit(mapUV); + if (intersect(ray,k,tri_v0,tri_v1,tri_v2,mapUV,hit)) + return epilog(hit.valid,hit); + return false; + } + + }; + } +} -- cgit v1.2.3