// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once #include "../common/ray.h" #include "../common/scene_grid_mesh.h" #include "../bvh/bvh.h" namespace embree { /* Stores M quads from an indexed face set */ struct SubGrid { /* Virtual interface to query information about the quad type */ struct Type : public PrimitiveType { const char* name() const; size_t sizeActive(const char* This) const; size_t sizeTotal(const char* This) const; size_t getBytes(const char* This) const; }; static Type type; public: /* primitive supports multiple time segments */ static const bool singleTimeSegment = false; /* Returns maximum number of stored quads */ static __forceinline size_t max_size() { return 1; } /* Returns required number of primitive blocks for N primitives */ static __forceinline size_t blocks(size_t N) { return (N+max_size()-1)/max_size(); } public: /* Default constructor */ __forceinline SubGrid() { } /* Construction from vertices and IDs */ __forceinline SubGrid(const unsigned int x, const unsigned int y, const unsigned int geomID, const unsigned int primID) : _x(x), _y(y), _geomID(geomID), _primID(primID) { } __forceinline bool invalid3x3X() const { return (unsigned int)_x & (1<<15); } __forceinline bool invalid3x3Y() const { return (unsigned int)_y & (1<<15); } /* Gather the quads */ __forceinline void gather(Vec3vf4& p0, Vec3vf4& p1, Vec3vf4& p2, Vec3vf4& p3, const GridMesh* const mesh, const GridMesh::Grid &g) const { /* first quad always valid */ const size_t vtxID00 = g.startVtxID + x() + y() * g.lineVtxOffset; const size_t vtxID01 = vtxID00 + 1; const vfloat4 vtx00 = vfloat4::loadu(mesh->vertexPtr(vtxID00)); const vfloat4 vtx01 = vfloat4::loadu(mesh->vertexPtr(vtxID01)); const size_t vtxID10 = vtxID00 + g.lineVtxOffset; const size_t vtxID11 = vtxID01 + g.lineVtxOffset; const vfloat4 vtx10 = vfloat4::loadu(mesh->vertexPtr(vtxID10)); const vfloat4 vtx11 = vfloat4::loadu(mesh->vertexPtr(vtxID11)); /* deltaX => vtx02, vtx12 */ const size_t deltaX = invalid3x3X() ? 0 : 1; const size_t vtxID02 = vtxID01 + deltaX; const vfloat4 vtx02 = vfloat4::loadu(mesh->vertexPtr(vtxID02)); const size_t vtxID12 = vtxID11 + deltaX; const vfloat4 vtx12 = vfloat4::loadu(mesh->vertexPtr(vtxID12)); /* deltaY => vtx20, vtx21 */ const size_t deltaY = invalid3x3Y() ? 0 : g.lineVtxOffset; const size_t vtxID20 = vtxID10 + deltaY; const size_t vtxID21 = vtxID11 + deltaY; const vfloat4 vtx20 = vfloat4::loadu(mesh->vertexPtr(vtxID20)); const vfloat4 vtx21 = vfloat4::loadu(mesh->vertexPtr(vtxID21)); /* deltaX/deltaY => vtx22 */ const size_t vtxID22 = vtxID11 + deltaX + deltaY; const vfloat4 vtx22 = vfloat4::loadu(mesh->vertexPtr(vtxID22)); transpose(vtx00,vtx01,vtx11,vtx10,p0.x,p0.y,p0.z); transpose(vtx01,vtx02,vtx12,vtx11,p1.x,p1.y,p1.z); transpose(vtx11,vtx12,vtx22,vtx21,p2.x,p2.y,p2.z); transpose(vtx10,vtx11,vtx21,vtx20,p3.x,p3.y,p3.z); } template __forceinline vfloat4 getVertexMB(const GridMesh* const mesh, const size_t offset, const size_t itime, const float ftime) const { const T v0 = T::loadu(mesh->vertexPtr(offset,itime+0)); const T v1 = T::loadu(mesh->vertexPtr(offset,itime+1)); return lerp(v0,v1,ftime); } /* Gather the quads */ __forceinline void gatherMB(Vec3vf4& p0, Vec3vf4& p1, Vec3vf4& p2, Vec3vf4& p3, const GridMesh* const mesh, const GridMesh::Grid &g, const size_t itime, const float ftime) const { /* first quad always valid */ const size_t vtxID00 = g.startVtxID + x() + y() * g.lineVtxOffset; const size_t vtxID01 = vtxID00 + 1; const vfloat4 vtx00 = getVertexMB(mesh,vtxID00,itime,ftime); const vfloat4 vtx01 = getVertexMB(mesh,vtxID01,itime,ftime); const size_t vtxID10 = vtxID00 + g.lineVtxOffset; const size_t vtxID11 = vtxID01 + g.lineVtxOffset; const vfloat4 vtx10 = getVertexMB(mesh,vtxID10,itime,ftime); const vfloat4 vtx11 = getVertexMB(mesh,vtxID11,itime,ftime); /* deltaX => vtx02, vtx12 */ const size_t deltaX = invalid3x3X() ? 0 : 1; const size_t vtxID02 = vtxID01 + deltaX; const vfloat4 vtx02 = getVertexMB(mesh,vtxID02,itime,ftime); const size_t vtxID12 = vtxID11 + deltaX; const vfloat4 vtx12 = getVertexMB(mesh,vtxID12,itime,ftime); /* deltaY => vtx20, vtx21 */ const size_t deltaY = invalid3x3Y() ? 0 : g.lineVtxOffset; const size_t vtxID20 = vtxID10 + deltaY; const size_t vtxID21 = vtxID11 + deltaY; const vfloat4 vtx20 = getVertexMB(mesh,vtxID20,itime,ftime); const vfloat4 vtx21 = getVertexMB(mesh,vtxID21,itime,ftime); /* deltaX/deltaY => vtx22 */ const size_t vtxID22 = vtxID11 + deltaX + deltaY; const vfloat4 vtx22 = getVertexMB(mesh,vtxID22,itime,ftime); transpose(vtx00,vtx01,vtx11,vtx10,p0.x,p0.y,p0.z); transpose(vtx01,vtx02,vtx12,vtx11,p1.x,p1.y,p1.z); transpose(vtx11,vtx12,vtx22,vtx21,p2.x,p2.y,p2.z); transpose(vtx10,vtx11,vtx21,vtx20,p3.x,p3.y,p3.z); } /* Gather the quads */ __forceinline void gather(Vec3vf4& p0, Vec3vf4& p1, Vec3vf4& p2, Vec3vf4& p3, const Scene *const scene) const { const GridMesh* const mesh = scene->get(geomID()); const GridMesh::Grid &g = mesh->grid(primID()); gather(p0,p1,p2,p3,mesh,g); } /* Gather the quads in the motion blur case */ __forceinline void gatherMB(Vec3vf4& p0, Vec3vf4& p1, Vec3vf4& p2, Vec3vf4& p3, const Scene *const scene, const size_t itime, const float ftime) const { const GridMesh* const mesh = scene->get(geomID()); const GridMesh::Grid &g = mesh->grid(primID()); gatherMB(p0,p1,p2,p3,mesh,g,itime,ftime); } /* Gather the quads */ __forceinline void gather(Vec3fa vtx[16], const Scene *const scene) const { const GridMesh* mesh = scene->get(geomID()); const GridMesh::Grid &g = mesh->grid(primID()); /* first quad always valid */ const size_t vtxID00 = g.startVtxID + x() + y() * g.lineVtxOffset; const size_t vtxID01 = vtxID00 + 1; const Vec3fa vtx00 = Vec3fa::loadu(mesh->vertexPtr(vtxID00)); const Vec3fa vtx01 = Vec3fa::loadu(mesh->vertexPtr(vtxID01)); const size_t vtxID10 = vtxID00 + g.lineVtxOffset; const size_t vtxID11 = vtxID01 + g.lineVtxOffset; const Vec3fa vtx10 = Vec3fa::loadu(mesh->vertexPtr(vtxID10)); const Vec3fa vtx11 = Vec3fa::loadu(mesh->vertexPtr(vtxID11)); /* deltaX => vtx02, vtx12 */ const size_t deltaX = invalid3x3X() ? 0 : 1; const size_t vtxID02 = vtxID01 + deltaX; const Vec3fa vtx02 = Vec3fa::loadu(mesh->vertexPtr(vtxID02)); const size_t vtxID12 = vtxID11 + deltaX; const Vec3fa vtx12 = Vec3fa::loadu(mesh->vertexPtr(vtxID12)); /* deltaY => vtx20, vtx21 */ const size_t deltaY = invalid3x3Y() ? 0 : g.lineVtxOffset; const size_t vtxID20 = vtxID10 + deltaY; const size_t vtxID21 = vtxID11 + deltaY; const Vec3fa vtx20 = Vec3fa::loadu(mesh->vertexPtr(vtxID20)); const Vec3fa vtx21 = Vec3fa::loadu(mesh->vertexPtr(vtxID21)); /* deltaX/deltaY => vtx22 */ const size_t vtxID22 = vtxID11 + deltaX + deltaY; const Vec3fa vtx22 = Vec3fa::loadu(mesh->vertexPtr(vtxID22)); vtx[ 0] = vtx00; vtx[ 1] = vtx01; vtx[ 2] = vtx11; vtx[ 3] = vtx10; vtx[ 4] = vtx01; vtx[ 5] = vtx02; vtx[ 6] = vtx12; vtx[ 7] = vtx11; vtx[ 8] = vtx10; vtx[ 9] = vtx11; vtx[10] = vtx21; vtx[11] = vtx20; vtx[12] = vtx11; vtx[13] = vtx12; vtx[14] = vtx22; vtx[15] = vtx21; } /* Gather the quads */ __forceinline void gatherMB(vfloat4 vtx[16], const Scene *const scene, const size_t itime, const float ftime) const { const GridMesh* mesh = scene->get(geomID()); const GridMesh::Grid &g = mesh->grid(primID()); /* first quad always valid */ const size_t vtxID00 = g.startVtxID + x() + y() * g.lineVtxOffset; const size_t vtxID01 = vtxID00 + 1; const vfloat4 vtx00 = getVertexMB(mesh,vtxID00,itime,ftime); const vfloat4 vtx01 = getVertexMB(mesh,vtxID01,itime,ftime); const size_t vtxID10 = vtxID00 + g.lineVtxOffset; const size_t vtxID11 = vtxID01 + g.lineVtxOffset; const vfloat4 vtx10 = getVertexMB(mesh,vtxID10,itime,ftime); const vfloat4 vtx11 = getVertexMB(mesh,vtxID11,itime,ftime); /* deltaX => vtx02, vtx12 */ const size_t deltaX = invalid3x3X() ? 0 : 1; const size_t vtxID02 = vtxID01 + deltaX; const vfloat4 vtx02 = getVertexMB(mesh,vtxID02,itime,ftime); const size_t vtxID12 = vtxID11 + deltaX; const vfloat4 vtx12 = getVertexMB(mesh,vtxID12,itime,ftime); /* deltaY => vtx20, vtx21 */ const size_t deltaY = invalid3x3Y() ? 0 : g.lineVtxOffset; const size_t vtxID20 = vtxID10 + deltaY; const size_t vtxID21 = vtxID11 + deltaY; const vfloat4 vtx20 = getVertexMB(mesh,vtxID20,itime,ftime); const vfloat4 vtx21 = getVertexMB(mesh,vtxID21,itime,ftime); /* deltaX/deltaY => vtx22 */ const size_t vtxID22 = vtxID11 + deltaX + deltaY; const vfloat4 vtx22 = getVertexMB(mesh,vtxID22,itime,ftime); vtx[ 0] = vtx00; vtx[ 1] = vtx01; vtx[ 2] = vtx11; vtx[ 3] = vtx10; vtx[ 4] = vtx01; vtx[ 5] = vtx02; vtx[ 6] = vtx12; vtx[ 7] = vtx11; vtx[ 8] = vtx10; vtx[ 9] = vtx11; vtx[10] = vtx21; vtx[11] = vtx20; vtx[12] = vtx11; vtx[13] = vtx12; vtx[14] = vtx22; vtx[15] = vtx21; } /* Calculate the bounds of the subgrid */ __forceinline const BBox3fa bounds(const Scene *const scene, const size_t itime=0) const { BBox3fa bounds = empty; FATAL("not implemented yet"); return bounds; } /* Calculate the linear bounds of the primitive */ __forceinline LBBox3fa linearBounds(const Scene* const scene, const size_t itime) { return LBBox3fa(bounds(scene,itime+0),bounds(scene,itime+1)); } __forceinline LBBox3fa linearBounds(const Scene *const scene, size_t itime, size_t numTimeSteps) { LBBox3fa allBounds = empty; FATAL("not implemented yet"); return allBounds; } __forceinline LBBox3fa linearBounds(const Scene *const scene, const BBox1f time_range) { LBBox3fa allBounds = empty; FATAL("not implemented yet"); return allBounds; } friend embree_ostream operator<<(embree_ostream cout, const SubGrid& sg) { return cout << "SubGrid " << " ( x = " << sg.x() << ", y = " << sg.y() << ", geomID = " << sg.geomID() << ", primID = " << sg.primID() << ", invalid3x3X() " << (int)sg.invalid3x3X() << ", invalid3x3Y() " << (int)sg.invalid3x3Y(); } __forceinline unsigned int geomID() const { return _geomID; } __forceinline unsigned int primID() const { return _primID; } __forceinline unsigned int x() const { return (unsigned int)_x & 0x7fff; } __forceinline unsigned int y() const { return (unsigned int)_y & 0x7fff; } private: unsigned short _x; unsigned short _y; unsigned int _geomID; // geometry ID of mesh unsigned int _primID; // primitive ID of primitive inside mesh }; struct SubGridID { unsigned short x; unsigned short y; unsigned int primID; __forceinline SubGridID() {} __forceinline SubGridID(const unsigned int x, const unsigned int y, const unsigned int primID) : x(x), y(y), primID(primID) {} }; /* QuantizedBaseNode as large subgrid leaf */ template struct SubGridQBVHN { /* Virtual interface to query information about the quad type */ struct Type : public PrimitiveType { const char* name() const; size_t sizeActive(const char* This) const; size_t sizeTotal(const char* This) const; size_t getBytes(const char* This) const; }; static Type type; public: __forceinline size_t size() const { for (size_t i=0;i::AABBNode node; node.clear(); for (size_t i=0;i::QuantizedBaseNode qnode; unsigned int _geomID; // geometry ID of mesh friend embree_ostream operator<<(embree_ostream cout, const SubGridQBVHN& sg) { cout << "SubGridQBVHN " << embree_endl; for (size_t i=0;i typename SubGridQBVHN::Type SubGridQBVHN::type; typedef SubGridQBVHN<4> SubGridQBVH4; typedef SubGridQBVHN<8> SubGridQBVH8; /* QuantizedBaseNode as large subgrid leaf */ template struct SubGridMBQBVHN { /* Virtual interface to query information about the quad type */ struct Type : public PrimitiveType { const char* name() const; size_t sizeActive(const char* This) const; size_t sizeTotal(const char* This) const; size_t getBytes(const char* This) const; }; static Type type; public: __forceinline size_t size() const { for (size_t i=0;i::AABBNode node0,node1; node0.clear(); node1.clear(); for (size_t i=0;i __forceinline vfloat adjustTime(const vfloat &t) const { return time_scale * (t-time_offset); } public: SubGridID subgridIDs[N]; typename BVHN::QuantizedBaseNodeMB qnode; float time_offset; float time_scale; unsigned int _geomID; // geometry ID of mesh friend embree_ostream operator<<(embree_ostream cout, const SubGridMBQBVHN& sg) { cout << "SubGridMBQBVHN " << embree_endl; for (size_t i=0;i