HDK
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
SIM_MatrixField.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_MatrixField.h ( SIM Library, C++)
7  *
8  * COMMENTS:
9  */
10 
11 #ifndef __SIM_MatrixField__
12 #define __SIM_MatrixField__
13 
14 #include "SIM_API.h"
15 
16 #include <UT/UT_VoxelArray.h>
17 
18 #include "SIM_Names.h"
19 #include "SIM_OptionsUser.h"
20 #include "SIM_DataUtils.h"
21 #include "SIM_RawField.h"
22 
23 class UT_IStream;
24 class SIM_Geometry;
25 class SIM_ScalarField;
26 class SIM_VectorField;
27 class SIM_IndexField;
28 
29 /// This class holds a three dimensional tensor field.
31  public SIM_OptionsUser
32 {
33 public:
35 
36  /// Accesses the relative path to the position data associated with
37  /// this geometry.
39 
40  /// Control the number of divisions.
44  GETSET_DATA_FUNCS_V3(SIM_NAME_DIV, RawDivisions);
45  GETSET_DATA_FUNCS_I("uniformdiv", RawUniformDivisions);
46  GETSET_DATA_FUNCS_F("divsize", RawDivisionSize);
49 
50  GETSET_DATA_FUNCS_V3("slicediv", SliceDivisions);
51  GETSET_DATA_FUNCS_V3("sliceoverlapneg", SliceOverlapNeg);
52  GETSET_DATA_FUNCS_V3("sliceoverlappos", SliceOverlapPos);
53  GETSET_DATA_FUNCS_I("slice", Slice)
54  exint getNumSlices() const { UT_Vector3D nslice = getSliceDivisions(); return exint(nslice.x() * nslice.y() * nslice.z()); }
55 
56  GETSET_DATA_FUNCS_I("totalvoxels", TotalVoxels);
57  GETSET_DATA_FUNCS_V3("totalvoxelres", TotalVoxelRes);
58 
60  GETSET_DATA_FUNCS_B("usefp16", UseFP16);
62  GETSET_DATA_FUNCS_I("border", RawBorder);
64  {
65  if (getRawBorder() == 3)
66  return UT_VOXELBORDER_MIRROR;
67  return (UT_VoxelBorderType) getRawBorder();
68  }
70  {
71  if (border == UT_VOXELBORDER_MIRROR)
72  setRawBorder(3);
73  setRawBorder(border);
74  }
75  GETSET_DATA_FUNCS_M3("initialvalue", InitialValue);
76 
77  /// Controls the dimensions of where the field is properly defined
78  /// in the field space.
79  void getBBox(UT_BoundingBox &bbox) const;
80 
82  {
83  return getCenter() - getSize()/2;
84  }
85 
86  /// Calculate the size and divisions according to options
87  /// such as 2d or equal sized voxels.
88  UT_Vector3 getDivisions() const;
89  UT_Vector3 getSize() const;
90  UT_Vector3 getCenter() const;
91 
92  /// Adjusts the size/divisions of this field, overriding
93  /// and twod or uniform voxel settings.
94  void setDivisions(const UT_Vector3 &div);
95  void setSize(const UT_Vector3 &div);
96  void setCenter(const UT_Vector3 &div);
97 
98  /// Resizes our field keeping our field data.
99  /// The final size will be an integer number of voxels matching
100  /// our current voxel size. The final center will be an integer
101  /// number of voxel offset from our current center. This allows
102  /// us to do a perfect copy of the data.
103  void resizeKeepData(const UT_Vector3 &size, const UT_Vector3 &center, bool keepdata, const char *address = 0, int port = -1);
104 
105  /// Match this field to the given reference field. We will
106  /// end up with the same size/divisions/twod/uniform,
107  /// but not the same sampling pattern
108  void matchField(const SIM_ScalarField *field);
109  void matchField(const SIM_VectorField *field);
110  void matchField(const SIM_MatrixField *field, bool matchsamples=false);
111  void matchField(const SIM_IndexField *field);
112 
113  bool isAligned(const SIM_ScalarField *field) const;
114  bool isAligned(const SIM_VectorField *field) const;
115  bool isAligned(const SIM_RawField *field) const;
116  /// True if we are component wise aligned, the subfields may still
117  /// not be aligned with respect to each other.
118  bool isAligned(const SIM_MatrixField *field) const;
119 
120  SIM_FieldSample getVoxelSample(int i, int j) const;
121  const UT_Vector3 &getVoxelSize(int i, int j) const;
122  fpreal getVoxelDiameter(int i, int j) const;
123  // Independent of sampling pattern, so constant between fields.
124  UT_Vector3 getVoxelSize() const { return getVoxelSize(0, 0); }
125  void setVoxelSize(const UT_Vector3 &voxelsize)
126  { for (int i = 0; i < 3; i++)
127  for (int j = 0; j < 3; j++)
128  myFields[i][j]->setVoxelSize(voxelsize);
129  }
130 
131  /// Access the field value given a world space location.
132  /// This does trilinear interpolation.
133  UT_Matrix3 getValue(const UT_Vector3 &pos) const;
134 
135  /// Gets the velocity at the given *voxel* location, interpolating
136  /// if we have corner or face velocities.
137  UT_Matrix3 getCellValue(int x, int y, int z) const;
138 
139  /// Adds a velocity to the given *voxel*. If this is face,
140  /// it is divided in two and spread on each of 6 faces. If it is
141  /// corner, it is divided by 8 and spread along each of 8 corners.
142  void addToCell(int x, int y, int z, const UT_Matrix3 &dv);
143 
144  /// Advects this field by the other given field.
145  void advect(const SIM_VectorField *vel, float timestep,
146  const SIM_RawField *collision,
147  SIM_FieldAdvection advectmethod,
148  float cfl);
149  void advect(sim_PointVelocity getVelocity, float timestep,
150  float voxelsize,
151  const SIM_RawField *collision = 0,
152  float cfl = 1.0f);
153 
154  /// Advects this by the velocity field, storing our min/max
155  /// interpolants into the min/max fields
156  void advectMinMax(SIM_MatrixField *minfield,
157  SIM_MatrixField *maxfield,
158  const SIM_VectorField *vel, float timestep,
159  const SIM_RawField *collision,
160  SIM_FieldAdvection advectmethod,
161  float cfl);
162 
163  /// Enforces boundary conditions on the array.
164  void enforceBoundary(const SIM_ScalarField *collision=0,
165  const SIM_MatrixField *cvel = 0,
166  const SIM_MatrixField *bvel = 0);
167 
168  /// Converts an integer index into a worldspace position.
169  bool indexToPos(int i, int j, int x, int y, int z, UT_Vector3 &pos) const;
170 
171  /// Converts a worldspace position into an integer index.
172  bool posToIndex(int i, int j, const UT_Vector3 &pos, int &x, int &y, int &z) const;
173 
174  /// Retrieve raw field.
175  const SIM_RawField *getField(int i, int j) const { return myFields[i][j]; }
176  SIM_RawField *getField(int i, int j) { return myFields[i][j]; }
177 
178  /// Sets the field to the given field, gaining ownership of it.
179  /// The new field must already match the field it will replace.
180  void setField(int i, int j, SIM_RawField *field);
181 
182  /// True if we contain any NANs
183  bool hasNan() const
184  {
185  int i, j;
186 
187  for (i = 0; i < 3; i++)
188  for (j = 0; j < 3; j++)
189  if (myFields[i][j]->hasNan())
190  return true;
191  return false;
192  }
193 
194  /// True if we have a constant value. Ignores end conditions
195  /// in determining this. Used as a rough guess that the field
196  /// is unused.
197  bool appearsToBeUnused() const
198  {
199  for (int i = 0; i < 3; i++)
200  for (int j = 0; j < 3; j++)
201  if (!getField(i, j)->field()->isConstant(0)) return false;
202  return true;
203  }
204 
205  /// Steals the field, replacing this copy with an empty field and
206  /// Steals the field, replacing this copy with an empty field and
207  /// returning the old version.
208  SIM_RawField *stealField(int i, int j);
209 
210  void testForNan() const;
212  {
213  testForNan();
215  }
217  { for (int i = 0; i < 3; i++) for (int j = 0; j < 3; j++) getField(i, j)->markGridAsChanged(); }
218 
219  /// Recomputes total number of voxels to be stored
220  /// on our options data for ease of reading
221  void updateTotalVoxels();
222 
223  /// Creates a GDP with us as a Volume Primitive inside it.
224  GU_ConstDetailHandle createSmokeRepresentation(const SIM_Data &root) const;
225 
226  /// Adds a volume primitive version of our field to the given
227  /// gdp.
228  void addSmokeRepresentation(const SIM_Data &root, GU_Detail *gdp) const;
229 
230 protected:
231  explicit SIM_MatrixField(const SIM_DataFactory *factory);
232  ~SIM_MatrixField() override;
233 
234  /// Overrides to properly implement this class as a SIM_Data.
235  void initializeSubclass() override;
236  /// myField aware copy constructor.
237  void makeEqualSubclass(const SIM_Data *source) override;
238 
239  /// Saves our attributes, and our internal data if it has been set.
240  void saveSubclass(std::ostream &os) const override;
241  /// Loads our attributes and internal data if it was set when we saved.
242  bool loadSubclass(UT_IStream &is) override;
243 
244  int64 getMemorySizeSubclass() const override;
245 
246  /// Override the setDivisions to rebuild our voxel array on demand.
247  void optionChangedSubclass(const char *name) override;
248 
249 private:
250  /// This method can be used to signal to this field not to attempt rebuilding
251  /// the raw field on option changes.
252  void setSkipFieldRebuildOnOptionChanged(bool skip)
253  {
254  mySkipFieldRebuild = skip;
255  }
256  /// Returns whether or not this field is set to skip rebuilding its raw field
257  /// on option changes.
258  bool getSkipFieldRebuildOnOptionChanged() const
259  {
260  return mySkipFieldRebuild;
261  }
262  /// This flag can be used to signal that the raw fields are not to be rebuilt due
263  /// to option changes.
264  bool mySkipFieldRebuild;
265 
266  friend class SkipFieldRebuildScope;
267 
268 public:
269  /// This helper class can be used to prevent the given field from automatically
270  /// attempting to rebuild its raw fields on option changes. The field will skip
271  /// rebuilds as long as this object remains in scope; the rebuild flag is reset
272  /// and rebuildField() is called when the object goes out of scope.
274  {
275  public:
277  {
278  myField = field;
279  myStashedValue = myField->getSkipFieldRebuildOnOptionChanged();
280  myField->setSkipFieldRebuildOnOptionChanged(true);
281  }
282 
284  {
285  myField->setSkipFieldRebuildOnOptionChanged(myStashedValue);
286  // Only invoke possible rebuilding if the old value was set to not
287  // skip.
288  if (!myStashedValue)
289  myField->rebuildFields();
290  }
291 
292  private:
293  SIM_MatrixField* myField;
294  bool myStashedValue;
295  };
296 
297 private:
298 
299  static const SIM_DopDescription *getMatrixFieldDopDescription();
300 
301  SIM_RawField *myFields[3][3];
302 
303  void rebuildFields();
304 
306 
308  SIM_Data,
309  "MatrixField",
310  getMatrixFieldDopDescription());
311 };
312 #endif
313 
#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)
#define SIM_NAME_VOXELSAMPLE
Definition: SIM_Names.h:217
#define DECLARE_STANDARD_GETCASTTOTYPE()
Definition: SIM_DataUtils.h:50
GA_API const UT_StringHolder div
virtual bool loadSubclass(UT_IStream &is)
#define SIM_NAME_TOLERANCE
Definition: SIM_Names.h:202
virtual void optionChangedSubclass(const char *name)
#define GETSET_DATA_FUNCS_B(DataName, FuncName)
#define SIM_NAME_CENTER
Definition: SIM_Names.h:82
void skip(T &in, int n)
Definition: ImfXdr.h:711
#define GETSET_DATA_FUNCS_S(DataName, FuncName)
#define SIM_NAME_DIV
Definition: SIM_Names.h:109
GLdouble GLdouble GLdouble z
Definition: glcorearb.h:848
virtual int64 getMemorySizeSubclass() const
UT_VoxelBorderType getBorder() const
constexpr SYS_FORCE_INLINE T & z() noexcept
Definition: UT_Vector3.h:667
int64 exint
Definition: SYS_Types.h:125
UT_VoxelBorderType
Definition: UT_VoxelArray.h:70
GLint y
Definition: glcorearb.h:103
This class holds a three dimensional scalar field.
#define GETSET_DATA_FUNCS_F(DataName, FuncName)
#define GETSET_DATA_FUNCS_M3(DataName, FuncName)
#define GETSET_DATA_FUNCS_V3(DataName, FuncName)
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
GLfloat f
Definition: glcorearb.h:1926
void pubHandleModification()
GLsizei GLsizei GLchar * source
Definition: glcorearb.h:803
virtual void saveSubclass(std::ostream &os) 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
void setBorder(UT_VoxelBorderType border)
#define SIM_NAME_TWOD
Definition: SIM_Names.h:207
SkipFieldRebuildScope(SIM_MatrixField *field)
GLuint const GLchar * name
Definition: glcorearb.h:786
This class holds a three dimensional tensor field.
GLint GLenum GLint x
Definition: glcorearb.h:409
GLint j
Definition: glad.h:2733
GLsizeiptr size
Definition: glcorearb.h:664
GLint GLint GLsizei GLint border
Definition: glcorearb.h:108
fpreal64 fpreal
Definition: SYS_Types.h:277
UT_Vector3 getVoxelSize() const
void handleModification(int code=-1)
SIM_FieldAdvection
Definition: SIM_RawField.h:60
#define SIM_API
Definition: SIM_API.h:12
This class holds a three dimensional scalar field.
SIM_RawField * getField(int i, int j)
constexpr SYS_FORCE_INLINE T & y() noexcept
Definition: UT_Vector3.h:665
const SIM_RawField * getField(int i, int j) const
Retrieve raw field.
This class holds a three dimensional vector field.
bool appearsToBeUnused() const
UT_Vector3 getOrig() const
SIM_RawField rawfield_type
bool hasNan() const
True if we contain any NANs.
constexpr SYS_FORCE_INLINE T & x() noexcept
Definition: UT_Vector3.h:663
void setVoxelSize(const UT_Vector3 &voxelsize)
virtual void initializeSubclass()