HDK
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
SOP_ParmOverride.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: SOP Library (C++)
7  *
8  * COMMENTS:
9  * Helper class for evaluating parms with override dropdown menus.
10  */
11 
12 #ifndef __SOP_ParmOverride_h__
13 #define __SOP_ParmOverride_h__
14 
15 #include "GA/GA_AIFTuple.h"
16 #include "SOP_API.h"
17 #include "SOP_NodeVerb.h"
18 #include <FS/FS_Info.h>
19 #include <GU/GU_GroomUtils.h>
21 #include <TIL/TIL_TextureMap.h>
22 #include <UT/UT_VoxelArray.h>
23 #include <GU/GU_Feather.h>
24 #include <type_traits>
25 
27 {
28 public:
29  enum class OverrideType
30  {
31  NONE = 0,
34  SKINATTRIB,
35  TEXTURE,
37  };
38 
39  enum class UVMode
40  {
41  SKIN = 0,
42  CURVE,
43  FEATHER
44  };
45 
46  enum class BarbMode
47  {
48  PERPOINT = 0,
49  MAX
50  };
51 
52  class CacheData
53  {
54  public:
70  bool doramp;
72  bool dofit;
75 
76  };
77 
78  struct EvalTemp
79  {
80  float length;
82  };
83 
84  template<typename T>
86  {
87  friend SOP_ParmOverride;
88  public:
90 
91  void setDims(
92  exint shaftdim,
93  exint barbdim)
94  {
95  if (barbdim > 2)
96  {
97  UT_ASSERT(barbdim % 2 == 0);
98  }
99 
100  myNumPoints = shaftdim;
101  myNumBarbPoints = barbdim;
102  myData.setSize(shaftdim * barbdim);
103  }
104 
105  void bumpDims(
106  exint shaftdim,
107  exint barbdim)
108  {
109  if (barbdim > 2)
110  {
111  UT_ASSERT(barbdim % 2 == 0);
112  }
113 
114  myNumPoints = shaftdim;
115  myNumBarbPoints = barbdim;
116  myData.bumpSize(shaftdim * barbdim);
117  }
118 
119  template<typename FIRSTOV>
120  static
121  void getMaxDim(
122  exint &shaftdim,
123  exint &barbdim,
124  FIRSTOV first)
125  {
126  shaftdim = first.getShaftDim();
127  barbdim = first.getBarbDim();
128  }
129 
130  // Compute the maximum dimensions of some OverrideValues
131  template<typename FIRSTOV, typename... OV>
132  static
133  void getMaxDim(
134  exint &shaftdim,
135  exint &barbdim,
136  FIRSTOV first,
137  OV... overvalues)
138  {
139  exint current_shaft, current_barb, rest_shaft, rest_barb;
140 
141  getMaxDim(current_shaft, current_barb, first);
142  getMaxDim(rest_shaft, rest_barb, overvalues...);
143 
144  shaftdim = SYSmax(current_shaft, rest_shaft);
145  barbdim = SYSmax(current_barb, rest_barb);
146  }
147 
150  {
151  return myData;
152  }
153 
155  exint size() const
156  {
157  return myData.size();
158  }
159 
162  {
163  return myNumPoints;
164  }
165 
168  {
169  return myNumBarbPoints;
170  }
171 
174  {
175  UT_ASSERT(i < myNumPoints * myNumBarbPoints);
176  return myData[i];
177  }
178 
179  // Address array directly, no bounds checking
181  T& operator()(exint point, exint barbpoint)
182  {
183  UT_ASSERT(point < myNumPoints);
184  UT_ASSERT(barbpoint < myNumBarbPoints);
185  return myData[myNumBarbPoints * point + barbpoint];
186  }
187 
188  // elements by shaft/barb indices, with some additional logic for
189  // safely accessing elements when dims are smaller than the actual
190  // feather geometry. This is not actual bounds checking, just special
191  // cases for when we only have one element for the shaft or one element
192  // for barbs, or per barb side. More detail below.
193  //
194  // If the override has barbdim = 1, barbpoint is internally
195  // set to 0, always accessing the one barb element, so callers
196  // can just pass in the barb index safely, without checking dims.
197  //
198  // If barbdim == 2, each side has its own element (barbside left
199  // accesses barb value 0, barbside right access barb value 1. barbpoint
200  // is still set to 0 internally.
201  //
202  // If barbdim > 2, it should match left barb count + right barb count,
203  // and no actual bounds checking is done.
204  //
205  //
206  // If shaftdim is 1, point is internally set to 0, always accessing that
207  // one element, so again, callers can safely access with the actual
208  // shaft point index.
209  //
210  // If shaftdim > 1, shaftdim should equal number of shaft points on the
211  // caller side, so no actual bounds checking is done.
214  exint point,
215  BarbSide barbside,
216  exint barbpoint)
217  {
218  return SYSconst_cast(get(
219  point, barbside, barbpoint, myNumPoints, myNumBarbPoints));
220  }
221 
223  const T& operator()(
224  exint point,
225  BarbSide barbside,
226  exint barbpoint) const
227  {
228  return get(
229  point, barbside, barbpoint, myNumPoints, myNumBarbPoints);
230  }
231 
234  exint point,
235  BarbSide barbside,
236  exint barbpoint,
237  exint shaftdim,
238  exint barbdim)
239  {
240  return SYSconst_cast(get(
241  point, barbside, barbpoint, shaftdim, barbdim));
242  }
243 
245  const T& operator()(
246  exint point,
247  BarbSide barbside,
248  exint barbpoint,
249  exint shaftdim,
250  exint barbdim) const
251  {
252  return get(
253  point, barbside, barbpoint, shaftdim, barbdim);
254  }
255 
256  template<typename FN>
257  void setEachElement(FN &&fn)
258  {
259  for (int i=0; i<myNumPoints; ++i)
260  {
261  for (int j=0; j<myNumBarbPoints; ++j)
262  {
263  int center = myNumBarbPoints / 2;
264  auto barbside = j < center ? BarbSide::LEFT : BarbSide::RIGHT;
265  int barbpoint = barbside == BarbSide::LEFT
266  ? -j + center - 1
267  : j - center;
268 
269  (*this)(i, barbside, barbpoint) = fn(i, barbside, barbpoint);
270  }
271  }
272  }
273 
274  typename UT_ValArray<T>::iterator begin() { return typename UT_ValArray<T>::iterator(myData.begin()); }
275  typename UT_ValArray<T>::iterator end() { return typename UT_ValArray<T>::iterator(myData.end()); }
276  private:
278  const T& get(
279  exint point,
280  BarbSide barbside,
281  exint barbpoint,
282  exint shaftdim,
283  exint barbdim) const
284  {
285  if (shaftdim == 1)
286  {
287  point = 0;
288  }
289  else
290  {
291  UT_ASSERT(point < shaftdim);
292  }
293 
294  if (barbdim == 1)
295  {
296  return myData[point];
297  }
298  else if (barbdim == 2)
299  {
300  return myData[barbdim * point + int(barbside) - 1];
301  }
302  else
303  {
304  UT_ASSERT(barbpoint < barbdim/2);
305  int offset = barbdim / 2;
306  offset += barbside == BarbSide::LEFT ? -1 - barbpoint : barbpoint;
307 
308  UT_ASSERT(offset >= 0 && offset < myData.size());
309  return myData[barbdim * point + offset];
310  }
311  }
312 
313  UT_ValArray<T> myData;
314  exint myNumPoints = 1;
315  exint myNumBarbPoints = 1;
316  };
317 
321 
323  const SOP_NodeVerb::CookParms &cookparms,
324  const SOP_NodeParms &parms,
325  const UT_StringHolder &baseparmname,
326  const GU_Detail *gdp,
327  const GU_Detail *clumpgdp,
328  const GU_Detail *skingdp,
329  const GU_Detail *texprimgdp,
330  const GA_ROHandleV3 &uvattrib,
331  const UT_ValArray<OverrideType> &overridetypes);
332 
334  const SOP_NodeVerb::CookParms &cookparms,
335  const SOP_NodeParms &parms,
336  const UT_StringHolder &baseparmname,
337  const GU_Detail *gdp,
338  const GU_Detail *clumpgdp,
339  const GU_Detail *skingdp,
340  const GU_Detail *texprimgdp,
341  const GA_ROHandleV3 &uvattrib,
342  const GA_ROHandleV3 &curveuvattrib,
343  const UT_ValArray<OverrideType> &overridetypes,
344  const GA_Attribute *barbl,
345  const GA_Attribute *barbr,
346  const GA_Attribute *barbuvl,
347  const GA_Attribute *barbuvr);
348 
350  {
351  myBarbMode = mode;
352  }
353 
355  {
356  return myOverrideType;
357  }
358 
360  {
361  return myBaseParmValue;
362  }
363 
364  // eval curve, clump, skin and texture
365  void eval(
366  UT_FloatArray &out,
368  const GA_Offset skinprimoff,
369  const GA_OffsetArray &skinvertoffsets,
370  const UT_FloatArray &skinvertweights,
371  const UT_Vector3 &uv,
372  const GA_Offset curveprimoff,
373  const GA_OffsetListRef &curvevertoffsets,
374  const GA_Offset clumpprimoff,
375  const UT_ValArray<GA_OffsetArray> &clumpvertoffsets,
376  const UT_ValArray<UT_FloatArray> &clumpvertweights)
377  {
378  eval(
379  out,
380  target,
381  skinprimoff,
382  &skinvertoffsets,
383  &skinvertweights,
384  uv,
385  curveprimoff,
386  &curvevertoffsets,
387  clumpprimoff,
388  &clumpvertoffsets,
389  &clumpvertweights);
390  }
391 
392  // eval curve, skin and texture
393  void eval(
394  UT_FloatArray &out,
396  const GA_Offset skinprimoff,
397  const GA_OffsetArray &skinvertoffsets,
398  const UT_FloatArray &skinvertweights,
399  const UT_Vector3 &uv,
400  const GA_Offset curveprimoff,
401  const GA_OffsetListRef &curvevertoffsets)
402  {
403  eval(
404  out,
405  target,
406  skinprimoff,
407  &skinvertoffsets,
408  &skinvertweights,
409  uv,
410  curveprimoff,
411  &curvevertoffsets,
412  GA_INVALID_OFFSET, // no clump offset
413  nullptr, // no clump vert arrays
414  nullptr);
415  }
416 
417  // eval curve, skin and texture with uv span
418  void eval(
420  EvalTemp &temp,
422  const GA_Offset skinprimoff,
423  const GA_OffsetArray &skinvertoffsets,
424  const UT_FloatArray &skinvertweights,
425  const UT_Vector3 &uv,
426  const GA_Offset curveprimoff,
427  const GA_OffsetListRef &curvevertoffsets)
428  {
429  eval(
430  out,
431  temp,
432  target,
433  skinprimoff,
434  &skinvertoffsets,
435  &skinvertweights,
436  uv,
437  curveprimoff,
438  &curvevertoffsets,
439  GA_INVALID_OFFSET, // no clump offset
440  nullptr, // no clump vert arrays
441  nullptr);
442  }
443 
445  const GA_Offset skinprimoff,
446  const GA_OffsetArray &skinvertoffsets,
447  const UT_FloatArray &skinvertweights,
448  const UT_Vector3 &uv);
449 
451  const GA_Offset skinptoff);
452 
454  GA_AttributeOwner target) const;
455 
456  float postProcessVarying(float value) const;
457 
458  bool needSkin() const;
459 
460  bool needTexPrim() const;
461 
462  bool needUV() const;
463 
464  const GA_Attribute* getRequiredAttrib() const;
465 
466  bool hasChanged(const CacheData *cache) const;
467 
468  const UT_StringHolder&
469  getBaseName() const
470  {
471  return myBaseParmName;
472  }
473 
475  {
476  return myUVMode;
477  }
478 
479  bool
482  {
483  if (!cachedata ||
484  hasChanged(cachedata.get()))
485  {
486  cachedata.reset(getCacheData());
487  return true;
488  }
489  return false;
490  }
491 
492 private:
493  typedef UT_Tuple<int, int> UdimCoord;
494  struct MyHashCompare {
495  static size_t hash( const UdimCoord& x ) {
496  int xhash = SYSwang_inthash(std::get<0>(x));
497  return SYSwang_inthash(xhash + std::get<1>(x));
498  }
499  //! True if strings are equal
500  static bool equal( const UdimCoord& x, const UdimCoord& y ) {
501  return x==y;
502  }
503  };
504  typedef UT_ConcurrentHashMap<UdimCoord, UT_UniquePtr<TIL_TextureMap>, MyHashCompare> TexPathMap;
505 
506  // This eval() accepts pointers to the various offset arrays,
507  // so the public functions, which accept references, can pass nullptrs
508  // for unused arrays.
509  void eval(
510  OverrideValue<float> &out,
511  EvalTemp &temp,
513  const GA_Offset skinprimoff,
514  const GA_OffsetArray *skinvertoffsets,
515  const UT_FloatArray *skinvertweights,
516  const UT_Vector3 &uv,
517  const GA_Offset curveprimoff,
518  const GA_OffsetListRef *curvevertoffsets,
519  const GA_Offset clumpprimoff,
520  const UT_ValArray<GA_OffsetArray> *clumpvertoffsets,
521  const UT_ValArray<UT_FloatArray> *clumpvertweights);
522 
523  void eval(
524  UT_FloatArray &out,
526  const GA_Offset skinprimoff,
527  const GA_OffsetArray *skinvertoffsets,
528  const UT_FloatArray *skinvertweights,
529  const UT_Vector3 &uv,
530  const GA_Offset curveprimoff,
531  const GA_OffsetListRef *curvevertoffsets,
532  const GA_Offset clumpprimoff,
533  const UT_ValArray<GA_OffsetArray> *clumpvertoffsets,
534  const UT_ValArray<UT_FloatArray> *clumpvertweights)
535  {
536  OverrideValue<float> temp_out;
537  EvalTemp temp;
538 
539  eval(
540  temp_out,
541  temp,
542  target,
543  skinprimoff,
544  skinvertoffsets,
545  skinvertweights,
546  uv,
547  curveprimoff,
548  curvevertoffsets,
549  clumpprimoff,
550  clumpvertoffsets,
551  clumpvertweights);
552 
553  out.swap(temp_out.getArray());
554  }
555 
556  template<typename LOOKUPFN>
557  void lookupTexture(
558  OverrideValue<float> &out,
559  GA_Offset curveprimoff,
560  const UT_Vector3 &uv,
561  const GA_OffsetListRef *curvevertoffsets,
562  LOOKUPFN &&lookupfn);
563 
564  float lookupTexture(const UT_Vector3 &uv);
565 
566  float lookupTexturePrim(const UT_Vector3 &uv);
567 
568  static exint
569  findParmIndex(
570  const SOP_NodeParms &parms,
571  const UT_StringHolder &parmname);
572 
573  CacheData *getCacheData() const;
574 
575  void check();
576 
577  const SOP_NodeVerb::CookParms &myCookParms;
578  const SOP_NodeParms &myParms;
579  const UT_StringHolder &myBaseParmName;
580  const GU_Detail *myCurveGdp;
581  const GU_Detail *myClumpGdp;
582  const GU_Detail *mySkinGdp;
583  const GU_Detail *myTexGdp;
584  const GA_ROHandleV3 &myUVAttrib;
585  GA_ROHandleV3 myCurveUVAttrib;
588  GU_FeatherBarbROHandle<UT_Vector3> myBarbUVLHandle;
589  GU_FeatherBarbROHandle<UT_Vector3> myBarbUVRHandle;
590  exint myBaseParmIndex;
591  SOP_NodeParms::ParmType myBaseParmType;
592  exint myOverrideParmIndex;
593  exint myOptionsParmIndex;
594  exint myCurveAttribParmIndex;
595  exint myClumpAttribParmIndex;
596  exint mySkinAttribParmIndex;
597  exint myTextureParmIndex;
598  exint myTexPrimParmIndex;
599  exint myUVModeParmIndex;
600  UT_StringHolder myTexPrimName;
601  UT_VoxelArrayReadHandleF myTexPrimReadHandle;
602  exint myRampParmIndex;
603  exint myBarbRampToggleIndex;
604  exint myInRangeParmIndex;
605  exint myOutRangeParmIndex;
606  UVMode myUVMode = UVMode::SKIN;
607 
608  fpreal myBaseParmValue;
609  OverrideType myOverrideType;
610  UT_StringHolder myCurveAttribName;
611  UT_StringHolder myClumpAttribName;
612  UT_StringHolder mySkinAttribName;
613  UT_StringHolder myTexturePath;
614  bool myTextureValid;
615  const GA_Attribute *myCurveAttrib;
616  const GA_AIFTuple *myCurveTuple;
617  GA_ROHandleV3 myCurvePAttrib;
618  GA_ROHandleF myClumpAttrib;
619  GA_ROHandleF mySkinAttrib;
620  GA_ROHandleS myTexPrimNameAttrib;
621  UT_UniquePtr<TIL_TextureMap> myTextureMap;
622  TexPathMap myUdimMaps;
623  UT_Lock myUdimLock;
624  bool myUseUdim = false;
625 
626  bool myDoFit = false;
627  bool myDoRamp = false;
628 
629  GU_GroomFastRamp myRemapRamp;
630  bool myRemapRampMapToBarbs = false;
631 
632  UT_Vector2D myInRange = {0.0, 1.0};
633  UT_Vector2D myOutRange = {0.0, 1.0};
634 
635  BarbMode myBarbMode = BarbMode::MAX;
636 
637  template<typename T>
638  static T
639  evalAttrib(
640  const GA_AttributeOwner target,
641  const GA_Attribute *attrib,
642  const GA_AIFTuple *tuple,
643  const GA_Offset &primoff,
644  const GA_Offset &vertoff)
645  {
646  T value(1.0);
647 
648  if (!attrib || !tuple)
649  return value;
650 
651  const auto &attribgdp = attrib->getDetail();
652 
653  GA_AttributeOwner owner = attrib->getOwner();
654  GA_Offset offset(0);
655  if (owner == GA_ATTRIB_VERTEX)
656  offset = vertoff;
657  else if (owner == GA_ATTRIB_POINT)
658  offset = attribgdp.vertexPoint(vertoff);
659  else if (owner == GA_ATTRIB_PRIMITIVE)
660  offset = primoff;
661 
662  if constexpr (std::is_integral_v<T> || std::is_floating_point_v<T>)
663  {
664  tuple->get(attrib, offset, value);
665  }
666  else
667  {
668  tuple->get(attrib, offset, value.data(), T::tuple_size, 0);
669  }
670 
671  return value;
672  }
673 };
674 
675 #endif
676 
#define SYSmax(a, b)
Definition: SYS_Math.h:1538
GLint first
Definition: glcorearb.h:405
typedef int(APIENTRYP RE_PFNGLXSWAPINTERVALSGIPROC)(int)
SYS_FORCE_INLINE const GA_Detail & getDetail() const
Definition: GA_Attribute.h:208
Definition of a geometry attribute.
Definition: GA_Attribute.h:198
UT_ValArray< T >::iterator begin()
SYS_FORCE_INLINE exint size() const
SYS_FORCE_INLINE T & operator()(exint point, exint barbpoint)
SYS_FORCE_INLINE T & operator()(exint point, BarbSide barbside, exint barbpoint, exint shaftdim, exint barbdim)
GA_API const UT_StringHolder uv
static void getMaxDim(exint &shaftdim, exint &barbdim, FIRSTOV first, OV...overvalues)
int64 GA_DataId
Definition: GA_Types.h:687
GLsizei const GLfloat * value
Definition: glcorearb.h:824
bool needUV() const
SYS_FORCE_INLINE T * SYSconst_cast(const T *foo)
Definition: SYS_Types.h:136
int64 exint
Definition: SYS_Types.h:125
bool needSkin() const
IMATH_HOSTDEVICE constexpr bool equal(T1 a, T2 b, T3 t) IMATH_NOEXCEPT
Definition: ImathFun.h:105
GLint y
Definition: glcorearb.h:103
fpreal evalSkinPoint(const GA_Offset skinptoff)
std::tuple< Types...> UT_Tuple
Definition: UT_Tuple.h:53
const UT_StringHolder & getBaseName() const
void setBarbPromotionMode(BarbMode mode)
#define GA_INVALID_OFFSET
Definition: GA_Types.h:678
virtual bool get(const GA_Attribute *attrib, GA_Offset ai, int32 &data, int index=0) const =0
std::unique_ptr< T, Deleter > UT_UniquePtr
A smart pointer for unique ownership of dynamically allocated objects.
Definition: UT_UniquePtr.h:39
GA_Size GA_Offset
Definition: GA_Types.h:641
SYS_FORCE_INLINE const T & operator()(exint point, BarbSide barbside, exint barbpoint, exint shaftdim, exint barbdim) const
SOP_ParmOverride(const SOP_NodeVerb::CookParms &cookparms, const SOP_NodeParms &parms, const UT_StringHolder &baseparmname, const GU_Detail *gdp, const GU_Detail *clumpgdp, const GU_Detail *skingdp, const GU_Detail *texprimgdp, const GA_ROHandleV3 &uvattrib, const UT_ValArray< OverrideType > &overridetypes)
GLintptr offset
Definition: glcorearb.h:665
static void getMaxDim(exint &shaftdim, exint &barbdim, FIRSTOV first)
SYS_FORCE_INLINE exint getShaftDim() const
#define SYS_FORCE_INLINE
Definition: SYS_Inline.h:45
base_iterator< T, true > iterator
Definition: UT_Array.h:978
UT_ValArray< T >::iterator end()
bool updateOverrideCache(UT_UniquePtr< SOP_ParmOverride::CacheData > &cachedata) const
GLenum target
Definition: glcorearb.h:1667
GLint GLenum GLint x
Definition: glcorearb.h:409
SYS_FORCE_INLINE T & operator()(exint point, BarbSide barbside, exint barbpoint)
const GA_Attribute * getRequiredAttrib() const
GLenum mode
Definition: glcorearb.h:99
GLint j
Definition: glad.h:2733
fpreal baseValue() const
GA_AttributeOwner
Definition: GA_Types.h:34
bool hasChanged(const CacheData *cache) const
void bumpDims(exint shaftdim, exint barbdim)
fpreal64 fpreal
Definition: SYS_Types.h:277
float postProcessVarying(float value) const
UVMode getUVMode() const
SYS_FORCE_INLINE T & operator()(exint i)
SYS_FORCE_INLINE exint getBarbDim() const
OverrideType overrideType() const
SYS_FORCE_INLINE GA_AttributeOwner getOwner() const
Definition: GA_Attribute.h:210
#define UT_ASSERT(ZZ)
Definition: UT_Assert.h:156
void setDims(exint shaftdim, exint barbdim)
Definition: core.h:1131
fpreal evalSkin(const GA_Offset skinprimoff, const GA_OffsetArray &skinvertoffsets, const UT_FloatArray &skinvertweights, const UT_Vector3 &uv)
bool evaluatesToSingleValue(GA_AttributeOwner target) const
void eval(UT_FloatArray &out, const GA_AttributeOwner target, const GA_Offset skinprimoff, const GA_OffsetArray &skinvertoffsets, const UT_FloatArray &skinvertweights, const UT_Vector3 &uv, const GA_Offset curveprimoff, const GA_OffsetListRef &curvevertoffsets)
Generic Attribute Interface class to access an attribute as a tuple.
Definition: GA_AIFTuple.h:32
SYS_FORCE_INLINE const T & operator()(exint point, BarbSide barbside, exint barbpoint) const
void eval(OverrideValue< float > &out, EvalTemp &temp, const GA_AttributeOwner target, const GA_Offset skinprimoff, const GA_OffsetArray &skinvertoffsets, const UT_FloatArray &skinvertweights, const UT_Vector3 &uv, const GA_Offset curveprimoff, const GA_OffsetListRef &curvevertoffsets)
void swap(UT_Array< T > &other)
Definition: UT_ArrayImpl.h:676
bool needTexPrim() const
void eval(UT_FloatArray &out, const GA_AttributeOwner target, const GA_Offset skinprimoff, const GA_OffsetArray &skinvertoffsets, const UT_FloatArray &skinvertweights, const UT_Vector3 &uv, const GA_Offset curveprimoff, const GA_OffsetListRef &curvevertoffsets, const GA_Offset clumpprimoff, const UT_ValArray< GA_OffsetArray > &clumpvertoffsets, const UT_ValArray< UT_FloatArray > &clumpvertweights)