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 
25 /// Sampler cache for PrimVolume and PrimVDB.
26 /// Converts to the requested tuple, possibly truncating or padding with zeros.
28 {
29 public:
32 
33  virtual bool isActive(const UT_Vector3 &pos) = 0;
34  virtual bool isActiveAtIndex(int ix, int iy, int iz) = 0;
35 
36  virtual fpreal getValueF(const UT_Vector3 &pos) = 0;
37  virtual UT_Vector2D getValueV2(const UT_Vector3 &pos) = 0;
38  virtual UT_Vector3D getValueV3(const UT_Vector3 &pos) = 0;
39  virtual UT_Vector4D getValueV4(const UT_Vector3 &pos) = 0;
40  virtual exint getValueI(const UT_Vector3 &pos) = 0;
41 
42  template <typename BASE>
43  BASE getValueByType(const UT_Vector3 &pos)
44  {
45  if constexpr (SYS_IsSame_v<UT_Vector4, BASE>)
46  return getValueV4(pos);
47  if constexpr (SYS_IsSame_v<UT_Vector3, BASE>)
48  return getValueV3(pos);
49  if constexpr (SYS_IsSame_v<UT_Vector2, BASE>)
50  return getValueV2(pos);
51  if constexpr (SYS_IsSame_v<float, BASE>)
52  return getValueF(pos);
53  if constexpr (SYS_IsSame_v<int64, BASE>)
54  return getValueI(pos);
55  }
56 
57  virtual fpreal getValueAtIndexF(int ix, int iy, int iz) = 0;
58  virtual UT_Vector2D getValueAtIndexV2(int ix, int iy, int iz) = 0;
59  virtual UT_Vector3D getValueAtIndexV3(int ix, int iy, int iz) = 0;
60  virtual UT_Vector4D getValueAtIndexV4(int ix, int iy, int iz) = 0;
61  virtual exint getValueAtIndexI(int ix, int iy, int iz) = 0;
62 
63  virtual fpreal getConstantIndexRegionF(UT_BoundingBox &indexbox, bool *isconstant, bool *isactive) = 0;
64  virtual UT_Vector2D getConstantIndexRegionV2(UT_BoundingBox &indexbox, bool *isconstant, bool *isactive) = 0;
65  virtual UT_Vector3D getConstantIndexRegionV3(UT_BoundingBox &indexbox, bool *isconstant, bool *isactive) = 0;
66  virtual UT_Vector4D getConstantIndexRegionV4(UT_BoundingBox &indexbox, bool *isconstant, bool *isactive) = 0;
67  virtual exint getConstantIndexRegionI(UT_BoundingBox &indexbox, bool *isconstant, bool *isactive) = 0;
68 
69  /// Null if the PrimVolume type does not match, or if it's a PrimVDB.
70  virtual UT_VoxelArrayReadHandleF getHandleF() = 0;
71  virtual UT_VoxelArrayReadHandleV2 getHandleV2() = 0;
72  virtual UT_VoxelArrayReadHandleV3 getHandleV3() = 0;
73  virtual UT_VoxelArrayReadHandleV4 getHandleV4() = 0;
74  virtual UT_VoxelArrayReadHandleI getHandleI() = 0;
75 };
76 
78 
80 {
81 public:
83  {
84  bindPrim(0);
85  }
87  {
88  bindPrim(prim);
89  }
90 
92  {
93  bindPrim(src.myPrim);
94  }
96  {
97  }
98 
100  {
101  bindPrim(src.myPrim);
102 
103  return *this;
104  }
105 
106  bool isBound()
107  {
108  return myVol != NULL || myVdb != NULL;
109  }
110 
112  {
113  if (myVol)
114  {
115  return myVol->getStoresIntegers();
116  }
117  else if (myVdb)
118  {
119  UT_VDBType vdbtype = myVdb->getStorageType();
120  return vdbtype == UT_VDB_INT32 ||
121  vdbtype == UT_VDB_INT64 ||
122  vdbtype == UT_VDB_VEC3I;
123  }
124 
125  return false;
126  }
127 
128  void bindPrim(const GEO_Primitive *prim)
129  {
130  mySamplerCache.reset();
131  myPrim = prim;
132  myVol = dynamic_cast<const GEO_PrimVolume *>(prim);
133  myVdb = dynamic_cast<const GEO_PrimVDB *>(prim);
134  myVectorSize = 0;
135  if (myVol)
136  {
137  myVectorSize = myVol->getTupleSize();
138  mySamplerCache = createVolumeCache(myVol);
139 
140  if (!mySamplerCache)
141  myVol = 0;
142  }
143  if (myVdb)
144  {
145  myVectorSize = myVdb->getTupleSize();
146  mySamplerCache = createVDBCache(myVdb);
147 
148  if (!mySamplerCache)
149  myVdb = 0;
150  }
151  }
152 
153  int getVectorSize() const { return myVectorSize; }
154 
155  /// Convert an index in the voxel array into the corresponding worldspace
156  /// location
157  void indexToPos(int x, int y, int z, UT_Vector3 &pos) const
158  {
159  if(myVol)
160  myVol->indexToPos(x,y,z,pos);
161  if(myVdb)
162  myVdb->indexToPos(x,y,z,pos);
163  }
165  {
166  if(myVol)
167  myVol->findexToPos(index, pos);
168  if(myVdb)
169  myVdb->findexToPos(index, pos);
170  }
171  void indexToPos(exint x, exint y, exint z, UT_Vector3D &pos) const
172  {
173  if(myVol)
174  myVol->indexToPos(x,y,z,pos);
175  if(myVdb)
176  myVdb->indexToPos(x,y,z,pos);
177  }
179  {
180  if(myVol)
181  myVol->findexToPos(index,pos);
182  if(myVdb)
183  myVdb->findexToPos(index,pos);
184  }
185 
186  /// Convert a 3d position into the closest index value.
187  void posToIndex(UT_Vector3 pos, int &x, int &y, int &z) const
188  {
189  if(myVol)
190  myVol->posToIndex(pos,x,y,z);
191  if(myVdb)
192  myVdb->posToIndex(pos,x,y,z);
193  }
195  {
196  if(myVol)
197  myVol->posToIndex(pos,index);
198  if(myVdb)
199  myVdb->posToIndex(pos,index);
200  }
201  void posToIndex(UT_Vector3D pos, exint &x, exint &y, exint &z) const
202  {
203  if(myVol)
204  myVol->posToIndex(pos,x,y,z);
205  if(myVdb)
206  myVdb->posToIndex(pos,x,y,z);
207  }
209  {
210  if(myVol)
211  myVol->posToIndex(pos,index);
212  if(myVdb)
213  myVdb->posToIndex(pos,index);
214  }
215 
217  if(myVol)
218  return myVol->getSpaceTransform();
219  if(myVdb)
220  return myVdb->getSpaceTransform();
221  return {};
222  }
223 
225  {
226  if (myVol)
227  return myVol->getIndexSpaceTransform();
228  if (myVdb)
229  return myVdb->getIndexSpaceTransform();
230  return {};
231  }
232 
233  /// Checks whether the given location falls within the volume's active
234  /// region.
235  inline bool isActive(const UT_Vector3 &pos)
236  {
237  if (mySamplerCache)
238  return mySamplerCache->isActive(pos);
239 
240  return false;
241  }
242 
243  /// Checks whether the given index is within the volume's active
244  /// region.
245  inline bool isActiveAtIndex(int ix, int iy, int iz)
246  {
247  if (mySamplerCache)
248  return mySamplerCache->isActiveAtIndex(ix, iy, iz);
249 
250  return false;
251  }
252 
253  inline fpreal getValueF(const UT_Vector3 &pos)
254  {
255  if (mySamplerCache)
256  return mySamplerCache->getValueF(pos);
257 
258  return 0;
259  }
260 
261  inline fpreal getValueAtIndexF(int ix, int iy, int iz)
262  {
263  if (mySamplerCache)
264  return mySamplerCache->getValueAtIndexF(ix, iy, iz);
265 
266  return 0;
267  }
268 
269  /// Conservatively determines if a box [minvec, maxvec] in index space
270  /// is constant or inactive. If there is doubt, it is reported as
271  /// non-constant and active.
272  ///
273  /// isconstant is true only if all voxels in the region have the same value
274  /// isactive is false only if all the voxels in the region are inactive.
275  ///
276  /// if isconstant is true, the returned value will the constant value.
277  fpreal getConstantIndexRegionF(UT_BoundingBox &indexbox, bool *isconstant, bool *isactive);
278  UT_Vector2D getConstantIndexRegionV2(UT_BoundingBox &indexbox, bool *isconstant, bool *isactive);
279  UT_Vector3D getConstantIndexRegionV3(UT_BoundingBox &indexbox, bool *isconstant, bool *isactive);
280  UT_Vector4D getConstantIndexRegionV4(UT_BoundingBox &indexbox, bool *isconstant, bool *isactive);
281  exint getConstantIndexRegionI(UT_BoundingBox &indexbox, bool *isconstant, bool *isactive);
282 
283  inline UT_Vector2D getValueV2(const UT_Vector3 &pos)
284  {
285  if (mySamplerCache)
286  return mySamplerCache->getValueV2(pos);
287 
288  return UT_Vector2D(0, 0);
289  }
290 
291  inline UT_Vector2D getValueAtIndexV2(int ix, int iy, int iz)
292  {
293  if (mySamplerCache)
294  return mySamplerCache->getValueAtIndexV2(ix, iy, iz);
295 
296  return UT_Vector2D(0, 0);
297  }
298 
299  inline UT_Vector3D getValueV3(const UT_Vector3 &pos)
300  {
301  if (mySamplerCache)
302  return mySamplerCache->getValueV3(pos);
303 
304  return UT_Vector3D(0, 0, 0);
305  }
306 
307  inline UT_Vector3D getValueAtIndexV3(int ix, int iy, int iz)
308  {
309  if (mySamplerCache)
310  return mySamplerCache->getValueAtIndexV3(ix, iy, iz);
311 
312  return UT_Vector3D(0, 0, 0);
313  }
314 
315  inline UT_Vector4D getValueV4(const UT_Vector3 &pos)
316  {
317  if (mySamplerCache)
318  return mySamplerCache->getValueV4(pos);
319 
320  return UT_Vector4D(0, 0, 0, 0);
321  }
322 
323  inline UT_Vector4D getValueAtIndexV4(int ix, int iy, int iz)
324  {
325  if (mySamplerCache)
326  return mySamplerCache->getValueAtIndexV4(ix, iy, iz);
327 
328  return UT_Vector4D(0, 0, 0, 0);
329  }
330 
331  inline exint getValueI(const UT_Vector3 &pos)
332  {
333  if (mySamplerCache)
334  return mySamplerCache->getValueI(pos);
335 
336  return 0;
337  }
338 
339  inline exint getValueAtIndexI(int ix, int iy, int iz)
340  {
341  if (mySamplerCache)
342  return mySamplerCache->getValueAtIndexI(ix, iy, iz);
343 
344  return 0;
345  }
346 
347  template <typename BASE>
348  BASE getValueByType(const UT_Vector3 &pos)
349  {
350  if constexpr (SYS_IsSame_v<UT_Vector4, BASE>)
351  return getValueV4(pos);
352  if constexpr (SYS_IsSame_v<UT_Vector3, BASE>)
353  return getValueV3(pos);
354  if constexpr (SYS_IsSame_v<UT_Vector2, BASE>)
355  return getValueV2(pos);
356  if constexpr (SYS_IsSame_v<float, BASE>)
357  return getValueF(pos);
358  if constexpr (SYS_IsSame_v<int64, BASE>)
359  return getValueI(pos);
360  }
361 
362  /// Gets values in the box [bbox.minvec(), bbox.maxvec())
363  /// Values are stored in the array `values` of size `size` that has to be at least `bbox.volume()`
364  /// The order of values is give by: `i + bbox.xsize() * (j + bbox.ysize() * k)`
365  ///
366  /// If returns true, values in `bbox` are constant and only values[0] is guaranteed to be assigned.
367  template <class T>
368  bool getValues(const UT_BoundingBoxI &bbox, T * values, const exint size)
369  {
370  constexpr int tuplesize = UT_FixedVectorTraits<T>::TupleSize;
371  SYS_STATIC_ASSERT(tuplesize >= 1 && tuplesize <= 4);
372  UT_ASSERT_P(bbox.volume() <= size);
373 
374  if (mySamplerCache)
375  {
377  if constexpr (SYS_IsSame_v<T, fpreal32>)
378  vox = mySamplerCache->getHandleF();
379  if constexpr (SYS_IsSame_v<T, UT_Vector2F>)
380  vox = mySamplerCache->getHandleV2();
381  if constexpr (SYS_IsSame_v<T, UT_Vector3F>)
382  vox = mySamplerCache->getHandleV3();
383  if constexpr (SYS_IsSame_v<T, UT_Vector4F>)
384  vox = mySamplerCache->getHandleV4();
385  if constexpr (SYS_IsSame_v<T, exint>)
386  vox = mySamplerCache->getHandleI();
387 
388  // Fast path if we match.
389  if (vox.get())
390  return vox->getValues(bbox, values, size);
391 
392  int idx = 0;
393  bool allconstant = true;
394 
395  for (int k = bbox.zmin(); k < bbox.zmax(); k++)
396  {
397  for (int j = bbox.ymin(); j < bbox.ymax(); j++)
398  {
399  for (int i = bbox.xmin(); i < bbox.xmax(); i++, idx++)
400  {
401  if constexpr (tuplesize == 1)
402  {
403  if constexpr (SYS_IsIntegral_v<T>)
404  values[idx] = mySamplerCache->getValueAtIndexI(i, j, k);
405  else
406  values[idx] = mySamplerCache->getValueAtIndexF(i, j, k);
407  }
408  if constexpr (tuplesize == 2)
409  values[idx] = mySamplerCache->getValueAtIndexV2(i, j, k);
410  if constexpr (tuplesize == 3)
411  values[idx] = mySamplerCache->getValueAtIndexV3(i, j, k);
412  if constexpr (tuplesize == 4)
413  values[idx] = mySamplerCache->getValueAtIndexV4(i, j, k);
414 
415  allconstant &= (values[0] == values[idx]);
416  }
417  }
418  }
419 
420  return allconstant;
421  }
422 
423  return false;
424  }
425 
426  static UT_UniquePtr<GEO_VolumeSamplerCache> createVolumeCache(const GEO_PrimVolume *vol);
427  static UT_UniquePtr<GEO_VolumeSamplerCache> createVDBCache(const GEO_PrimVDB *vdb);
428 
429 protected:
435 };
436 
437 #endif // __GEO_VOLUMESAMPLER_H_INCLUDED__
438 
int getVectorSize() const
exint getValueI(const UT_Vector3 &pos)
void posToIndex(UT_Vector3 pos, int &x, int &y, int &z) const
Convert a 3d position into the closest index value.
GEO_VolumeSampler & operator=(const GEO_VolumeSampler &src)
#define SYS_STATIC_ASSERT(expr)
void indexToPos(exint x, exint y, exint z, UT_Vector3D &pos) const
void posToIndex(UT_Vector3 pos, UT_Vector3 &index) const
BASE getValueByType(const UT_Vector3 &pos)
void findexToPos(UT_Vector3D index, UT_Vector3D &pos) const
UT_Vector2T< fpreal64 > UT_Vector2D
UT_Vector2D getValueAtIndexV2(int ix, int iy, int iz)
void findexToPos(UT_Vector3 index, UT_Vector3 &pos) const
UT_Vector2D getValueV2(const UT_Vector3 &pos)
GLdouble GLdouble GLdouble z
Definition: glcorearb.h:848
int64 exint
Definition: SYS_Types.h:125
void posToIndex(UT_Vector3D pos, UT_Vector3D &index) const
const Data * get() const
Definition: UT_COW.h:225
GLint y
Definition: glcorearb.h:103
UT_VDBType
Definition: UT_VDBUtils.h:25
fpreal getValueAtIndexF(int ix, int iy, int iz)
UT_Vector3D getValueAtIndexV3(int ix, int iy, int iz)
std::unique_ptr< T, Deleter > UT_UniquePtr
A smart pointer for unique ownership of dynamically allocated objects.
Definition: UT_UniquePtr.h:39
bool isActive(const UT_Vector3 &pos)
bool isActiveAtIndex(int ix, int iy, int iz)
GEO_PrimVolumeXform getIndexSpaceTransform() const
GEO_VolumeSampler(const GEO_Primitive *prim)
GEO_VolumeSampler(const GEO_VolumeSampler &src)
UT_Vector4D getValueV4(const UT_Vector3 &pos)
#define UT_ASSERT_P(ZZ)
Definition: UT_Assert.h:164
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:185
UT_Vector3T< fpreal64 > UT_Vector3D
UT_UniquePtr< GEO_VolumeSamplerCache > mySamplerCache
GLint GLenum GLint x
Definition: glcorearb.h:409
void indexToPos(int x, int y, int z, UT_Vector3 &pos) const
BASE getValueByType(const UT_Vector3 &pos)
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:283
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)
UT_Vector4T< fpreal64 > UT_Vector4D
const GEO_PrimVolume * myVol
UT_Vector4D getValueAtIndexV4(int ix, int iy, int iz)
exint getValueAtIndexI(int ix, int iy, int iz)
void posToIndex(UT_Vector3D pos, exint &x, exint &y, exint &z) const
GLenum src
Definition: glcorearb.h:1793