| 1 | // Copyright 2009-2021 Intel Corporation | 
| 2 | // SPDX-License-Identifier: Apache-2.0 | 
| 3 |  | 
| 4 | #pragma once | 
| 5 |  | 
| 6 | #include "../common/ray.h" | 
| 7 | #include "../common/scene_grid_mesh.h" | 
| 8 | #include "../bvh/bvh.h" | 
| 9 |  | 
| 10 | namespace embree | 
| 11 | { | 
| 12 |     /* Stores M quads from an indexed face set */ | 
| 13 |       struct SubGrid | 
| 14 |       { | 
| 15 |         /* Virtual interface to query information about the quad type */ | 
| 16 |         struct Type : public PrimitiveType | 
| 17 |         { | 
| 18 |           const char* name() const; | 
| 19 |           size_t sizeActive(const char* This) const; | 
| 20 |           size_t sizeTotal(const char* This) const; | 
| 21 |           size_t getBytes(const char* This) const; | 
| 22 |         }; | 
| 23 |         static Type type; | 
| 24 |  | 
| 25 |       public: | 
| 26 |  | 
| 27 |         /* primitive supports multiple time segments */ | 
| 28 |         static const bool singleTimeSegment = false; | 
| 29 |  | 
| 30 |         /* Returns maximum number of stored quads */ | 
| 31 |         static __forceinline size_t max_size() { return 1; } | 
| 32 |  | 
| 33 |         /* Returns required number of primitive blocks for N primitives */ | 
| 34 |         static __forceinline size_t blocks(size_t N) { return (N+max_size()-1)/max_size(); } | 
| 35 |  | 
| 36 |       public: | 
| 37 |  | 
| 38 |         /* Default constructor */ | 
| 39 |         __forceinline SubGrid() {  } | 
| 40 |  | 
| 41 |         /* Construction from vertices and IDs */ | 
| 42 |         __forceinline SubGrid(const unsigned int x, | 
| 43 |                               const unsigned int y, | 
| 44 |                               const unsigned int geomID, | 
| 45 |                               const unsigned int primID) | 
| 46 |           : _x(x), _y(y), _geomID(geomID), _primID(primID) | 
| 47 |         { | 
| 48 |         } | 
| 49 |  | 
| 50 |         __forceinline bool invalid3x3X() const { return (unsigned int)_x & (1<<15); } | 
| 51 |         __forceinline bool invalid3x3Y() const { return (unsigned int)_y & (1<<15); } | 
| 52 |  | 
| 53 |         /* Gather the quads */ | 
| 54 |         __forceinline void gather(Vec3vf4& p0, | 
| 55 |                                   Vec3vf4& p1, | 
| 56 |                                   Vec3vf4& p2, | 
| 57 |                                   Vec3vf4& p3, | 
| 58 |                                   const GridMesh* const mesh, | 
| 59 |                                   const GridMesh::Grid &g) const | 
| 60 |         { | 
| 61 |           /* first quad always valid */ | 
| 62 |           const size_t vtxID00 = g.startVtxID + x() + y() * g.lineVtxOffset; | 
| 63 |           const size_t vtxID01 = vtxID00 + 1; | 
| 64 |           const vfloat4 vtx00  = vfloat4::loadu(a: mesh->vertexPtr(i: vtxID00)); | 
| 65 |           const vfloat4 vtx01  = vfloat4::loadu(a: mesh->vertexPtr(i: vtxID01)); | 
| 66 |           const size_t vtxID10 = vtxID00 + g.lineVtxOffset; | 
| 67 |           const size_t vtxID11 = vtxID01 + g.lineVtxOffset; | 
| 68 |           const vfloat4 vtx10  = vfloat4::loadu(a: mesh->vertexPtr(i: vtxID10)); | 
| 69 |           const vfloat4 vtx11  = vfloat4::loadu(a: mesh->vertexPtr(i: vtxID11)); | 
| 70 |  | 
| 71 |           /* deltaX => vtx02, vtx12 */ | 
| 72 |           const size_t deltaX  = invalid3x3X() ? 0 : 1; | 
| 73 |           const size_t vtxID02 = vtxID01 + deltaX;        | 
| 74 |           const vfloat4 vtx02  = vfloat4::loadu(a: mesh->vertexPtr(i: vtxID02)); | 
| 75 |           const size_t vtxID12 = vtxID11 + deltaX;        | 
| 76 |           const vfloat4 vtx12  = vfloat4::loadu(a: mesh->vertexPtr(i: vtxID12)); | 
| 77 |  | 
| 78 |           /* deltaY => vtx20, vtx21 */ | 
| 79 |           const size_t deltaY  = invalid3x3Y() ? 0 : g.lineVtxOffset; | 
| 80 |           const size_t vtxID20 = vtxID10 + deltaY; | 
| 81 |           const size_t vtxID21 = vtxID11 + deltaY; | 
| 82 |           const vfloat4 vtx20  = vfloat4::loadu(a: mesh->vertexPtr(i: vtxID20)); | 
| 83 |           const vfloat4 vtx21  = vfloat4::loadu(a: mesh->vertexPtr(i: vtxID21)); | 
| 84 |  | 
| 85 |           /* deltaX/deltaY => vtx22 */ | 
| 86 |           const size_t vtxID22 = vtxID11 + deltaX + deltaY;        | 
| 87 |           const vfloat4 vtx22  = vfloat4::loadu(a: mesh->vertexPtr(i: vtxID22)); | 
| 88 |  | 
| 89 |           transpose(r0: vtx00,r1: vtx01,r2: vtx11,r3: vtx10,c0&: p0.x,c1&: p0.y,c2&: p0.z); | 
| 90 |           transpose(r0: vtx01,r1: vtx02,r2: vtx12,r3: vtx11,c0&: p1.x,c1&: p1.y,c2&: p1.z); | 
| 91 |           transpose(r0: vtx11,r1: vtx12,r2: vtx22,r3: vtx21,c0&: p2.x,c1&: p2.y,c2&: p2.z); | 
| 92 |           transpose(r0: vtx10,r1: vtx11,r2: vtx21,r3: vtx20,c0&: p3.x,c1&: p3.y,c2&: p3.z);                     | 
| 93 |         } | 
| 94 |  | 
| 95 |         template<typename T> | 
| 96 |         __forceinline vfloat4 getVertexMB(const GridMesh* const mesh, const size_t offset, const size_t itime, const float ftime) const | 
| 97 |         { | 
| 98 |           const T v0 = T::loadu(mesh->vertexPtr(i: offset,itime: itime+0)); | 
| 99 |           const T v1 = T::loadu(mesh->vertexPtr(i: offset,itime: itime+1)); | 
| 100 |           return lerp(v0,v1,ftime); | 
| 101 |         } | 
| 102 |  | 
| 103 |         /* Gather the quads */ | 
| 104 |         __forceinline void gatherMB(Vec3vf4& p0, | 
| 105 |                                     Vec3vf4& p1, | 
| 106 |                                     Vec3vf4& p2, | 
| 107 |                                     Vec3vf4& p3, | 
| 108 |                                     const GridMesh* const mesh, | 
| 109 |                                     const GridMesh::Grid &g, | 
| 110 |                                     const size_t itime,  | 
| 111 |                                     const float ftime) const | 
| 112 |         { | 
| 113 |           /* first quad always valid */ | 
| 114 |           const size_t vtxID00 = g.startVtxID + x() + y() * g.lineVtxOffset; | 
| 115 |           const size_t vtxID01 = vtxID00 + 1; | 
| 116 |           const vfloat4 vtx00  = getVertexMB<vfloat4>(mesh,offset: vtxID00,itime,ftime); | 
| 117 |           const vfloat4 vtx01  = getVertexMB<vfloat4>(mesh,offset: vtxID01,itime,ftime); | 
| 118 |           const size_t vtxID10 = vtxID00 + g.lineVtxOffset; | 
| 119 |           const size_t vtxID11 = vtxID01 + g.lineVtxOffset; | 
| 120 |           const vfloat4 vtx10  = getVertexMB<vfloat4>(mesh,offset: vtxID10,itime,ftime); | 
| 121 |           const vfloat4 vtx11  = getVertexMB<vfloat4>(mesh,offset: vtxID11,itime,ftime); | 
| 122 |  | 
| 123 |           /* deltaX => vtx02, vtx12 */ | 
| 124 |           const size_t deltaX  = invalid3x3X() ? 0 : 1; | 
| 125 |           const size_t vtxID02 = vtxID01 + deltaX;        | 
| 126 |           const vfloat4 vtx02  = getVertexMB<vfloat4>(mesh,offset: vtxID02,itime,ftime); | 
| 127 |           const size_t vtxID12 = vtxID11 + deltaX;        | 
| 128 |           const vfloat4 vtx12  = getVertexMB<vfloat4>(mesh,offset: vtxID12,itime,ftime); | 
| 129 |  | 
| 130 |           /* deltaY => vtx20, vtx21 */ | 
| 131 |           const size_t deltaY  = invalid3x3Y() ? 0 : g.lineVtxOffset; | 
| 132 |           const size_t vtxID20 = vtxID10 + deltaY; | 
| 133 |           const size_t vtxID21 = vtxID11 + deltaY; | 
| 134 |           const vfloat4 vtx20  = getVertexMB<vfloat4>(mesh,offset: vtxID20,itime,ftime); | 
| 135 |           const vfloat4 vtx21  = getVertexMB<vfloat4>(mesh,offset: vtxID21,itime,ftime); | 
| 136 |  | 
| 137 |           /* deltaX/deltaY => vtx22 */ | 
| 138 |           const size_t vtxID22 = vtxID11 + deltaX + deltaY;        | 
| 139 |           const vfloat4 vtx22  = getVertexMB<vfloat4>(mesh,offset: vtxID22,itime,ftime); | 
| 140 |  | 
| 141 |           transpose(r0: vtx00,r1: vtx01,r2: vtx11,r3: vtx10,c0&: p0.x,c1&: p0.y,c2&: p0.z); | 
| 142 |           transpose(r0: vtx01,r1: vtx02,r2: vtx12,r3: vtx11,c0&: p1.x,c1&: p1.y,c2&: p1.z); | 
| 143 |           transpose(r0: vtx11,r1: vtx12,r2: vtx22,r3: vtx21,c0&: p2.x,c1&: p2.y,c2&: p2.z); | 
| 144 |           transpose(r0: vtx10,r1: vtx11,r2: vtx21,r3: vtx20,c0&: p3.x,c1&: p3.y,c2&: p3.z);                     | 
| 145 |         } | 
| 146 |  | 
| 147 |  | 
| 148 |  | 
| 149 |         /* Gather the quads */ | 
| 150 |         __forceinline void gather(Vec3vf4& p0, | 
| 151 |                                   Vec3vf4& p1, | 
| 152 |                                   Vec3vf4& p2, | 
| 153 |                                   Vec3vf4& p3, | 
| 154 |                                   const Scene *const scene) const | 
| 155 |         { | 
| 156 |           const GridMesh* const mesh = scene->get<GridMesh>(i: geomID()); | 
| 157 |           const GridMesh::Grid &g    = mesh->grid(i: primID()); | 
| 158 |           gather(p0,p1,p2,p3,mesh,g); | 
| 159 |         } | 
| 160 |  | 
| 161 |         /* Gather the quads in the motion blur case */ | 
| 162 |         __forceinline void gatherMB(Vec3vf4& p0, | 
| 163 |                                     Vec3vf4& p1, | 
| 164 |                                     Vec3vf4& p2, | 
| 165 |                                     Vec3vf4& p3, | 
| 166 |                                     const Scene *const scene, | 
| 167 |                                     const size_t itime,  | 
| 168 |                                     const float ftime) const | 
| 169 |         { | 
| 170 |           const GridMesh* const mesh = scene->get<GridMesh>(i: geomID()); | 
| 171 |           const GridMesh::Grid &g    = mesh->grid(i: primID()); | 
| 172 |           gatherMB(p0,p1,p2,p3,mesh,g,itime,ftime); | 
| 173 |         } | 
| 174 |  | 
| 175 |         /* Gather the quads */ | 
| 176 |         __forceinline void gather(Vec3fa vtx[16], const Scene *const scene) const | 
| 177 |         { | 
| 178 |           const GridMesh* mesh     = scene->get<GridMesh>(i: geomID()); | 
| 179 |           const GridMesh::Grid &g  = mesh->grid(i: primID()); | 
| 180 |  | 
| 181 |           /* first quad always valid */ | 
| 182 |           const size_t vtxID00 = g.startVtxID + x() + y() * g.lineVtxOffset; | 
| 183 |           const size_t vtxID01 = vtxID00 + 1; | 
| 184 |           const Vec3fa vtx00  = Vec3fa::loadu(a: mesh->vertexPtr(i: vtxID00)); | 
| 185 |           const Vec3fa vtx01  = Vec3fa::loadu(a: mesh->vertexPtr(i: vtxID01)); | 
| 186 |           const size_t vtxID10 = vtxID00 + g.lineVtxOffset; | 
| 187 |           const size_t vtxID11 = vtxID01 + g.lineVtxOffset; | 
| 188 |           const Vec3fa vtx10  = Vec3fa::loadu(a: mesh->vertexPtr(i: vtxID10)); | 
| 189 |           const Vec3fa vtx11  = Vec3fa::loadu(a: mesh->vertexPtr(i: vtxID11)); | 
| 190 |  | 
| 191 |           /* deltaX => vtx02, vtx12 */ | 
| 192 |           const size_t deltaX  = invalid3x3X() ? 0 : 1; | 
| 193 |           const size_t vtxID02 = vtxID01 + deltaX;        | 
| 194 |           const Vec3fa vtx02  = Vec3fa::loadu(a: mesh->vertexPtr(i: vtxID02)); | 
| 195 |           const size_t vtxID12 = vtxID11 + deltaX;        | 
| 196 |           const Vec3fa vtx12  = Vec3fa::loadu(a: mesh->vertexPtr(i: vtxID12)); | 
| 197 |  | 
| 198 |           /* deltaY => vtx20, vtx21 */ | 
| 199 |           const size_t deltaY  = invalid3x3Y() ? 0 : g.lineVtxOffset; | 
| 200 |           const size_t vtxID20 = vtxID10 + deltaY; | 
| 201 |           const size_t vtxID21 = vtxID11 + deltaY; | 
| 202 |           const Vec3fa vtx20  = Vec3fa::loadu(a: mesh->vertexPtr(i: vtxID20)); | 
| 203 |           const Vec3fa vtx21  = Vec3fa::loadu(a: mesh->vertexPtr(i: vtxID21)); | 
| 204 |  | 
| 205 |           /* deltaX/deltaY => vtx22 */ | 
| 206 |           const size_t vtxID22 = vtxID11 + deltaX + deltaY;        | 
| 207 |           const Vec3fa vtx22  = Vec3fa::loadu(a: mesh->vertexPtr(i: vtxID22)); | 
| 208 |  | 
| 209 |           vtx[ 0] = vtx00; vtx[ 1] = vtx01; vtx[ 2] = vtx11; vtx[ 3] = vtx10; | 
| 210 |           vtx[ 4] = vtx01; vtx[ 5] = vtx02; vtx[ 6] = vtx12; vtx[ 7] = vtx11; | 
| 211 |           vtx[ 8] = vtx10; vtx[ 9] = vtx11; vtx[10] = vtx21; vtx[11] = vtx20; | 
| 212 |           vtx[12] = vtx11; vtx[13] = vtx12; vtx[14] = vtx22; vtx[15] = vtx21; | 
| 213 |         } | 
| 214 |  | 
| 215 |         /* Gather the quads */ | 
| 216 |         __forceinline void gatherMB(vfloat4 vtx[16], const Scene *const scene, const size_t itime, const float ftime) const | 
| 217 |         { | 
| 218 |           const GridMesh* mesh     = scene->get<GridMesh>(i: geomID()); | 
| 219 |           const GridMesh::Grid &g  = mesh->grid(i: primID()); | 
| 220 |  | 
| 221 |           /* first quad always valid */ | 
| 222 |           const size_t vtxID00 = g.startVtxID + x() + y() * g.lineVtxOffset; | 
| 223 |           const size_t vtxID01 = vtxID00 + 1; | 
| 224 |           const vfloat4 vtx00  = getVertexMB<vfloat4>(mesh,offset: vtxID00,itime,ftime); | 
| 225 |           const vfloat4 vtx01  = getVertexMB<vfloat4>(mesh,offset: vtxID01,itime,ftime); | 
| 226 |           const size_t vtxID10 = vtxID00 + g.lineVtxOffset; | 
| 227 |           const size_t vtxID11 = vtxID01 + g.lineVtxOffset; | 
| 228 |           const vfloat4 vtx10  = getVertexMB<vfloat4>(mesh,offset: vtxID10,itime,ftime); | 
| 229 |           const vfloat4 vtx11  = getVertexMB<vfloat4>(mesh,offset: vtxID11,itime,ftime); | 
| 230 |  | 
| 231 |           /* deltaX => vtx02, vtx12 */ | 
| 232 |           const size_t deltaX  = invalid3x3X() ? 0 : 1; | 
| 233 |           const size_t vtxID02 = vtxID01 + deltaX;        | 
| 234 |           const vfloat4 vtx02  = getVertexMB<vfloat4>(mesh,offset: vtxID02,itime,ftime); | 
| 235 |           const size_t vtxID12 = vtxID11 + deltaX;        | 
| 236 |           const vfloat4 vtx12  = getVertexMB<vfloat4>(mesh,offset: vtxID12,itime,ftime); | 
| 237 |  | 
| 238 |           /* deltaY => vtx20, vtx21 */ | 
| 239 |           const size_t deltaY  = invalid3x3Y() ? 0 : g.lineVtxOffset; | 
| 240 |           const size_t vtxID20 = vtxID10 + deltaY; | 
| 241 |           const size_t vtxID21 = vtxID11 + deltaY; | 
| 242 |           const vfloat4 vtx20  = getVertexMB<vfloat4>(mesh,offset: vtxID20,itime,ftime); | 
| 243 |           const vfloat4 vtx21  = getVertexMB<vfloat4>(mesh,offset: vtxID21,itime,ftime); | 
| 244 |  | 
| 245 |           /* deltaX/deltaY => vtx22 */ | 
| 246 |           const size_t vtxID22 = vtxID11 + deltaX + deltaY;        | 
| 247 |           const vfloat4 vtx22  = getVertexMB<vfloat4>(mesh,offset: vtxID22,itime,ftime); | 
| 248 |  | 
| 249 |           vtx[ 0] = vtx00; vtx[ 1] = vtx01; vtx[ 2] = vtx11; vtx[ 3] = vtx10; | 
| 250 |           vtx[ 4] = vtx01; vtx[ 5] = vtx02; vtx[ 6] = vtx12; vtx[ 7] = vtx11; | 
| 251 |           vtx[ 8] = vtx10; vtx[ 9] = vtx11; vtx[10] = vtx21; vtx[11] = vtx20; | 
| 252 |           vtx[12] = vtx11; vtx[13] = vtx12; vtx[14] = vtx22; vtx[15] = vtx21; | 
| 253 |         }         | 
| 254 |            | 
| 255 |  | 
| 256 |         /* Calculate the bounds of the subgrid */ | 
| 257 |         __forceinline const BBox3fa bounds(const Scene *const scene, const size_t itime=0) const | 
| 258 |         { | 
| 259 |           BBox3fa bounds = empty; | 
| 260 |           FATAL("not implemented yet" ); | 
| 261 |           return bounds; | 
| 262 |         } | 
| 263 |  | 
| 264 |         /* Calculate the linear bounds of the primitive */ | 
| 265 |         __forceinline LBBox3fa linearBounds(const Scene* const scene, const size_t itime) | 
| 266 |         { | 
| 267 |           return LBBox3fa(bounds(scene,itime: itime+0),bounds(scene,itime: itime+1)); | 
| 268 |         } | 
| 269 |  | 
| 270 |         __forceinline LBBox3fa linearBounds(const Scene *const scene, size_t itime, size_t numTimeSteps) | 
| 271 |         { | 
| 272 |           LBBox3fa allBounds = empty; | 
| 273 |           FATAL("not implemented yet" ); | 
| 274 |           return allBounds; | 
| 275 |         } | 
| 276 |  | 
| 277 |         __forceinline LBBox3fa linearBounds(const Scene *const scene, const BBox1f time_range) | 
| 278 |         { | 
| 279 |           LBBox3fa allBounds = empty; | 
| 280 |           FATAL("not implemented yet" ); | 
| 281 |           return allBounds; | 
| 282 |         } | 
| 283 |  | 
| 284 |  | 
| 285 |         friend embree_ostream operator<<(embree_ostream cout, const SubGrid& sg) { | 
| 286 |           return cout << "SubGrid "  << " ( x "  << sg.x() << ", y = "  << sg.y() << ", geomID = "  << sg.geomID() << ", primID = "  << sg.primID() << " )" ; | 
| 287 |         } | 
| 288 |  | 
| 289 |         __forceinline unsigned int geomID() const { return _geomID; } | 
| 290 |         __forceinline unsigned int primID() const { return _primID; } | 
| 291 |         __forceinline unsigned int x() const { return (unsigned int)_x & 0x7fff; } | 
| 292 |         __forceinline unsigned int y() const { return (unsigned int)_y & 0x7fff; } | 
| 293 |  | 
| 294 |       private: | 
| 295 |         unsigned short _x; | 
| 296 |         unsigned short _y; | 
| 297 |         unsigned int _geomID;    // geometry ID of mesh | 
| 298 |         unsigned int _primID;    // primitive ID of primitive inside mesh | 
| 299 |       }; | 
| 300 |  | 
| 301 |       struct SubGridID { | 
| 302 |         unsigned short x; | 
| 303 |         unsigned short y; | 
| 304 |         unsigned int primID; | 
| 305 |          | 
| 306 |         __forceinline SubGridID() {} | 
| 307 |         __forceinline SubGridID(const unsigned int x, const unsigned int y, const unsigned int primID) : | 
| 308 |         x(x), y(y), primID(primID) {}         | 
| 309 |       }; | 
| 310 |  | 
| 311 |       /* QuantizedBaseNode as large subgrid leaf */ | 
| 312 |       template<int N> | 
| 313 |       struct SubGridQBVHN | 
| 314 |       { | 
| 315 |         /* Virtual interface to query information about the quad type */ | 
| 316 |         struct Type : public PrimitiveType | 
| 317 |         { | 
| 318 |           const char* name() const; | 
| 319 |           size_t sizeActive(const char* This) const; | 
| 320 |           size_t sizeTotal(const char* This) const; | 
| 321 |           size_t getBytes(const char* This) const; | 
| 322 |         }; | 
| 323 |         static Type type; | 
| 324 |  | 
| 325 |       public: | 
| 326 |  | 
| 327 |         __forceinline size_t size() const | 
| 328 |         { | 
| 329 |           for (size_t i=0;i<N;i++) | 
| 330 |             if (primID(i) == -1) return i; | 
| 331 |           return N; | 
| 332 |         } | 
| 333 |  | 
| 334 |       __forceinline void clear() { | 
| 335 |         for (size_t i=0;i<N;i++) | 
| 336 |           subgridIDs[i] = SubGridID(0,0,(unsigned int)-1); | 
| 337 |         qnode.clear(); | 
| 338 |       } | 
| 339 |  | 
| 340 |         /* Default constructor */ | 
| 341 |         __forceinline SubGridQBVHN() {  } | 
| 342 |  | 
| 343 |         /* Construction from vertices and IDs */ | 
| 344 |         __forceinline SubGridQBVHN(const unsigned int x[N], | 
| 345 |                                    const unsigned int y[N], | 
| 346 |                                    const unsigned int primID[N], | 
| 347 |                                    const BBox3fa * const subGridBounds, | 
| 348 |                                    const unsigned int geomID, | 
| 349 |                                    const unsigned int items) | 
| 350 |         { | 
| 351 |           clear(); | 
| 352 |           _geomID = geomID; | 
| 353 |  | 
| 354 |           __aligned(64) typename BVHN<N>::AABBNode node; | 
| 355 |           node.clear();           | 
| 356 |           for (size_t i=0;i<items;i++) | 
| 357 |           { | 
| 358 |             subgridIDs[i] = SubGridID(x[i],y[i],primID[i]); | 
| 359 |             node.setBounds(i,subGridBounds[i]); | 
| 360 |           } | 
| 361 |           qnode.init_dim(node); | 
| 362 |         } | 
| 363 |  | 
| 364 |         __forceinline unsigned int geomID() const { return _geomID; } | 
| 365 |         __forceinline unsigned int primID(const size_t i) const { assert(i < N); return subgridIDs[i].primID; } | 
| 366 |         __forceinline unsigned int x(const size_t i) const { assert(i < N); return subgridIDs[i].x; } | 
| 367 |         __forceinline unsigned int y(const size_t i) const { assert(i < N); return subgridIDs[i].y; } | 
| 368 |  | 
| 369 |         __forceinline SubGrid subgrid(const size_t i) const { | 
| 370 |           assert(i < N); | 
| 371 |           assert(primID(i) != -1); | 
| 372 |           return SubGrid(x(i),y(i),geomID(),primID(i)); | 
| 373 |         } | 
| 374 |  | 
| 375 |       public: | 
| 376 |         SubGridID subgridIDs[N]; | 
| 377 |  | 
| 378 |         typename BVHN<N>::QuantizedBaseNode qnode; | 
| 379 |  | 
| 380 |         unsigned int _geomID;    // geometry ID of mesh | 
| 381 |  | 
| 382 |  | 
| 383 |         friend embree_ostream operator<<(embree_ostream cout, const SubGridQBVHN& sg) { | 
| 384 |           cout << "SubGridQBVHN "  << embree_endl; | 
| 385 |           for (size_t i=0;i<N;i++) | 
| 386 |             cout << i << " ( x = "  << sg.subgridIDs[i].x << ", y = "  << sg.subgridIDs[i].y << ", primID = "  << sg.subgridIDs[i].primID << " )"  << embree_endl; | 
| 387 |           cout << "geomID "  << sg._geomID << embree_endl; | 
| 388 |           cout << "lowerX "  << sg.qnode.dequantizeLowerX() << embree_endl; | 
| 389 |           cout << "upperX "  << sg.qnode.dequantizeUpperX() << embree_endl; | 
| 390 |           cout << "lowerY "  << sg.qnode.dequantizeLowerY() << embree_endl; | 
| 391 |           cout << "upperY "  << sg.qnode.dequantizeUpperY() << embree_endl; | 
| 392 |           cout << "lowerZ "  << sg.qnode.dequantizeLowerZ() << embree_endl; | 
| 393 |           cout << "upperZ "  << sg.qnode.dequantizeUpperZ() << embree_endl; | 
| 394 |           return cout; | 
| 395 |         } | 
| 396 |  | 
| 397 |       }; | 
| 398 |  | 
| 399 |       template<int N> | 
| 400 |         typename SubGridQBVHN<N>::Type SubGridQBVHN<N>::type; | 
| 401 |  | 
| 402 |       typedef SubGridQBVHN<4> SubGridQBVH4; | 
| 403 |       typedef SubGridQBVHN<8> SubGridQBVH8; | 
| 404 |  | 
| 405 |  | 
| 406 |       /* QuantizedBaseNode as large subgrid leaf */ | 
| 407 |       template<int N> | 
| 408 |       struct SubGridMBQBVHN | 
| 409 |       { | 
| 410 |         /* Virtual interface to query information about the quad type */ | 
| 411 |         struct Type : public PrimitiveType | 
| 412 |         { | 
| 413 |           const char* name() const; | 
| 414 |           size_t sizeActive(const char* This) const; | 
| 415 |           size_t sizeTotal(const char* This) const; | 
| 416 |           size_t getBytes(const char* This) const; | 
| 417 |         }; | 
| 418 |         static Type type; | 
| 419 |  | 
| 420 |       public: | 
| 421 |  | 
| 422 |         __forceinline size_t size() const | 
| 423 |         { | 
| 424 |           for (size_t i=0;i<N;i++) | 
| 425 |             if (primID(i) == -1) return i; | 
| 426 |           return N; | 
| 427 |         } | 
| 428 |  | 
| 429 |       __forceinline void clear() { | 
| 430 |         for (size_t i=0;i<N;i++) | 
| 431 |           subgridIDs[i] = SubGridID(0,0,(unsigned int)-1); | 
| 432 |         qnode.clear(); | 
| 433 |       } | 
| 434 |  | 
| 435 |         /* Default constructor */ | 
| 436 |         __forceinline SubGridMBQBVHN() {  } | 
| 437 |  | 
| 438 |         /* Construction from vertices and IDs */ | 
| 439 |         __forceinline SubGridMBQBVHN(const unsigned int x[N], | 
| 440 |                                      const unsigned int y[N], | 
| 441 |                                      const unsigned int primID[N], | 
| 442 |                                      const BBox3fa * const subGridBounds0, | 
| 443 |                                      const BBox3fa * const subGridBounds1, | 
| 444 |                                      const unsigned int geomID, | 
| 445 |                                      const float toffset, | 
| 446 |                                      const float tscale, | 
| 447 |                                      const unsigned int items) | 
| 448 |         { | 
| 449 |           clear(); | 
| 450 |           _geomID = geomID; | 
| 451 |           time_offset = toffset; | 
| 452 |           time_scale  = tscale; | 
| 453 |  | 
| 454 |           __aligned(64) typename BVHN<N>::AABBNode node0,node1; | 
| 455 |           node0.clear();           | 
| 456 |           node1.clear();           | 
| 457 |           for (size_t i=0;i<items;i++) | 
| 458 |           { | 
| 459 |             subgridIDs[i] = SubGridID(x[i],y[i],primID[i]); | 
| 460 |             node0.setBounds(i,subGridBounds0[i]); | 
| 461 |             node1.setBounds(i,subGridBounds1[i]); | 
| 462 |           } | 
| 463 |           qnode.node0.init_dim(node0); | 
| 464 |           qnode.node1.init_dim(node1); | 
| 465 |         } | 
| 466 |  | 
| 467 |         __forceinline unsigned int geomID() const { return _geomID; } | 
| 468 |         __forceinline unsigned int primID(const size_t i) const { assert(i < N); return subgridIDs[i].primID; } | 
| 469 |         __forceinline unsigned int x(const size_t i) const { assert(i < N); return subgridIDs[i].x; } | 
| 470 |         __forceinline unsigned int y(const size_t i) const { assert(i < N); return subgridIDs[i].y; } | 
| 471 |  | 
| 472 |         __forceinline SubGrid subgrid(const size_t i) const { | 
| 473 |           assert(i < N); | 
| 474 |           assert(primID(i) != -1); | 
| 475 |           return SubGrid(x(i),y(i),geomID(),primID(i)); | 
| 476 |         } | 
| 477 |  | 
| 478 |         __forceinline float adjustTime(const float t) const { return time_scale * (t-time_offset); } | 
| 479 |  | 
| 480 |         template<int K> | 
| 481 |         __forceinline vfloat<K> adjustTime(const vfloat<K> &t) const { return time_scale * (t-time_offset); } | 
| 482 |  | 
| 483 |       public: | 
| 484 |         SubGridID subgridIDs[N]; | 
| 485 |  | 
| 486 |         typename BVHN<N>::QuantizedBaseNodeMB qnode; | 
| 487 |  | 
| 488 |         float time_offset; | 
| 489 |         float time_scale; | 
| 490 |         unsigned int _geomID;    // geometry ID of mesh | 
| 491 |  | 
| 492 |  | 
| 493 |         friend embree_ostream operator<<(embree_ostream cout, const SubGridMBQBVHN& sg) { | 
| 494 |           cout << "SubGridMBQBVHN "  << embree_endl; | 
| 495 |           for (size_t i=0;i<N;i++) | 
| 496 |             cout << i << " ( x = "  << sg.subgridIDs[i].x << ", y = "  << sg.subgridIDs[i].y << ", primID = "  << sg.subgridIDs[i].primID << " )"  << embree_endl; | 
| 497 |           cout << "geomID      "  << sg._geomID << embree_endl; | 
| 498 |           cout << "time_offset "  << sg.time_offset << embree_endl; | 
| 499 |           cout << "time_scale  "  << sg.time_scale << embree_endl;          | 
| 500 |           cout << "lowerX "  << sg.qnode.node0.dequantizeLowerX() << embree_endl; | 
| 501 |           cout << "upperX "  << sg.qnode.node0.dequantizeUpperX() << embree_endl; | 
| 502 |           cout << "lowerY "  << sg.qnode.node0.dequantizeLowerY() << embree_endl; | 
| 503 |           cout << "upperY "  << sg.qnode.node0.dequantizeUpperY() << embree_endl; | 
| 504 |           cout << "lowerZ "  << sg.qnode.node0.dequantizeLowerZ() << embree_endl; | 
| 505 |           cout << "upperZ "  << sg.qnode.node0.dequantizeUpperZ() << embree_endl; | 
| 506 |           cout << "lowerX "  << sg.qnode.node1.dequantizeLowerX() << embree_endl; | 
| 507 |           cout << "upperX "  << sg.qnode.node1.dequantizeUpperX() << embree_endl; | 
| 508 |           cout << "lowerY "  << sg.qnode.node1.dequantizeLowerY() << embree_endl; | 
| 509 |           cout << "upperY "  << sg.qnode.node1.dequantizeUpperY() << embree_endl; | 
| 510 |           cout << "lowerZ "  << sg.qnode.node1.dequantizeLowerZ() << embree_endl; | 
| 511 |           cout << "upperZ "  << sg.qnode.node1.dequantizeUpperZ() << embree_endl; | 
| 512 |           return cout; | 
| 513 |         } | 
| 514 |  | 
| 515 |       }; | 
| 516 |  | 
| 517 | } | 
| 518 |  |