HDK
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
GEO_PrimVolume.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_PrimVolume.h ( GEO Library, C++)
7  *
8  * COMMENTS:
9  */
10 
11 #ifndef __GEO_PrimVolume__
12 #define __GEO_PrimVolume__
13 
14 #include <UT/UT_BoundingRect.h>
15 #include <UT/UT_VoxelArray.h>
16 #include <GA/GA_PrimVolumeXform.h>
17 
18 #include "GEO_API.h"
19 #include "GEO_Primitive.h"
20 #include "GEO_VolumeOptions.h"
21 
22 class UT_CameraParms;
23 class UT_JSONWriter;
24 class UT_JSONParser;
25 class GA_SaveMap;
26 class GA_LoadMap;
27 class CE_Grid;
28 class CE_Image;
29 class IMX_Layer;
30 
31 ///
32 /// Stores the transform associated with a volume, allowing the
33 /// to/from code to be inlined outside of this library.
34 ///
36 
38 {
39 protected:
40  /// NOTE: The constructor should only be called from subclass
41  /// constructors.
43 
44  /// NOTE: The destructor should only be called from subclass
45  /// destructors.
46  ~GEO_PrimVolume() override;
47 
48 public:
50  {
51  // The order here matches typeid() in VEX:
52  // If you change the order, update the intrinsics.
58  };
59 
60 //
61 // Methods common to all primitives.
63  UT_Vector3 &nml,
64  float u, float v=0, float w=0) const override;
65  bool getBBox(UT_BoundingBox *bbox) const override;
66  void addToBSphere(
67  UT_BoundingSphere *bsphere) const override;
68  void enlargePointBounds(UT_BoundingBox &box) const override;
69  /// @{
70  /// Enlarge a bounding box by the bounding box of the primitive. A
71  /// return value of false indicates an error in the operation, most
72  /// likely an invalid P. For any attribute other than the position
73  /// these methods simply enlarge the bounding box based on the vertex.
74  bool enlargeBoundingBox(
76  const GA_Attribute *P) const override;
77  bool enlargeBoundingBox(
79  const GA_Attribute *P) const override;
80  /// @}
81  /// Enlarge a bounding sphere to encompass the primitive. A return value
82  /// of false indicates an error in the operation, most likely an invalid
83  /// P. For any attribute other than the position this method simply
84  /// enlarges the sphere based on the vertex.
87  const GA_Attribute *P) const override;
88  /// For a volume the barycenter is the same as the point.
89  UT_Vector3 baryCenter() const override;
90  UT_Vector3 computeNormal() const override;
91  UT_Vector3D computeNormalD() const override;
92  bool saveH9(
93  std::ostream &os, bool binary,
94  const UT_Array<GA_AttribSaveDataH9> &prim_attribs,
95  const UT_Array<GA_AttribSaveDataH9> &vtx_attribs
96  ) const override;
97  bool loadH9(
98  UT_IStream &is,
99  const UT_Array<GA_AttribLoadDataH9> &prim_attribs,
100  const UT_Array<GA_AttribLoadDataH9> &vtx_attribs
101  ) override;
102 
103  bool saveVoxelArray(UT_JSONWriter &w,
104  const GA_SaveMap &map) const;
105  bool loadVoxelArray(UT_JSONParser &p,
106  const GA_LoadMap &map);
107 
108  bool loadRes(const UT_JSONValue &jval);
109  bool loadStorageType(const char *storagename);
110  bool saveBorder(UT_JSONWriter &w,
111  const GA_SaveMap &map) const;
112  bool loadBorder(UT_JSONParser &p,
113  const GA_LoadMap &map);
114  bool saveCompression(UT_JSONWriter &w,
115  const GA_SaveMap &map) const;
116  bool loadCompression(UT_JSONParser &p,
117  const GA_LoadMap &map);
118  bool saveVisualization(UT_JSONWriter &w,
119  const GA_SaveMap &map) const;
120  bool loadVisualization(UT_JSONParser &p,
121  const GA_LoadMap &map);
122 
123  /// @{
124  /// Methods to save/load shared voxel data
125  static const int theSharedVoxelMagic=('V'<<24)|('o'<<16)|('x'<<8)|('l');
127  int dtype,
128  GA_SharedDataHandlePtr data) override;
129  bool saveSharedLoadData(
130  UT_JSONWriter &w,
131  GA_SaveMap &save,
132  GA_GeometryIndex *geo_index) const override;
133  bool getSharedVoxelKey(UT_WorkBuffer &key) const;
135  allocateSharedDataLoader();
136  /// @}
137 
138  // Transforms the matrix associated with this primitive. The
139  // translate component is ignored: Translate the vertices of
140  // the primitive to translate the primitive.
141  // This only works with quadrics (sphere, tube, metaballs) and volumes.
142  void transform(const UT_Matrix4 &mat) override;
143 
144  void reverse() override {}
145  GEO_Primitive *copy(int preserve_shared_pts = 0) const override;
146  void copyPrimitive(const GEO_Primitive *src) override;
147  void copySubclassData(const GA_Primitive *source) override;
152 
155  {
156  return getVertexOffset(0);
157  }
160  {
161  return getPointOffset(0);
162  }
165  {
166  return getPos3(0);
167  }
169  void setPos3(const UT_Vector3 &pos)
170  {
171  return setPos3(0, pos);
172  }
173 
174  // Take the whole set of points into consideration when applying the
175  // point removal operation to this primitive. The method returns 0 if
176  // successful, -1 if it failed because it would have become degenerate,
177  // and -2 if it failed because it would have had to remove the primitive
178  // altogether.
179  int detachPoints(GA_PointGroup &grp) override;
180 
181  /// Before a point is deleted, all primitives using the point will be
182  /// notified. The method should return "false" if it's impossible to
183  /// delete the point. Otherwise, the vertices should be removed.
184  GA_DereferenceStatus dereferencePoint(GA_Offset point,
185  bool dry_run=false) override;
186  GA_DereferenceStatus dereferencePoints(const GA_RangeMemberQuery &pt_q,
187  bool dry_run=false) override;
188 
189  bool isDegenerate() const override;
190 
191  // Map the normalized length (distance value [0,1]) parameter to the unit
192  // parameterization of the primitve
194  float ulength, float vlength,
195  float &uparm, float &vparm) const override;
197  float ulength, float vlength,
198  float &uparm, float &vparm,
199  float tolerance) const override;
200 
202  float uparm, float vparm,
203  float &ulength, float &vlength) const override;
204 
205  fpreal calcVolume(const UT_Vector3 &refpt) const override;
206  fpreal calcArea() const override;
207 
208 //
209 // Methods unique to PrimVolume.
210 
211 #if GA_PRIMITIVE_VERTEXLIST
213  void setVertexPoint(GA_Offset pt)
214  {
216  }
217 #else
219  {
220  wireVertex(myVertex, pt);
221  }
222 #endif
223 
224  /// This method assigns a preallocated vertex to the quadric, optionally
225  /// creating the topological link between the primitive and new vertex.
226  void assignVertex(GA_Offset new_vtx, bool update_topology);
227 
228  // Have we been deactivated and stashed?
229  void stashed(bool beingstashed,
230  GA_Offset offset = GA_INVALID_OFFSET) override;
231 
232  /// Sets the number of components for the volume. comps is internally
233  /// clamped to be between 1 and 4. Calling this function resets the
234  /// primitive.
235  void setTupleSize(int comps);
236  /// Returns the number of components (or the tuple size) for this volume.
237  int getTupleSize() const { return myChannelCount; };
238 
239  /// Changes this volume to one storing integers. Calling this function
240  /// resets the primitive.
241  void setStoresIntegers(bool ints);
242  /// Returns true if this volume stores integers.
243  bool getStoresIntegers() const { return myStoreIntegers; }
244 
245  /// Return the current storage type of the volume.
246  StorageType getStorageType() const;
247  /// Changes this volume to the specified storage type. Resets
248  /// the primitive.
249  void setStorageType(StorageType store);
250 
251  /// True if this is a traditional scalar volume.
252  bool isScalarVolume() const
253  { return getTupleSize() == 1 && getStoresIntegers() == false; }
254 
255  const UT_Matrix3 &getTransform() const { return myXform; }
256  void setTransform(const UT_Matrix3 &m)
257  { myXform = m;
258  myInverseXform = m;
259  myInverseXform.invert();
260  }
261 
262  void getTransform4( UT_Matrix4 &matx) const;
263  void getTransform4( UT_DMatrix4 &matx) const;
264  void setTransform4(const UT_Matrix4 &matx);
265  void setTransform4(const UT_DMatrix4 &matx);
266 
267  void getLocalTransform(UT_Matrix3D &x) const override;
268  void setLocalTransform(const UT_Matrix3D &x) override;
269 
270  /// Converts from world space to local space.
271  const UT_Matrix3 &getInverseTransform() const { return myInverseXform; }
272  void getInverseTransform4(UT_Matrix4 &matx) const;
273 
274  float getTaperX() const { return myTaperX; }
275  void setTaperX(float t) { myTaperX = t; }
276  float getTaperY() const { return myTaperY; }
277  void setTaperY(float t) { myTaperY = t; }
278 
279  /// True if the two volumes have same resolution and map the
280  /// same indices to the same positions.
281  bool isAligned(const GEO_PrimVolume *vol) const;
282 
283  /// True if we are aligned with the world axes. Ie, all our
284  /// off diagonals are zero and our diagonal is positive.
285  bool isWorldAxisAligned() const;
286 
287  /// Returns the POD class which can convert to and from
288  /// 0..1 voxel space coordinates.
289  GEO_PrimVolumeXform getSpaceTransform() const;
290  void setSpaceTransform(GEO_PrimVolumeXform xform);
291 
292  /// Returns the POD class which can convert to and from
293  /// voxel index space coordinates.
294  /// Note: The transformation is not the same as `posToIndex`
295  /// getIndexSpaceTransform().toVoxelSpace(pos) == posToIndex(pos) + {0.5, 0.5, 0.5}
296  GEO_PrimVolumeXform getIndexSpaceTransform() const;
297  template <typename T>
298  GEO_PrimVolumeXform getIndexSpaceTransform(const UT_VoxelArray<T> &vox) const;
299 
300  /// Converts from world space to 0..1 voxel space.
301  UT_Vector3 toVoxelSpace(const UT_Vector3 &pos) const;
302  /// Converts from 0..1 voxel space to world space.
303  UT_Vector3 fromVoxelSpace(const UT_Vector3 &pos) const;
304 
305  /// Converts from world space to 0..1 voxel space.
306  void toVoxelSpace(UT_BoundingBox &box) const;
307  /// Converts from 0..1 voxel space to world space.
308  void fromVoxelSpace(UT_BoundingBox &box) const;
309 
310  /// Copies the given voxel array and makes it our own voxel array.
311  void setVoxels(const UT_VoxelArrayF *vox);
312  void setVoxels(const UT_VoxelArrayV2 *vox);
313  void setVoxels(const UT_VoxelArrayV3 *vox);
314  void setVoxels(const UT_VoxelArrayV4 *vox);
315  void setVoxels(const UT_VoxelArrayI *vox);
316  void setVoxels(UT_VoxelArrayHandleF handle);
317  void setVoxels(UT_VoxelArrayHandleV2 handle);
318  void setVoxels(UT_VoxelArrayHandleV3 handle);
319  void setVoxels(UT_VoxelArrayHandleV4 handle);
320  void setVoxels(UT_VoxelArrayHandleI handle);
321 
322  /// Takes ownership of the voxel array, caller should not refer
323  /// to vox any more.
324  void stealVoxels(UT_VoxelArrayF *vox);
325  void stealVoxels(UT_VoxelArrayV2 *vox);
326  void stealVoxels(UT_VoxelArrayV3 *vox);
327  void stealVoxels(UT_VoxelArrayV4 *vox);
328  void stealVoxels(UT_VoxelArrayI *vox);
329 
330  /// Returns a handle to a voxel array containing our data.
331  /// This is should be thought of a copy of the data - changing
332  /// it will not change the underlying data, casting this to
333  /// a write handle will write to the newly created handle, not
334  /// the one stored in this volume.
335  UT_VoxelArrayHandleF getVoxelHandle() const;
337  {
338  return getVoxelHandle();
339  }
340  UT_VoxelArrayHandleV2 getVoxelHandleV2() const;
341  UT_VoxelArrayHandleV3 getVoxelHandleV3() const;
342  UT_VoxelArrayHandleV4 getVoxelHandleV4() const;
343  UT_VoxelArrayHandleI getVoxelHandleI() const;
344 
345  template <typename BASE>
347  {
348  if constexpr (SYS_IsSame_v<UT_Vector4, BASE>)
349  return getVoxelHandleV4();
350  if constexpr (SYS_IsSame_v<UT_Vector3, BASE>)
351  return getVoxelHandleV3();
352  if constexpr (SYS_IsSame_v<UT_Vector2, BASE>)
353  return getVoxelHandleV2();
354  if constexpr (SYS_IsSame_v<float, BASE>)
355  return getVoxelHandleF();
356  if constexpr (SYS_IsSame_v<int64, BASE>)
357  return getVoxelHandleI();
358  }
359 
360  template <typename BASE>
362  {
363  UT_COWReadHandle<UT_VoxelArray<BASE>> vox(getVoxelHandleByType<BASE>());
364  return vox;
365  }
366 
367  template <typename BASE>
369  {
370  if constexpr (SYS_IsSame_v<UT_Vector4, BASE>)
371  return getVoxelWriteHandleV4();
372  if constexpr (SYS_IsSame_v<UT_Vector3, BASE>)
373  return getVoxelWriteHandleV3();
374  if constexpr (SYS_IsSame_v<UT_Vector2, BASE>)
375  return getVoxelWriteHandleV2();
376  if constexpr (SYS_IsSame_v<float, BASE>)
377  return getVoxelWriteHandleF();
378  if constexpr (SYS_IsSame_v<int64, BASE>)
379  return getVoxelWriteHandleI();
380 
381  }
382 
383  /// Returns a voxel handle without trying to load the shared data
384  /// This should only be used for the loader
385  /// DO NOT USE! IF YOU THINK YOU SHOULD YOU'RE PROBABLY WRONG
386  template <typename BASE = float>
388  {
389  if constexpr (SYS_IsSame_v<UT_Vector4, BASE>)
390  return myVoxelHandleP;
391  if constexpr (SYS_IsSame_v<UT_Vector3, BASE>)
392  return myVoxelHandleV;
393  if constexpr (SYS_IsSame_v<UT_Vector2, BASE>)
394  return myVoxelHandleU;
395  if constexpr (SYS_IsSame_v<float, BASE>)
396  return myVoxelHandleF;
397  if constexpr (SYS_IsSame_v<int64, BASE>)
398  return myVoxelHandleI;
399  }
400 
401  /// This is a handle that you can write to and affect the volume.
402  UT_VoxelArrayWriteHandleF getVoxelWriteHandle();
404  {
405  return getVoxelWriteHandle();
406  }
407  UT_VoxelArrayWriteHandleV2 getVoxelWriteHandleV2();
408  UT_VoxelArrayWriteHandleV3 getVoxelWriteHandleV3();
409  UT_VoxelArrayWriteHandleV4 getVoxelWriteHandleV4();
410  UT_VoxelArrayWriteHandleI getVoxelWriteHandleI();
411 
412  /// This function calls operator() on op with a COW read handle to this
413  /// volume's actual voxel array handle. operator() must be templated to
414  /// support different handles:
415  /// template <typename T>
416  /// void operator()(const UT_COWReadHandle<UT_VoxelArray<T>>&);
417  template <typename OP>
418  void dispatchToReadHandle(OP& op) const;
419 
420  /// This function calls operator() on op with a COW write handle to this
421  /// volume's actual voxel array handle. operator() must be templated to
422  /// support different handles:
423  /// template <typename T>
424  /// void operator()(const UT_COWWriteHandle<UT_VoxelArray<T>>&);
425  /// If force_load is true, voxel data is first fully loaded; otherwise,
426  /// the handle is used as is.
427  template <typename OP>
428  void dispatchToWriteHandle(OP& op, bool force_load);
429 
430  template <typename OP>
431  void dispatch(const OP &op) const
432  { dispatch(getStorageType(), op); }
433 
434  template <typename OP>
435  static void dispatch(StorageType storage, const OP &op)
436  {
437  switch (storage)
438  {
439  case VOLUME_TYPE_FLOAT: op((float) 0); break;
440  case VOLUME_TYPE_VECTOR2: op(UT_Vector2(0,0)); break;
441  case VOLUME_TYPE_VECTOR3: op(UT_Vector3(0,0,0)); break;
442  case VOLUME_TYPE_VECTOR4: op(UT_Vector4(0,0,0,0)); break;
443  case VOLUME_TYPE_INTEGER: op((int64) 0); break;
444  }
445  }
446 
447  /// Convert an index in the voxel array into the corresponding worldspace
448  /// location
449  bool indexToPos(int x, int y, int z, UT_Vector3 &pos) const;
450  void findexToPos(UT_Vector3 index, UT_Vector3 &pos) const;
451  bool indexToPos(exint x, exint y, exint z, UT_Vector3D &pos) const;
452  void findexToPos(UT_Vector3D index, UT_Vector3D &pos) const;
453 
454  /// Returns true if the given point is entirely inside the volume's
455  /// definition, ie, if posToIndex would return true.
456  bool isInside(UT_Vector3 pos) const;
457 
458  /// Returns true only if strictly inside. This means only actual
459  /// voxel samples will be used for interpolation, so the boundary
460  /// conditions will be unused
461  bool isInsideStrict(UT_Vector3 pos) const;
462  /// By passing in a specific read handle, we can accelerate
463  /// isInsideStrict()
464  template <typename T>
465  bool isInsideStrict(const UT_Vector3 &opos,
466  const UT_COWReadHandle<UT_VoxelArray<T>> &vox) const;
467 
468  /// Returns true only if index is inside.
469  bool isIndexInside(int x, int y, int z) const;
470  /// By passing in a specific read handle, we can accelerate
471  template <typename T>
472  bool isIndexInside(int x, int y, int z,
473  const UT_COWReadHandle<UT_VoxelArray<T>> &vox) const;
474 
475  /// Convert a 3d position into the closest index value. Returns
476  /// false if the resulting index was out of range (but still sets it)
477  bool posToIndex(UT_Vector3 pos, int &x, int &y, int &z) const;
478  bool posToIndex(UT_Vector3 pos, UT_Vector3 &index) const;
479  bool posToIndex(UT_Vector3D pos, exint &x, exint &y, exint &z) const;
480  bool posToIndex(UT_Vector3D pos, UT_Vector3D &index) const;
481 
482  /// Evaluate the voxel value at the given world space position.
483  fpreal getValue(const UT_Vector3 &pos) const;
484  void getValues(float *f, int stride, const UT_Vector3 *p, int num) const;
485  void getValues(double *f, int stride, const UT_Vector3D *p, int num) const;
486  void getValues(UT_Vector2F *f, int stride, const UT_Vector3 *p, int num) const;
487  void getValues(UT_Vector2D *f, int stride, const UT_Vector3D *p, int num) const;
488  void getValues(UT_Vector3F *f, int stride, const UT_Vector3 *p, int num) const;
489  void getValues(UT_Vector3D *f, int stride, const UT_Vector3D *p, int num) const;
490  void getValues(UT_Vector4F *f, int stride, const UT_Vector3 *p, int num) const;
491  void getValues(UT_Vector4D *f, int stride, const UT_Vector3D *p, int num) const;
492  void getValues(int32 *f, int stride, const UT_Vector3 *p, int num) const;
493  void getValues(int64 *f, int stride, const UT_Vector3D *p, int num) const;
494  // Only works with scalar grids.
495  UT_Vector3 getGradient(const UT_Vector3 &pos) const;
496  UT_Vector3 getGradient(const UT_Vector3 &pos, const UT_VoxelArrayReadHandleF &handle) const;
497 
498  /// By passing in a specific read handle and inverse transform
499  /// we can accelerate the getValue()
500  fpreal getValue(const UT_Vector3 &pos, const UT_VoxelArrayReadHandleF &handle) const;
501 
502  template <typename TYPE>
503  TYPE getValueByType(const UT_Vector3 &pos) const
504  {
505  return getValueByType<TYPE>(pos, getVoxelHandleByType<TYPE>());
506  }
507  template <typename TYPE>
508  TYPE getValueByType(const UT_Vector3 &pos, const UT_VoxelArrayReadHandle<TYPE> &vox) const
509  {
510  if constexpr (SYSisSame<TYPE, float>())
511  {
512  return getValue(pos, vox);
513  }
514  else
515  {
516  UT_Vector3 localpos;
517  localpos = toVoxelSpace(pos);
518 
519  // Now we can evaluate normally.
520  return (*vox)(localpos);
521  }
522  }
523 
524  /// Evaluate the specific voxel indexed from 0,0,0.
525  fpreal getValueAtIndex(int ix, int iy, int iz) const;
526  void getValuesAtIndices(float *f, int stride, const int *ix, const int *iy, const int *iz, int num) const;
527  void getValuesAtIndices(int *f, int stride, const int *ix, const int *iy, const int *iz, int num) const;
528  void getValuesAtIndices(double *f, int stride, const exint *ix, const exint *iy, const exint *iz, int num) const;
529  void getValuesAtIndices(exint *f, int stride, const exint *ix, const exint *iy, const exint *iz, int num) const;
530  /// Returns the resolution of the voxel array.
531  void getRes(int &rx, int &ry, int &rz) const;
532  void getRes(int64 &rx, int64 &ry, int64 &rz) const;
533  /// Computes the voxel diameter by taking a step in x, y, and z
534  /// converting to world space and taking the length of that vector.
535  fpreal getVoxelDiameter() const;
536 
537  /// Returns the length of the voxel when you take an x, y, and z step
538  UT_Vector3 getVoxelSize() const;
539 
540  /// Computes the total density of the volume, scaled by
541  /// the volume's size. Negative values will be ignored.
542  fpreal calcPositiveDensity() const;
543 
544  /// Compute useful aggregate properties of the volume.
545  fpreal calcMinimum(int channel = 0) const;
546  fpreal calcMaximum(int channel = 0) const;
547  fpreal calcAverage(int channel = 0) const;
548  exint calcMinimumI(int channel = 0) const;
549  exint calcMaximumI(int channel = 0) const;
550 
551  /// Determines if we should be treated as an SDF. This means
552  /// our function will continue to increase outside of the bounding
553  /// box according to the distance to the bounding box.
554  bool isSDF() const { return myIsSDF; }
555 
556  /// Determine our orientation if we are to be considered a heightfield.
557  /// Returns false if we shouldn't be treated as a heightfield.
558  bool computeHeightFieldProperties(int &a1, int &a2, int &axis, fpreal &scale) const;
559  bool computeHeightFieldProperties(int &a1, int &a2, int &axis, fpreal &scale, const UT_VoxelArrayF &vox, const GEO_PrimVolumeXform &indexxform) const;
560 
561  /// Get the border options in terms of GEO's values.
562  static const char *getBorderToken(GEO_VolumeBorder border);
563  static GEO_VolumeBorder getBorderEnum(const char *token,
565  void setBorder(GEO_VolumeBorder border, fpreal val, int component = 0);
566  GEO_VolumeBorder getBorder() const;
567  fpreal getBorderValue(int component = 0) const;
568 
569  /// Windowing is optional - if not set, data offset is 0,0,0,
570  /// display == data, and windowvoxelscale is 1
571  bool hasWindow() const;
572  /// The equivalent of pixel scale; this scales from the volume's
573  /// voxels (which are "buffer" in IMX) to the canonical voxel grid.
574  UT_Vector3D windowVoxelScale() const;
575  /// data window offset is the position on canonical voxel grid of
576  /// the bottom-left-front of the volume's voxels array.
577  UT_Vector3D dataWindowOffset() const;
578  /// data window size is the volume's voxel resolution scaled by
579  /// the voxelscale
580  UT_Vector3D dataWindowSize() const;
581  /// display window offset is the position on canonical voxel grid of
582  /// the bottom-left-front of the display window of the volume.
583  UT_Vector3D displayWindowOffset() const;
584  /// display window size in canonical voxels.
585  UT_Vector3D displayWindowSize() const;
586  /// Mark the data/display/scale as non-present to restore identity
587  /// behaviour.
588  void clearWindow();
589  /// Create a default window setup.
590  void createDefaultWindow();
591  /// Adjust the ratio from volume's voxels into canonical voxel grid,
592  /// note this will not update any other values, so if you adjust
593  /// windowvoxelscale you will have to likewise adjust other window
594  /// values.
595  void setWindowVoxelScale(UT_Vector3D scale);
596  /// Adjust the bottom left front coord of the data window - note this
597  /// is in canonical voxels, not in the volume's voxels. The size
598  /// is always implied from the resolution.
599  void setDataWindowOffset(UT_Vector3D xyz);
600  /// Set the display window in the space of canonical voxels.
601  void setDisplayWindowOffset(UT_Vector3D xyz);
602  void setDisplayWindowSize(UT_Vector3D size);
603 
604  /// Control the compression of these objects.
605  fpreal getCompressionTolerance() const;
606  void setCompressionTolerance(fpreal tol);
607  void recompress();
608 
609  /// Control how we display this in the viewport
610  static const char *getVisualizationToken(GEO_VolumeVis vis);
611  static GEO_VolumeVis getVisualizationEnum(const char *vis,
613  const GEO_VolumeOptions &getVisOptions() const { return myVis; }
615  { setVisualization(vis.myMode, vis.myIso, vis.myDensity); }
616  void setVisualization(GEO_VolumeVis vis, fpreal iso, fpreal density);
617  fpreal getVisIso() const { return myVis.myIso; }
618  fpreal getVisDensity() const { return myVis.myDensity; }
619  fpreal getVisTiles() const { return myVis.myTiles; }
620  void setVisTiles(fpreal tiles) { myVis.myTiles = tiles; }
621  GEO_VolumeVis getVisualization() const { return myVis.myMode; }
622  GEO_VolumeTypeInfo getTypeInfo() const { return myVis.myTypeInfo; }
623  void setTypeInfo(GEO_VolumeTypeInfo info) { myVis.myTypeInfo = info; }
624 
625  const GA_PrimitiveJSON *getJSON() const override;
626 
627  /// Voxel traverser. This serializes the voxels into a linear array of
628  /// scalar data.
629  template <typename T>
631  {
632  public:
633  serializeT() = default;
634 
635 
636  /// Random access of a voxel value
638  {
639  constexpr bool SCALAR = std::is_arithmetic<T>::value;
640  if (index >= 0 && index < myEntries)
641  {
642  exint tuple = index % myTupleSize;
643  index -= tuple;
644  index /= myTupleSize;
645  exint x, y, z;
646  x = index % myXres;
647  index = (index - x) / myXres;
648  y = index % myYres;
649  index = (index - y) / myYres;
650  z = index % myZres;
651  T val = (*myVoxels)(x, y, z);
652  if constexpr(SCALAR)
653  {
654  return val;
655  }
656  else
657  {
658  return val[tuple];
659  }
660  }
661  return myBorder;
662  }
663 
664  /// @{
665  /// Iterator interface
666  bool atEnd() const { return myCurr >= myEntries; }
667  void rewind() { myCurr = 0; }
668  void advance() { myCurr++; }
669  serializeT &operator++() { advance(); return *this; }
670  /// No post increment as it is harmful.
671  /// @}
672  /// Iterator access methods
673  exint entries() const { return myEntries; }
674  exint index() const { return myCurr; }
675  fpreal voxel() const { return getVoxel(myCurr); }
676  private:
677  serializeT(const GEO_PrimVolume &prim)
678  : myVoxels(prim.getVoxelHandleByType<T>())
679  , myCurr(0)
680  {
681  prim.getRes(myXres, myYres, myZres);
682  myBorder = prim.getBorderValue();
683  myTupleSize = prim.getTupleSize();
684  myEntries = myXres*myYres*myZres * myTupleSize;
685  }
687  fpreal myBorder = 0;
688  int myTupleSize = 1;
689  exint myCurr = 0, myEntries = 0;
690  int myXres = 0, myYres = 0, myZres = 0;
691  friend class GEO_PrimVolume;
692  };
693 
695 
696  serialize getSerialize() const { return serialize(*this); }
697  template <typename T>
699  { return serializeT<T>(*this); }
700 
701 
702  /// Acquire a CE grid and cache it on the GPU. If marked for
703  /// writing, the CPU version will be overwritten.
704  /// Note that the getVoxelHandle does *NOT* auto-flush these!
705  /// NOTE: If someone else fetches a non-read grid, and you fetch it
706  /// as a read grid, you will not get any copied data.
707  CE_Grid *getCEGrid(bool read, bool write) const;
708 
709  /// Acquire an IMX layer for this volume. If marked for reading, it will
710  /// have identical data to this volume. If marked for writing, this volume's
711  /// data will be overwritten.
712  UT_SharedPtr<IMX_Layer> getIMXLayer(bool read, bool write) const;
713 
714  /// Initializes the given layer to one matching this volume. If data_too is
715  /// true, the data is also copied from this volume to the layer; otherwise,
716  /// the layer is only appropriately formatted and sized to match the volume.
717  void initIMXLayer(IMX_Layer& layer, bool data_too = false) const;
718 
719  /// Any modified CE cache on the GPU will be copied back to the
720  /// CPU. Will leave result on GPU.
721  void flushCEWriteCaches() override;
722 
723  /// Remove all CE caches from the GPU, possibly writing back
724  /// if necessary.
725  void flushCECaches() override;
726 
727  /// Remove all CE caches from the GPU, without writing back.
728  void clearCECaches() override;
729 
730  /// Steal the underlying CE buffer from the source.
731  void stealCEBuffers(const GA_Primitive *src) override;
732 
733  /// Copy the underlying CE buffer from the source.
734  void copyCEBuffers(const GA_Primitive *src) override;
735 
736  /// Set a proxy compute image that we may reference for our data, but not
737  /// modify. Upon first request, the data is then copied to a main voxel
738  /// array.
740  /// Returns true if this volume primitive has a compute image that is ready
741  /// with clean data.
742  /// NOTE: this method should only be used to query presence of a ready
743  /// compute image; getCEImage() will automatically make a copy if needed.
744  bool hasIMXLayer() const
745  { return (bool) myIMXLayer; }
746 
747  /// Get the 2D volume's camera parameters, favoring the XY plane if the
748  /// volume is flat in several dimensions. Returns false if the volume is 3D.
750  UT_Vector3D &pos,
751  UT_Matrix3D &rot) const;
752 
753  /// Set a "proxy" compute grid that we may reference for our data, but
754  /// not modify. Upon first request, the data is then copied to a main
755  /// voxel array.
756  void setBorrowedCEGrid(CE_Grid* grid);
757  /// Returns true if this volume primitive has a compute grid that is
758  /// externally owned.
759  /// NOTE: this method should only be used to query presence of a borrowed
760  /// compute grid; getCEGrid() will automatically make a copy if needed.
761  bool hasBorrowedCEGrid() const { return !myCEGridIsOwned; }
762  /// Returns true if the volume is fully loaded. If it has a pending
763  /// CE grid (hasBorrowedCEGrid) or shared data to load, returns false.
764  bool isFullyLoaded() const
765  {
766  if (mySharedVoxelData) return false;
767  if (!myCEGridIsOwned && myCEGridAuthoritative) return false;
768  if (myIMXLayerAuthoritative) return false;
769  return true;
770  }
771 
772 protected:
774  { return GA_FAMILY_NONE; }
775 
776 #if !GA_PRIMITIVE_VERTEXLIST
777  virtual void clearForDeletion();
778 #endif
779 
780 #if !GA_PRIMITIVE_VERTEXLIST
781  /// Defragmentation
782  virtual void swapVertexOffsets(const GA_Defragment &defrag);
783 #endif
784 
785  GA_DECLARE_INTRINSICS(override)
786 
787  virtual bool savePrivateH9(std::ostream &os, bool binary) const;
788  virtual bool loadPrivateH9(UT_IStream &is);
789 
790  // A versioned loading method.
791  bool loadVoxelDataH9(UT_IStream &is,
793  int version);
794 
795  // Resets all voxel array handles belonging to this primitive and
796  // allocates the needed ones. Also relinquishes any non-owned CE
797  // data.
799 
801  { return getPointOffset(); }
802 
803  /// Gets the handle to our voxels
809 
810 
811  // All accesses of myVoxelHandle should go though getMyVoxelHandle
812  // so that the voxels are loaded from shared data before access
823 
824  bool myHasWindow = false;
829 
830  mutable CE_Grid *myCEGrid;
831  mutable bool myCEGridAuthoritative;
832  mutable bool myCEGridIsOwned;
833 
834  /// If this is not null, then the data on it is clean.
836  /// If this is true, the data in the IMX layer is the most up-to-date state
837  /// of the volume.
839 
840  bool evaluatePointRefMap(
841  GA_Offset result_vtx,
842  GA_AttributeRefMap &hlist,
843  fpreal u, fpreal v,
844  uint du, uint dv) const override;
846  UT_Vector4 &pos,
847  float u, float v = 0,
848  unsigned du=0, unsigned dv=0) const override
849  {
850  return GEO_Primitive::evaluatePointV4(pos, u, v,
851  du, dv);
852  }
854  GA_Offset result_vertex,
855  GA_AttributeRefMap &hlist) const override;
856 
858  GA_Offset result_vtx,
859  GA_AttributeRefMap &map,
860  fpreal u, fpreal v, fpreal w=0) const override;
862  UT_Vector4 &pos,
863  fpreal u, fpreal v, fpreal w=0) const override;
864 
865 private:
866 #if !GA_PRIMITIVE_VERTEXLIST
867  GA_Offset myVertex; // My vertex
868 #endif
869  UT_Matrix3 myXform; // My Transform
870  UT_Matrix3 myInverseXform; // My inverse transform
871  bool myIsSDF : 1; // Are we a signed distance field?
872 
873  GEO_VolumeOptions myVis;
874 
875  // The taper is the radius of the bottom half, z-minus, of the default box
876  // The top half's radius is one. These radii are then modified by
877  // myXform.
878  fpreal myTaperX, myTaperY;
879 
880  friend std::ostream &operator<<(std::ostream &os, const GEO_PrimVolume &d)
881  {
882  d.saveH9(os, 0,
885  return os;
886  }
888 };
890 
891 /// Returns string token from the StorageType enum value.
894 /// Returns the GEO_PrimVolume::StorageType enum value from string token. def is
895 /// returned if token is unknown.
898  const char *token,
900 
901 inline size_t
903 {
904  UT::Format::Writer writer(buf, bufsize);
906  return f.format(writer, "{}", {GEOgetVolumeStorageTypeToken(v)});
907 }
908 
909 #endif
virtual void flushCEWriteCaches()
Copy any modified caches from the GPU back to CPU cache.
Definition: GA_Primitive.h:816
void setTaperX(float t)
virtual void flushCECaches()
Definition: GA_Primitive.h:820
serialize getSerialize() const
Definition of a geometry attribute.
Definition: GA_Attribute.h:203
GEO_VolumeVis getVisualization() const
GLenum GLuint GLenum GLsizei const GLchar * buf
Definition: glcorearb.h:2540
virtual GEO_Primitive * copy(int preserve_shared_pts=0) const
SYS_FORCE_INLINE GA_Offset getPointOffset(GA_Size i) const
Definition: GA_Primitive.h:258
GLenum GLuint GLsizei bufsize
Definition: glcorearb.h:1818
virtual UT_Vector3 baryCenter() const
UT_SharedPtr< IMX_Layer > getIMXLayer(bool read, bool write) const
UT_COWHandle< UT_VoxelArray< BASE > > getHandleToVoxelsWithoutLoading() const
virtual void copyPrimitive(const GEO_Primitive *src)=0
int int32
Definition: SYS_Types.h:39
void initIMXLayer(IMX_Layer &layer, bool data_too=false) const
virtual void clearForDeletion()
Definition: GA_Primitive.h:691
Used to pass options and map offset values during saving.
Definition: GA_SaveMap.h:48
bool loadVoxelDataH9(UT_IStream &is, UT_VoxelArrayWriteHandleF voxels, int version)
bool isFullyLoaded() const
UT_Vector2T< float > UT_Vector2
UT_VoxelArrayHandleV4 myVoxelHandleP
TYPE getValueByType(const UT_Vector3 &pos, const UT_VoxelArrayReadHandle< TYPE > &vox) const
virtual UT_Vector3D computeNormalD() const =0
getFileOption("OpenEXR:storage") storage
Definition: HDK_Image.dox:276
const GLdouble * v
Definition: glcorearb.h:837
UT_VoxelArrayHandleV2 & getMyVoxelHandleV2() const
#define SYS_DEPRECATED_PUSH_DISABLE()
float getTaperY() const
UT_Vector3D myWindowVoxelScale
#define SYS_DEPRECATED_POP_DISABLE()
virtual void copySubclassData(const GA_Primitive *source)
Definition: GA_Primitive.h:512
GLsizei const GLfloat * value
Definition: glcorearb.h:824
void setVisOptions(const GEO_VolumeOptions &vis)
bool enlargeBoundingBox(UT_BoundingRect &b, const GA_Attribute *p) const override
bool myCEGridAuthoritative
static void dispatch(StorageType storage, const OP &op)
int evaluatePointV4(UT_Vector4 &pos, float u, float v=0, unsigned du=0, unsigned dv=0) const override
const GLuint GLenum const void * binary
Definition: glcorearb.h:1924
fpreal calcVolume(const UT_Vector3 &) const override
UT_Vector3T< float > UT_Vector3
GA_API const UT_StringHolder rot
GLdouble GLdouble GLdouble z
Definition: glcorearb.h:848
SYS_FORCE_INLINE UT_Vector3 getPos3() const
virtual bool saveSharedLoadData(UT_JSONWriter &w, GA_SaveMap &save, GA_GeometryIndex *geo_index) const
int64 exint
Definition: SYS_Types.h:125
fpreal getVisDensity() const
void resetAndAllocateHandles()
UT_COWReadHandle< UT_VoxelArray< BASE > > getVoxelReadHandleByType() const
const GEO_VolumeOptions & getVisOptions() const
bool hasIMXLayer() const
static GA_PrimitiveFamilyMask buildFamilyMask()
void reverse() override
Reverse the order of vertices.
GA_Offset vertexPoint() const
GA_SharedDataHandlePtr mySharedVoxelData
virtual GA_DereferenceStatus dereferencePoint(GA_Offset point, bool dry_run=false)=0
SYS_FORCE_INLINE GA_Offset getVertexOffset() const
JSON reader class which handles parsing of JSON or bJSON files.
Definition: UT_JSONParser.h:87
#define GA_DECLARE_INTRINSICS(OVERRIDE)
Definition: GA_Primitive.h:80
GEO_VolumeVis myMode
GLint y
Definition: glcorearb.h:103
Class which writes ASCII or binary JSON streams.
Definition: UT_JSONWriter.h:39
Abstract base class for a range membership query object.
GEO_API const char * GEOgetVolumeStorageTypeToken(GEO_PrimVolume::StorageType type)
Returns string token from the StorageType enum value.
virtual bool savePrivateH9(std::ostream &os, bool binary) const
int getTupleSize() const
Returns the number of components (or the tuple size) for this volume.
fpreal calcArea() const override
UT_SharedPtr< GA_SharedDataHandle > GA_SharedDataHandlePtr
UT_VoxelArrayHandleV4 & getMyVoxelHandleV4() const
virtual void swapVertexOffsets(const GA_Defragment &defrag)
virtual void unitToUnitLengthPair(float uparm, float vparm, float &ulength, float &vlength) const
void wireVertex(GA_Offset vertex, GA_Offset point)
virtual bool loadH9(UT_IStream &is, const UT_Array< GA_AttribLoadDataH9 > &prim_attribs, const UT_Array< GA_AttribLoadDataH9 > &vtx_attribs)
GA_PrimitiveFamilyMask
virtual UT_Vector3 computeNormal() const =0
Return a normal vector for the primitive.
UT_VoxelArrayHandleV3 myVoxelHandleV
#define GA_INVALID_OFFSET
Definition: GA_Types.h:694
__hostdev__ float getValue(uint32_t i) const
Definition: NanoVDB.h:5578
UT_VoxelArrayWriteHandleF getVoxelWriteHandleF()
GLenum GLuint GLint GLint layer
Definition: glcorearb.h:1299
friend std::ostream & operator<<(std::ostream &os, const GEO_PrimVolume &d)
virtual bool isDegenerate() const =0
Is the primitive degenerate.
fpreal getVisTiles() const
GA_Size GA_Offset
Definition: GA_Types.h:653
virtual bool enlargeBoundingSphere(UT_BoundingSphere &b, const GA_Attribute *P) const
virtual void clearCECaches()
Clear all caches from the GPU, without copying any data to the CPU.
Definition: GA_Primitive.h:823
const UT_Matrix3 & getTransform() const
GA_API const UT_StringHolder scale
UT_VoxelArrayHandleV3 & getMyVoxelHandleV3() const
SYS_FORCE_INLINE UT_Vector3 getPos3(GA_Size i) const
Definition: GA_Primitive.h:278
GLfloat f
Definition: glcorearb.h:1926
virtual void setLocalTransform(const UT_Matrix3D &matrix)
Set the local transform. The default implementation does nothing.
GLint GLint GLsizei GLint GLenum GLenum type
Definition: glcorearb.h:108
UT_VoxelArrayHandleF & getMyVoxelHandleF() const
Gets the handle to our voxels.
UT_Vector4T< float > UT_Vector4
TYPE getValueByType(const UT_Vector3 &pos) const
serializeT< float > serialize
GLintptr offset
Definition: glcorearb.h:665
GEO_VolumeBorder
virtual int evaluateInteriorPointV4(UT_Vector4 &pos, fpreal u, fpreal v, fpreal w=0) const
GEO_VolumeTypeInfo getTypeInfo() const
void setTransform(const UT_Matrix3 &m)
std::shared_ptr< T > UT_SharedPtr
Wrapper around std::shared_ptr.
Definition: UT_SharedPtr.h:36
bool hasBorrowedCEGrid() const
GEO_VolumeTypeInfo
#define SYS_FORCE_INLINE
Definition: SYS_Inline.h:45
const UT_Matrix3 & getInverseTransform() const
Converts from world space to local space.
virtual const GA_PrimitiveJSON * getJSON() const =0
GLsizei GLsizei GLchar * source
Definition: glcorearb.h:803
Provide a JSON interface to a primitive.
GLint GLenum GLboolean GLsizei stride
Definition: glcorearb.h:872
UT_COWWriteHandle< UT_VoxelArray< BASE > > getVoxelWriteHandleByType()
fpreal getVisIso() const
void setBorrowedCEGrid(CE_Grid *grid)
#define GEO_API
Definition: GEO_API.h:14
GEO_VolumeVis
long long int64
Definition: SYS_Types.h:116
A handle to simplify manipulation of multiple attributes.
Options during loading.
Definition: GA_LoadMap.h:42
Defragmentation of IndexMaps.
Definition: GA_Defragment.h:45
bool getStoresIntegers() const
Returns true if this volume stores integers.
float getTaperX() const
UT_Vector3D myDisplayWindowSize
UT_Lock mySharedDataLock
GLboolean GLboolean GLboolean b
Definition: glcorearb.h:1222
GLint GLenum GLint x
Definition: glcorearb.h:409
serializeT< T > getSerializeByType() const
bool saveH9(std::ostream &os, bool binary, const UT_Array< GA_AttribSaveDataH9 > &prim_attribs, const UT_Array< GA_AttribSaveDataH9 > &vtx_attribs) const override
fpreal getBorderValue(int component=0) const
SYS_FORCE_INLINE void setPos3(const UT_Vector3 &pos)
bool mySharedDataHandleLoaded
virtual GA_DereferenceStatus dereferencePoints(const GA_RangeMemberQuery &pt_q, bool dry_run=false)=0
bool isSDF() const
virtual bool saveH9(std::ostream &os, bool binary, const UT_Array< GA_AttribSaveDataH9 > &prim_attribs, const UT_Array< GA_AttribSaveDataH9 > &vtx_attribs) const
SYS_FORCE_INLINE void setPos3(GA_Size i, const UT_Vector3 &pos) const
Definition: GA_Primitive.h:290
GLdouble t
Definition: glad.h:2397
UT_COWHandle< UT_VoxelArray< BASE > > getVoxelHandleByType() const
UT_VoxelArrayHandleF getVoxelHandleF() const
virtual void unitLengthToUnitPair(float ulength, float vlength, float &uparm, float &vparm) const
GT_API const UT_StringHolder version
virtual bool evaluateBaryCenterRefMap(GA_Offset result_vtx, GA_AttributeRefMap &map) const
virtual bool evaluateInteriorPointRefMap(GA_Offset result_vtx, GA_AttributeRefMap &map, fpreal u, fpreal v, fpreal w=0) const
CE_Grid * getCEGrid(bool read, bool write) const
virtual void transform(const UT_Matrix4 &)
virtual void enlargePointBounds(UT_BoundingBox &box) const
GLsizeiptr size
Definition: glcorearb.h:664
virtual void getLocalTransform(UT_Matrix3D &matrix) const
GA_API const UT_StringHolder parms
#define SCALAR(T)
Simplify checking for scalar types.
Definition: GA_Handle.h:520
bool myIMXLayerAuthoritative
virtual bool loadPrivateH9(UT_IStream &is)
UT_VoxelArrayHandleF myVoxelHandleF
void setVertexPoint(GA_Offset pt)
virtual int detachPoints(GA_PointGroup &grp)=0
bool getLayerCameraParms(UT_CameraParms &parms, UT_Vector3D &pos, UT_Matrix3D &rot) const
GLint GLint GLsizei GLint border
Definition: glcorearb.h:108
UT_Vector3D myDisplayWindowOffset
fpreal getVoxel(exint index) const
Random access of a voxel value.
void setTaperY(float t)
static const UT_Array< GA_AttribSaveDataH9 > & theEmptySaveAttribs
Convience objects to pass as arguments to saveH9()/loadH9().
UT_SharedPtr< IMX_Layer > myIMXLayer
If this is not null, then the data on it is clean.
fpreal64 fpreal
Definition: SYS_Types.h:283
virtual bool getBBox(UT_BoundingBox *bbox) const =0
GLuint index
Definition: glcorearb.h:786
GLuint GLfloat * val
Definition: glcorearb.h:1608
virtual int evaluateNormalVector(UT_Vector3 &nml, float u, float v=0, float w=0) const
SYS_FORCE_INLINE GA_Offset getVertexOffset(GA_Size primvertexnum) const
Definition: GA_Primitive.h:244
virtual void stealCEBuffers(const GA_Primitive *src)
Steal the underlying CE buffer from the source.
Definition: GA_Primitive.h:826
GU_API void xform(CE_Context &context, bool recompile, int npts, const cl::Buffer &outPos, const cl::Buffer &inPos, const cl::Buffer &surfacexform, const cl::Buffer *grp=nullptr)
Class to store JSON objects as C++ objects.
Definition: UT_JSONValue.h:99
virtual bool evaluatePointRefMap(GA_Offset result_vtx, GA_AttributeRefMap &map, fpreal u, fpreal v=0, uint du=0, uint dv=0) const =0
void setVisTiles(fpreal tiles)
virtual void addToBSphere(UT_BoundingSphere *bsphere) const
void setTypeInfo(GEO_VolumeTypeInfo info)
SYS_FORCE_INLINE GA_Offset getPointOffset() const
CE_Grid * myCEGrid
GLubyte GLubyte GLubyte GLubyte w
Definition: glcorearb.h:857
virtual void copyCEBuffers(const GA_Primitive *src)
Copy the underlying CE buffer from the source.
Definition: GA_Primitive.h:829
void setBorrowedIMXLayer(const UT_SharedPtr< IMX_Layer > &l)
size_t format(W &writer, const char *format, std::initializer_list< ArgValue > args)
UT_VoxelArrayHandleV2 myVoxelHandleU
UT_Vector3D myDataWindowOffset
UT_VoxelArrayHandleI myVoxelHandleI
virtual bool registerSharedLoadData(int load_data_type, GA_SharedDataHandlePtr item)
UT_VoxelArrayHandleI & getMyVoxelHandleI() const
unsigned int uint
Definition: SYS_Types.h:45
void getRes(int &rx, int &ry, int &rz) const
Returns the resolution of the voxel array.
GEO_API GEO_PrimVolume::StorageType GEOgetVolumeStorageTypeEnum(const char *token, GEO_PrimVolume::StorageType def)
void dispatch(const OP &op) const
bool isScalarVolume() const
True if this is a traditional scalar volume.
virtual int evaluatePointV4(UT_Vector4 &pos, float u, float v=0, unsigned du=0, unsigned dv=0) const
virtual void stashed(bool beingstashed, GA_Offset offset=GA_INVALID_OFFSET)
size_t UTformatBuffer(char *buf, size_t bufsize, const GEO_PrimVolume::StorageType &v)
Definition: format.h:1821
GLenum src
Definition: glcorearb.h:1793