HDK
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
GEO_VolumeSampler.h
Go to the documentation of this file.
1 /*
2  * PROPRIETARY INFORMATION. This software is proprietary to
3  * Side Effects Software Inc., and is not to be reproduced,
4  * transmitted, or disclosed in any way without written permission.
5  *
6  * NAME: GEO_VolumeSampler.h (GEO Library, C++)
7  *
8  * COMMENTS:
9  * This is an adapter class that lets you efficiently
10  * sample both PrimVolumes and PrimVDBs.
11  *
12  * It is *not* threadsafe to use the same volume sampler
13  * from multiple threads!
14  */
15 
16 #ifndef __GEO_VOLUMESAMPLER_H_INCLUDED__
17 #define __GEO_VOLUMESAMPLER_H_INCLUDED__
18 
19 #include <UT/UT_VoxelArray.h>
20 
21 #include "GEO_API.h"
22 #include "GEO_PrimVolume.h"
23 #include "GEO_PrimVDB.h"
24 
26 {
27 public:
30 
31  virtual bool isActive(const UT_Vector3 &pos) = 0;
32  virtual bool isActiveAtIndex(int ix, int iy, int iz) = 0;
33  virtual fpreal getValueF(const UT_Vector3 &pos) = 0;
34  virtual fpreal getValueAtIndexF(int ix, int iy, int iz) = 0;
35  virtual UT_Vector3D getValueV3(const UT_Vector3 &pos) = 0;
36  virtual UT_Vector3D getValueAtIndexV3(int ix, int iy, int iz) = 0;
37  virtual fpreal getConstantIndexRegionF(UT_BoundingBox &indexbox, bool *isconstant, bool *isactive) = 0;
38  virtual UT_Vector3D getConstantIndexRegionV3(UT_BoundingBox &indexbox, bool *isconstant, bool *isactive) = 0;
39 };
40 
42 {
43 public:
45  {
46  myVDBCache = 0;
47  bindPrim(0);
48  }
50  {
51  myVDBCache = 0;
52  bindPrim(prim);
53  }
54 
56  {
57  myVDBCache = 0;
58  bindPrim(src.myPrim);
59  }
61  {
62  delete myVDBCache;
63  }
64 
66  {
67  delete myVDBCache;
68  myVDBCache = 0;
69  bindPrim(src.myPrim);
70 
71  return *this;
72  }
73 
74  bool isBound()
75  {
76  return myVol != NULL || myVdb != NULL;
77  }
78 
79  void bindPrim(const GEO_Primitive *prim)
80  {
81  delete myVDBCache;
82  myVDBCache = 0;
83 
84  myPrim = prim;
85  myVol = dynamic_cast<const GEO_PrimVolume *>(prim);
86  myVdb = dynamic_cast<const GEO_PrimVDB *>(prim);
87  myVectorSize = 0;
88  if (myVol)
89  {
90  myHandle = myVol->getVoxelHandle();
91  myVectorSize = 1;
92  }
93  if (myVdb)
94  {
95  myVectorSize = myVdb->getTupleSize();
96  myVDBCache = createVDBCache(myVdb);
97 
98  if (!myVDBCache)
99  myVdb = 0;
100  }
101  }
102 
103  int getVectorSize() const { return myVectorSize; }
104 
105  /// Convert an index in the voxel array into the corresponding worldspace
106  /// location
107  void indexToPos(int x, int y, int z, UT_Vector3 &pos) const
108  {
109  if(myVol)
110  myVol->indexToPos(x,y,z,pos);
111  if(myVdb)
112  myVdb->indexToPos(x,y,z,pos);
113  }
115  {
116  if(myVol)
117  myVol->findexToPos(index, pos);
118  if(myVdb)
119  myVdb->findexToPos(index, pos);
120  }
121  void indexToPos(exint x, exint y, exint z, UT_Vector3D &pos) const
122  {
123  if(myVol)
124  myVol->indexToPos(x,y,z,pos);
125  if(myVdb)
126  myVdb->indexToPos(x,y,z,pos);
127  }
129  {
130  if(myVol)
131  myVol->findexToPos(index,pos);
132  if(myVdb)
133  myVdb->findexToPos(index,pos);
134  }
135 
136  /// Convert a 3d position into the closest index value.
137  void posToIndex(UT_Vector3 pos, int &x, int &y, int &z) const
138  {
139  if(myVol)
140  myVol->posToIndex(pos,x,y,z);
141  if(myVdb)
142  myVdb->posToIndex(pos,x,y,z);
143  }
145  {
146  if(myVol)
147  myVol->posToIndex(pos,index);
148  if(myVdb)
149  myVdb->posToIndex(pos,index);
150  }
151  void posToIndex(UT_Vector3D pos, exint &x, exint &y, exint &z) const
152  {
153  if(myVol)
154  myVol->posToIndex(pos,x,y,z);
155  if(myVdb)
156  myVdb->posToIndex(pos,x,y,z);
157  }
159  {
160  if(myVol)
161  myVol->posToIndex(pos,index);
162  if(myVdb)
163  myVdb->posToIndex(pos,index);
164  }
165 
167  if(myVol)
168  return myVol->getSpaceTransform();
169  if(myVdb)
170  return myVdb->getSpaceTransform();
171  return {};
172  }
173 
175  {
176  if (myVol)
177  return myVol->getIndexSpaceTransform();
178  if (myVdb)
179  return myVdb->getIndexSpaceTransform();
180  return {};
181  }
182 
183  /// Checks whether the given location falls within the volume's active
184  /// region.
185  inline bool isActive(const UT_Vector3 &pos)
186  {
187  if (myVol)
188  return myVol->isInsideStrict(pos, myHandle);
189  if (myVdb)
190  return myVDBCache->isActive(pos);
191 
192  return false;
193  }
194 
195  /// Checks whether the given index is within the volume's active
196  /// region.
197  inline bool isActiveAtIndex(int ix, int iy, int iz)
198  {
199  if (myVol)
200  return myHandle->isValidIndex(ix, iy, iz);
201  if (myVdb)
202  return myVDBCache->isActiveAtIndex(ix, iy, iz);
203 
204  return false;
205  }
206 
207  inline fpreal getValueF(const UT_Vector3 &pos)
208  {
209  if (myVol)
210  return myVol->getValue(pos, myHandle);
211  if (myVdb)
212  return myVDBCache->getValueF(pos);
213 
214  return 0;
215  }
216 
217  inline fpreal getValueAtIndexF(int ix, int iy, int iz)
218  {
219  if (myVol)
220  return myHandle->getValue(ix, iy, iz);
221  if (myVdb)
222  return myVDBCache->getValueAtIndexF(ix, iy, iz);
223 
224  return 0;
225  }
226 
227  /// Conservatively determines if a box [minvec, maxvec] in index space
228  /// is constant or inactive. If there is doubt, it is reported as
229  /// non-constant and active.
230  ///
231  /// isconstant is true only if all voxels in the region have the same value
232  /// isactive is false only if all the voxels in the region are inactive.
233  ///
234  /// if isconstant is true, the returned value will the constant value.
235  fpreal getConstantIndexRegionF(UT_BoundingBox &indexbox, bool *isconstant, bool *isactive);
236  UT_Vector3D getConstantIndexRegionV3(UT_BoundingBox &indexbox, bool *isconstant, bool *isactive);
237 
238  inline UT_Vector3D getValueV3(const UT_Vector3 &pos)
239  {
240  if (myVol)
241  return UT_Vector3D(myVol->getValue(pos, myHandle), 0, 0);
242  if (myVdb)
243  return myVDBCache->getValueV3(pos);
244 
245  return UT_Vector3D(0, 0, 0);
246  }
247 
248  inline UT_Vector3D getValueAtIndexV3(int ix, int iy, int iz)
249  {
250  if (myVol)
251  return UT_Vector3D(myHandle->getValue(ix, iy, iz), 0, 0);
252  if (myVdb)
253  return myVDBCache->getValueAtIndexV3(ix, iy, iz);
254 
255  return UT_Vector3D(0, 0, 0);
256  }
257 
258  /// Gets values in the box [bbox.minvec(), bbox.maxvec())
259  /// Values are stored in the array `values` of size `size` that has to be at least `bbox.volume()`
260  /// The order of values is give by: `i + bbox.xsize() * (j + bbox.ysize() * k)`
261  ///
262  /// If returns true, values in `bbox` are constant and only values[0] is guaranteed to be assigned.
263  template <class T>
264  bool getValues(const UT_BoundingBoxI &bbox, T * values, const exint size)
265  {
266  UT_ASSERT_P(bbox.volume() <= size);
267 
268  constexpr bool IS_SCALAR = SYS_IsFloatingPoint_v<T>;
269 
270  static_assert(
271  SYS_IsFloatingPoint_v<T> ||
274  "Return value has to be scalar or three dimensional vector!");
275 
276  if (myVol)
277  {
278  if constexpr (IS_SCALAR){
279  return myHandle->getValues(bbox, values, size);
280  }
281  else
282  {
283  static_assert(
284  sizeof(T) >= sizeof(float),
285  "This implementation assumes that sizeof(T) >= "
286  "sizeof(float). Memory leak happens otherwise.");
287  const int n = bbox.volume();
288  // This is a bit of a hack, re-using the space of `values` array.
289  float * data = reinterpret_cast<float*>(values);
290  const bool isconstant = myHandle->getValues(bbox, data, size);
291  // Spreading out values stored under `data`
292  for(int i=n-1; i>=0; i--){
293  values[i] = T{data[i], 0.f, 0.f};
294  }
295  return isconstant;
296  }
297  }
298 
299  if (myVdb)
300  {
301  int id = 0;
302  for (int k = bbox.zmin(); k < bbox.zmax(); k++)
303  {
304  for (int j = bbox.ymin(); j < bbox.ymax(); j++)
305  {
306  for (int i = bbox.xmin(); i < bbox.xmax(); i++)
307  {
308  if constexpr (IS_SCALAR)
309  {
310  values[id++] = myVDBCache->getValueAtIndexF(i,j, k);
311  }
312  else
313  {
314  values[id++] = myVDBCache->getValueAtIndexV3(i,j, k);
315  }
316  }
317  }
318  }
319  }
320  return false;
321  }
322 
323  static GEO_VolumeSamplerVDBCache *createVDBCache(const GEO_PrimVDB *vdb);
324 
325 protected:
332 };
333 
334 #endif // __GEO_VOLUMESAMPLER_H_INCLUDED__
335 
int getVectorSize() const
void posToIndex(UT_Vector3 pos, int &x, int &y, int &z) const
Convert a 3d position into the closest index value.
GEO_VolumeSamplerVDBCache * myVDBCache
GEO_VolumeSampler & operator=(const GEO_VolumeSampler &src)
void indexToPos(exint x, exint y, exint z, UT_Vector3D &pos) const
void posToIndex(UT_Vector3 pos, UT_Vector3 &index) const
void findexToPos(UT_Vector3D index, UT_Vector3D &pos) const
UT_VoxelArrayReadHandleF myHandle
void findexToPos(UT_Vector3 index, UT_Vector3 &pos) const
GLdouble GLdouble GLdouble z
Definition: glcorearb.h:848
int64 exint
Definition: SYS_Types.h:125
void posToIndex(UT_Vector3D pos, UT_Vector3D &index) const
GLint y
Definition: glcorearb.h:103
fpreal getValueAtIndexF(int ix, int iy, int iz)
UT_Vector3D getValueAtIndexV3(int ix, int iy, int iz)
bool isActive(const UT_Vector3 &pos)
bool isActiveAtIndex(int ix, int iy, int iz)
GLdouble n
Definition: glcorearb.h:2008
GEO_PrimVolumeXform getIndexSpaceTransform() const
GEO_VolumeSampler(const GEO_Primitive *prim)
GEO_VolumeSampler(const GEO_VolumeSampler &src)
#define UT_ASSERT_P(ZZ)
Definition: UT_Assert.h:155
const GEO_PrimVDB * myVdb
#define GEO_API
Definition: GEO_API.h:14
SYS_FORCE_INLINE int getTupleSize() const
Get the tuple size, usually 1 or 3.
Definition: GEO_PrimVDB.h:159
UT_Vector3T< fpreal64 > UT_Vector3D
GLint GLenum GLint x
Definition: glcorearb.h:409
void indexToPos(int x, int y, int z, UT_Vector3 &pos) const
GLint j
Definition: glad.h:2733
T volume() const
GLsizeiptr size
Definition: glcorearb.h:664
GLenum GLsizei GLsizei GLint * values
Definition: glcorearb.h:1602
fpreal64 fpreal
Definition: SYS_Types.h:277
GLuint index
Definition: glcorearb.h:786
const GEO_Primitive * myPrim
bool getValues(const UT_BoundingBoxI &bbox, T *values, const exint size)
void bindPrim(const GEO_Primitive *prim)
GEO_PrimVolumeXform getSpaceTransform() const
fpreal getValueF(const UT_Vector3 &pos)
UT_Vector3D getValueV3(const UT_Vector3 &pos)
const GEO_PrimVolume * myVol
Definition: format.h:895
void posToIndex(UT_Vector3D pos, exint &x, exint &y, exint &z) const
GLenum src
Definition: glcorearb.h:1793