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