HDK
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
SIM_VectorField.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: SIM_VectorField.h ( SIM Library, C++)
7  *
8  * COMMENTS:
9  */
10 
11 #ifndef __SIM_VectorField__
12 #define __SIM_VectorField__
13 
14 #include "SIM_API.h"
15 
16 #include <UT/UT_VoxelArray.h>
17 #include <UT/UT_DMatrix3.h>
19 
20 #include "SIM_Names.h"
21 #include "SIM_OptionsUser.h"
22 #include "SIM_DataUtils.h"
23 #include "SIM_RawField.h"
24 
25 class UT_IStream;
26 class SIM_Geometry;
27 class SIM_RawField;
28 class SIM_ScalarField;
29 class SIM_MatrixField;
30 class SIM_IndexField;
31 class GEO_PrimVDB;
32 
33 /// This class holds a three dimensional vector field.
35  public SIM_OptionsUser
36 {
37 public:
39 
40  /// Accesses the relative path to the position data associated with
41  /// this geometry.
43 
44  /// Control the number of divisions.
48  GETSET_DATA_FUNCS_V3(SIM_NAME_DIV, RawDivisions);
49  GETSET_DATA_FUNCS_I("uniformdiv", RawUniformDivisions);
50  GETSET_DATA_FUNCS_F("divsize", RawDivisionSize);
53 
54  GETSET_DATA_FUNCS_V3("slicediv", SliceDivisions);
55  GETSET_DATA_FUNCS_V3("sliceoverlapneg", SliceOverlapNeg);
56  GETSET_DATA_FUNCS_V3("sliceoverlappos", SliceOverlapPos);
57  GETSET_DATA_FUNCS_I("slice", Slice)
58  exint getNumSlices() const { UT_Vector3D nslice = getSliceDivisions(); return exint(nslice.x() * nslice.y() * nslice.z()); }
59 
60  GETSET_DATA_FUNCS_I("totalvoxels", TotalVoxels);
61  GETSET_DATA_FUNCS_V3("totalvoxelres", TotalVoxelRes);
62 
64  GETSET_DATA_FUNCS_B("closedends", ClosedEnds);
65  GETSET_DATA_FUNCS_B("closexneg", CloseXNeg);
66  GETSET_DATA_FUNCS_B("closeyneg", CloseYNeg);
67  GETSET_DATA_FUNCS_B("closezneg", CloseZNeg);
68  GETSET_DATA_FUNCS_B("closexpos", CloseXPos);
69  GETSET_DATA_FUNCS_B("closeypos", CloseYPos);
70  GETSET_DATA_FUNCS_B("closezpos", CloseZPos);
71 
72  GETSET_DATA_FUNCS_V3(SIM_NAME_DIRECTION, ExternalDirection);
74  GETSET_DATA_FUNCS_B("usefp16", UseFP16);
75  GETSET_DATA_FUNCS_I("border", RawBorder);
76  UT_VoxelBorderType getBorder() const { return (UT_VoxelBorderType) getRawBorder(); }
77  void setBorder(UT_VoxelBorderType border) { setRawBorder(border); }
78 
79  /// Controls the dimensions of where the field is properly defined
80  /// in the field space.
81  void getBBox(UT_BoundingBox &bbox) const;
82 
84  {
85  return getCenter() - getSize()/2;
86  }
87 
88  /// Calculate the size and divisions according to options
89  /// such as 2d or equal sized voxels.
90  UT_Vector3 getDivisions() const;
91  UT_Vector3 getSize() const;
92  UT_Vector3 getCenter() const;
93 
94  /// Adjusts the size/divisions of this field, overriding
95  /// and twod or uniform voxel settings.
96  void setDivisions(const UT_Vector3 &div);
97  void setSize(const UT_Vector3 &div);
98  void setCenter(const UT_Vector3 &div);
99 
100  /// Resizes our field keeping our field data.
101  /// The final size will be an integer number of voxels matching
102  /// our current voxel size. The final center will be an integer
103  /// number of voxel offset from our current center. This allows
104  /// us to do a perfect copy of the data.
105  void resizeKeepData(const UT_Vector3 &size, const UT_Vector3 &center, bool keepdata, const char *address = 0, int port = -1);
106 
107  /// Match this field to the given reference field. We will
108  /// end up with the same size/divisions/twod/uniform,
109  /// but not the same sampling pattern
110  void matchField(const SIM_ScalarField *field);
111  void matchField(const SIM_VectorField *field, bool matchsample = false);
112  void matchField(const SIM_MatrixField *field);
113  void matchField(const SIM_IndexField *field);
114 
115  void matchVolume(const GEO_PrimVolume *vol, const UT_DMatrix4 &xform);
116  void matchVDB(const GEO_PrimVDB *vdb, const UT_DMatrix4 &xform);
117 
118  bool isAligned(const SIM_ScalarField *field) const;
119  bool isAligned(const SIM_MatrixField *field) const;
120  /// True if we are component-wise aligned, our x/y/z fields
121  /// may still be unaligned with respect to each other.
122  bool isAligned(const SIM_VectorField *field) const;
123  bool isAligned(const SIM_RawField *field) const;
124 
125  /// Determines if we match in terms of voxel cells - same bounding
126  /// box and number of cells. Due to sampling, this does not mean
127  /// the sample points will match
128  /// Because our internal fields are always matching by definition,
129  /// we can just test the first field.
130  bool isMatching(const SIM_VectorField *field) const
131  { return getField(0)->isMatching(field->getField(0)); }
132 
133  bool isFaceSampled() const
134  { return getVoxelSample(0) == SIM_SAMPLE_FACEX &&
135  getVoxelSample(1) == SIM_SAMPLE_FACEY &&
136  getVoxelSample(2) == SIM_SAMPLE_FACEZ; }
137 
138  bool isCenterSampled() const
139  { return getVoxelSample(0) == SIM_SAMPLE_CENTER &&
140  getVoxelSample(1) == SIM_SAMPLE_CENTER &&
141  getVoxelSample(2) == SIM_SAMPLE_CENTER; }
142 
143  bool isCornerSampled() const
144  { return getVoxelSample(0) == SIM_SAMPLE_CORNER &&
145  getVoxelSample(1) == SIM_SAMPLE_CORNER &&
146  getVoxelSample(2) == SIM_SAMPLE_CORNER; }
147 
148  /// True if our internal fields are aligned.
149  bool isSelfAligned() const
150  { return getVoxelSample(0) == getVoxelSample(1) &&
151  getVoxelSample(1) == getVoxelSample(2); }
152 
153 
154  SIM_FieldSample getVoxelSample(int axis) const;
155  const UT_Vector3 &getVoxelSize(int axis) const { return myFields[axis]->getVoxelSize(); }
156  fpreal getVoxelDiameter(int axis) const { return myFields[axis]->getVoxelDiameter(); }
157  // Independent of sampling pattern, so constant between fields.
158  UT_Vector3 getVoxelSize() const { return getVoxelSize(0); }
159  void setVoxelSize(const UT_Vector3 &voxelsize)
160  { myFields[0]->setVoxelSize(voxelsize);
161  myFields[1]->setVoxelSize(voxelsize);
162  myFields[2]->setVoxelSize(voxelsize);
163  }
164 
165  /// Access the field value given a world space location.
166  /// This does trilinear interpolation.
167  UT_Vector3 getValue(const UT_Vector3 &pos) const;
168 
169  /// Computes the gradient of the vector field in world space..
170  UT_DMatrix3 getGradient(const UT_Vector3 &pos) const;
171 
172  /// Computes the curl at a given worldspace
173  UT_Vector3 getCurl(const UT_Vector3 &pos) const;
174 
175  /// Gets the velocity at the given *voxel* location, interpolating
176  /// if we have corner or face velocities.
177  UT_Vector3 getCellValue(int x, int y, int z) const;
178 
179  /// Adds a velocity to the given *voxel*. If this is face,
180  /// it is divided in two and spread on each of 6 faces. If it is
181  /// corner, it is divided by 8 and spread along each of 8 corners.
182  void addToCell(int x, int y, int z, const UT_Vector3 &dv);
183 
184  /// Treats this field as a velocity field and advects the given
185  /// position for the given length of time.
186  /// Uses first order explicit euler integration
187  void advect(UT_Vector3 &pos, float time, float cfl = 1.0f) const
188  {
189  SIM_RawField::advect(pos, getXField(), getYField(), getZField(), time, 0, cfl);
190  }
191 
192  /// Uses second order explicit runge-kutta integration.
193  void advectMidpoint(UT_Vector3 &pos, float time, float cfl = 1.0f) const
194  {
195  SIM_RawField::advectMidpoint(pos, getXField(), getYField(), getZField(), time, 0, cfl);
196  }
197 
198  /// Uses third order explicit runge-kutta integration.
199  void advectRK3(UT_Vector3 &pos, float time, float cfl = 1.0f) const
200  {
201  SIM_RawField::advectRK3(pos, getXField(), getYField(), getZField(), time, 0, cfl);
202  }
203 
204  /// Uses fourth order explicit runge-kutta integration.
205  void advectRK4(UT_Vector3 &pos, float time, float cfl = 1.0f) const
206  {
207  SIM_RawField::advectRK4(pos, getXField(), getYField(), getZField(), time, 0, cfl);
208  }
209 
210  /// Advects this field by the other given field. Handles the possibility
211  /// that the other field is this field.
212  void advect(const SIM_VectorField *vel, float timestep,
213  const SIM_RawField *collision,
214  SIM_FieldAdvection advectmethod,
215  float cfl);
216  void advect(sim_PointVelocity getVelocity, float timestep,
217  float voxelsize,
218  const SIM_RawField *collision = 0,
219  float cfl = 1.0f);
220 
221  /// Advects this by the velocity field, storing our min/max
222  /// interpolants into the min/max fields
223  void advectMinMax(SIM_VectorField *minfield,
224  SIM_VectorField *maxfield,
225  const SIM_VectorField *vel, float timestep,
226  const SIM_RawField *collision,
227  SIM_FieldAdvection advectmethod,
228  float cfl);
229 
230  /// Projects the field into the space of non-divergent fields.
231  /// All divergent components of this field are removed.
232  void projectToNonDivergent(const SIM_RawField *pressureboundary = 0, const SIM_RawField *collision = 0, SIM_RawField *pressureout = 0, bool preservebubble = true, const SIM_RawField *goaldiv = 0, SIM_RawIndexField *compout = 0, bool ghostfluid = true, bool variational = true, SIM_RawField::PCG_METHOD pcgmethod = SIM_RawField::PCG_MIC, int numiterforcenter = 20);
233  void projectToNonDivergentCenter(const SIM_RawField *pressureboundary, const SIM_RawField *goaldiv, int numiter);
234  void projectToNonDivergentFace(const SIM_RawField *pressureboundary, const SIM_RawField *collision, SIM_RawField *pressureout = 0, bool preservebubble = true, const SIM_RawField *goaldiv = 0, SIM_RawIndexField *compout = 0, bool ghostfluid = true, bool variational = true, SIM_RawField::PCG_METHOD pcgmethod = SIM_RawField::PCG_MIC);
235 
236  /// Evaluates the divergence field for this velocity field.
237  /// If toCorner is true, the divergence field lives at the corners of the
238  /// grid. Note that if toCorner is false, then the computed divergence
239  /// field suffers from even-odd decoupling.
240  /// If a stencil field is provided, this velocity field is only affected for
241  /// voxels where the stencil value is greater than 0.5. The stencil field must
242  /// match this field.
244  bool toCorner = false) const
245  {
246  if(toCorner)
247  buildDivergenceCornerInternal(div, stencil, true);
248  else
249  buildDivergenceCenterInternal(div, stencil);
250  }
251  /// Evaluates the divergence field for this velocity field.
252  /// If a stencil field is provided, this velocity field is only affected for
253  /// voxels where the stencil value is greater than 0.5. The stencil field must
254  /// match this field, but be center-sampled (as opposed to corner-sampled).
256  const SIM_RawField* stencil = NULL) const
257  {
258  buildDivergenceCornerInternal(div, stencil, false);
259  }
260 
261  /// Applies a pressure differential to the given component of our
262  /// velocity field
263  /// If a stencil field is provided, it must be aligned with pressure.
264  /// A face velocity will be updated if one of the adjacent stencil voxels
265  /// is greater than 0.5.
266  THREADED_METHOD6(SIM_VectorField, getField(axis)->shouldMultiThread(),
267  applyPressureGradientFace,
268  int, axis,
269  const SIM_RawField *, pressure,
270  const SIM_RawField *, surface,
271  const SIM_RawIndexField *, comp,
272  const SIM_RawField *, stencil,
273  bool, pressureBoundaryAtFace)
274  void applyPressureGradientFacePartial(int axis,
275  const SIM_RawField *pressure,
276  const SIM_RawField *surface,
277  const SIM_RawIndexField *comp,
278  const SIM_RawField *stencil,
279  bool pressureBoundaryAtFace,
280  const UT_JobInfo &info);
281 
282  /// Applies the pressure gradient to this velocity field. If fromCorner is
283  /// true, the pressure samples are assumed to live at the corners of the grid.
284  /// Note that if fromCorner is false, then the pressure gradient will suffer
285  /// from even-odd decoupling.
286  /// If a stencil field is provided, this velocity field is only affected for
287  /// voxels where the stencil value is greater than 0.5. The stencil field must
288  /// match this field.
289  void applyPressureGradientCenter(const SIM_RawField* pressure,
290  const SIM_RawField* stencil = NULL,
291  bool fromCorner = false)
292  {
293  if(fromCorner)
294  applyPressureGradientCornerInternal(pressure, stencil, false);
295  else
296  applyPressureGradientCenterInternal(pressure, stencil);
297  }
298  /// Applies the pressure gradient to this velocity field.
299  /// If a stencil field is provided, this velocity field is only affected for
300  /// voxels where the stencil value is greater than 0.5. The stencil field must
301  /// match this field, but be center-sampled (as opposed to corner-sampled).
303  const SIM_RawField* stencil = NULL)
304  {
305  applyPressureGradientCornerInternal(pressure, stencil, true);
306  }
307 
308  /// Distributes any divergence in the boundary condition among
309  /// all voxels equally.
310  void distributeBoundaryDivergenceToVolumeFace(SIM_RawField &div, const SIM_RawField *pressureboundary = 0, int compnum = -1, const SIM_RawIndexField *comp = 0);
311 
312  /// Determines if the given component has any surface cells.
313  /// result should be preloaded with false.
314  THREADED_METHOD6_CONST(SIM_VectorField, div.shouldMultiThread(),
315  hasSurfaceCell,
316  bool *, result,
317  SIM_RawField &, div,
318  const SIM_RawField *, pressureboundary,
319  const SIM_RawField *, collision,
320  int, compnum,
321  const SIM_RawIndexField &, comp)
322  void hasSurfaceCellPartial(bool *result, SIM_RawField &div, const SIM_RawField *pressureboundary, const SIM_RawField *collision, int compnum, const SIM_RawIndexField &comp, const UT_JobInfo &info) const;
323 
324  /// Distributes any divergence in the boundary condition among
325  /// all voxels that are on the boundary of the pressureboundary
326  /// but not on the collision boundary.
327  void distributeBoundaryDivergenceToSurfaceFace(SIM_RawField &div, const SIM_RawField *pressureboundary, const SIM_RawField *collision, int compnum, const UT_VoxelArray<int64> &comp);
328 
329  /// Enforces boundary conditions on the array.
330  /// Boundary line should be given in world space
331  void enforceBoundary(const SIM_ScalarField *collision=0,
332  const SIM_VectorField *cvel = 0,
333  const SIM_VectorField *bvel = 0, // Apply velocity to the SIM_BOUNDARY
334  const SIM_BoundaryLine &worldbline = SIM_BoundaryLine());
335 
336  typedef UT_Vector3 (*ut_velocityCalc)(const UT_Vector3 &pos, void *vp);
337  typedef void (*ut_physParmCalc)(const UT_Vector3 &pos, void *vp,
338  fpreal &bounce,
339  fpreal &friction,
340  fpreal &dynfriction);
341 
342 
343  /// Enforces boundary conditions on a velocity field by making
344  /// sure we are lifting from the surface, allowing tangential
345  /// motion.
346  /// forbidinterference keeps the normal enforcement behaviour of
347  /// explicitly setting all side boundaries that have a inward
348  /// pointing velocity to zero relative motion
349  /// SIM_BoundaryLine is given in world space and allows for an
350  /// open boundary to exist above a "line" in an otherwise closed
351  /// boundary.
352 
353  void enforceVelBoundary(const SIM_ScalarField *collision,
354  ut_velocityCalc calcVelocity,
355  void *vvp,
356  ut_physParmCalc calcPhysParms,
357  void *vpp,
358  bool forbidinterference,
359  const SIM_BoundaryLine &worldbline = SIM_BoundaryLine());
360 
361  /// Enforces boundary conditions on a velocity field by making
362  /// sure we are lifting from the surface, allowing tangential
363  /// motion.
364  /// forbidinterference keeps the normal enforcement behaviour of
365  /// explicitly setting all side boundaries that have a inward
366  /// pointing velocity to zero relative motion.
367  void enforceVelBoundaryVariational(const SIM_ScalarField *collision,
368  const SIM_VectorField *weights,
369  ut_velocityCalc calcVelocity,
370  void *vvp,
371  ut_physParmCalc calcPhysParms,
372  void *vpp,
373  bool threadsafe,
374  fpreal bandwidth);
375 
377  {
378  public:
382  ut_velocityCalc calcVelocity;
383  void *vvp;
384  ut_physParmCalc calcPhysParms;
385  void *vpp;
388  int axis;
389  };
390 
391  THREADED_METHOD1(SIM_VectorField, parms.u->shouldMultiThread(),
392  enforceVelBoundaryVariationalAxis,
394 
395 
396  void enforceVelBoundaryVariationalAxisPartial(
398  const UT_JobInfo &info);
399 
400  /// Converts an integer index into a worldspace position.
401  bool indexToPos(int axis, int x, int y, int z, UT_Vector3 &pos) const;
402 
403  /// Converts a worldspace position into an integer index.
404  bool posToIndex(int axis, const UT_Vector3 &pos, int &x, int &y, int &z) const;
405 
406  /// Retrieve raw field.
407  const SIM_RawField *getField(int axis) const { return myFields[axis]; }
408  const SIM_RawField *getXField() const { return myFields[0]; }
409  const SIM_RawField *getYField() const { return myFields[1]; }
410  const SIM_RawField *getZField() const { return myFields[2]; }
411 
412  SIM_RawField *getField(int axis) { return myFields[axis]; }
413  SIM_RawField *getXField() { return myFields[0]; }
414  SIM_RawField *getYField() { return myFields[1]; }
415  SIM_RawField *getZField() { return myFields[2]; }
416 
417  /// Sets the field to the given field, gaining ownership of it.
418  /// The new field must already match the field it will replace.
419  void setField(int axis, SIM_RawField *field);
420 
421  /// True if we contain any NANs
422  bool hasNan() const
423  { return getField(0)->hasNan() || getField(1)->hasNan() || getField(2)->hasNan(); }
424 
425  /// True if we have a constant value. Ignores end conditions
426  /// in determining this. Used as a rough guess that the field
427  /// is unused.
428  bool appearsToBeUnused() const
429  {
430  for (int i = 0; i < 3; i++)
431  if (!getField(i)->field()->isConstant(0)) return false;
432  return true;
433  }
434 
435  /// Steals the field, replacing this copy with an empty field and
436  /// returning the old version.
437  SIM_RawField *stealField(int axis);
438 
439  void testForNan() const;
440 
442  {
443  testForNan();
445  }
446 
448  { for (int i = 0; i < 3; i++) getField(i)->markGridAsChanged(); }
449 
450  /// Recomputes total number of voxels to be stored
451  /// on our options data for ease of reading
452  void updateTotalVoxels();
453 
454  /// Creates a GDP with us as a Volume Primitive inside it.
455  GU_ConstDetailHandle createSmokeRepresentation(const SIM_Data &root) const;
456 
457  /// Adds a volume primitive version of our field to the given
458  /// gdp.
459  void addSmokeRepresentation(const SIM_Data &root, GU_Detail *gdp) const;
460 
461 protected:
462  explicit SIM_VectorField(const SIM_DataFactory *factory);
463  ~SIM_VectorField() override;
464 
465  /// Overrides to properly implement this class as a SIM_Data.
466  void initializeSubclass() override;
467  /// myField aware copy constructor.
468  void makeEqualSubclass(const SIM_Data *source) override;
469 
470  /// Saves our attributes, and our internal data if it has been set.
471  void saveSubclass(std::ostream &os) const override;
472  /// Loads our attributes and internal data if it was set when we saved.
473  bool loadSubclass(UT_IStream &is) override;
474 
475  int64 getMemorySizeSubclass() const override;
476 
477  /// Override the setDivisions to rebuild our voxel array on demand.
478  void optionChangedSubclass(const char *name) override;
479 
480  /// Calculates the divergence at cell centers, using central finite difference of
481  /// the next and previous samples.
482  THREADED_METHOD2_CONST(SIM_VectorField, getField(0)->shouldMultiThread(),
483  buildDivergenceCenterInternal,
484  SIM_RawField&, div,
485  const SIM_RawField*, stencil);
486  void buildDivergenceCenterInternalPartial(SIM_RawField& div,
487  const SIM_RawField* stencil,
488  const UT_JobInfo& info) const;
489  /// Evaluates the divergence field for this velocity field.
490  /// If backCorner is true, the (i, j, k) divergence sample is assumed to live in the
491  /// back-left-down corner of the (i, j, k) cell; otherwise it lives in the front-right-up
492  /// corner.
493  THREADED_METHOD3_CONST(SIM_VectorField, getField(0)->shouldMultiThread(),
494  buildDivergenceCornerInternal,
495  SIM_RawField&, div,
496  const SIM_RawField*, stencil,
497  bool, backCorner);
498  void buildDivergenceCornerInternalPartial(SIM_RawField& div, const SIM_RawField* stencil,
499  bool backCorner, const UT_JobInfo& info) const;
500 
501  /// Applies gradient of the pressure field to this velocity field, using central
502  /// finite difference of the next and previous samples.
503  THREADED_METHOD2(SIM_VectorField, getField(0)->shouldMultiThread(),
504  applyPressureGradientCenterInternal,
505  const SIM_RawField*, pressure,
506  const SIM_RawField*, stencil);
507  void applyPressureGradientCenterInternalPartial(const SIM_RawField* pressure,
508  const SIM_RawField* stencil,
509  const UT_JobInfo& info);
510 
511  /// Applies gradient of the pressure field to this velocity field.
512  /// If backCorner is true, the (i, j, k) gradient sample is assumed to live in the
513  /// back-left-down corner of the (i, j, k) cell; otherwise it lives in the front-right-up
514  /// corner.
515  THREADED_METHOD3(SIM_VectorField, getField(0)->shouldMultiThread(),
516  applyPressureGradientCornerInternal,
517  const SIM_RawField*, pressure,
518  const SIM_RawField*, stencil,
519  bool, backCorner);
520  void applyPressureGradientCornerInternalPartial(const SIM_RawField* pressure,
521  const SIM_RawField* stencil,
522  bool backCorner,
523  const UT_JobInfo &info);
524 
525 private:
526  /// This method can be used to signal to this field not to attempt rebuilding
527  /// the raw field on option changes.
528  void setSkipFieldRebuildOnOptionChanged(bool skip)
529  {
530  mySkipFieldRebuild = skip;
531  }
532  /// Returns whether or not this field is set to skip rebuilding its raw field
533  /// on option changes.
534  bool getSkipFieldRebuildOnOptionChanged() const
535  {
536  return mySkipFieldRebuild;
537  }
538  /// This flag can be used to signal that the raw fields are not to be rebuilt due
539  /// to option changes.
540  bool mySkipFieldRebuild;
541 
542  friend class SkipFieldRebuildScope;
543 
544 public:
545  /// This helper class can be used to prevent the given field from automatically
546  /// attempting to rebuild its raw fields on option changes. The field will skip
547  /// rebuilds as long as this object remains in scope; the rebuild flag is reset
548  /// and rebuildField() is called when the object goes out of scope.
550  {
551  public:
553  {
554  myField = field;
555  myStashedValue = myField->getSkipFieldRebuildOnOptionChanged();
556  myField->setSkipFieldRebuildOnOptionChanged(true);
557  }
558 
560  {
561  myField->setSkipFieldRebuildOnOptionChanged(myStashedValue);
562  // Only invoke possible rebuilding if the old value was set to not
563  // skip.
564  if (!myStashedValue)
565  myField->rebuildFields();
566  }
567 
568  private:
569  SIM_VectorField* myField;
570  bool myStashedValue;
571  };
572 
573 private:
574  static const SIM_DopDescription *getVectorFieldDopDescription();
575 
576  SIM_RawField *myFields[3];
577 
578  void rebuildFields();
579 
581 
583  SIM_Data,
584  "VectorField",
585  getVectorFieldDopDescription());
586 };
587 #endif
588 
#define SIM_NAME_VOXELPLANE
Definition: SIM_Names.h:218
#define SIM_NAME_POSITIONPATH
Definition: SIM_Names.h:169
virtual void makeEqualSubclass(const SIM_Data *source)
bool appearsToBeUnused() const
#define SIM_NAME_VOXELSAMPLE
Definition: SIM_Names.h:217
#define DECLARE_STANDARD_GETCASTTOTYPE()
Definition: SIM_DataUtils.h:50
typedef int(APIENTRYP RE_PFNGLXSWAPINTERVALSGIPROC)(int)
GA_API const UT_StringHolder div
virtual bool loadSubclass(UT_IStream &is)
#define SIM_NAME_TOLERANCE
Definition: SIM_Names.h:202
#define THREADED_METHOD6_CONST(CLASSNAME, DOMULTI, METHOD, PARMTYPE1, PARMNAME1, PARMTYPE2, PARMNAME2, PARMTYPE3, PARMNAME3, PARMTYPE4, PARMNAME4, PARMTYPE5, PARMNAME5, PARMTYPE6, PARMNAME6)
virtual void optionChangedSubclass(const char *name)
static void advectRK3(UT_Vector3 &pos, const SIM_RawField *velx, const SIM_RawField *vely, const SIM_RawField *velz, float time, const SIM_RawField *collision=0, float cfl=1.0F)
Advect a point with TVD-RK3 method.
const UT_Vector3 & getVoxelSize(int axis) const
#define GETSET_DATA_FUNCS_B(DataName, FuncName)
void
Definition: png.h:1083
#define SIM_NAME_DIRECTION
Definition: SIM_Names.h:102
#define SIM_NAME_CENTER
Definition: SIM_Names.h:82
void skip(T &in, int n)
Definition: ImfXdr.h:613
GT_API const UT_StringHolder time
void buildDivergenceCorner(SIM_RawField &div, const SIM_RawField *stencil=NULL) const
#define THREADED_METHOD1(CLASSNAME, DOMULTI, METHOD, PARMTYPE1, PARMNAME1)
#define GETSET_DATA_FUNCS_S(DataName, FuncName)
#define SIM_NAME_DIV
Definition: SIM_Names.h:109
UT_Vector3T< float > UT_Vector3
bool isSelfAligned() const
True if our internal fields are aligned.
GLdouble GLdouble GLdouble z
Definition: glcorearb.h:848
virtual int64 getMemorySizeSubclass() const
static void advectRK4(UT_Vector3 &pos, const SIM_RawField *velx, const SIM_RawField *vely, const SIM_RawField *velz, float time, const SIM_RawField *collision=0, float cfl=1.0F)
Advect a point with TVD-RK4 method.
constexpr SYS_FORCE_INLINE T & z() noexcept
Definition: UT_Vector3.h:667
int64 exint
Definition: SYS_Types.h:125
const SIM_RawField * getField(int axis) const
Retrieve raw field.
const SIM_RawField * getYField() const
UT_VoxelBorderType
Definition: UT_VoxelArray.h:70
SIM_RawField * getXField()
static void advectMidpoint(UT_Vector3 &pos, const SIM_RawField *velx, const SIM_RawField *vely, const SIM_RawField *velz, float time, const SIM_RawField *collision=0, float cfl=1.0F)
Advect a point with the midpoint method.
GLint y
Definition: glcorearb.h:103
This class holds a three dimensional scalar field.
**But if you need a result
Definition: thread.h:613
SIM_RawField rawfield_type
#define GETSET_DATA_FUNCS_F(DataName, FuncName)
void setBorder(UT_VoxelBorderType border)
#define GETSET_DATA_FUNCS_V3(DataName, FuncName)
#define THREADED_METHOD3(CLASSNAME, DOMULTI, METHOD, PARMTYPE1, PARMNAME1, PARMTYPE2, PARMNAME2, PARMTYPE3, PARMNAME3)
__hostdev__ float getValue(uint32_t i) const
Definition: NanoVDB.h:5578
SIM_FieldSample
Definition: SIM_RawField.h:38
#define DECLARE_DATAFACTORY(DataClass, SuperClass, Description, DopParms)
Definition: SIM_DataUtils.h:63
#define SIM_NAME_SIZE
Definition: SIM_Names.h:184
void pubHandleModification()
GLfloat f
Definition: glcorearb.h:1926
UT_Vector3 getVoxelSize() const
SIM_RawField * getField(int axis)
#define THREADED_METHOD2(CLASSNAME, DOMULTI, METHOD, PARMTYPE1, PARMNAME1, PARMTYPE2, PARMNAME2)
GLsizei GLsizei GLchar * source
Definition: glcorearb.h:803
virtual void saveSubclass(std::ostream &os) const
SkipFieldRebuildScope(SIM_VectorField *field)
const SIM_RawField * getZField() const
bool isCornerSampled() const
#define SIM_NAME_UNIFORMVOXELS
Definition: SIM_Names.h:208
#define GETSET_DATA_FUNCS_I(DataName, FuncName)
long long int64
Definition: SYS_Types.h:116
#define SIM_NAME_TWOD
Definition: SIM_Names.h:207
GLuint const GLchar * name
Definition: glcorearb.h:786
bool isMatching(const SIM_VectorField *field) const
UT_VoxelBorderType getBorder() const
UT_Vector3 getOrig() const
This class holds a three dimensional tensor field.
GLint GLenum GLint x
Definition: glcorearb.h:409
bool isFaceSampled() const
#define THREADED_METHOD2_CONST(CLASSNAME, DOMULTI, METHOD, PARMTYPE1, PARMNAME1, PARMTYPE2, PARMNAME2)
bool hasNan() const
True if we contain any NANs.
static void advect(UT_Vector3 &pos, const SIM_RawField *velx, const SIM_RawField *vely, const SIM_RawField *velz, float time, const SIM_RawField *collision=0, float cfl=1.0F)
Verbs that can be performed on these fields.
GLsizeiptr size
Definition: glcorearb.h:664
GLint GLint GLsizei GLint border
Definition: glcorearb.h:108
void setVoxelSize(const UT_Vector3 &voxelsize)
fpreal64 fpreal
Definition: SYS_Types.h:277
void handleModification(int code=-1)
bool isCenterSampled() const
SIM_FieldAdvection
Definition: SIM_RawField.h:60
#define SIM_API
Definition: SIM_API.h:12
#define THREADED_METHOD6(CLASSNAME, DOMULTI, METHOD, PARMTYPE1, PARMNAME1, PARMTYPE2, PARMNAME2, PARMTYPE3, PARMNAME3, PARMTYPE4, PARMNAME4, PARMTYPE5, PARMNAME5, PARMTYPE6, PARMNAME6)
This class holds a three dimensional scalar field.
void advectRK3(UT_Vector3 &pos, float time, float cfl=1.0f) const
Uses third order explicit runge-kutta integration.
SIM_RawField * getYField()
void applyPressureGradientCorner(const SIM_RawField *pressure, const SIM_RawField *stencil=NULL)
void advect(UT_Vector3 &pos, float time, float cfl=1.0f) const
GLint GLfloat GLint stencil
Definition: glcorearb.h:1278
constexpr SYS_FORCE_INLINE T & y() noexcept
Definition: UT_Vector3.h:665
#define THREADED_METHOD3_CONST(CLASSNAME, DOMULTI, METHOD, PARMTYPE1, PARMNAME1, PARMTYPE2, PARMNAME2, PARMTYPE3, PARMNAME3)
fpreal getVoxelDiameter(int axis) const
This class holds a three dimensional vector field.
const SIM_RawField * getXField() const
void buildDivergenceCenter(SIM_RawField &div, const SIM_RawField *stencil=NULL, bool toCorner=false) const
SIM_RawField * getZField()
constexpr SYS_FORCE_INLINE T & x() noexcept
Definition: UT_Vector3.h:663
void advectRK4(UT_Vector3 &pos, float time, float cfl=1.0f) const
Uses fourth order explicit runge-kutta integration.
virtual void initializeSubclass()
void advectMidpoint(UT_Vector3 &pos, float time, float cfl=1.0f) const
Uses second order explicit runge-kutta integration.