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  bool 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  UT_Vector3D computeNormalD() const override;
344  bool saveH9(
345  std::ostream &os, bool binary,
346  const UT_Array<GA_AttribSaveDataH9> &prim_attribs,
347  const UT_Array<GA_AttribSaveDataH9> &vtx_attribs
348  ) const override;
349  bool loadH9(
350  UT_IStream &is,
351  const UT_Array<GA_AttribLoadDataH9> &prim_attribs,
352  const UT_Array<GA_AttribLoadDataH9> &vtx_attribs
353  ) override;
354 
355  bool saveVoxelArray(UT_JSONWriter &w,
356  const GA_SaveMap &map) const;
357  bool loadVoxelArray(UT_JSONParser &p,
358  const GA_LoadMap &map);
359 
360  bool loadRes(const UT_JSONValue &jval);
361  bool saveBorder(UT_JSONWriter &w,
362  const GA_SaveMap &map) const;
363  bool loadBorder(UT_JSONParser &p,
364  const GA_LoadMap &map);
365  bool saveCompression(UT_JSONWriter &w,
366  const GA_SaveMap &map) const;
367  bool loadCompression(UT_JSONParser &p,
368  const GA_LoadMap &map);
369  bool saveVisualization(UT_JSONWriter &w,
370  const GA_SaveMap &map) const;
371  bool loadVisualization(UT_JSONParser &p,
372  const GA_LoadMap &map);
373 
374  /// @{
375  /// Methods to save/load shared voxel data
376  static const int theSharedVoxelMagic=('V'<<24)|('o'<<16)|('x'<<8)|('l');
378  int dtype,
379  GA_SharedDataHandlePtr data) override;
380  bool saveSharedLoadData(
381  UT_JSONWriter &w,
382  GA_SaveMap &save,
383  GA_GeometryIndex *geo_index) const override;
384  bool getSharedVoxelKey(UT_WorkBuffer &key) const;
386  allocateSharedDataLoader();
387  /// @}
388 
389  // Transforms the matrix associated with this primitive. The
390  // translate component is ignored: Translate the vertices of
391  // the primitive to translate the primitive.
392  // This only works with quadrics (sphere, tube, metaballs) and volumes.
393  void transform(const UT_Matrix4 &mat) override;
394 
395  void reverse() override {}
396  GEO_Primitive *copy(int preserve_shared_pts = 0) const override;
397  void copyPrimitive(const GEO_Primitive *src) override;
398  void copySubclassData(const GA_Primitive *source) override;
403 
406  {
407  return getVertexOffset(0);
408  }
411  {
412  return getPointOffset(0);
413  }
416  {
417  return getPos3(0);
418  }
420  void setPos3(const UT_Vector3 &pos)
421  {
422  return setPos3(0, pos);
423  }
424 
425  // Take the whole set of points into consideration when applying the
426  // point removal operation to this primitive. The method returns 0 if
427  // successful, -1 if it failed because it would have become degenerate,
428  // and -2 if it failed because it would have had to remove the primitive
429  // altogether.
430  int detachPoints(GA_PointGroup &grp) override;
431 
432  /// Before a point is deleted, all primitives using the point will be
433  /// notified. The method should return "false" if it's impossible to
434  /// delete the point. Otherwise, the vertices should be removed.
435  GA_DereferenceStatus dereferencePoint(GA_Offset point,
436  bool dry_run=false) override;
437  GA_DereferenceStatus dereferencePoints(const GA_RangeMemberQuery &pt_q,
438  bool dry_run=false) override;
439 
440  bool isDegenerate() const override;
441 
442  // Map the normalized length (distance value [0,1]) parameter to the unit
443  // parameterization of the primitve
445  float ulength, float vlength,
446  float &uparm, float &vparm) const override;
448  float ulength, float vlength,
449  float &uparm, float &vparm,
450  float tolerance) const override;
451 
453  float uparm, float vparm,
454  float &ulength, float &vlength) const override;
455 
456  fpreal calcVolume(const UT_Vector3 &refpt) const override;
457  fpreal calcArea() const override;
458 
459 //
460 // Methods unique to PrimVolume.
461 
462 #if GA_PRIMITIVE_VERTEXLIST
464  void setVertexPoint(GA_Offset pt)
465  {
467  }
468 #else
470  {
471  wireVertex(myVertex, pt);
472  }
473 #endif
474 
475  /// This method assigns a preallocated vertex to the quadric, optionally
476  /// creating the topological link between the primitive and new vertex.
477  void assignVertex(GA_Offset new_vtx, bool update_topology);
478 
479  // Have we been deactivated and stashed?
480  void stashed(bool beingstashed,
481  GA_Offset offset = GA_INVALID_OFFSET) override;
482 
483  const UT_Matrix3 &getTransform() const { return myXform; }
484  void setTransform(const UT_Matrix3 &m)
485  { myXform = m;
486  myInverseXform = m;
487  myInverseXform.invert();
488  }
489 
490  void getTransform4( UT_Matrix4 &matx) const;
491  void getTransform4( UT_DMatrix4 &matx) const;
492  void setTransform4(const UT_Matrix4 &matx);
493  void setTransform4(const UT_DMatrix4 &matx);
494 
495  void getLocalTransform(UT_Matrix3D &x) const override;
496  void setLocalTransform(const UT_Matrix3D &x) override;
497 
498  /// Converts from world space to local space.
499  const UT_Matrix3 &getInverseTransform() const { return myInverseXform; }
500  void getInverseTransform4(UT_Matrix4 &matx) const;
501 
502  float getTaperX() const { return myTaperX; }
503  void setTaperX(float t) { myTaperX = t; }
504  float getTaperY() const { return myTaperY; }
505  void setTaperY(float t) { myTaperY = t; }
506 
507  /// True if the two volumes have same resolution and map the
508  /// same indices to the same positions.
509  bool isAligned(const GEO_PrimVolume *vol) const;
510 
511  /// True if we are aligned with the world axes. Ie, all our
512  /// off diagonals are zero and our diagonal is positive.
513  bool isWorldAxisAligned() const;
514 
515  /// Returns the POD class which can convert to and from
516  /// 0..1 voxel space coordinates.
517  GEO_PrimVolumeXform getSpaceTransform() const;
518  void setSpaceTransform(GEO_PrimVolumeXform xform);
519 
520  /// Returns the POD class which can convert to and from
521  /// voxel index space coordinates.
522  /// Note: The transformation is not the same as `posToIndex`
523  /// getIndexSpaceTransform().toVoxelSpace(pos) == posToIndex(pos) + {0.5, 0.5, 0.5}
524  GEO_PrimVolumeXform getIndexSpaceTransform() const;
525  GEO_PrimVolumeXform getIndexSpaceTransform(const UT_VoxelArrayF &vox) const;
526 
527  /// Converts from world space to 0..1 voxel space.
528  UT_Vector3 toVoxelSpace(const UT_Vector3 &pos) const;
529  /// Converts from 0..1 voxel space to world space.
530  UT_Vector3 fromVoxelSpace(const UT_Vector3 &pos) const;
531 
532  /// Converts from world space to 0..1 voxel space.
533  void toVoxelSpace(UT_BoundingBox &box) const;
534  /// Converts from 0..1 voxel space to world space.
535  void fromVoxelSpace(UT_BoundingBox &box) const;
536 
537  /// Copies the given voxel array and makes it our own voxel array.
538  void setVoxels(const UT_VoxelArrayF *vox);
539  void setVoxels(UT_VoxelArrayHandleF handle);
540 
541  /// Takes ownership of the voxel array, caller should not refer
542  /// to vox any more.
543  void stealVoxels(UT_VoxelArrayF *vox);
544 
545  /// Returns a handle to a voxel array containing our data.
546  /// This is should be thought of a copy of the data - changing
547  /// it will not change the underlying data, casting this to
548  /// a write handle will write to the newly created handle, not
549  /// the one stored in this volume.
550  UT_VoxelArrayHandleF getVoxelHandle() const;
551 
552  /// Returns a voxel handle without trying to load the shared data
553  /// This should only be used for the loader
554  /// DO NOT USE! IF YOU THINK YOU SHOULD YOUR PROBABLY WRONG
556  {
557  return myVoxelHandle;
558  }
559 
560  /// This is a handle that you can write to and affect the volume.
561  UT_VoxelArrayWriteHandleF getVoxelWriteHandle();
562 
563  /// Convert an index in the voxel array into the corresponding worldspace
564  /// location
565  bool indexToPos(int x, int y, int z, UT_Vector3 &pos) const;
566  void findexToPos(UT_Vector3 index, UT_Vector3 &pos) const;
567  bool indexToPos(exint x, exint y, exint z, UT_Vector3D &pos) const;
568  void findexToPos(UT_Vector3D index, UT_Vector3D &pos) const;
569 
570  /// Returns true if the given point is entirely inside the volume's
571  /// definition, ie, if posToIndex would return true.
572  bool isInside(UT_Vector3 pos) const;
573 
574  /// Returns true only if strictly inside. This means only actual
575  /// voxel samples will be used for interpolation, so the boundary
576  /// conditions will be unused
577  bool isInsideStrict(UT_Vector3 pos) const;
578  /// By passing in a specific read handle, we can accelerate
579  /// isInsideStrict()
580  bool isInsideStrict(const UT_Vector3 &opos, const UT_VoxelArrayReadHandleF &vox) const;
581 
582  /// Returns true only if index is inside.
583  bool isIndexInside(int x, int y, int z) const;
584  /// By passing in a specific read handle, we can accelerate
585  bool isIndexInside(int x, int y, int z, const UT_VoxelArrayReadHandleF &vox) const;
586 
587  /// Convert a 3d position into the closest index value. Returns
588  /// false if the resulting index was out of range (but still sets it)
589  bool posToIndex(UT_Vector3 pos, int &x, int &y, int &z) const;
590  bool posToIndex(UT_Vector3 pos, UT_Vector3 &index) const;
591  bool posToIndex(UT_Vector3D pos, exint &x, exint &y, exint &z) const;
592  bool posToIndex(UT_Vector3D pos, UT_Vector3D &index) const;
593 
594  /// Evaluate the voxel value at the given world space position.
595  fpreal getValue(const UT_Vector3 &pos) const;
596  void getValues(float *f, int stride, const UT_Vector3 *p, int num) const;
597  void getValues(double *f, int stride, const UT_Vector3D *p, int num) const;
598  // Only works with scalar grids.
599  UT_Vector3 getGradient(const UT_Vector3 &pos) const;
600  UT_Vector3 getGradient(const UT_Vector3 &pos, const UT_VoxelArrayReadHandleF &handle) const;
601 
602  /// By passing in a specific read handle and inverse transform
603  /// we can accelerate the getValue()
604  fpreal getValue(const UT_Vector3 &pos, const UT_VoxelArrayReadHandleF &handle) const;
605 
606  /// Evaluate the specific voxel indexed from 0,0,0.
607  fpreal getValueAtIndex(int ix, int iy, int iz) const;
608  void getValuesAtIndices(float *f, int stride, const int *ix, const int *iy, const int *iz, int num) const;
609  void getValuesAtIndices(int *f, int stride, const int *ix, const int *iy, const int *iz, int num) const;
610  void getValuesAtIndices(double *f, int stride, const exint *ix, const exint *iy, const exint *iz, int num) const;
611  void getValuesAtIndices(exint *f, int stride, const exint *ix, const exint *iy, const exint *iz, int num) const;
612  /// Returns the resolution of the voxel array.
613  void getRes(int &rx, int &ry, int &rz) const;
614  /// Computes the voxel diameter by taking a step in x, y, and z
615  /// converting to world space and taking the length of that vector.
616  fpreal getVoxelDiameter() const;
617 
618  /// Returns the length of the voxel when you take an x, y, and z step
619  UT_Vector3 getVoxelSize() const;
620 
621  /// Computes the total density of the volume, scaled by
622  /// the volume's size. Negative values will be ignored.
623  fpreal calcPositiveDensity() const;
624 
625  /// Compute useful aggregate properties of the volume.
626  fpreal calcMinimum() const;
627  fpreal calcMaximum() const;
628  fpreal calcAverage() const;
629 
630  /// Determines if we should be treated as an SDF. This means
631  /// our function will continue to increase outside of the bounding
632  /// box according to the distance to the bounding box.
633  bool isSDF() const { return myIsSDF; }
634 
635  /// Determine our orientation if we are to be considered a heightfield.
636  /// Returns false if we shouldn't be treated as a heightfield.
637  bool computeHeightFieldProperties(int &a1, int &a2, int &axis, fpreal &scale) const;
638  bool computeHeightFieldProperties(int &a1, int &a2, int &axis, fpreal &scale, const UT_VoxelArrayF &vox, const GEO_PrimVolumeXform &indexxform) const;
639 
640  /// Get the border options in terms of GEO's values.
641  static const char *getBorderToken(GEO_VolumeBorder border);
642  static GEO_VolumeBorder getBorderEnum(const char *token,
644  void setBorder(GEO_VolumeBorder border, fpreal val);
645  GEO_VolumeBorder getBorder() const;
646  fpreal getBorderValue() const;
647 
648  /// Control the compression of these objects.
649  fpreal getCompressionTolerance() const;
650  void setCompressionTolerance(fpreal tol);
651  void recompress();
652 
653  /// Control how we display this in the viewport
654  static const char *getVisualizationToken(GEO_VolumeVis vis);
655  static GEO_VolumeVis getVisualizationEnum(const char *vis,
657  const GEO_VolumeOptions &getVisOptions() const { return myVis; }
659  { setVisualization(vis.myMode, vis.myIso, vis.myDensity); }
660  void setVisualization(GEO_VolumeVis vis, fpreal iso, fpreal density);
661  fpreal getVisIso() const { return myVis.myIso; }
662  fpreal getVisDensity() const { return myVis.myDensity; }
663  GEO_VolumeVis getVisualization() const { return myVis.myMode; }
664 
665  const GA_PrimitiveJSON *getJSON() const override;
666 
667  /// Voxel traverser. This serializes the voxels into a linear array of
668  /// scalar data.
669  class serialize
670  {
671  public:
673  : myVoxels()
674  , myBorder(0)
675  , myXres(0)
676  , myYres(0)
677  , myZres(0)
678  , myEntries(0)
679  , myCurr(0)
680  {}
682  : myVoxels(src.myVoxels)
683  , myBorder(src.myBorder)
684  , myXres(src.myXres)
685  , myYres(src.myYres)
686  , myZres(src.myZres)
687  , myEntries(src.myEntries)
688  , myCurr(src.myCurr)
689  {}
691  {
692  myVoxels = src.myVoxels;
693  myBorder = src.myBorder;
694  myXres = src.myXres;
695  myYres = src.myYres;
696  myZres = src.myZres;
697  myEntries = src.myEntries;
698  myCurr = src.myCurr;
699  return *this;
700  }
701  /// Random access of a voxel value
703  {
704  if (index >= 0 && index < myEntries)
705  {
706  exint x, y, z;
707  x = index % myXres;
708  index = (index - x) / myXres;
709  y = index % myYres;
710  index = (index - y) / myYres;
711  z = index % myZres;
712  return (*myVoxels)(x, y, z);
713  }
714  return myBorder;
715  }
716 
717  /// @{
718  /// Iterator interface
719  bool atEnd() const { return myCurr >= myEntries; }
720  void rewind() { myCurr = 0; }
721  void advance() { myCurr++; }
722  serialize &operator++() { advance(); return *this; }
723  /// No post increment as it is harmful.
724  /// @}
725  /// Iterator access methods
726  exint entries() const { return myEntries; }
727  exint index() const { return myCurr; }
728  fpreal voxel() const { return getVoxel(myCurr); }
729  private:
730  serialize(const GEO_PrimVolume &prim)
731  : myVoxels(prim.getVoxelHandle())
732  , myCurr(0)
733  {
734  prim.getRes(myXres, myYres, myZres);
735  myBorder = prim.getBorderValue();
736  myEntries = myXres*myYres*myZres;
737  }
738  UT_VoxelArrayReadHandleF myVoxels;
739  fpreal myBorder;
740  exint myCurr, myEntries;
741  int myXres, myYres, myZres;
742  friend class GEO_PrimVolume;
743  };
744  serialize getSerialize() const { return serialize(*this); }
745 
746 
747  /// Acquire a CE grid and cache it on the GPU. If marked for
748  /// writing, the CPU version will be overwritten.
749  /// Note that the getVoxelHandle does *NOT* auto-flush these!
750  /// NOTE: If someone else fetches a non-read grid, and you fetch it
751  /// as a read grid, you will not get any copied data.
752  CE_Grid *getCEGrid(bool read, bool write) const;
753 
754  /// Any modified CE cache on the GPU will be copied back to the
755  /// CPU. Will leave result on GPU.
756  void flushCEWriteCaches() override;
757 
758  /// Remove all CE caches from the GPU, possibly writing back
759  /// if necessary.
760  void flushCECaches() override;
761 
762  /// Steal the underlying CE buffer from the source.
763  void stealCEBuffers(const GA_Primitive *src) override;
764 
765  /// Set a "proxy" compute grid that we may reference for our data, but
766  /// not modify. Upon first request, the data is then copied to a main
767  /// voxel array.
768  void setBorrowedCEGrid(CE_Grid* grid);
769  /// Returns true if this volume primitive has a compute grid that is
770  /// externally owned.
771  /// NOTE: this method should only be used to query presence of a borrowed
772  /// compute grid; getCEGrid() will automatically make a copy if needed.
773  bool hasBorrowedCEGrid() const { return !myCEGridIsOwned; }
774  /// Returns true if the volume is fully loaded. If it has a pending
775  /// CE grid (hasBorrowedCEGrid) or shared data to load, returns false.
776  bool isFullyLoaded() const
777  {
778  if (mySharedVoxelData) return false;
779  if (!myCEGridIsOwned && myCEGridAuthorative) return false;
780  return true;
781  }
782 
783 protected:
785  { return GA_FAMILY_NONE; }
786 
787 #if !GA_PRIMITIVE_VERTEXLIST
788  virtual void clearForDeletion();
789 #endif
790 
791 #if !GA_PRIMITIVE_VERTEXLIST
792  /// Defragmentation
793  virtual void swapVertexOffsets(const GA_Defragment &defrag);
794 #endif
795 
796  GA_DECLARE_INTRINSICS(override)
797 
798  virtual bool savePrivateH9(std::ostream &os, bool binary) const;
799  virtual bool loadPrivateH9(UT_IStream &is);
800 
801  // A versioned loading method.
802  bool loadVoxelDataH9(UT_IStream &is,
804  int version);
805 
807  { return getPointOffset(); }
808 
809  /// Gets the handle to our voxels
811 
812  // All accesses of myVoxelHandle should go though getMyVoxelHandle
813  // so that the voxels are loaded from shared data before access
818 
819  mutable CE_Grid *myCEGrid;
820  mutable bool myCEGridAuthorative;
821  mutable bool myCEGridIsOwned;
822 
823  bool evaluatePointRefMap(
824  GA_Offset result_vtx,
825  GA_AttributeRefMap &hlist,
826  fpreal u, fpreal v,
827  uint du, uint dv) const override;
829  UT_Vector4 &pos,
830  float u, float v = 0,
831  unsigned du=0, unsigned dv=0) const override
832  {
833  return GEO_Primitive::evaluatePointV4(pos, u, v,
834  du, dv);
835  }
837  GA_Offset result_vertex,
838  GA_AttributeRefMap &hlist) const override;
839 
841  GA_Offset result_vtx,
842  GA_AttributeRefMap &map,
843  fpreal u, fpreal v, fpreal w=0) const override;
845  UT_Vector4 &pos,
846  fpreal u, fpreal v, fpreal w=0) const override;
847 
848 private:
849 #if !GA_PRIMITIVE_VERTEXLIST
850  GA_Offset myVertex; // My vertex
851 #endif
852  UT_Matrix3 myXform; // My Transform
853  UT_Matrix3 myInverseXform; // My inverse transform
854  bool myIsSDF : 1; // Are we a signed distance field?
855 
856  GEO_VolumeOptions myVis;
857 
858  // The taper is the radius of the bottom half, z-minus, of the default box
859  // The top half's radius is one. These radii are then modified by
860  // myXform.
861  fpreal myTaperX, myTaperY;
862 
863  friend std::ostream &operator<<(std::ostream &os, const GEO_PrimVolume &d)
864  {
865  d.saveH9(os, 0,
868  return os;
869  }
871 };
873 
874 #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:798
void setTaperX(float t)
virtual void flushCECaches()
Definition: GA_Primitive.h:802
serialize getSerialize() const
GLboolean GLboolean GLboolean b
Definition: glcorearb.h:1222
Definition of a geometry attribute.
Definition: GA_Attribute.h:197
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:108
virtual UT_Vector3 baryCenter() const
virtual void copyPrimitive(const GEO_Primitive *src)=0
virtual void clearForDeletion()
Definition: GA_Primitive.h:673
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)
bool isFullyLoaded() const
virtual UT_Vector3D computeNormalD() const =0
#define SYS_DEPRECATED_PUSH_DISABLE()
float getTaperY() const
#define SYS_DEPRECATED_POP_DISABLE()
virtual void copySubclassData(const GA_Primitive *source)
Definition: GA_Primitive.h:499
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:1924
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
constexpr SYS_FORCE_INLINE T & z() noexcept
Definition: UT_Vector3.h:657
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:1793
fpreal calcArea() const override
UT_SharedPtr< GA_SharedDataHandle > GA_SharedDataHandlePtr
void read(T &in, bool &v)
Definition: ImfXdr.h:502
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:409
friend std::ostream & operator<<(std::ostream &os, const GEO_PrimVolume &d)
GLsizeiptr size
Definition: glcorearb.h:664
GLubyte GLubyte GLubyte GLubyte w
Definition: glcorearb.h:857
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
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:837
GLsizei GLsizei GLchar * source
Definition: glcorearb.h:803
#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
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:848
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
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:286
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
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:1608
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
virtual bool getBBox(UT_BoundingBox *bbox) const =0
GLuint index
Definition: glcorearb.h:786
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:805
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:1926
virtual bool evaluatePointRefMap(GA_Offset result_vtx, GA_AttributeRefMap &map, fpreal u, fpreal v=0, uint du=0, uint dv=0) const =0
virtual void addToBSphere(UT_BoundingSphere *bsphere) const
SYS_FORCE_INLINE GA_Offset getPointOffset() const
CE_Grid * myCEGrid
GLintptr offset
Definition: glcorearb.h:665
#define const
Definition: zconf.h:214
GLint GLenum GLboolean GLsizei stride
Definition: glcorearb.h:872
constexpr SYS_FORCE_INLINE T & y() noexcept
Definition: UT_Vector3.h:655
void write(T &out, bool v)
Definition: ImfXdr.h:287
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:103
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:895
UT_VoxelArrayHandleF getHandleToVoxelsWithoutLoading() const
constexpr SYS_FORCE_INLINE T & x() noexcept
Definition: UT_Vector3.h:653