HDK
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
SIM_RawIndexField.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_RawendexField.h ( SIM Library, C++)
7  *
8  * COMMENTS:
9  * An RawIndexField tracks a per-voxel index so one can
10  * convert a raw field to a linear coordinate system
11  * and back again.
12  */
13 
14 #ifndef __SIM_RawIndexField__
15 #define __SIM_RawIndexField__
16 
17 #include "SIM_API.h"
18 
19 #include <UT/UT_VoxelArray.h>
20 
22 
23 #include "SIM_RawField.h"
24 
25 /// Voxel boxes are used to define voxel groups
27 {
28  SIM_VoxelBox();
29  SIM_VoxelBox(
30  const int xMin, const int yMin, const int zMin,
31  const int xEnd, const int yEnd, const int zEnd
32  );
33 
34  bool contains(const int x, const int y, const int z) const;
35 
36  // Represent all voxels v with begin[d] <= v[d] < end[d] for d < 3.
37  int begin[3];
38  int end[3];
39 };
40 
42 {
43 public:
45  typedef SIM_VoxelBox Box;
47  typedef int64 ScalarType;
48 
50  virtual ~SIM_RawIndexField();
51 
52  /// Copy constructor:
54 
55  /// Assigment operator:
57 
58  /// Initializes the field.
59  /// The resolution given is in terms of voxels, the actual dimensions
60  /// of this field may be slightly different due to the sampling
61  /// choice.
62  void init(SIM_FieldSample sample,
63  const UT_Vector3 &orig, const UT_Vector3 &size,
64  int xres, int yres, int zres);
65  void init(SIM_FieldSample sample,
66  const UT_Vector3 &orig, const UT_Vector3 &size,
67  int xres, int yres, int zres,
68  const UT_Vector3 &voxelsize);
69  /// Initializes the field.
70  /// Will gain ownership of the given voxel array.
71  void init(SIM_FieldSample sample,
72  const UT_Vector3 &orig, const UT_Vector3 &size,
73  UT_VoxelArrayI *voxels,
74  const UT_Vector3 &voxelsize);
75 
76  /// Initialize this to be the same dimension and sampling
77  /// patern as the given field.
78  void match(const SIM_RawField &src);
79  void match(const SIM_RawIndexField &src);
80 
81  /// Sets this field to a constant value
82  void makeConstant(exint cval);
83 
84  /// Convert indices to world coordinates and vice-versa. Note this uses
85  /// this field's indices which change depending on sampling.
86  bool indexToPos(int x, int y, int z, UT_Vector3 &pos) const;
87  bool indexToPos(exint x, exint y, exint z, UT_Vector3D &pos) const;
88  bool indexToPos(UT_Vector3I index, UT_Vector3 &pos) const;
89  UT_Vector3 indexToPos(UT_Vector3I index) const;
90 
91  /// Converts a worldspace position into an integer index.
92  bool posToIndex(UT_Vector3 pos, int &x, int &y, int &z) const;
93  UT_Vector3I posToIndex(UT_Vector3 pos) const;
94 
95 
96  /// Returns true if the given field and this one match in terms
97  /// of number of voxels and bounding box size.
98  /// This means the voxel cells match - not necessarily the sample
99  /// points!
100  bool isMatching(const SIM_RawIndexField *field) const;
101  bool isMatching(const SIM_RawField *field) const;
102 
103  /// Returns true if the two fields are precisely aligned. This
104  /// means that samples are matched so a given integer index
105  /// into either field would give the same result.
106  bool isAligned(const SIM_RawIndexField *field) const;
107  bool isAligned(const SIM_RawField *field) const;
108 
109  /// Returns true if two fields have voxels aligned.
110  /// They do not have to be of the same resolution or share origin.
111  /// However, using the `offset` allows to access this field with index
112  /// of the other field.
113  /// i.e. field->indexToPos(index) == this->indexToPos(index + offset)
114  bool isColocated(const SIM_RawField *field, UT_Vector3I &offset) const;
115  bool isColocated(const SIM_RawIndexField *field, UT_Vector3I &offset) const;
116 
117  /// Steals the voxel array, leaving this pointing to a 0 constant array.
118  UT_VoxelArrayI *steal();
119 
120  exint getMemoryUsage() const;
121 
122  /// Returns the resolution of the voxel grid that we are sampling.
123  /// This is a count of voxels, so may differ for our different
124  /// sampling methods.
125  UT_Vector3I getVoxelRes() const;
126  void getVoxelRes(int &xres, int &yres, int &zres) const;
127 
128  /// Returns the actual number of samples in each resolution.
129  /// Preferred over field()->getXRes() as it doesn't require a
130  /// copy of the CE fields.
131  int getXRes() const { return myField->getXRes(); }
132  int getYRes() const { return myField->getYRes(); }
133  int getZRes() const { return myField->getZRes(); }
134 
135  /// Consistently compute a world origin for what world space 0,0,0
136  /// would map to. A bit tricky as we want to avoid round off
137  /// if we line up to 0.5...
138  /// This is not necessarily 0,0,0.
139  void getWorldOrigin(int &origx, int &origy, int &origz) const;
140 
141  const UT_Vector3 &getVoxelSize() const { return myVoxelSize; }
142  void setVoxelSize(const UT_Vector3 &voxelsize)
143  { myVoxelSize = voxelsize;
144  myVoxelDiameter = voxelsize.length(); }
145  fpreal getVoxelDiameter() const { return myVoxelDiameter; }
146 
147  UT_VoxelBorderType getBorder() const { return myField->getBorder(); }
148  exint getBorderValue() const { return myField->getBorderValue(); }
150  { myField->setBorder(border, bval); }
151 
152  /// Returns true if the given x, y, z values lie inside the valid index.
153  bool isValidIndex(int x, int y, int z) const
154  {
155  return field()->isValidIndex(x, y, z);
156  }
157 
158  /// Returns the set of samples in *this* field which correspond
159  /// to the given location & sampling pattern.
160  /// ix, iy, and iz should be size 8.
161  /// If you want the deltas for the sampling pattern, call with
162  /// x, y, z zero and clamp to false.
163  void getSamplePattern(SIM_FieldSample sample,
164  int x, int y, int z,
165  int &numsample,
166  int *ix, int *iy, int *iz,
167  bool clamp) const;
168 
169  /// Builds from a surface & collision field.
170  /// -1 if inside collision, -2 if not in collision and not in
171  /// surface, otherwise a unique number.
172  /// Returns maximum index (which you can also get from getMaxIndex)
173  exint buildIndex(const SIM_RawField *surface,
174  const SIM_RawField *collision);
175 
176  // Partitions the voxels into sets.
177  exint buildPartitionedIndex(const SIM_RawField *surface,
178  const SIM_RawField *collision);
179 
180  // Each voxel is an index of where we should copy our values
181  // to perform a SAME boundary collision. this should already
182  // be inited to the desired resolution.
183  // -1 for voxels that don't need collision lookups, otherwise
184  // it is x+(y+z*yres)*xres
185  // Will only write to non- -1 voxels, so call constant(-1) first.
186  THREADED_METHOD1(SIM_RawIndexField, shouldMultiThread(),
187  buildCollisionLookup,
188  const SIM_RawField *, collision)
189  void buildCollisionLookupPartial(const SIM_RawField *collision,
190  const UT_JobInfo &info);
191 
192  /// Computes the connected components of the given field.
193  /// Anything with a value < 0 will be considered "inside" and
194  /// connected to each other. Voxels with a value >= 0 will be
195  /// flagged as being in component -1.
196  /// The maxIndex will store the number of connected components.
197  exint computeConnectedComponents(const SIM_RawField &surface);
198 
199  /// Computes the connected components according to the given index
200  /// values. Areas of -1, -2, and >=0 will be consdiered three different
201  /// material types and connectivity computed respectively.
202  exint computeConnectedComponents(const SIM_RawIndexField &idx);
203 
204  exint computeConnectedComponentsWeighted(const SIM_RawIndexField &idx,
205  const SIM_RawField *weights[3],
206  const SIM_RawIndexField *sliceindex = 0,
207  int thisslice = -1);
208 
209  /// Computes connectivity of the -2 and >= 0 material types.
210  void computeMetaConnected(UT_IntArray &metagroups,
211  const SIM_RawIndexField &idx) const;
212 
213  /// Returns true if this should be multithreaded.
214  bool shouldMultiThread() const
215  {
216  return field()->numTiles() > 1;
217  }
218 
219  exint operator()(int x, int y, int z) const
220  {
221  return (*field())(x, y, z);
222  }
224  {
225  return (*field())(vit.x(), vit.y(), vit.z());
226  }
227 
228  exint getValue(const UT_Vector3 &pos) const;
229 
230  const UT_VoxelArrayI *field() const { return myField; }
231  UT_VoxelArrayI *fieldNC() const { return myField; }
232 
233  exint maxIndex() const { return myMaxIndex; }
234 
235  const UT_Vector3 &getOrig() const { return myOrig; }
236  const UT_Vector3 &getSize() const { return mySize; }
237  const UT_Vector3 &getBBoxOrig() const { return myBBoxOrig; }
238  const UT_Vector3 &getBBoxSize() const { return myBBoxSize; }
239 
240  SIM_FieldSample getSample() const { return mySample; }
241 
242  void extrapolateClosestPoints(const SIM_RawIndexField *altclosept,
243  const GU_Detail *gdp,
244  const openvdb::tools::PointIndexGrid *ptgridvdb,
245  fpreal uniformradius,
246  fpreal bandwidth,
247  bool rebuildsdf,
248  SIM_RawField *dest = NULL,
249  const SIM_RawField::sim_particleToFieldParms *parms = NULL);
250 
251 protected:
252 
253  /// Given a set of connectivity classes, collapse into the minimal
254  /// set and renumber from 0. myMaxIndex will be updated with the
255  /// resulting maximum & the number of components returned.
256  exint collapseClassIndices();
257 
258  /// Determines if two indices should be connected using our empty
259  /// cell merge rule.
260  bool shouldConnectIndices(exint idx1, exint idx2) const;
261 
262  THREADED_METHOD3(SIM_RawIndexField, shouldMultiThread(),
263  initConnectedComponents,
264  const SIM_RawIndexField &, idx,
265  const SIM_RawIndexField *, sliceindex,
266  int, thisslice);
267  void initConnectedComponentsPartial(const SIM_RawIndexField &idx,
268  const SIM_RawIndexField *sliceindex,
269  int thisslice,
270  const UT_JobInfo &info);
271 
272  THREADED_METHOD1(SIM_RawIndexField, shouldMultiThread(),
273  applyLookup,
274  const UT_VoxelArrayI &, lut);
275  void applyLookupPartial(const UT_VoxelArrayI &lut,
276  const UT_JobInfo &info);
277 
281 
282  // This is the size and offset which converts our UT_VoxelArray into
283  // world coordinates.
285 
286  // This is our actual official size.
287  UT_Vector3 myBBoxOrig, myBBoxSize;
288 
289  // Cached metrics.
292 
293  // Find ranges of indices for valid voxels
294  void findRange
295  (
296  const SIM_RawField* surface,
297  const SIM_RawField* collision,
298  int begin[3],
299  int end[3]
300  ) const;
301 
302  // Count all valid voxels in a box
303  exint countVoxelsInBox
304  (
305  const SIM_RawField* surface,
306  const SIM_RawField* collision,
307  const Box& box
308  ) const;
309 
310 
311  // Closest point extrapolation functions.
313 
314  static sim_extrapelem indexToElement(const UT_VoxelArrayI &U,
315  int x, int y, int z);
316 
317  static void elementToIndex(const UT_VoxelArrayI &U, sim_extrapelem idx,
318  int &x, int &y, int &z);
319 
320  void computeQueryOffsets(const SIM_RawIndexField *nindex,
321  int nsamples,
322  const int *dx, const int *dy, const int *dz,
323  UT_Vector3Array &queryoffsets,
324  UT_ValArray<fpreal> &radii) const;
325 
327  {
331  const GU_Detail *gdp;
338  };
339 
340  THREADED_METHOD1(SIM_RawIndexField, shouldMultiThread(),
341  buildActiveLists,
342  const sim_buildActiveParms &, parms);
343 
344  void buildActiveListsPartial(const sim_buildActiveParms &parms,
345  const UT_JobInfo &info);
346 
347  THREADED_METHOD4(SIM_RawIndexField, tileoccupied.entries() > 10,
348  uncompressActiveTiles,
349  UT_VoxelArrayI &, closept,
350  UT_VoxelArrayI &, newclosept,
351  UT_VoxelArrayF *, dest,
352  const UT_ValArray<bool> &, tileoccupied);
353 
354  void uncompressActiveTilesPartial(UT_VoxelArrayI &closept,
355  UT_VoxelArrayI &newclosept,
356  UT_VoxelArrayF *dest,
357  const UT_ValArray<bool> &tileoccupied,
358  const UT_JobInfo &info);
359 
361  {
362  const GU_Detail *gdp;
373  };
374 
375  THREADED_METHOD1(SIM_RawIndexField, parms.elements->entries() > 50,
376  extrapolateActiveElements,
377  const sim_extrapActiveParms &, parms);
378 
379  void extrapolateActiveElementsPartial(const sim_extrapActiveParms &parms,
380  const UT_JobInfo &info);
381 
382  THREADED_METHOD4(SIM_RawIndexField, elements.entries() > 100,
383  applyExtrapolatedParticleToField,
384  const UT_ValArray<sim_extrapelem> &, elements,
385  const GU_Detail *, gdp,
386  SIM_RawField *, dest,
387  const SIM_RawField::sim_particleToFieldParms &, ptfparms);
388 
389  void applyExtrapolatedParticleToFieldPartial(
391  const GU_Detail *gdp,
392  SIM_RawField *dest,
394  const UT_JobInfo &info);
395 };
396 
397 #endif
398 
const UT_Vector3 & getBBoxOrig() const
int x() const
Retrieve the current location of the iterator.
const UT_ValArray< sim_extrapelem > * elements
const UT_VoxelArrayI * field() const
exint getBorderValue() const
const openvdb::tools::PointIndexGrid * ptgridvdb
UT_Array< int64 > Indices
exint operator()(int x, int y, int z) const
GLenum clamp
Definition: glcorearb.h:1234
exint maxIndex() const
void
Definition: png.h:1083
#define THREADED_METHOD1(CLASSNAME, DOMULTI, METHOD, PARMTYPE1, PARMNAME1)
const UT_Vector3 & getBBoxSize() const
Voxel boxes are used to define voxel groups.
GLdouble GLdouble GLdouble z
Definition: glcorearb.h:848
int64 exint
Definition: SYS_Types.h:125
UT_VoxelBorderType
Definition: UT_VoxelArray.h:70
UT_ValArray< UT_ValArray< sim_extrapelem > > * lists
GLint y
Definition: glcorearb.h:103
constexpr SYS_FORCE_INLINE T length() const noexcept
Definition: UT_Vector3.h:361
const UT_Vector3 & getVoxelSize() const
SIM_FieldSample getSample() const
bool isValidIndex(int x, int y, int z) const
Returns true if the given x, y, z values lie inside the valid index.
#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
UT_VoxelBorderType getBorder() const
UT_VoxelArrayI * myField
SIM_FieldSample mySample
GLintptr offset
Definition: glcorearb.h:665
GLuint GLuint end
Definition: glcorearb.h:475
const UT_Vector3 & getSize() const
long long int64
Definition: SYS_Types.h:116
#define THREADED_METHOD4(CLASSNAME, DOMULTI, METHOD, PARMTYPE1, PARMNAME1, PARMTYPE2, PARMNAME2, PARMTYPE3, PARMNAME3, PARMTYPE4, PARMNAME4)
GLint GLenum GLint x
Definition: glcorearb.h:409
void setVoxelSize(const UT_Vector3 &voxelsize)
GLsizeiptr size
Definition: glcorearb.h:664
Grid< PointIndexTree > PointIndexGrid
Point index grid.
GLint GLint GLsizei GLint border
Definition: glcorearb.h:108
fpreal64 fpreal
Definition: SYS_Types.h:277
Space-partitioning acceleration structure for points. Partitions the points into voxels to accelerate...
LeafData & operator=(const LeafData &)=delete
GLuint index
Definition: glcorearb.h:786
const UT_Vector3 & getOrig() const
#define SIM_API
Definition: SIM_API.h:12
const SIM_RawField::sim_particleToFieldParms * ptfparms
UT_VoxelArrayI * fieldNC() const
UT_Array< Box > Boxes
bool OIIO_UTIL_API contains(string_view a, string_view b)
Does 'a' contain the string 'b' within it?
fpreal getVoxelDiameter() const
void setBorder(UT_VoxelBorderType border, exint bval)
exint getIndex(const UT_VoxelArrayIteratorF &vit) const
UT_ValArray< UT_ValArray< sim_extrapelem > > * newelemlists
GLenum src
Definition: glcorearb.h:1793
PcpNodeRef_ChildrenIterator begin(const PcpNodeRef::child_const_range &r)
Support for range-based for loops for PcpNodeRef children ranges.
Definition: node.h:558