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 };
39 
41 {
42 public:
44  {
45  myVDBCache = 0;
46  bindPrim(0);
47  }
49  {
50  myVDBCache = 0;
51  bindPrim(prim);
52  }
53 
55  {
56  myVDBCache = 0;
57  bindPrim(src.myPrim);
58  }
60  {
61  delete myVDBCache;
62  }
63 
65  {
66  delete myVDBCache;
67  myVDBCache = 0;
68  bindPrim(src.myPrim);
69 
70  return *this;
71  }
72 
73  bool isBound()
74  {
75  return myVol != NULL || myVdb != NULL;
76  }
77 
78  void bindPrim(const GEO_Primitive *prim)
79  {
80  delete myVDBCache;
81  myVDBCache = 0;
82 
83  myPrim = prim;
84  myVol = dynamic_cast<const GEO_PrimVolume *>(prim);
85  myVdb = dynamic_cast<const GEO_PrimVDB *>(prim);
86  myVectorSize = 0;
87  if (myVol)
88  {
89  myHandle = myVol->getVoxelHandle();
90  myVectorSize = 1;
91  }
92  if (myVdb)
93  {
94  myVectorSize = myVdb->getTupleSize();
95  myVDBCache = createVDBCache(myVdb);
96 
97  if (!myVDBCache)
98  myVdb = 0;
99  }
100  }
101 
102  int getVectorSize() const { return myVectorSize; }
103 
104  /// Convert an index in the voxel array into the corresponding worldspace
105  /// location
106  void indexToPos(int x, int y, int z, UT_Vector3 &pos) const
107  {
108  if(myVol)
109  myVol->indexToPos(x,y,z,pos);
110  if(myVdb)
111  myVdb->indexToPos(x,y,z,pos);
112  }
114  {
115  if(myVol)
116  myVol->findexToPos(index, pos);
117  if(myVdb)
118  myVdb->findexToPos(index, pos);
119  }
120  void indexToPos(exint x, exint y, exint z, UT_Vector3D &pos) const
121  {
122  if(myVol)
123  myVol->indexToPos(x,y,z,pos);
124  if(myVdb)
125  myVdb->indexToPos(x,y,z,pos);
126  }
128  {
129  if(myVol)
130  myVol->findexToPos(index,pos);
131  if(myVdb)
132  myVdb->findexToPos(index,pos);
133  }
134 
135  /// Convert a 3d position into the closest index value.
136  void posToIndex(UT_Vector3 pos, int &x, int &y, int &z) const
137  {
138  if(myVol)
139  myVol->posToIndex(pos,x,y,z);
140  if(myVdb)
141  myVdb->posToIndex(pos,x,y,z);
142  }
144  {
145  if(myVol)
146  myVol->posToIndex(pos,index);
147  if(myVdb)
148  myVdb->posToIndex(pos,index);
149  }
150  void posToIndex(UT_Vector3D pos, exint &x, exint &y, exint &z) const
151  {
152  if(myVol)
153  myVol->posToIndex(pos,x,y,z);
154  if(myVdb)
155  myVdb->posToIndex(pos,x,y,z);
156  }
158  {
159  if(myVol)
160  myVol->posToIndex(pos,index);
161  if(myVdb)
162  myVdb->posToIndex(pos,index);
163  }
164 
166  if(myVol)
167  return myVol->getSpaceTransform();
168  if(myVdb)
169  return myVdb->getSpaceTransform();
170  return {};
171  }
172 
174  {
175  if (myVol)
176  return myVol->getIndexSpaceTransform();
177  if (myVdb)
178  return myVdb->getIndexSpaceTransform();
179  return {};
180  }
181 
182  /// Checks whether the given location falls within the volume's active
183  /// region.
184  inline bool isActive(const UT_Vector3 &pos)
185  {
186  if (myVol)
187  return myVol->isInsideStrict(pos, myHandle);
188  if (myVdb)
189  return myVDBCache->isActive(pos);
190 
191  return false;
192  }
193 
194  /// Checks whether the given index is within the volume's active
195  /// region.
196  inline bool isActiveAtIndex(int ix, int iy, int iz)
197  {
198  if (myVol)
199  return myHandle->isValidIndex(ix, iy, iz);
200  if (myVdb)
201  return myVDBCache->isActiveAtIndex(ix, iy, iz);
202 
203  return false;
204  }
205 
206  inline fpreal getValueF(const UT_Vector3 &pos)
207  {
208  if (myVol)
209  return myVol->getValue(pos, myHandle);
210  if (myVdb)
211  return myVDBCache->getValueF(pos);
212 
213  return 0;
214  }
215 
216  inline fpreal getValueAtIndexF(int ix, int iy, int iz)
217  {
218  if (myVol)
219  return myHandle->getValue(ix, iy, iz);
220  if (myVdb)
221  return myVDBCache->getValueAtIndexF(ix, iy, iz);
222 
223  return 0;
224  }
225 
226  /// Conservatively determines if a box [minvec, maxvec] in index space
227  /// is constant or inactive. If there is doubt, it is reported as
228  /// non-constant and active.
229  ///
230  /// isconstant is true only if all voxels in the region have the same value
231  /// isactive is false only if all the voxels in the region are inactive.
232  ///
233  /// if isconstant is true, the returned value will the constant value.
234  fpreal getConstantIndexRegionF(UT_BoundingBox &indexbox, bool *isconstant, bool *isactive);
235 
236  inline UT_Vector3D getValueV3(const UT_Vector3 &pos)
237  {
238  if (myVol)
239  return UT_Vector3D(myVol->getValue(pos, myHandle), 0, 0);
240  if (myVdb)
241  return myVDBCache->getValueV3(pos);
242 
243  return UT_Vector3D(0, 0, 0);
244  }
245 
246  inline UT_Vector3D getValueAtIndexV3(int ix, int iy, int iz)
247  {
248  if (myVol)
249  return UT_Vector3D(myHandle->getValue(ix, iy, iz), 0, 0);
250  if (myVdb)
251  return myVDBCache->getValueAtIndexV3(ix, iy, iz);
252 
253  return UT_Vector3D(0, 0, 0);
254  }
255 
256  /// Gets values in the box [bbox.minvec(), bbox.maxvec())
257  /// Values are stored in the array `values` of size `size` that has to be at least `bbox.volume()`
258  /// The order of values is give by: `i + bbox.xsize() * (j + bbox.ysize() * k)`
259  ///
260  /// If returns true, values in `bbox` are constant and only values[0] is guaranteed to be assigned.
261  template <class T>
262  bool getValues(const UT_BoundingBoxI &bbox, T * values, const exint size)
263  {
264  UT_ASSERT_P(bbox.volume() <= size);
265 
266  constexpr bool IS_SCALAR = SYS_IsFloatingPoint_v<T>;
267 
268  static_assert(
269  SYS_IsFloatingPoint_v<T> ||
272  "Return value has to be scalar or three dimensional vector!");
273 
274  if (myVol)
275  {
276  if constexpr (IS_SCALAR){
277  return myHandle->getValues(bbox, values, size);
278  }
279  else
280  {
281  static_assert(
282  sizeof(T) >= sizeof(float),
283  "This implementation assumes that sizeof(T) >= "
284  "sizeof(float). Memory leak happens otherwise.");
285  const int n = bbox.volume();
286  // This is a bit of a hack, re-using the space of `values` array.
287  float * data = reinterpret_cast<float*>(values);
288  const bool isconstant = myHandle->getValues(bbox, data, size);
289  // Spreading out values stored under `data`
290  for(int i=n-1; i>=0; i--){
291  values[i] = T{data[i], 0.f, 0.f};
292  }
293  return isconstant;
294  }
295  }
296 
297  if (myVdb)
298  {
299  int id = 0;
300  for (int k = bbox.zmin(); k < bbox.zmax(); k++)
301  {
302  for (int j = bbox.ymin(); j < bbox.ymax(); j++)
303  {
304  for (int i = bbox.xmin(); i < bbox.xmax(); i++)
305  {
306  if constexpr (IS_SCALAR)
307  {
308  values[id++] = myVDBCache->getValueAtIndexF(i,j, k);
309  }
310  else
311  {
312  values[id++] = myVDBCache->getValueAtIndexV3(i,j, k);
313  }
314  }
315  }
316  }
317  }
318  return false;
319  }
320 
321  static GEO_VolumeSamplerVDBCache *createVDBCache(const GEO_PrimVDB *vdb);
322 
323 protected:
330 };
331 
332 #endif // __GEO_VOLUMESAMPLER_H_INCLUDED__
333 
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
int64 exint
Definition: SYS_Types.h:125
void posToIndex(UT_Vector3D pos, UT_Vector3D &index) const
GLenum src
Definition: glcorearb.h:1793
fpreal getValueAtIndexF(int ix, int iy, int iz)
UT_Vector3D getValueAtIndexV3(int ix, int iy, int iz)
GLenum GLsizei GLsizei GLint * values
Definition: glcorearb.h:1602
GLint GLenum GLint x
Definition: glcorearb.h:409
bool isActive(const UT_Vector3 &pos)
bool isActiveAtIndex(int ix, int iy, int iz)
GLsizeiptr size
Definition: glcorearb.h:664
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:152
const GEO_PrimVDB * myVdb
#define GEO_API
Definition: GEO_API.h:14
#define IS_SCALAR
GLdouble GLdouble GLdouble z
Definition: glcorearb.h:848
SYS_FORCE_INLINE int getTupleSize() const
Get the tuple size, usually 1 or 3.
Definition: GEO_PrimVDB.h:159
UT_Vector3T< fpreal64 > UT_Vector3D
void indexToPos(int x, int y, int z, UT_Vector3 &pos) const
GLdouble n
Definition: glcorearb.h:2008
T volume() const
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
GLint y
Definition: glcorearb.h:103
Definition: format.h:895
void posToIndex(UT_Vector3D pos, exint &x, exint &y, exint &z) const