mirror of
				https://github.com/godotengine/godot.git
				synced 2025-10-31 13:41:03 +00:00 
			
		
		
		
	
		
			
	
	
		
			368 lines
		
	
	
	
		
			14 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
		
		
			
		
	
	
			368 lines
		
	
	
	
		
			14 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
|   | // Copyright 2009-2021 Intel Corporation
 | ||
|  | // SPDX-License-Identifier: Apache-2.0
 | ||
|  | 
 | ||
|  | #pragma once
 | ||
|  | 
 | ||
|  | #include "subgrid.h"
 | ||
|  | #include "quad_intersector_moeller.h"
 | ||
|  | #include "quad_intersector_pluecker.h"
 | ||
|  | 
 | ||
|  | namespace embree | ||
|  | { | ||
|  |   namespace isa | ||
|  |   { | ||
|  | 
 | ||
|  |     template<int M> | ||
|  |     __forceinline void interpolateUV(PlueckerHitM<M,UVIdentity<M>> &hit,const GridMesh::Grid &g, const SubGrid& subgrid, const vint<M> &stepX, const vint<M> &stepY)  | ||
|  |     { | ||
|  |       /* correct U,V interpolation across the entire grid */ | ||
|  |       const vint<M> sx((int)subgrid.x()); | ||
|  |       const vint<M> sy((int)subgrid.y()); | ||
|  |       const vint<M> sxM(sx + stepX); | ||
|  |       const vint<M> syM(sy + stepY); | ||
|  |       const float inv_resX = rcp((float)((int)g.resX-1)); | ||
|  |       const float inv_resY = rcp((float)((int)g.resY-1));           | ||
|  |       hit.U = (hit.U + vfloat<M>(sxM) * hit.UVW) * inv_resX; | ||
|  |       hit.V = (hit.V + vfloat<M>(syM) * hit.UVW) * inv_resY; | ||
|  |     } | ||
|  |      | ||
|  |     template<int M, bool filter> | ||
|  |       struct SubGridQuadMIntersector1Pluecker; | ||
|  | 
 | ||
|  |     template<int M, bool filter> | ||
|  |       struct SubGridQuadMIntersector1Pluecker | ||
|  |       { | ||
|  |         __forceinline SubGridQuadMIntersector1Pluecker() {} | ||
|  | 
 | ||
|  |         __forceinline SubGridQuadMIntersector1Pluecker(const Ray& ray, const void* ptr) {} | ||
|  | 
 | ||
|  |         __forceinline void intersect(RayHit& ray, IntersectContext* context, | ||
|  |                                      const Vec3vf<M>& v0, const Vec3vf<M>& v1, const Vec3vf<M>& v2, const Vec3vf<M>& v3, | ||
|  |                                      const GridMesh::Grid &g, const SubGrid& subgrid) const | ||
|  |         { | ||
|  |           UVIdentity<M> mapUV; | ||
|  |           PlueckerHitM<M,UVIdentity<M>> hit(mapUV); | ||
|  |           PlueckerIntersector1<M> intersector(ray,nullptr); | ||
|  | 	   | ||
|  |           Intersect1EpilogMU<M,filter> epilog(ray,context,subgrid.geomID(),subgrid.primID()); | ||
|  | 
 | ||
|  |           /* intersect first triangle */ | ||
|  | 	  if (intersector.intersect(ray,v0,v1,v3,mapUV,hit))  | ||
|  |           { | ||
|  |             interpolateUV<M>(hit,g,subgrid,vint<M>(0,1,1,0),vint<M>(0,0,1,1)); | ||
|  |             epilog(hit.valid,hit); | ||
|  |           } | ||
|  | 
 | ||
|  |           /* intersect second triangle */ | ||
|  | 	  if (intersector.intersect(ray,v2,v3,v1,mapUV,hit))  | ||
|  |           { | ||
|  | 	    hit.U = hit.UVW - hit.U; | ||
|  | 	    hit.V = hit.UVW - hit.V; | ||
|  |             interpolateUV<M>(hit,g,subgrid,vint<M>(0,1,1,0),vint<M>(0,0,1,1)); | ||
|  |             epilog(hit.valid,hit); | ||
|  |           } | ||
|  |         } | ||
|  |        | ||
|  |         __forceinline bool occluded(Ray& ray, IntersectContext* context, | ||
|  |                                     const Vec3vf<M>& v0, const Vec3vf<M>& v1, const Vec3vf<M>& v2, const Vec3vf<M>& v3, | ||
|  |                                     const GridMesh::Grid &g, const SubGrid& subgrid) const | ||
|  |         { | ||
|  |           UVIdentity<M> mapUV; | ||
|  |           PlueckerHitM<M,UVIdentity<M>> hit(mapUV); | ||
|  |           PlueckerIntersector1<M> intersector(ray,nullptr); | ||
|  |           Occluded1EpilogMU<M,filter> epilog(ray,context,subgrid.geomID(),subgrid.primID()); | ||
|  | 
 | ||
|  |           /* intersect first triangle */ | ||
|  | 	  if (intersector.intersect(ray,v0,v1,v3,mapUV,hit))  | ||
|  |           { | ||
|  |             interpolateUV<M>(hit,g,subgrid,vint<M>(0,1,1,0),vint<M>(0,0,1,1)); | ||
|  |             if (epilog(hit.valid,hit)) | ||
|  | 	      return true; | ||
|  |           } | ||
|  | 
 | ||
|  |           /* intersect second triangle */ | ||
|  | 	  if (intersector.intersect(ray,v2,v3,v1,mapUV,hit))  | ||
|  |           { | ||
|  | 	    hit.U = hit.UVW - hit.U; | ||
|  | 	    hit.V = hit.UVW - hit.V; | ||
|  |             interpolateUV<M>(hit,g,subgrid,vint<M>(0,1,1,0),vint<M>(0,0,1,1)); | ||
|  |             if (epilog(hit.valid,hit)) | ||
|  | 	      return true; | ||
|  |           } | ||
|  |           return false; | ||
|  |         } | ||
|  |       }; | ||
|  | 
 | ||
|  | #if defined (__AVX__)
 | ||
|  | 
 | ||
|  |     /*! Intersects 4 quads with 1 ray using AVX */ | ||
|  |     template<bool filter> | ||
|  |       struct SubGridQuadMIntersector1Pluecker<4,filter> | ||
|  |     { | ||
|  |       __forceinline SubGridQuadMIntersector1Pluecker() {} | ||
|  | 
 | ||
|  |       __forceinline SubGridQuadMIntersector1Pluecker(const Ray& ray, const void* ptr) {} | ||
|  |        | ||
|  |       template<typename Epilog> | ||
|  |         __forceinline bool intersect(Ray& ray, const Vec3vf4& v0, const Vec3vf4& v1, const Vec3vf4& v2, const Vec3vf4& v3, const GridMesh::Grid &g, const SubGrid& subgrid, const Epilog& epilog) const | ||
|  |       { | ||
|  |         const Vec3vf8 vtx0(vfloat8(v0.x,v2.x),vfloat8(v0.y,v2.y),vfloat8(v0.z,v2.z)); | ||
|  | #if !defined(EMBREE_BACKFACE_CULLING)
 | ||
|  |         const Vec3vf8 vtx1(vfloat8(v1.x),vfloat8(v1.y),vfloat8(v1.z)); | ||
|  |         const Vec3vf8 vtx2(vfloat8(v3.x),vfloat8(v3.y),vfloat8(v3.z));         | ||
|  | #else
 | ||
|  |         const Vec3vf8 vtx1(vfloat8(v1.x,v3.x),vfloat8(v1.y,v3.y),vfloat8(v1.z,v3.z)); | ||
|  |         const Vec3vf8 vtx2(vfloat8(v3.x,v1.x),vfloat8(v3.y,v1.y),vfloat8(v3.z,v1.z)); | ||
|  | #endif
 | ||
|  | 
 | ||
|  |         UVIdentity<8> mapUV; | ||
|  |         PlueckerHitM<8,UVIdentity<8>> hit(mapUV); | ||
|  |         PlueckerIntersector1<8> intersector(ray,nullptr); | ||
|  |         const vbool8 flags(0,0,0,0,1,1,1,1); | ||
|  |         if (unlikely(intersector.intersect(ray,vtx0,vtx1,vtx2,mapUV,hit))) | ||
|  |         { | ||
|  | 	  /* correct U,V interpolation across the entire grid */ | ||
|  | 	  const vfloat8 U = select(flags,hit.UVW - hit.V,hit.U);	   | ||
|  | 	  const vfloat8 V = select(flags,hit.UVW - hit.U,hit.V); | ||
|  | 	  hit.U = U; | ||
|  | 	  hit.V = V;	   | ||
|  | 	  hit.vNg *= select(flags,vfloat8(-1.0f),vfloat8(1.0f));  | ||
|  |           interpolateUV<8>(hit,g,subgrid,vint<8>(0,1,1,0,0,1,1,0),vint<8>(0,0,1,1,0,0,1,1)); | ||
|  |           if (unlikely(epilog(hit.valid,hit))) | ||
|  |             return true; | ||
|  |         } | ||
|  |         return false; | ||
|  |       } | ||
|  |        | ||
|  |       __forceinline bool intersect(RayHit& ray, IntersectContext* context, | ||
|  |                                    const Vec3vf4& v0, const Vec3vf4& v1, const Vec3vf4& v2, const Vec3vf4& v3,  | ||
|  |                                    const GridMesh::Grid &g, const SubGrid& subgrid) const | ||
|  |       { | ||
|  |           return intersect(ray,v0,v1,v2,v3,g,subgrid,Intersect1EpilogMU<8,filter>(ray,context,subgrid.geomID(),subgrid.primID())); | ||
|  |       } | ||
|  |        | ||
|  |       __forceinline bool occluded(Ray& ray, IntersectContext* context, | ||
|  |                                   const Vec3vf4& v0, const Vec3vf4& v1, const Vec3vf4& v2, const Vec3vf4& v3,  | ||
|  |                                   const GridMesh::Grid &g, const SubGrid& subgrid) const | ||
|  |       { | ||
|  |           return intersect(ray,v0,v1,v2,v3,g,subgrid,Occluded1EpilogMU<8,filter>(ray,context,subgrid.geomID(),subgrid.primID())); | ||
|  |       } | ||
|  |     }; | ||
|  | 
 | ||
|  | #endif
 | ||
|  | 
 | ||
|  | 
 | ||
|  |     /* ----------------------------- */ | ||
|  |     /* -- ray packet intersectors -- */ | ||
|  |     /* ----------------------------- */ | ||
|  | 
 | ||
|  |     template<int K> | ||
|  |     __forceinline void interpolateUV(const vbool<K>& valid, PlueckerHitK<K,UVIdentity<K>> &hit,const GridMesh::Grid &g, const SubGrid& subgrid, const unsigned int i)  | ||
|  |     { | ||
|  |       /* correct U,V interpolation across the entire grid */ | ||
|  |       const unsigned int sx = subgrid.x() + (unsigned int)(i % 2); | ||
|  |       const unsigned int sy = subgrid.y() + (unsigned int)(i >>1); | ||
|  |       const float inv_resX = rcp((float)(int)(g.resX-1)); | ||
|  |       const float inv_resY = rcp((float)(int)(g.resY-1));       | ||
|  |       hit.U = select(valid,(hit.U + vfloat<K>((float)sx) * hit.UVW) * inv_resX,hit.U); | ||
|  |       hit.V = select(valid,(hit.V + vfloat<K>((float)sy) * hit.UVW) * inv_resY,hit.V); | ||
|  |     } | ||
|  |      | ||
|  |     template<int M, int K, bool filter> | ||
|  |       struct SubGridQuadMIntersectorKPlueckerBase | ||
|  |       { | ||
|  |         __forceinline SubGridQuadMIntersectorKPlueckerBase(const vbool<K>& valid, const RayK<K>& ray) {} | ||
|  | 
 | ||
|  |         template<typename Epilog> | ||
|  |         __forceinline bool intersectK(const vbool<K>& valid,  | ||
|  |                                       RayK<K>& ray, | ||
|  |                                       const Vec3vf<K>& v0, | ||
|  |                                       const Vec3vf<K>& v1, | ||
|  |                                       const Vec3vf<K>& v2, | ||
|  |                                       const Vec3vf<K>& v3, | ||
|  |                                       const GridMesh::Grid &g,  | ||
|  |                                       const SubGrid &subgrid, | ||
|  |                                       const unsigned int i, | ||
|  |                                       const Epilog& epilog) const | ||
|  |         { | ||
|  | 	  UVIdentity<K> mapUV; | ||
|  | 	  PlueckerHitK<K,UVIdentity<K>> hit(mapUV); | ||
|  | 	  PlueckerIntersectorK<M,K> intersector; | ||
|  | 
 | ||
|  |           const vbool<K> valid0 = intersector.intersectK(valid,ray,v0,v1,v3,mapUV,hit); | ||
|  | 	  if (any(valid0)) | ||
|  | 	    { | ||
|  | 	      interpolateUV(valid0,hit,g,subgrid,i); | ||
|  | 	      epilog(valid0,hit); | ||
|  | 	    } | ||
|  |           const vbool<K> valid1 = intersector.intersectK(valid,ray,v2,v3,v1,mapUV,hit); | ||
|  | 	  if (any(valid1)) | ||
|  | 	    { | ||
|  | 	      hit.U = hit.UVW - hit.U; | ||
|  | 	      hit.V = hit.UVW - hit.V;	       | ||
|  | 	      interpolateUV(valid1,hit,g,subgrid,i); | ||
|  | 	      epilog(valid1,hit); | ||
|  | 	    } | ||
|  | 	  return any(valid0|valid1);	   | ||
|  |         } | ||
|  | 
 | ||
|  |        template<typename Epilog> | ||
|  |         __forceinline bool occludedK(const vbool<K>& valid,  | ||
|  | 				     RayK<K>& ray, | ||
|  | 				     const Vec3vf<K>& v0, | ||
|  | 				     const Vec3vf<K>& v1, | ||
|  | 				     const Vec3vf<K>& v2, | ||
|  | 				     const Vec3vf<K>& v3, | ||
|  | 				     const GridMesh::Grid &g,  | ||
|  | 				     const SubGrid &subgrid, | ||
|  | 				     const unsigned int i, | ||
|  | 				     const Epilog& epilog) const | ||
|  |         { | ||
|  | 	  UVIdentity<K> mapUV; | ||
|  | 	  PlueckerHitK<K,UVIdentity<K>> hit(mapUV); | ||
|  | 	  PlueckerIntersectorK<M,K> intersector; | ||
|  | 
 | ||
|  | 	  vbool<K> valid_final = valid; | ||
|  |           const vbool<K> valid0 = intersector.intersectK(valid,ray,v0,v1,v3,mapUV,hit); | ||
|  | 	  if (any(valid0)) | ||
|  | 	    { | ||
|  | 	      interpolateUV(valid0,hit,g,subgrid,i); | ||
|  | 	      epilog(valid0,hit); | ||
|  | 	      valid_final &= !valid0; | ||
|  | 	    } | ||
|  | 	  if (none(valid_final)) return true;	      	   | ||
|  |           const vbool<K> valid1 = intersector.intersectK(valid,ray,v2,v3,v1,mapUV,hit); | ||
|  | 	  if (any(valid1)) | ||
|  | 	    { | ||
|  | 	      hit.U = hit.UVW - hit.U; | ||
|  | 	      hit.V = hit.UVW - hit.V;	       | ||
|  | 	      interpolateUV(valid1,hit,g,subgrid,i); | ||
|  | 	      epilog(valid1,hit); | ||
|  | 	      valid_final &= !valid1;	       | ||
|  | 	    } | ||
|  | 	  return none(valid_final); | ||
|  |         } | ||
|  | 
 | ||
|  | 	 | ||
|  |       }; | ||
|  | 
 | ||
|  | 
 | ||
|  |      | ||
|  | 
 | ||
|  |     template<int M, int K, bool filter> | ||
|  |       struct SubGridQuadMIntersectorKPluecker : public SubGridQuadMIntersectorKPlueckerBase<M,K,filter> | ||
|  |     { | ||
|  |       __forceinline SubGridQuadMIntersectorKPluecker(const vbool<K>& valid, const RayK<K>& ray) | ||
|  |         : SubGridQuadMIntersectorKPlueckerBase<M,K,filter>(valid,ray) {} | ||
|  | 
 | ||
|  |       __forceinline void intersect1(RayHitK<K>& ray, size_t k, IntersectContext* context, | ||
|  |                                     const Vec3vf<M>& v0, const Vec3vf<M>& v1, const Vec3vf<M>& v2, const Vec3vf<M>& v3, const GridMesh::Grid &g, const SubGrid &subgrid) const | ||
|  |       { | ||
|  | 	UVIdentity<M> mapUV; | ||
|  | 	PlueckerHitM<M,UVIdentity<M>> hit(mapUV); | ||
|  |         Intersect1KEpilogMU<M,K,filter> epilog(ray,k,context,subgrid.geomID(),subgrid.primID()); | ||
|  | 	PlueckerIntersectorK<M,K> intersector; | ||
|  | 	 | ||
|  | 	/* intersect first triangle */ | ||
|  | 	if (intersector.intersect(ray,k,v0,v1,v3,mapUV,hit))  | ||
|  |           { | ||
|  |             interpolateUV<M>(hit,g,subgrid,vint<M>(0,1,1,0),vint<M>(0,0,1,1)); | ||
|  |             epilog(hit.valid,hit); | ||
|  |           } | ||
|  | 
 | ||
|  | 	/* intersect second triangle */ | ||
|  | 	if (intersector.intersect(ray,k,v2,v3,v1,mapUV,hit))  | ||
|  |           { | ||
|  | 	    hit.U = hit.UVW - hit.U; | ||
|  | 	    hit.V = hit.UVW - hit.V; | ||
|  |             interpolateUV<M>(hit,g,subgrid,vint<M>(0,1,1,0),vint<M>(0,0,1,1)); | ||
|  |             epilog(hit.valid,hit); | ||
|  |           } | ||
|  |       } | ||
|  |        | ||
|  |       __forceinline bool occluded1(RayK<K>& ray, size_t k, IntersectContext* context, | ||
|  |                                    const Vec3vf<M>& v0, const Vec3vf<M>& v1, const Vec3vf<M>& v2, const Vec3vf<M>& v3, const GridMesh::Grid &g, const SubGrid &subgrid) const | ||
|  |       { | ||
|  | 	UVIdentity<M> mapUV; | ||
|  | 	PlueckerHitM<M,UVIdentity<M>> hit(mapUV); | ||
|  |         Occluded1KEpilogMU<M,K,filter> epilog(ray,k,context,subgrid.geomID(),subgrid.primID());	 | ||
|  | 	PlueckerIntersectorK<M,K> intersector; | ||
|  | 	 | ||
|  | 	/* intersect first triangle */ | ||
|  | 	if (intersector.intersect(ray,k,v0,v1,v3,mapUV,hit))  | ||
|  |         { | ||
|  |           interpolateUV<M>(hit,g,subgrid,vint<M>(0,1,1,0),vint<M>(0,0,1,1)); | ||
|  |           if (epilog(hit.valid,hit)) return true; | ||
|  |         } | ||
|  | 
 | ||
|  | 	/* intersect second triangle */ | ||
|  | 	if (intersector.intersect(ray,k,v2,v3,v1,mapUV,hit))  | ||
|  |         { | ||
|  | 	  hit.U = hit.UVW - hit.U; | ||
|  | 	  hit.V = hit.UVW - hit.V;	   | ||
|  |           interpolateUV<M>(hit,g,subgrid,vint<M>(0,1,1,0),vint<M>(0,0,1,1)); | ||
|  |           if (epilog(hit.valid,hit)) return true; | ||
|  |         } | ||
|  |         return false; | ||
|  |       } | ||
|  |     }; | ||
|  | 
 | ||
|  | 
 | ||
|  | #if defined (__AVX__)
 | ||
|  | 
 | ||
|  |     /*! Intersects 4 quads with 1 ray using AVX */ | ||
|  |     template<int K, bool filter> | ||
|  |       struct SubGridQuadMIntersectorKPluecker<4,K,filter> : public SubGridQuadMIntersectorKPlueckerBase<4,K,filter> | ||
|  |     { | ||
|  |       __forceinline SubGridQuadMIntersectorKPluecker(const vbool<K>& valid, const RayK<K>& ray) | ||
|  |         : SubGridQuadMIntersectorKPlueckerBase<4,K,filter>(valid,ray) {} | ||
|  |        | ||
|  |       template<typename Epilog> | ||
|  |         __forceinline bool intersect1(RayK<K>& ray, size_t k,const Vec3vf4& v0, const Vec3vf4& v1, const Vec3vf4& v2, const Vec3vf4& v3,  | ||
|  |                                       const GridMesh::Grid &g, const SubGrid &subgrid, const Epilog& epilog) const | ||
|  |       { | ||
|  |         const Vec3vf8 vtx0(vfloat8(v0.x,v2.x),vfloat8(v0.y,v2.y),vfloat8(v0.z,v2.z)); | ||
|  | #if !defined(EMBREE_BACKFACE_CULLING)
 | ||
|  |         const Vec3vf8 vtx1(vfloat8(v1.x),vfloat8(v1.y),vfloat8(v1.z)); | ||
|  |         const Vec3vf8 vtx2(vfloat8(v3.x),vfloat8(v3.y),vfloat8(v3.z)); | ||
|  | #else
 | ||
|  |         const Vec3vf8 vtx1(vfloat8(v1.x,v3.x),vfloat8(v1.y,v3.y),vfloat8(v1.z,v3.z)); | ||
|  |         const Vec3vf8 vtx2(vfloat8(v3.x,v1.x),vfloat8(v3.y,v1.y),vfloat8(v3.z,v1.z)); | ||
|  | #endif
 | ||
|  | 	UVIdentity<8> mapUV; | ||
|  | 	PlueckerHitM<8,UVIdentity<8>> hit(mapUV); | ||
|  | 	PlueckerIntersectorK<8,K> intersector; | ||
|  | 	const vbool8 flags(0,0,0,0,1,1,1,1); | ||
|  |         if (unlikely(intersector.intersect(ray,k,vtx0,vtx1,vtx2,mapUV,hit)))	 | ||
|  |         { | ||
|  |           /* correct U,V interpolation across the entire grid */ | ||
|  | 	  const vfloat8 U = select(flags,hit.UVW - hit.V,hit.U);	   | ||
|  | 	  const vfloat8 V = select(flags,hit.UVW - hit.U,hit.V); | ||
|  | 	  hit.U = U; | ||
|  | 	  hit.V = V;	   | ||
|  | 	  hit.vNg *= select(flags,vfloat8(-1.0f),vfloat8(1.0f));  | ||
|  |           interpolateUV<8>(hit,g,subgrid,vint<8>(0,1,1,0,0,1,1,0),vint<8>(0,0,1,1,0,0,1,1)); | ||
|  |           if (unlikely(epilog(hit.valid,hit))) | ||
|  |             return true; | ||
|  |         } | ||
|  |         return false; | ||
|  |       } | ||
|  |        | ||
|  |       __forceinline bool intersect1(RayHitK<K>& ray, size_t k, IntersectContext* context, | ||
|  |                                     const Vec3vf4& v0, const Vec3vf4& v1, const Vec3vf4& v2, const Vec3vf4& v3, const GridMesh::Grid &g, const SubGrid &subgrid) const | ||
|  |       { | ||
|  |         return intersect1(ray,k,v0,v1,v2,v3,g,subgrid,Intersect1KEpilogMU<8,K,filter>(ray,k,context,subgrid.geomID(),subgrid.primID())); | ||
|  |       } | ||
|  |        | ||
|  |       __forceinline bool occluded1(RayK<K>& ray, size_t k, IntersectContext* context, | ||
|  |                                    const Vec3vf4& v0, const Vec3vf4& v1, const Vec3vf4& v2, const Vec3vf4& v3, const GridMesh::Grid &g, const SubGrid &subgrid) const | ||
|  |       { | ||
|  |         return intersect1(ray,k,v0,v1,v2,v3,g,subgrid,Occluded1KEpilogMU<8,K,filter>(ray,k,context,subgrid.geomID(),subgrid.primID())); | ||
|  |       } | ||
|  |     }; | ||
|  | #endif
 | ||
|  | 
 | ||
|  |      | ||
|  |   } | ||
|  | } |