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 
17 #include "GEO_API.h"
18 #include "GEO_Primitive.h"
19 #include "GEO_VolumeOptions.h"
20 
21 class UT_JSONWriter;
22 class UT_JSONParser;
23 class GA_SaveMap;
24 class GA_LoadMap;
25 class CE_Grid;
26 
27 ///
28 /// Stores the transform associated with a volume, allowing the
29 /// to/from code to be inlined outside of this library.
30 ///
32 {
33 public:
34  // Converts from world space to [0,1] space.
36  {
37  pos -= myCenter;
38  pos *= myInverseXform;
39 
40  // Undo any taper effect.
41  if (myHasTaper)
42  {
43  fpreal zscale = (1 - pos.z()) * 0.5f;
44  fpreal taperx = 1 + (-1 + myTaperX) * zscale;
45  fpreal tapery = 1 + (-1 + myTaperY) * zscale;
46 
47  if (taperx == 0.0f)
48  pos.x() = 0.0;
49  else
50  pos.x() /= taperx;
51  if (tapery == 0.0f)
52  pos.y() = 0.0;
53  else
54  pos.y() /= tapery;
55  }
56 
57  // This gets us a value in the -1 to 1 box. We need to evaluate
58  // in the 0 to 1 box, however.
59  pos.x() += 1;
60  pos.y() += 1;
61  pos.z() += 1;
62  pos *= 0.5;
63 
64  return pos;
65  }
66 
67  // Converts from [0,1] space over the voxels to world space
69  {
70  // convert to -1 to 1 box.
71  pos.x() -= 0.5;
72  pos.y() -= 0.5;
73  pos.z() -= 0.5;
74  pos *= 2;
75 
76  // Apply the taper effect.
77  if (myHasTaper)
78  {
79  fpreal zscale = (1 - pos.z()) * 0.5f;
80  fpreal taperx = 1 + (-1 + myTaperX) * zscale;
81  fpreal tapery = 1 + (-1 + myTaperY) * zscale;
82 
83  pos.x() *= taperx;
84  pos.y() *= tapery;
85  }
86  // Convert to world space.
87  pos *= myXform;
88  pos += myCenter;
89 
90  return pos;
91  }
92 
93  // Returns jacobian of the transformation `toVoxelSpace` at point `pos`
94  //
95  // If `myHasTaper() == false` then the jacobian does not depend on the position `pos`.
96  //
97  // Vector `v` located at point `pos` gets transformed by `toVoxelSpace` map as:
98  // v -> v * toVoxelSpaceJacobian(pos)
99  //
100  // `toVoxelSpaceJacobian(pos)` is inverse of `fromVoxelSpaceJacobian(toVoxelSpace(pos))`
102  {
103  if (!myHasTaper)
104  return myInverseXform*0.5;
105 
106  pos -= myCenter;
107  pos *= myInverseXform;
108 
109  float zscale = (1 - pos.z()) * 0.5f;
110  float taperx = 1 + (-1 + myTaperX) * zscale;
111  float tapery = 1 + (-1 + myTaperY) * zscale;
112 
113  UT_Matrix3 tapergrad{
114  1.f / taperx,
115  0.f,
116  0.f,
117  0.f,
118  1.f / tapery,
119  0.f,
120  0.5f * (myTaperX - 1.f) * pos.x() / (taperx * taperx),
121  0.5f * (myTaperY - 1.f) * pos.y() / (tapery * tapery),
122  1.f};
123 
124  return myInverseXform*tapergrad*0.5;
125  }
126 
127  // Returns jacobian of the transformation `fromVoxelSpace` at point `pos`
128  //
129  // If `myHasTaper == false` then the jacobian does not depend on the position `pos`.
130  //
131  // Vector `v` located at point `pos` gets transformed by `fromVoxelSpace` map as:
132  // v -> v * fromVoxelSpaceJacobian(pos)
133  //
134  // `fromVoxelSpaceJacobian(pos)` is inverse of `toVoxelSpaceJacobian(fromVoxelSpace(pos))`
136  {
137  if (!myHasTaper)
138  return 2.f*myXform;
139 
140  pos.x() -= 0.5;
141  pos.y() -= 0.5;
142  pos.z() -= 0.5;
143  pos *= 2;
144 
145  float zscale = (1 - pos.z()) * 0.5f;
146  float taperx = 1 + (-1 + myTaperX) * zscale;
147  float tapery = 1 + (-1 + myTaperY) * zscale;
148 
149  UT_Matrix3 tapergrad{
150  1.f * taperx,
151  0.f,
152  0.f,
153  0.f,
154  1.f * tapery,
155  0.f,
156  0.5f * (1.f - myTaperX) * pos.x(),
157  0.5f * (1.f - myTaperY) * pos.y(),
158  1.f};
159 
160  return 2.f*tapergrad*myXform;
161  }
162 
163 
164 
165  inline void toVoxelSpace(UT_BoundingBox &box) const
166  {
167  int i;
168  UT_Vector3 v[8] = {
169  UT_Vector3(box.xmin(), box.ymin(), box.zmin()),
170  UT_Vector3(box.xmin(), box.ymin(), box.zmax()),
171  UT_Vector3(box.xmin(), box.ymax(), box.zmin()),
172  UT_Vector3(box.xmin(), box.ymax(), box.zmax()),
173  UT_Vector3(box.xmax(), box.ymin(), box.zmin()),
174  UT_Vector3(box.xmax(), box.ymin(), box.zmax()),
175  UT_Vector3(box.xmax(), box.ymax(), box.zmin()),
176  UT_Vector3(box.xmax(), box.ymax(), box.zmax()),
177  };
178 
179  box.initBounds();
180  for (i = 0; i < 8; i++)
181  {
182  box.enlargeBounds(toVoxelSpace(v[i]));
183  }
184  }
185 
186  inline void fromVoxelSpace(UT_BoundingBox &box) const
187  {
188  int i;
189  UT_Vector3 v[8] = {
190  UT_Vector3(box.xmin(), box.ymin(), box.zmin()),
191  UT_Vector3(box.xmin(), box.ymin(), box.zmax()),
192  UT_Vector3(box.xmin(), box.ymax(), box.zmin()),
193  UT_Vector3(box.xmin(), box.ymax(), box.zmax()),
194  UT_Vector3(box.xmax(), box.ymin(), box.zmin()),
195  UT_Vector3(box.xmax(), box.ymin(), box.zmax()),
196  UT_Vector3(box.xmax(), box.ymax(), box.zmin()),
197  UT_Vector3(box.xmax(), box.ymax(), box.zmax()),
198  };
199 
200  box.initBounds();
201  for (i = 0; i < 8; i++)
202  {
203  box.enlargeBounds(fromVoxelSpace(v[i]));
204  }
205  }
206 
207  /// Returns the *un-tapered* matrix4 corresponding to fromVoxelSpace().
208  /// @{
209  void getTransform4(UT_Matrix4F &matx) const;
210  void getTransform4(UT_Matrix4D &matx) const;
211  /// @}
212 
213  /// Compute the size for this transform (relative to myCenter)
214  UT_Vector3R computeSize() const;
215 
216  // NOTE: This ordering is saved in .hip files!
218  {
219  NON_SQUARE = 0,
224  BY_SIZE
225  };
226 
227  /// Convert the "uniformsamples" parm menu item index to a sampling type
229  { return SamplingType(i); }
230 
231  /// Compute the resolution (and size) from a common set of parameters.
232  /// If twod_axis is one of [0,1,2], then that axis clamped to a divisions
233  /// of 1 and a size of 0. The number of divisions is returned with size
234  /// set to div_size multiplied by divisions before the z_div_scale.
235  static UT_Vector3R computeResolution(
236  SamplingType sampling_type,
237  const UT_Vector3R &non_uniform_divs,
238  fpreal uniform_divs,
239  fpreal div_size,
240  fpreal z_div_scale,
241  UT_Vector3R &size_inout,
242  int twod_axis = -1);
243 
244  /// Compute a space transform from center, size, and taper
245  static GEO_PrimVolumeXform frustumSpaceTransform(
246  const UT_Vector3R &size,
247  const UT_Vector3R &center,
248  fpreal taper_x, fpreal taper_y);
249 
250  /// Compute a space transform from camera settings.
251  /// The ortho_zoom parameter is only used when is_ortho = true.
252  static GEO_PrimVolumeXform cameraFrustum(
253  fpreal focal,
254  fpreal aperture,
255  const UT_Vector2R &image_res,
256  fpreal pixel_aspect,
257  bool is_ortho,
258  fpreal ortho_zoom,
259  fpreal clip_near,
260  fpreal clip_far,
261  bool use_cam_window,
262  const UT_BoundingRectR &cam_window,
263  const UT_BoundingRectR &cam_crop,
264  const UT_BoundingRectR &window,
265  const UT_Matrix4R &post_xform,
266  const GEO_Detail *match_src);
267 
268 public:
269  // @{
270  void save(std::ostream &os, bool binary = false) const;
271  bool load(UT_IStream &is);
272  // @}
273 
274  void init()
275  {
276  myCenter.assign(0, 0, 0);
277  myXform.identity();
278  myInverseXform.identity();
279  myHasTaper = false;
280  myTaperX = 1.0;
281  myTaperY = 1.0;
282  }
283 
284  bool operator==(const GEO_PrimVolumeXform &x) const
285  {
286  return
287  myXform == x.myXform &&
288  myCenter == x.myCenter &&
289  myHasTaper == x.myHasTaper &&
290  myTaperX == x.myTaperX &&
291  myTaperY == x.myTaperY;
292  }
293 
294  UT_Matrix3 myXform, myInverseXform;
297  float myTaperX, myTaperY;
298 };
299 
301 {
302 protected:
303  /// NOTE: The constructor should only be called from subclass
304  /// constructors.
306 
307  /// NOTE: The destructor should only be called from subclass
308  /// destructors.
309  ~GEO_PrimVolume() override;
310 
311 public:
312 //
313 // Methods common to all primitives.
315  UT_Vector3 &nml,
316  float u, float v=0, float w=0) const override;
317  int getBBox(UT_BoundingBox *bbox) const override;
318  void addToBSphere(
319  UT_BoundingSphere *bsphere) const override;
320  void enlargePointBounds(UT_BoundingBox &box) const override;
321  /// @{
322  /// Enlarge a bounding box by the bounding box of the primitive. A
323  /// return value of false indicates an error in the operation, most
324  /// likely an invalid P. For any attribute other than the position
325  /// these methods simply enlarge the bounding box based on the vertex.
326  bool enlargeBoundingBox(
328  const GA_Attribute *P) const override;
329  bool enlargeBoundingBox(
330  UT_BoundingBox &b,
331  const GA_Attribute *P) const override;
332  /// @}
333  /// Enlarge a bounding sphere to encompass the primitive. A return value
334  /// of false indicates an error in the operation, most likely an invalid
335  /// P. For any attribute other than the position this method simply
336  /// enlarges the sphere based on the vertex.
339  const GA_Attribute *P) const override;
340  /// For a volume the barycenter is the same as the point.
341  UT_Vector3 baryCenter() const override;
342  UT_Vector3 computeNormal() const override;
343  bool saveH9(
344  std::ostream &os, bool binary,
345  const UT_Array<GA_AttribSaveDataH9> &prim_attribs,
346  const UT_Array<GA_AttribSaveDataH9> &vtx_attribs
347  ) const override;
348  bool loadH9(
349  UT_IStream &is,
350  const UT_Array<GA_AttribLoadDataH9> &prim_attribs,
351  const UT_Array<GA_AttribLoadDataH9> &vtx_attribs
352  ) override;
353 
354  bool saveVoxelArray(UT_JSONWriter &w,
355  const GA_SaveMap &map) const;
356  bool loadVoxelArray(UT_JSONParser &p,
357  const GA_LoadMap &map);
358 
359  bool loadRes(const UT_JSONValue &jval);
360  bool saveBorder(UT_JSONWriter &w,
361  const GA_SaveMap &map) const;
362  bool loadBorder(UT_JSONParser &p,
363  const GA_LoadMap &map);
364  bool saveCompression(UT_JSONWriter &w,
365  const GA_SaveMap &map) const;
366  bool loadCompression(UT_JSONParser &p,
367  const GA_LoadMap &map);
368  bool saveVisualization(UT_JSONWriter &w,
369  const GA_SaveMap &map) const;
370  bool loadVisualization(UT_JSONParser &p,
371  const GA_LoadMap &map);
372 
373  /// @{
374  /// Methods to save/load shared voxel data
375  static const int theSharedVoxelMagic=('V'<<24)|('o'<<16)|('x'<<8)|('l');
377  int dtype,
378  GA_SharedDataHandlePtr data) override;
379  bool saveSharedLoadData(
380  UT_JSONWriter &w,
381  GA_SaveMap &save,
382  GA_GeometryIndex *geo_index) const override;
383  bool getSharedVoxelKey(UT_WorkBuffer &key) const;
385  allocateSharedDataLoader();
386  /// @}
387 
388  // Transforms the matrix associated with this primitive. The
389  // translate component is ignored: Translate the vertices of
390  // the primitive to translate the primitive.
391  // This only works with quadrics (sphere, tube, metaballs) and volumes.
392  void transform(const UT_Matrix4 &mat) override;
393 
394  void reverse() override {}
395  GEO_Primitive *copy(int preserve_shared_pts = 0) const override;
396  void copyPrimitive(const GEO_Primitive *src) override;
397  void copySubclassData(const GA_Primitive *source) override;
402 
405  {
406  return getVertexOffset(0);
407  }
410  {
411  return getPointOffset(0);
412  }
415  {
416  return getPos3(0);
417  }
419  void setPos3(const UT_Vector3 &pos)
420  {
421  return setPos3(0, pos);
422  }
423 
424  // Take the whole set of points into consideration when applying the
425  // point removal operation to this primitive. The method returns 0 if
426  // successful, -1 if it failed because it would have become degenerate,
427  // and -2 if it failed because it would have had to remove the primitive
428  // altogether.
429  int detachPoints(GA_PointGroup &grp) override;
430 
431  /// Before a point is deleted, all primitives using the point will be
432  /// notified. The method should return "false" if it's impossible to
433  /// delete the point. Otherwise, the vertices should be removed.
434  GA_DereferenceStatus dereferencePoint(GA_Offset point,
435  bool dry_run=false) override;
436  GA_DereferenceStatus dereferencePoints(const GA_RangeMemberQuery &pt_q,
437  bool dry_run=false) override;
438 
439  bool isDegenerate() const override;
440 
441  // Map the normalized length (distance value [0,1]) parameter to the unit
442  // parameterization of the primitve
444  float ulength, float vlength,
445  float &uparm, float &vparm) const override;
447  float ulength, float vlength,
448  float &uparm, float &vparm,
449  float tolerance) const override;
450 
452  float uparm, float vparm,
453  float &ulength, float &vlength) const override;
454 
455  fpreal calcVolume(const UT_Vector3 &refpt) const override;
456  fpreal calcArea() const override;
457 
458 //
459 // Methods unique to PrimVolume.
460 
461 #if GA_PRIMITIVE_VERTEXLIST
463  void setVertexPoint(GA_Offset pt)
464  {
466  }
467 #else
469  {
470  wireVertex(myVertex, pt);
471  }
472 #endif
473 
474  /// This method assigns a preallocated vertex to the quadric, optionally
475  /// creating the topological link between the primitive and new vertex.
476  void assignVertex(GA_Offset new_vtx, bool update_topology);
477 
478  // Have we been deactivated and stashed?
479  void stashed(bool beingstashed,
480  GA_Offset offset = GA_INVALID_OFFSET) override;
481 
482  const UT_Matrix3 &getTransform() const { return myXform; }
483  void setTransform(const UT_Matrix3 &m)
484  { myXform = m;
485  myInverseXform = m;
486  myInverseXform.invert();
487  }
488 
489  void getTransform4( UT_Matrix4 &matx) const;
490  void getTransform4( UT_DMatrix4 &matx) const;
491  void setTransform4(const UT_Matrix4 &matx);
492  void setTransform4(const UT_DMatrix4 &matx);
493 
494  void getLocalTransform(UT_Matrix3D &x) const override;
495  void setLocalTransform(const UT_Matrix3D &x) override;
496 
497  /// Converts from world space to local space.
498  const UT_Matrix3 &getInverseTransform() const { return myInverseXform; }
499  void getInverseTransform4(UT_Matrix4 &matx) const;
500 
501  float getTaperX() const { return myTaperX; }
502  void setTaperX(float t) { myTaperX = t; }
503  float getTaperY() const { return myTaperY; }
504  void setTaperY(float t) { myTaperY = t; }
505 
506  /// True if the two volumes have same resolution and map the
507  /// same indices to the same positions.
508  bool isAligned(const GEO_PrimVolume *vol) const;
509 
510  /// True if we are aligned with the world axes. Ie, all our
511  /// off diagonals are zero and our diagonal is positive.
512  bool isWorldAxisAligned() const;
513 
514  /// Returns the POD class which can convert to and from
515  /// 0..1 voxel space coordinates.
516  GEO_PrimVolumeXform getSpaceTransform() const;
517  void setSpaceTransform(GEO_PrimVolumeXform xform);
518 
519  /// Returns the POD class which can convert to and from
520  /// voxel index space coordinates.
521  /// Note: The transformation is not the same as `posToIndex`
522  /// getIndexSpaceTransform().toVoxelSpace(pos) == posToIndex(pos) + {0.5, 0.5, 0.5}
523  GEO_PrimVolumeXform getIndexSpaceTransform() const;
524  GEO_PrimVolumeXform getIndexSpaceTransform(const UT_VoxelArrayF &vox) const;
525 
526  /// Converts from world space to 0..1 voxel space.
527  UT_Vector3 toVoxelSpace(const UT_Vector3 &pos) const;
528  /// Converts from 0..1 voxel space to world space.
529  UT_Vector3 fromVoxelSpace(const UT_Vector3 &pos) const;
530 
531  /// Converts from world space to 0..1 voxel space.
532  void toVoxelSpace(UT_BoundingBox &box) const;
533  /// Converts from 0..1 voxel space to world space.
534  void fromVoxelSpace(UT_BoundingBox &box) const;
535 
536  /// Copies the given voxel array and makes it our own voxel array.
537  void setVoxels(const UT_VoxelArrayF *vox);
538  void setVoxels(UT_VoxelArrayHandleF handle);
539 
540  /// Takes ownership of the voxel array, caller should not refer
541  /// to vox any more.
542  void stealVoxels(UT_VoxelArrayF *vox);
543 
544  /// Returns a handle to a voxel array containing our data.
545  /// This is should be thought of a copy of the data - changing
546  /// it will not change the underlying data, casting this to
547  /// a write handle will write to the newly created handle, not
548  /// the one stored in this volume.
549  UT_VoxelArrayHandleF getVoxelHandle() const;
550 
551  /// Returns a voxel handle without trying to load the shared data
552  /// This should only be used for the loader
553  /// DO NOT USE! IF YOU THINK YOU SHOULD YOUR PROBABLY WRONG
555  {
556  return myVoxelHandle;
557  }
558 
559  /// This is a handle that you can write to and affect the volume.
560  UT_VoxelArrayWriteHandleF getVoxelWriteHandle();
561 
562  /// Convert an index in the voxel array into the corresponding worldspace
563  /// location
564  bool indexToPos(int x, int y, int z, UT_Vector3 &pos) const;
565  void findexToPos(UT_Vector3 index, UT_Vector3 &pos) const;
566  bool indexToPos(exint x, exint y, exint z, UT_Vector3D &pos) const;
567  void findexToPos(UT_Vector3D index, UT_Vector3D &pos) const;
568 
569  /// Returns true if the given point is entirely inside the volume's
570  /// definition, ie, if posToIndex would return true.
571  bool isInside(UT_Vector3 pos) const;
572 
573  /// Returns true only if strictly inside. This means only actual
574  /// voxel samples will be used for interpolation, so the boundary
575  /// conditions will be unused
576  bool isInsideStrict(UT_Vector3 pos) const;
577  /// By passing in a specific read handle, we can accelerate
578  /// isInsideStrict()
579  bool isInsideStrict(const UT_Vector3 &opos, const UT_VoxelArrayReadHandleF &vox) const;
580 
581  /// Returns true only if index is inside.
582  bool isIndexInside(int x, int y, int z) const;
583  /// By passing in a specific read handle, we can accelerate
584  bool isIndexInside(int x, int y, int z, const UT_VoxelArrayReadHandleF &vox) const;
585 
586  /// Convert a 3d position into the closest index value. Returns
587  /// false if the resulting index was out of range (but still sets it)
588  bool posToIndex(UT_Vector3 pos, int &x, int &y, int &z) const;
589  bool posToIndex(UT_Vector3 pos, UT_Vector3 &index) const;
590  bool posToIndex(UT_Vector3D pos, exint &x, exint &y, exint &z) const;
591  bool posToIndex(UT_Vector3D pos, UT_Vector3D &index) const;
592 
593  /// Evaluate the voxel value at the given world space position.
594  fpreal getValue(const UT_Vector3 &pos) const;
595  void getValues(float *f, int stride, const UT_Vector3 *p, int num) const;
596  void getValues(double *f, int stride, const UT_Vector3D *p, int num) const;
597  // Only works with scalar grids.
598  UT_Vector3 getGradient(const UT_Vector3 &pos) const;
599  UT_Vector3 getGradient(const UT_Vector3 &pos, const UT_VoxelArrayReadHandleF &handle) const;
600 
601  /// By passing in a specific read handle and inverse transform
602  /// we can accelerate the getValue()
603  fpreal getValue(const UT_Vector3 &pos, const UT_VoxelArrayReadHandleF &handle) const;
604 
605  /// Evaluate the specific voxel indexed from 0,0,0.
606  fpreal getValueAtIndex(int ix, int iy, int iz) const;
607  void getValuesAtIndices(float *f, int stride, const int *ix, const int *iy, const int *iz, int num) const;
608  void getValuesAtIndices(int *f, int stride, const int *ix, const int *iy, const int *iz, int num) const;
609  void getValuesAtIndices(double *f, int stride, const exint *ix, const exint *iy, const exint *iz, int num) const;
610  void getValuesAtIndices(exint *f, int stride, const exint *ix, const exint *iy, const exint *iz, int num) const;
611  /// Returns the resolution of the voxel array.
612  void getRes(int &rx, int &ry, int &rz) const;
613  /// Computes the voxel diameter by taking a step in x, y, and z
614  /// converting to world space and taking the length of that vector.
615  fpreal getVoxelDiameter() const;
616 
617  /// Returns the length of the voxel when you take an x, y, and z step
618  UT_Vector3 getVoxelSize() const;
619 
620  /// Computes the total density of the volume, scaled by
621  /// the volume's size. Negative values will be ignored.
622  fpreal calcPositiveDensity() const;
623 
624  /// Compute useful aggregate properties of the volume.
625  fpreal calcMinimum() const;
626  fpreal calcMaximum() const;
627  fpreal calcAverage() const;
628 
629  /// Determines if we should be treated as an SDF. This means
630  /// our function will continue to increase outside of the bounding
631  /// box according to the distance to the bounding box.
632  bool isSDF() const { return myIsSDF; }
633 
634  /// Determine our orientation if we are to be considered a heightfield.
635  /// Returns false if we shouldn't be treated as a heightfield.
636  bool computeHeightFieldProperties(int &a1, int &a2, int &axis, fpreal &scale) const;
637  bool computeHeightFieldProperties(int &a1, int &a2, int &axis, fpreal &scale, const UT_VoxelArrayF &vox, const GEO_PrimVolumeXform &indexxform) const;
638 
639  /// Get the border options in terms of GEO's values.
640  static const char *getBorderToken(GEO_VolumeBorder border);
641  static GEO_VolumeBorder getBorderEnum(const char *token,
643  void setBorder(GEO_VolumeBorder border, fpreal val);
644  GEO_VolumeBorder getBorder() const;
645  fpreal getBorderValue() const;
646 
647  /// Control the compression of these objects.
648  fpreal getCompressionTolerance() const;
649  void setCompressionTolerance(fpreal tol);
650  void recompress();
651 
652  /// Control how we display this in the viewport
653  static const char *getVisualizationToken(GEO_VolumeVis vis);
654  static GEO_VolumeVis getVisualizationEnum(const char *vis,
656  const GEO_VolumeOptions &getVisOptions() const { return myVis; }
658  { setVisualization(vis.myMode, vis.myIso, vis.myDensity); }
659  void setVisualization(GEO_VolumeVis vis, fpreal iso, fpreal density);
660  fpreal getVisIso() const { return myVis.myIso; }
661  fpreal getVisDensity() const { return myVis.myDensity; }
662  GEO_VolumeVis getVisualization() const { return myVis.myMode; }
663 
664  const GA_PrimitiveJSON *getJSON() const override;
665 
666  /// Voxel traverser. This serializes the voxels into a linear array of
667  /// scalar data.
668  class serialize
669  {
670  public:
672  : myVoxels()
673  , myBorder(0)
674  , myXres(0)
675  , myYres(0)
676  , myZres(0)
677  , myEntries(0)
678  , myCurr(0)
679  {}
681  : myVoxels(src.myVoxels)
682  , myBorder(src.myBorder)
683  , myXres(src.myXres)
684  , myYres(src.myYres)
685  , myZres(src.myZres)
686  , myEntries(src.myEntries)
687  , myCurr(src.myCurr)
688  {}
690  {
691  myVoxels = src.myVoxels;
692  myBorder = src.myBorder;
693  myXres = src.myXres;
694  myYres = src.myYres;
695  myZres = src.myZres;
696  myEntries = src.myEntries;
697  myCurr = src.myCurr;
698  return *this;
699  }
700  /// Random access of a voxel value
702  {
703  if (index >= 0 && index < myEntries)
704  {
705  exint x, y, z;
706  x = index % myXres;
707  index = (index - x) / myXres;
708  y = index % myYres;
709  index = (index - y) / myYres;
710  z = index % myZres;
711  return (*myVoxels)(x, y, z);
712  }
713  return myBorder;
714  }
715 
716  /// @{
717  /// Iterator interface
718  bool atEnd() const { return myCurr >= myEntries; }
719  void rewind() { myCurr = 0; }
720  void advance() { myCurr++; }
721  serialize &operator++() { advance(); return *this; }
722  /// No post increment as it is harmful.
723  /// @}
724  /// Iterator access methods
725  exint entries() const { return myEntries; }
726  exint index() const { return myCurr; }
727  fpreal voxel() const { return getVoxel(myCurr); }
728  private:
729  serialize(const GEO_PrimVolume &prim)
730  : myVoxels(prim.getVoxelHandle())
731  , myCurr(0)
732  {
733  prim.getRes(myXres, myYres, myZres);
734  myBorder = prim.getBorderValue();
735  myEntries = myXres*myYres*myZres;
736  }
737  UT_VoxelArrayReadHandleF myVoxels;
738  fpreal myBorder;
739  exint myCurr, myEntries;
740  int myXres, myYres, myZres;
741  friend class GEO_PrimVolume;
742  };
743  serialize getSerialize() const { return serialize(*this); }
744 
745 
746  /// Acquire a CE grid and cache it on the GPU. If marked for
747  /// writing, the CPU version will be overwritten.
748  /// Note that the getVoxelHandle does *NOT* auto-flush these!
749  /// NOTE: If someone else fetches a non-read grid, and you fetch it
750  /// as a read grid, you will not get any copied data.
751  CE_Grid *getCEGrid(bool read, bool write) const;
752 
753  /// Any modified CE cache on the GPU will be copied back to the
754  /// CPU. Will leave result on GPU.
755  void flushCEWriteCaches() override;
756 
757  /// Remove all CE caches from the GPU, possibly writing back
758  /// if necessary.
759  void flushCECaches() override;
760 
761  /// Steal the underlying CE buffer from the source.
762  void stealCEBuffers(const GA_Primitive *src) override;
763 
764  /// Set a "proxy" compute grid that we may reference for our data, but
765  /// not modify. Upon first request, the data is then copied to a main
766  /// voxel array.
767  void setBorrowedCEGrid(CE_Grid* grid);
768  /// Returns true if this volume primitive has a compute grid that is
769  /// externally owned.
770  /// NOTE: this method should only be used to query presence of a borrowed
771  /// compute grid; getCEGrid() will automatically make a copy if needed.
772  bool hasBorrowedCEGrid() const { return !myCEGridIsOwned; }
773 
774 protected:
776  { return GA_FAMILY_NONE; }
777 
778 #if !GA_PRIMITIVE_VERTEXLIST
779  virtual void clearForDeletion();
780 #endif
781 
782 #if !GA_PRIMITIVE_VERTEXLIST
783  /// Defragmentation
784  virtual void swapVertexOffsets(const GA_Defragment &defrag);
785 #endif
786 
787  GA_DECLARE_INTRINSICS(override)
788 
789  virtual bool savePrivateH9(std::ostream &os, bool binary) const;
790  virtual bool loadPrivateH9(UT_IStream &is);
791 
792  // A versioned loading method.
793  bool loadVoxelDataH9(UT_IStream &is,
795  int version);
796 
798  { return getPointOffset(); }
799 
800  /// Gets the handle to our voxels
802 
803  // All accesses of myVoxelHandle should go though getMyVoxelHandle
804  // so that the voxels are loaded from shared data before access
809 
810  mutable CE_Grid *myCEGrid;
811  mutable bool myCEGridAuthorative;
812  mutable bool myCEGridIsOwned;
813 
814  bool evaluatePointRefMap(
815  GA_Offset result_vtx,
816  GA_AttributeRefMap &hlist,
817  fpreal u, fpreal v,
818  uint du, uint dv) const override;
820  UT_Vector4 &pos,
821  float u, float v = 0,
822  unsigned du=0, unsigned dv=0) const override
823  {
824  return GEO_Primitive::evaluatePointV4(pos, u, v,
825  du, dv);
826  }
828  GA_Offset result_vertex,
829  GA_AttributeRefMap &hlist) const override;
830 
832  GA_Offset result_vtx,
833  GA_AttributeRefMap &map,
834  fpreal u, fpreal v, fpreal w=0) const override;
836  UT_Vector4 &pos,
837  fpreal u, fpreal v, fpreal w=0) const override;
838 
839 private:
840 #if !GA_PRIMITIVE_VERTEXLIST
841  GA_Offset myVertex; // My vertex
842 #endif
843  UT_Matrix3 myXform; // My Transform
844  UT_Matrix3 myInverseXform; // My inverse transform
845  bool myIsSDF : 1; // Are we a signed distance field?
846 
847  GEO_VolumeOptions myVis;
848 
849  // The taper is the radius of the bottom half, z-minus, of the default box
850  // The top half's radius is one. These radii are then modified by
851  // myXform.
852  fpreal myTaperX, myTaperY;
853 
854  friend std::ostream &operator<<(std::ostream &os, const GEO_PrimVolume &d)
855  {
856  d.saveH9(os, 0,
859  return os;
860  }
862 };
864 
865 #endif
void fromVoxelSpace(UT_BoundingBox &box) const
virtual void flushCEWriteCaches()
Copy any modified caches from the GPU back to CPU cache.
Definition: GA_Primitive.h:783
void setTaperX(float t)
virtual void flushCECaches()
Definition: GA_Primitive.h:787
serialize getSerialize() const
GLboolean GLboolean GLboolean b
Definition: glcorearb.h:1221
Definition of a geometry attribute.
Definition: GA_Attribute.h:196
GEO_VolumeVis getVisualization() const
virtual GEO_Primitive * copy(int preserve_shared_pts=0) const
SYS_FORCE_INLINE GA_Offset getPointOffset(GA_Size i) const
Definition: GA_Primitive.h:254
UT_Matrix3 fromVoxelSpaceJacobian(UT_Vector3 pos) const
GLint GLint GLsizei GLint border
Definition: glcorearb.h:107
virtual UT_Vector3 baryCenter() const
virtual void copyPrimitive(const GEO_Primitive *src)=0
virtual void clearForDeletion()
Definition: GA_Primitive.h:658
UT_VoxelArrayHandleF myVoxelHandle
GLenum GLenum GLenum GLenum GLenum scale
Definition: glew.h:14163
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)
#define SYS_DEPRECATED_PUSH_DISABLE()
float getTaperY() const
#define SYS_DEPRECATED_POP_DISABLE()
virtual void copySubclassData(const GA_Primitive *source)
Definition: GA_Primitive.h:484
void setVisOptions(const GEO_VolumeOptions &vis)
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:1923
fpreal calcVolume(const UT_Vector3 &) const override
UT_Vector3T< float > UT_Vector3
SYS_FORCE_INLINE UT_Vector3 getPos3() const
serialize & operator=(const serialize &src)
virtual bool saveSharedLoadData(UT_JSONWriter &w, GA_SaveMap &save, GA_GeometryIndex *geo_index) const
int64 exint
Definition: SYS_Types.h:125
fpreal getVisDensity() const
const GEO_VolumeOptions & getVisOptions() 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:88
#define GA_DECLARE_INTRINSICS(OVERRIDE)
Definition: GA_Primitive.h:80
bool enlargeBoundingBox(UT_BoundingRect &b, const GA_Attribute *P) const override
GEO_VolumeVis myMode
Class which writes ASCII or binary JSON streams.
Definition: UT_JSONWriter.h:35
Abstract base class for a range membership query object.
virtual bool savePrivateH9(std::ostream &os, bool binary) const
GLenum src
Definition: glcorearb.h:1792
fpreal calcArea() const override
UT_SharedPtr< GA_SharedDataHandle > GA_SharedDataHandlePtr
void read(T &in, bool &v)
Definition: ImfXdr.h:611
GLdouble GLdouble t
Definition: glew.h:1403
virtual void swapVertexOffsets(const GA_Defragment &defrag)
UT_Vector3 fromVoxelSpace(UT_Vector3 pos) const
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.
#define GA_INVALID_OFFSET
Definition: GA_Types.h:677
GLint GLenum GLint x
Definition: glcorearb.h:408
friend std::ostream & operator<<(std::ostream &os, const GEO_PrimVolume &d)
GLsizeiptr size
Definition: glcorearb.h:663
GLubyte GLubyte GLubyte GLubyte w
Definition: glcorearb.h:856
virtual bool isDegenerate() const =0
Is the primitive degenerate.
GA_Size GA_Offset
Definition: GA_Types.h:640
virtual bool enlargeBoundingSphere(UT_BoundingSphere &b, const GA_Attribute *P) const
const UT_Matrix3 & getTransform() const
UT_Vector3 toVoxelSpace(UT_Vector3 pos) const
SYS_FORCE_INLINE UT_Vector3 getPos3(GA_Size i) const
Definition: GA_Primitive.h:274
virtual void setLocalTransform(const UT_Matrix3D &matrix)
Set the local transform. The default implementation does nothing.
UT_Matrix3 toVoxelSpaceJacobian(UT_Vector3 pos) const
SYS_FORCE_INLINE T & y()
Definition: UT_Vector3.h:508
GEO_VolumeBorder
virtual int evaluateInteriorPointV4(UT_Vector4 &pos, fpreal u, fpreal v, fpreal w=0) const
UT_VoxelArrayHandleF & getMyVoxelHandle() const
Gets the handle to our voxels.
void setTransform(const UT_Matrix3 &m)
bool hasBorrowedCEGrid() const
const GLdouble * v
Definition: glcorearb.h:836
GLsizei GLsizei GLchar * source
Definition: glcorearb.h:802
#define SYS_FORCE_INLINE
Definition: SYS_Inline.h:45
const UT_Matrix3 & getInverseTransform() const
Converts from world space to local space.
SYS_FORCE_INLINE T & z()
Definition: UT_Vector3.h:510
virtual const GA_PrimitiveJSON * getJSON() const =0
fpreal getVoxel(exint index) const
Random access of a voxel value.
GLuint num
Definition: glew.h:2695
Provide a JSON interface to a primitive.
fpreal getVisIso() const
void setBorrowedCEGrid(CE_Grid *grid)
#define GEO_API
Definition: GEO_API.h:14
GLdouble GLdouble GLdouble z
Definition: glcorearb.h:847
GEO_VolumeVis
fpreal getBorderValue() const
A handle to simplify manipulation of multiple attributes.
GLfloat GLfloat p
Definition: glew.h:16656
Options during loading.
Definition: GA_LoadMap.h:42
virtual int getBBox(UT_BoundingBox *bbox) const =0
Defragmentation of IndexMaps.
Definition: GA_Defragment.h:45
float getTaperX() const
void toVoxelSpace(UT_BoundingBox &box) const
UT_Lock mySharedDataLock
void enlargeBounds(const UT_Vector3T< T > &min, const UT_Vector3T< T > &max)
bool saveH9(std::ostream &os, bool binary, const UT_Array< GA_AttribSaveDataH9 > &prim_attribs, const UT_Array< GA_AttribSaveDataH9 > &vtx_attribs) const override
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
static SamplingType samplingType(int i)
Convert the "uniformsamples" parm menu item index to a sampling type.
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:280
serialize(const serialize &src)
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
GLboolean * data
Definition: glcorearb.h:130
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
GLuint GLfloat * val
Definition: glcorearb.h:1607
virtual void getLocalTransform(UT_Matrix3D &matrix) const
virtual bool loadPrivateH9(UT_IStream &is)
GLsizei const GLint box[]
Definition: glew.h:11654
void setVertexPoint(GA_Offset pt)
virtual int detachPoints(GA_PointGroup &grp)=0
void setTaperY(float t)
static const UT_Array< GA_AttribSaveDataH9 > & theEmptySaveAttribs
Convience objects to pass as arguments to saveH9()/loadH9().
fpreal64 fpreal
Definition: SYS_Types.h:277
GLuint index
Definition: glcorearb.h:785
bool operator==(const GEO_PrimVolumeXform &x) const
SYS_FORCE_INLINE void initBounds()
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:240
virtual void stealCEBuffers(const GA_Primitive *src)
Steal the underlying CE buffer from the source.
Definition: GA_Primitive.h:790
const GLdouble * m
Definition: glew.h:9166
Class to store JSON objects as C++ objects.
Definition: UT_JSONValue.h:77
GLfloat f
Definition: glcorearb.h:1925
virtual bool evaluatePointRefMap(GA_Offset result_vtx, GA_AttributeRefMap &map, fpreal u, fpreal v=0, uint du=0, uint dv=0) const =0
SYS_FORCE_INLINE T & x()
Definition: UT_Vector3.h:506
virtual void addToBSphere(UT_BoundingSphere *bsphere) const
SYS_FORCE_INLINE GA_Offset getPointOffset() const
CE_Grid * myCEGrid
GLintptr offset
Definition: glcorearb.h:664
#define const
Definition: zconf.h:214
GLint GLenum GLboolean GLsizei stride
Definition: glcorearb.h:871
void write(T &out, bool v)
Definition: ImfXdr.h:332
virtual bool registerSharedLoadData(int load_data_type, GA_SharedDataHandlePtr item)
unsigned int uint
Definition: SYS_Types.h:45
void getRes(int &rx, int &ry, int &rz) const
Returns the resolution of the voxel array.
GLint y
Definition: glcorearb.h:102
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)
UT_VoxelArrayHandleF getHandleToVoxelsWithoutLoading() const