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 */
max_sizeSubGrid31         static __forceinline size_t max_size() { return 1; }
32 
33         /* Returns required number of primitive blocks for N primitives */
blocksSubGrid34         static __forceinline size_t blocks(size_t N) { return (N+max_size()-1)/max_size(); }
35 
36       public:
37 
38         /* Default constructor */
SubGridSubGrid39         __forceinline SubGrid() {  }
40 
41         /* Construction from vertices and IDs */
SubGridSubGrid42         __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 
invalid3x3XSubGrid50         __forceinline bool invalid3x3X() const { return (unsigned int)_x & (1<<15); }
invalid3x3YSubGrid51         __forceinline bool invalid3x3Y() const { return (unsigned int)_y & (1<<15); }
52 
53         /* Gather the quads */
gatherSubGrid54         __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(mesh->vertexPtr(vtxID00));
65           const vfloat4 vtx01  = vfloat4::loadu(mesh->vertexPtr(vtxID01));
66           const size_t vtxID10 = vtxID00 + g.lineVtxOffset;
67           const size_t vtxID11 = vtxID01 + g.lineVtxOffset;
68           const vfloat4 vtx10  = vfloat4::loadu(mesh->vertexPtr(vtxID10));
69           const vfloat4 vtx11  = vfloat4::loadu(mesh->vertexPtr(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(mesh->vertexPtr(vtxID02));
75           const size_t vtxID12 = vtxID11 + deltaX;
76           const vfloat4 vtx12  = vfloat4::loadu(mesh->vertexPtr(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(mesh->vertexPtr(vtxID20));
83           const vfloat4 vtx21  = vfloat4::loadu(mesh->vertexPtr(vtxID21));
84 
85           /* deltaX/deltaY => vtx22 */
86           const size_t vtxID22 = vtxID11 + deltaX + deltaY;
87           const vfloat4 vtx22  = vfloat4::loadu(mesh->vertexPtr(vtxID22));
88 
89           transpose(vtx00,vtx01,vtx11,vtx10,p0.x,p0.y,p0.z);
90           transpose(vtx01,vtx02,vtx12,vtx11,p1.x,p1.y,p1.z);
91           transpose(vtx11,vtx12,vtx22,vtx21,p2.x,p2.y,p2.z);
92           transpose(vtx10,vtx11,vtx21,vtx20,p3.x,p3.y,p3.z);
93         }
94 
95         template<typename T>
getVertexMBSubGrid96         __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(offset,itime+0));
99           const T v1 = T::loadu(mesh->vertexPtr(offset,itime+1));
100           return lerp(v0,v1,ftime);
101         }
102 
103         /* Gather the quads */
gatherMBSubGrid104         __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,vtxID00,itime,ftime);
117           const vfloat4 vtx01  = getVertexMB<vfloat4>(mesh,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,vtxID10,itime,ftime);
121           const vfloat4 vtx11  = getVertexMB<vfloat4>(mesh,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,vtxID02,itime,ftime);
127           const size_t vtxID12 = vtxID11 + deltaX;
128           const vfloat4 vtx12  = getVertexMB<vfloat4>(mesh,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,vtxID20,itime,ftime);
135           const vfloat4 vtx21  = getVertexMB<vfloat4>(mesh,vtxID21,itime,ftime);
136 
137           /* deltaX/deltaY => vtx22 */
138           const size_t vtxID22 = vtxID11 + deltaX + deltaY;
139           const vfloat4 vtx22  = getVertexMB<vfloat4>(mesh,vtxID22,itime,ftime);
140 
141           transpose(vtx00,vtx01,vtx11,vtx10,p0.x,p0.y,p0.z);
142           transpose(vtx01,vtx02,vtx12,vtx11,p1.x,p1.y,p1.z);
143           transpose(vtx11,vtx12,vtx22,vtx21,p2.x,p2.y,p2.z);
144           transpose(vtx10,vtx11,vtx21,vtx20,p3.x,p3.y,p3.z);
145         }
146 
147 
148 
149         /* Gather the quads */
gatherSubGrid150         __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>(geomID());
157           const GridMesh::Grid &g    = mesh->grid(primID());
158           gather(p0,p1,p2,p3,mesh,g);
159         }
160 
161         /* Gather the quads in the motion blur case */
gatherMBSubGrid162         __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>(geomID());
171           const GridMesh::Grid &g    = mesh->grid(primID());
172           gatherMB(p0,p1,p2,p3,mesh,g,itime,ftime);
173         }
174 
175         /* Gather the quads */
gatherSubGrid176         __forceinline void gather(Vec3fa vtx[16], const Scene *const scene) const
177         {
178           const GridMesh* mesh     = scene->get<GridMesh>(geomID());
179           const GridMesh::Grid &g  = mesh->grid(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(mesh->vertexPtr(vtxID00));
185           const Vec3fa vtx01  = Vec3fa::loadu(mesh->vertexPtr(vtxID01));
186           const size_t vtxID10 = vtxID00 + g.lineVtxOffset;
187           const size_t vtxID11 = vtxID01 + g.lineVtxOffset;
188           const Vec3fa vtx10  = Vec3fa::loadu(mesh->vertexPtr(vtxID10));
189           const Vec3fa vtx11  = Vec3fa::loadu(mesh->vertexPtr(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(mesh->vertexPtr(vtxID02));
195           const size_t vtxID12 = vtxID11 + deltaX;
196           const Vec3fa vtx12  = Vec3fa::loadu(mesh->vertexPtr(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(mesh->vertexPtr(vtxID20));
203           const Vec3fa vtx21  = Vec3fa::loadu(mesh->vertexPtr(vtxID21));
204 
205           /* deltaX/deltaY => vtx22 */
206           const size_t vtxID22 = vtxID11 + deltaX + deltaY;
207           const Vec3fa vtx22  = Vec3fa::loadu(mesh->vertexPtr(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 */
gatherMBSubGrid216         __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>(geomID());
219           const GridMesh::Grid &g  = mesh->grid(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,vtxID00,itime,ftime);
225           const vfloat4 vtx01  = getVertexMB<vfloat4>(mesh,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,vtxID10,itime,ftime);
229           const vfloat4 vtx11  = getVertexMB<vfloat4>(mesh,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,vtxID02,itime,ftime);
235           const size_t vtxID12 = vtxID11 + deltaX;
236           const vfloat4 vtx12  = getVertexMB<vfloat4>(mesh,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,vtxID20,itime,ftime);
243           const vfloat4 vtx21  = getVertexMB<vfloat4>(mesh,vtxID21,itime,ftime);
244 
245           /* deltaX/deltaY => vtx22 */
246           const size_t vtxID22 = vtxID11 + deltaX + deltaY;
247           const vfloat4 vtx22  = getVertexMB<vfloat4>(mesh,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 */
linearBoundsSubGrid265         __forceinline LBBox3fa linearBounds(const Scene* const scene, const size_t itime)
266         {
267           return LBBox3fa(bounds(scene,itime+0),bounds(scene,itime+1));
268         }
269 
linearBoundsSubGrid270         __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 
linearBoundsSubGrid277         __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 
geomIDSubGrid289         __forceinline unsigned int geomID() const { return _geomID; }
primIDSubGrid290         __forceinline unsigned int primID() const { return _primID; }
xSubGrid291         __forceinline unsigned int x() const { return (unsigned int)_x & 0x7fff; }
ySubGrid292         __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 
SubGridIDSubGridID306         __forceinline SubGridID() {}
SubGridIDSubGridID307         __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 
sizeSubGridQBVHN327         __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 
clearSubGridQBVHN334       __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 */
SubGridQBVHNSubGridQBVHN341         __forceinline SubGridQBVHN() {  }
342 
343         /* Construction from vertices and IDs */
SubGridQBVHNSubGridQBVHN344         __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 
geomIDSubGridQBVHN364         __forceinline unsigned int geomID() const { return _geomID; }
primIDSubGridQBVHN365         __forceinline unsigned int primID(const size_t i) const { assert(i < N); return subgridIDs[i].primID; }
xSubGridQBVHN366         __forceinline unsigned int x(const size_t i) const { assert(i < N); return subgridIDs[i].x; }
ySubGridQBVHN367         __forceinline unsigned int y(const size_t i) const { assert(i < N); return subgridIDs[i].y; }
368 
subgridSubGridQBVHN369         __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 
sizeSubGridMBQBVHN422         __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 
clearSubGridMBQBVHN429       __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 */
SubGridMBQBVHNSubGridMBQBVHN436         __forceinline SubGridMBQBVHN() {  }
437 
438         /* Construction from vertices and IDs */
SubGridMBQBVHNSubGridMBQBVHN439         __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 
geomIDSubGridMBQBVHN467         __forceinline unsigned int geomID() const { return _geomID; }
primIDSubGridMBQBVHN468         __forceinline unsigned int primID(const size_t i) const { assert(i < N); return subgridIDs[i].primID; }
xSubGridMBQBVHN469         __forceinline unsigned int x(const size_t i) const { assert(i < N); return subgridIDs[i].x; }
ySubGridMBQBVHN470         __forceinline unsigned int y(const size_t i) const { assert(i < N); return subgridIDs[i].y; }
471 
subgridSubGridMBQBVHN472         __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 
adjustTimeSubGridMBQBVHN478         __forceinline float adjustTime(const float t) const { return time_scale * (t-time_offset); }
479 
480         template<int K>
adjustTimeSubGridMBQBVHN481         __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