HDK
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
GU_GroomUtils.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: GU Library (C++)
7  *
8  */
9 
10 #ifndef __GU_GroomUtils_h__
11 #define __GU_GroomUtils_h__
12 
13 #include "GA/GA_Types.h"
14 #include "GU_API.h"
15 #include "GU_Detail.h"
16 #include "GU_RayIntersect.h"
17 
18 #include <UT/UT_LineTree.h>
19 #include <UT/UT_Set.h>
20 #include <UT/UT_Tuple.h>
21 #include <GA/GA_Attribute.h>
22 #include <GA/GA_AttributeRefMap.h>
23 #include <GA/GA_Handle.h>
24 #include <GA/GA_SplittableRange.h>
25 #include <GEO/GEO_PointTree.h>
26 #include <GEO/GEO_PrimPoly.h>
27 
28 #include <functional>
29 
31 {
32 public:
33  static GA_Attribute*
34  findOrCreateFloatAttribute(
35  GU_Detail &gdp,
36  const GA_AttributeOwner owner,
37  const UT_StringRef &name,
38  const exint tsize,
39  const GA_Defaults &defaults = GA_Defaults(0.0),
41 
42  static GA_Attribute*
43  findOrCreateIntAttribute(
44  GU_Detail &gdp,
45  const GA_AttributeOwner owner,
46  const UT_StringRef &name,
47  const exint tsize,
48  const GA_Defaults &defaults = GA_Defaults(0),
50 
51  static GA_Attribute*
52  findOrCreateStringAttribute(
53  GU_Detail &gdp,
54  const GA_AttributeOwner owner,
55  const UT_StringRef &name);
56 
57  static GA_Attribute*
59  GU_Detail &gdp,
60  GA_AttributeOwner owner,
61  const UT_StringRef &name,
62  int tsize)
63  {
64  GA_Attribute *attrib = gdp.findStringArray(owner, name);
65 
66  if (!attrib)
67  attrib = gdp.addStringArray(owner, name, tsize);
68 
69  return attrib;
70  }
71 
72  static GA_Attribute*
74  GU_Detail &gdp,
75  GA_AttributeOwner owner,
76  const UT_StringRef &name,
77  int tsize,
79  {
80  GA_Attribute *attrib = gdp.findIntArray(owner, name);
81 
82  if (!attrib)
83  attrib = gdp.addIntArray(owner, name, tsize);
84 
85  return attrib;
86  }
87 
88  static GA_Attribute*
90  GU_Detail &gdp,
91  GA_AttributeOwner owner,
92  const UT_StringRef &name,
93  int tsize,
95  {
96  GA_Attribute *attrib = gdp.findFloatArray(owner, name);
97 
98  if (!attrib)
99  attrib = gdp.addFloatArray(owner, name, tsize);
100 
101  return attrib;
102  }
103 
104  static GA_Attribute*
105  findNamedOrient(GU_Detail &gdp, const UT_StringRef &name);
106 
107  static const GA_Attribute*
108  findNamedOrient(const GU_Detail &gdp, const UT_StringRef &name);
109 
110  static GA_Attribute*
111  findOrCreateNamedOrient(GU_Detail &gdp, const UT_StringRef &name);
112 
113  static void getPrimPointPositions(
114  UT_Vector3Array &positions,
115  GA_Offset primoff,
116  const GU_Detail &gdp,
117  const GA_ROHandleV3 &pos_handle);
118 
119 
120  static void setPrimPointPositions(
121  UT_Vector3Array &positions,
122  GA_Offset primoff,
123  const GU_Detail &gdp,
124  const GA_RWHandleV3 &pos_handle);
125 
126  static fpreal calcPerimeter(UT_Vector3Array &pos);
127 
128  static float unitLengthToUnitDomain(
129  const UT_Vector3Array &pos,
130  float perimeter,
131  const UT_FloatArray &edgelengths,
132  float ulength);
133 
134  static float unitToUnitLengthDomain(
135  float perimeter,
136  const UT_FloatArray &edgelengths,
137  float uparm);
138 
139  static float unitLengthToUnitDomain(
141  const UT_FloatArray &edgelengths,
142  float ulength);
143 
144  static float
145  openCurveUnitToReal(int n, float u_unit)
146  {
147  if (n <= 0 || !u_unit) return 0.0f;
148 
149  if (u_unit < 0.0f) u_unit = 0.0f;
150  else if (u_unit > 1.0f) u_unit = 1.0f;
151 
152  return u_unit * float(n-1);
153  }
154 
157  {
158  if (n == 0)
159  {
160  return { {0.0f, 0.0f}, {-1, -1} };
161  }
162 
163  if (n == 1)
164  {
165  return { {1.0f, 0.0f}, {0, -1} };
166  }
167 
168  u = openCurveUnitToReal(n, u); // Also checks out of bounds etc.
169 
170  int vcrt, vseq;
171  float rem = GEO_Face::getIndices(u, vcrt, vseq, n-1, false /*ifclosed*/);
172 
173  if (rem == 0 || vcrt == vseq) {
174  return { {1.0f, 0.0f}, {vcrt, -1} };
175  }
176 
177  return {
178  {1.0f-rem, rem},
179  {vcrt, vseq}
180  };
181  }
182 
183  template<typename T>
184  static T
185  interpAttrib(
186  const GA_ROHandleT<T> &attrib,
187  const GA_Offset &primoff,
188  const GA_OffsetArray &vertoffsets,
189  const UT_FloatArray &vertweights,
190  const T defaultvalue=T(0.0f));
191 
192  static fpreal
193  computeLength(
194  const UT_Vector3Array &positions);
195 
196  static fpreal
197  computeEdgeLengths(
198  const UT_Vector3Array &positions,
199  UT_FloatArray &edgelengths);
200 
201  static fpreal
202  computeEdgeLengths(
203  const GU_Detail &gdp,
204  const GA_ROHandleV3 &P,
205  GA_Offset primoff,
206  UT_FloatArray &edgelengths);
207 
208  // stores all quats of influencing guides for each point and attribute
209  // in a linear array. Guides are the smallest dimension, so all the guides
210  // for a point and attribute are in a continuous block of memory, ready
211  // to be used with UT_Quaternion::interpolate().
213  {
214  public:
216  void setDim(int pointcount, int attribcount, int guidecount)
217  {
218  myPointCount = pointcount;
219  myAttribCount = attribcount;
220  myGuideCount = guidecount;
221  myQuats.setSize(attribcount * pointcount * guidecount);
222  };
223 
225  int getLinearIndex(int pointindex, int attribindex, int guideindex)
226  {
227  int index = pointindex * (myAttribCount * myGuideCount)
228  + attribindex * myGuideCount
229  + guideindex;
230 
231  return index;
232  }
233 
235  const UT_QuaternionF&
236  getValue(int pointindex, int attribindex, int guideindex)
237  {
238  int index = getLinearIndex(pointindex, attribindex, guideindex);
239 
240  return myQuats[index];
241  }
242 
244  void
245  setValue(int pointindex, int attribindex, int guideindex, UT_QuaternionF &quat)
246  {
247  int index = getLinearIndex(pointindex, attribindex, guideindex);
248 
249  myQuats[index] = quat;
250  }
251 
253  const UT_QuaternionFArray&
255  {
256  return myQuats;
257  }
258 
259  private:
260  int myPointCount = 0;
261  int myAttribCount = 0;
262  int myGuideCount = 0;
263 
264  UT_QuaternionFArray myQuats;
265  };
266 
267  // positions must have size == vtxcount and initialized to 0.
268  static void
269  addWeightedGuide(
270  const GU_Detail &guidegdp,
271  const GEO_PrimPoly * const guideprim,
272  const GA_Offset guideprimoff,
273  const int guideindex,
274  const float guideweight,
275  const GA_ROHandleF &guidetightnessattrib,
276  const GA_ROHandleV3 &guidetangentattrib,
277  const GA_ROHandleV3 &guidenormalattrib,
278  const GA_ROHandleV3 &guidePattrib,
279  const GA_AttributeRefMap &guidepointlinattribmap,
280  const GA_AttributeRefMap &guidepointquatattribmap,
281 
282  // settings
283  const bool extrude,
284  const bool setpos,
285  const bool uniformguidesegments,
286  const GA_Size vtxcount,
287  const UT_Vector3 rootpos,
288  const GA_OffsetListRef &vtxlist,
289  // temp storage
290  UT_FloatArray &glengths,
291  GA_OffsetArray &guidevertoffsets,
292  UT_FloatArray &guidevertweights,
293  // output
294  UT_Array<UT_Vector3> &positions,
295  UT_ValArray<GA_WeightedSum> &pointsums,
296  QuatInterpTempStorage &quattemp,
297  const UT_Matrix3 *guidetoposrot = nullptr);
298 
299  static void
300  removeNonGuidesFromGroup(
301  GA_PrimitiveGroup &guidegroup,
302  GU_Detail &gdp);
303 
304  static void
305  removeHiddenPrimitivesFromGroup(
306  GA_PrimitiveGroup &guidegroup,
307  GU_Detail &gdp);
308 
309  static void
310  setGuideGroupMembers(
311  GA_PrimitiveGroup &guidegroup,
312  const GA_ElementGroup *ingroup,
313  const GA_ElementGroup *inmirrorgroup,
314  const GA_PrimitiveGroup *templategroup,
315  GU_Detail &gdp);
316 
317  enum class SetLengthMode
318  {
319  SET = 0,
320  MULTIPLY,
321  ADD,
322  SUBTRACT,
323  SETMIN,
324  SETMAX
325  };
326 
327  static fpreal
329  fpreal prevlength,
331  fpreal value)
332  {
333  if (mode == SetLengthMode::SETMIN)
334  {
335  return SYSmin(prevlength, value);
336  }
337  else if (mode == SetLengthMode::SETMAX)
338  {
339  return SYSmax(prevlength, value);
340  }
341  else if (mode == SetLengthMode::ADD)
342  {
343  return (prevlength+value);
344  }
345  else if (mode == SetLengthMode::SUBTRACT)
346  {
347  return (prevlength-value);
348  }
349  else if (mode == SetLengthMode::SET)
350  {
351  return value;
352  }
353 
354  return value;
355  }
356 
357  static void
358  scaleCurve(
359  GU_Detail &gdp,
360  const GA_RWHandleV3 &Pattrib,
361  GA_Offset primoff,
362  GA_OffsetListRef &curvevertoffs,
363  float factor);
364 
365  static void
366  setCurveLength(
367  GU_Detail &gdp,
368  const GA_RWHandleV3 &Pattrib,
369  GA_Offset primoff,
370  fpreal prevlength,
371  fpreal newlength,
372  GA_OffsetListRef &curvevertoffs,
373  UT_FloatArray &tempu,
374  UT_Vector3Array &temppos);
375 
376  static void
377  setCurveLength(
378  UT_Vector3Array &positions,
379  fpreal prevlength,
380  fpreal newlength,
381  UT_FloatArray &tempu,
382  UT_Vector3Array &temppos);
383 
384  static float
385  circlePackRootPoints(
386  const GU_Detail &gdp,
387  const GA_ROHandleV3 &restPattrib,
389  UT_FloatArray &sqdists,
390  const GA_Offset * const offsets,
391  exint numcurves,
392  const UT_Vector3 &clumproot,
393  const UT_Matrix3 &clumprot,
394  const GA_RWHandleV2 &bundleposattrib);
395 
396  // copy of vex intrinsic in $SHS/vex/intrinsics/opmath.vfl
397  static UT_Vector3
398  slideFrame(
399  const UT_Vector3 x0,
400  const UT_Vector3 t0,
401  const UT_Vector3 n0,
402  const UT_Vector3 x1,
403  const UT_Vector3 t1);
404 
405  static UT_Matrix3
406  computeTangentFrame(
407  const UT_Vector3 &tangent,
408  const UT_Vector3 &normal);
409 
410  static void
411  computeTangentFrames(
412  UT_ValArray<UT_Matrix3> &frames,
413  const UT_Vector3Array &positions,
414  const UT_Vector3 &roottangent,
415  const UT_Vector3 &rootnormal);
416 
418  static GA_Offset
420  {
421  return gdp.getPrimitiveVertexOffset(primoff, index);
422  }
423 
425  static GA_Offset
427  {
428  GA_Offset firstvtxoff(primVertexOffset(gdp, primoff, index));
429  return gdp.vertexPoint(firstvtxoff);
430  }
431 
432  static void setPagesConstant(GA_RWHandleF attribhandle, float value)
433  {
434  GA_Offset size = attribhandle->getIndexMap().offsetSize();
435 
436  UT_PageNum numpages(attribhandle->getData().numPages(size));
437 
438  for(GA_PageNum pagenum(0); pagenum < numpages; ++pagenum)
439  attribhandle.setPageConstant(pagenum, &value);
440  }
441 
442  static bool
444  const GA_ROHandleI &skinprimattrib,
445  const GU_Detail &skingdp,
446  const GA_ElementGroup *group = nullptr)
447  {
448  UT_ASSERT(!group || skinprimattrib->getOwner() == group->getOwner());
449 
450  auto &constgdp = skinprimattrib.getAttribute()->getDetail();
451  bool skinprimfail = false;
452  GA_Range range = skinprimattrib->getOwner() == GA_ATTRIB_POINT
453  ? constgdp.getPointRange(dynamic_cast<const GA_PointGroup*>(group))
454  : constgdp.getPrimitiveRange(dynamic_cast<const GA_PrimitiveGroup*>(group));
456  [&](const GA_SplittableRange &r)
457  {
458  GA_Offset startoff;
459  GA_Offset endoff;
460 
461  for (GA_Iterator ptit(r); ptit.blockAdvance(startoff, endoff); )
462  {
463  if (skinprimfail)
464  return;
465 
466  for (GA_Offset off = startoff; off < endoff; ++off)
467  {
468  GA_Index skinprimindex = skinprimattrib.get(off);
469  if (skinprimindex < 0 ||
470  skinprimindex >= skingdp.getNumPrimitives())
471  {
472  skinprimfail = true;
473  return;
474  }
475  }
476  }
477  });
478 
479  return !skinprimfail;
480  }
481 
484  GU_Detail &gdp,
485  GA_AttributeOwner owner,
486  const UT_StringHolder &name_attrib_name,
487  const UT_StringHolder &weight_attrib_name)
488  {
489  GA_Attribute* keyattrib = findOrCreateStringArrayAttribute(
490  gdp, owner, name_attrib_name, 1);
491 
492  GA_Attribute* weightattrib = findOrCreateFloatArrayAttribute(
493  gdp, owner, weight_attrib_name, 1);
494 
495  return UTmakeTuple(keyattrib, weightattrib);
496  }
497 
500  GU_Detail &gdp,
501  GA_AttributeOwner owner,
502  const UT_StringHolder &name_attrib_name,
503  const UT_StringHolder &weight_attrib_name)
504  {
505  GA_Attribute* keyattrib = findOrCreateIntArrayAttribute(
506  gdp, owner, name_attrib_name, 1);
507 
508  GA_Attribute* weightattrib = findOrCreateFloatArrayAttribute(
509  gdp, owner, weight_attrib_name, 1);
510 
511  return UTmakeTuple(keyattrib, weightattrib);
512  }
513 };
514 
516 {
517 public:
519  const GU_Detail &gdp,
520  const GA_Attribute *restattrib);
521 
522  void findAttribs(const GU_Detail &gdp);
523 
525  {
526  return myAttribMissing;
527  }
528 
530  {
531  return myAttribMissingWarning;
532  }
533 
538 
539 private:
540  bool myAttribMissing = false;
541 
542  static const UT_StringHolder myAttribMissingWarning;
543 };
544 
546 
548 {
549 public:
552 };
553 
555 {
556 public:
558  const GU_RayIntersect &rayintersect)
559  : myRayIntersect(rayintersect)
560  , mySkinGdp(*rayintersect.detail())
561  , mySkinP(mySkinGdp.getP())
562  {}
563 
565  const GU_RayIntersect &rayintersect,
566  const GA_Attribute &normal)
567  : myRayIntersect(rayintersect)
568  , mySkinGdp(*rayintersect.detail())
569  , mySkinP(mySkinGdp.getP())
570  , mySkinN(&normal)
571  {}
572 
574  const GU_Detail&
576  {
577  return mySkinGdp;
578  }
579 
581  {
582  return myRayIntersect;
583  }
584 
586  bool
588  const UT_Vector3 &pos,
589  GU_MinInfo &mininfo) const
590  {
591  int hitcount = myRayIntersect.minimumPoint(pos, mininfo);
592 
593  // If nothing hit within radius (unlikely), fall back to infinite radius
594  if (hitcount == 0)
595  {
596  mininfo = GU_MinInfo(FLT_MAX, 0, true);
597  hitcount = myRayIntersect.minimumPoint(pos, mininfo);
598  }
599 
600  return hitcount > 0;
601  }
602 
605  {
606  int hits = myRayIntersect.sendRay(pos, dir, info);
607 
608  return hits > 0;
609  }
610 
612  static void
614  const GU_MinInfo &mininfo,
615  GU_GroomInterpCoords &interpcoords)
616  {
618  interpcoords.offsets, interpcoords.weights,
619  mininfo.u1,
620  mininfo.v1,
621  0.0f);
622  }
623 
625  static void
627  const GU_RayInfo &hitinfo,
628  GU_GroomInterpCoords &interpcoords)
629  {
631  interpcoords.offsets, interpcoords.weights,
632  hitinfo.myU,
633  hitinfo.myV,
634  0.0f);
635  }
636 
637  template<typename T>
638  T
640  const GA_ROHandleT<T> &attrib,
641  const GU_GroomInterpCoords &interpcoords) const
642  {
644  attrib, GA_INVALID_OFFSET,
645  interpcoords.offsets, interpcoords.weights);
646  }
647 
649  UT_Vector3
651  const GU_GroomInterpCoords &interpcoords) const
652  {
653  return interpAttrib(mySkinP, interpcoords);
654  }
655 
657  UT_Vector3
659  const GU_GroomInterpCoords &interpcoords) const
660  {
661  UT_ASSERT(mySkinN.isValid());
662  UT_Vector3 normal = interpAttrib(mySkinN, interpcoords);
663 
664  normal.normalize();
665 
666  return normal;
667  }
668 
670  bool
672  UT_Vector3 &pos,
673  GU_MinInfo &mininfo,
674  GU_GroomInterpCoords &interpcoords)
675  {
676  if (!closestPointInfo(pos, mininfo))
677  return false;
678 
679  computeVertWeights(mininfo, interpcoords);
680 
681  pos = interpAttrib(mySkinP, interpcoords);
682 
683  return true;
684  }
685 
686 private:
687  const GU_RayIntersect &myRayIntersect;
688  const GU_Detail &mySkinGdp;
689  const GA_ROHandleV3 mySkinP;
690  const GA_ROHandleV3 mySkinN;
691 };
692 
694 {
695 public:
697  {
698  void setArraySize(unsigned int size)
699  {
700  lines.setSize(size);
701  dist2s.setSize(size);
702  }
703 
706 
708  };
709 
710  GU_GroomPartingLineLookup(unsigned int maxpartlines)
711  : myMaxPartLines(maxpartlines)
712  {}
713 
715  unsigned int maxpartlines,
716  GU_GroomSkinIntersect *skinintersect)
717  : myMaxPartLines(maxpartlines)
718  {}
719 
720  static const GA_PrimitiveGroup*
721  findGroup(const GU_Detail &gdp)
722  {
723  return gdp.findPrimitiveGroup("partinglines");
724  }
725 
726  static GA_PrimitiveGroup&
728  {
729  GA_PrimitiveGroup *group = gdp.findPrimitiveGroup("partinglines");
730 
731  if (group)
732  return *group;
733 
734  return *gdp.newPrimitiveGroup("partinglines");
735  }
736 
737  static GA_PrimitiveGroup*
739  {
740  return gdp.findPrimitiveGroup("partinglines");
741  }
742 
743  void
744  setLines(
745  const GU_Detail &gdp,
746  const GA_ROHandleV3 &restattrib,
747  const GA_PrimitiveGroup &partlinesgroup);
748 
749  float
750  computePartingWeight(
751  const UT_Vector3 &posA,
752  const UT_Vector3 &posB,
753  const GU_GroomPartingLineAttribs &attribs,
754  PerThreadData &threadvalues,
755  const GU_GroomSkinIntersect *skinintersect = nullptr) const;
756 
757  GA_Offset getLineOffset1(int id) const
758  {
759  return myLineOffsets(2 * id);
760  }
761 
762  GA_Offset getLineOffset2(int id) const
763  {
764  return myLineOffsets(2 * id + 1);
765  }
766 
767  int64 getMemoryUsage(bool inclusive) const
768  {
769  int64 size(inclusive ? sizeof(*this) : 0);
770 
771  size += myLineOffsets.getMemoryUsage(true);
772 
773  return size;
774  }
775 
776 private:
777  int addLine(const GA_Offset ptoff1, const UT_Vector3 &pt1,
778  const GA_Offset ptoff2, const UT_Vector3 &pt2);
779 
780  const unsigned int myMaxPartLines;
781  UT_LineTree myLineTree;
782  GA_OffsetArray myLineOffsets;
783 };
784 
786 {
787 public:
789  GU_Detail &dstgdp,
790  const GU_Detail *srcgdp = nullptr)
791  : myDstGdp(dstgdp)
792  , mySrcGdp(srcgdp != nullptr ? *srcgdp : dstgdp)
793  , myAttribMap(myDstGdp, &mySrcGdp)
794  , myLengthScaledAttribMap(myDstGdp, &mySrcGdp)
795  {
796  }
797 
798  void
799  addAttrib(const UT_StringRef &name)
800  {
801  addAttribToMap(myAttribMap, name);
802  }
803 
804  void
806  {
807  addAttribToMap(myLengthScaledAttribMap, name);
808  }
809 
810  void
811  sampleAttribs(
812  const GEO_PrimPoly &dstpoly,
813  const GEO_PrimPoly &srcpoly,
814  float blend);
815 
816  void
818  const GEO_PrimPoly &dstprimpoly,
819  GA_Offset sourceprimoff,
820  float blend)
821  {
822  const GEO_Primitive *srcgeoprim = mySrcGdp.getGEOPrimitive(
823  sourceprimoff);
824  const GEO_PrimPoly *srcpoly(nullptr);
825 
826  // We only do polygons
827  if (srcgeoprim->getTypeId() == GEO_PRIMPOLY)
828  {
829  srcpoly = static_cast<const GEO_PrimPoly *>(srcgeoprim);
830 
831  sampleAttribs(dstprimpoly, *srcpoly, blend);
832  }
833  }
834 
835 private:
836  void
837  addAttribToMap(GA_AttributeRefMap &map, const char *attribname);
838 
839  GU_Detail &myDstGdp;
840  const GU_Detail &mySrcGdp;
841 
842  GA_AttributeRefMap myAttribMap;
843  GA_AttributeRefMap myLengthScaledAttribMap;
844 };
845 
846 // A tree that can be built using an arbitrary prim or point attribute as the
847 // point position. When using a prim attribute, this allows direct lookup of
848 // curve primitives.
850 {
851 public:
852  /// Rebuilds the tree with the given detail and primitive group,
853  /// This creates a point per primitive using the primitive attribute of the
854  /// specified name as the point position.
855  /// if primgroup is NULL then all primitives are used.
856  void
857  build(
858  const GEO_Detail *gdp,
859  const GA_PrimitiveGroup *primgroup,
860  const char *attrib,
861  bool enable_multithreading=true);
862 
863  // Methods that must delegate to base class due to overloads
864  void build(
865  const GEO_Detail *gdp,
866  const GA_PointGroup *ptgroup,
867  bool enable_multithreading=true)
868  {
869  GEO_PointTreeGAOffset::build(gdp, ptgroup, enable_multithreading);
870  }
871 
872  void build(
873  const GEO_Detail *gdp,
874  const GA_PointGroup *ptgroup,
875  const char *attrib,
876  bool enable_multithreading=true)
877  {
878  GEO_PointTreeGAOffset::build(gdp, ptgroup, attrib, enable_multithreading);
879  }
880 };
881 
883 {
884 public:
885  GU_GroomFastRamp(int numsamples=1000)
886  : myNumSamples(numsamples)
887  {}
888 
889  bool operator==(const GU_GroomFastRamp& ramp) const
890  {
891  return mySamples == ramp.mySamples
892  && myNumSamples == ramp.myNumSamples
893  && myIsConstant == ramp.myIsConstant;
894  }
895 
896  bool operator!=(const GU_GroomFastRamp& ramp) const
897  {
898  return !(*this == ramp);
899  }
900 
901  bool update(const UT_Ramp *widthramp);
902 
903  void update(const UT_FloatArray &values);
904 
906  bool isConstant() { return myIsConstant; }
907 
909  float lookup(float u) const
910  {
911  float us = u * (mySamples.size()-1);
912  int indexA = SYSclamp(exint(us), exint(0), mySamples.size()-1);
913  if (indexA == mySamples.size()-1)
914  return mySamples(indexA);
915  int indexB = indexA + 1;
916  return SYSlerp(mySamples(indexA), mySamples(indexB), us - indexA);
917  }
918 
920  float lookupNearest(float u) const
921  {
922  int index = SYSclamp(
923  exint(u * (mySamples.size()-1) + 0.5),
924  exint(0),
925  mySamples.size()-1);
926  return mySamples(index);
927  }
928 
929  const UT_FloatArray &samples() const;
930 
931 private:
932  UT_FloatArray mySamples;
933  int myNumSamples;
934  bool myIsConstant = false;
935 };
936 
938 {
939 public:
941  GU_Detail *dest,
942  const GU_Detail *source,
943  const GA_AttributeOwner destowner)
944  : dest(dest)
945  , source(source)
946  , destowner(destowner)
947  {}
948 
949  using AttribMatchTuple = std::pair<GA_AttributeOwner, UT_StringHolder>;
950 
951  void addSourceAttribs(
952  const GA_AttributeOwner sourceowner,
953  const char *matchpattern,
954  UT_Set<AttribMatchTuple> &alreadymapped,
955  const GA_AttributeFilter *filter=nullptr);
956 
958  {
961  STORAGE
962  };
963 
964  class CacheData
965  {
966  private:
967  UT_ValArray<int> targetindices;
970  UT_ValArray<int> typeids;
971  UT_ValArray<int> tuplesizes;
972  UT_ValArray<GA_DataId> dataids;
973 
975 
976  };
977 
979  GA_AttributeRefMap &map) const
980  {
981  mapAndCreateAttribs(map, nullptr);
982  }
983 
984 
985  void mapAndCreateAttrib(
986  GA_AttributeRefMap &map,
987  const UT_ValArray<AttribChange> *changes,
988  int index) const;
989 
990  // Creates or updates attributes as required by the changes array
991  //
992  // Attributes that need their data copied are added to map.
994  GA_AttributeRefMap &map,
995  const UT_ValArray<AttribChange> *changes) const
996  {
997  for (int i = 0; i < sourceattribs.size(); ++i)
998  mapAndCreateAttrib(map, changes, i);
999  }
1000 
1001  // Creates or updates attributes as required by the changes array
1002  //
1003  // Attributes that need their data copied are added to map.
1005  GA_AttributeRefMap &map,
1006  const UT_ValArray<AttribChange> *changes,
1007  const std::function<bool(const GA_Attribute &)>& filter ) const
1008  {
1009  for (int i = 0; i < sourceattribs.size(); ++i)
1010  if (filter(*sourceattribs[i]))
1011  mapAndCreateAttrib(map, changes, i);
1012  }
1013 
1014  void
1016  GA_AttributeRefMap &map,
1017  const UT_ValArray<AttribChange> *changes) const
1018  {
1019  static auto &&theFilter = [](const GA_Attribute &attrib)
1020  {
1021  return attrib.getStorageClass() == GA_STORECLASS_REAL;
1022  };
1023 
1024  mapAndCreateAttribs(map, changes, theFilter);
1025  }
1026 
1027  void
1029  GA_AttributeRefMap &map,
1030  const UT_ValArray<AttribChange> *changes) const
1031  {
1032  static auto &&theFilter = [](const GA_Attribute &attrib)
1033  {
1034  return attrib.getStorageClass() != GA_STORECLASS_REAL;
1035  };
1036 
1037  mapAndCreateAttribs(map, changes, theFilter);
1038  }
1039 
1040  bool updateCache(
1041  UT_UniquePtr<CacheData> &cachedata,
1042  UT_ValArray<AttribChange> &changes) const;
1043 
1044 private:
1045  CacheData* getCacheData() const;
1046 
1047  const GU_Detail *source;
1048  UT_ValArray<const GA_Attribute*> sourceattribs;
1049  GU_Detail *dest;
1050  const GA_AttributeOwner destowner;
1051 };
1052 
1054 {
1055 public:
1056  GU_ROWeightArrayPairHandle() = default;
1057 
1059  const GEO_Detail &detail,
1060  GA_AttributeOwner attrib_owner,
1061  const UT_StringHolder &key_attrib_name,
1062  const UT_StringHolder &weight_attrib_name)
1063  {
1064  bind(detail, attrib_owner, key_attrib_name, weight_attrib_name);
1065  }
1066 
1067  bool bind(
1068  const GEO_Detail &detail,
1069  GA_AttributeOwner attrib_owner,
1070  const UT_StringHolder &key_attrib_name,
1071  const UT_StringHolder &weight_attrib_name)
1072  {
1073  return bindImpl(SYSconst_cast(detail), attrib_owner, key_attrib_name, weight_attrib_name);
1074  }
1075 
1076  void bind(
1077  const GA_Attribute *key_attrib,
1078  const GA_Attribute *weight_attrib)
1079  {
1080  bindImpl(SYSconst_cast(key_attrib), SYSconst_cast(weight_attrib));
1081 
1082  setAIFArrays();
1083  }
1084 
1085  bool
1086  isValid() const
1087  {
1088  return myKeyAttrib && myWeightAttrib;
1089  }
1090 
1091  const GA_Attribute *
1092  keyAttrib() const
1093  {
1094  return myKeyAttrib;
1095  }
1096 
1097  const GA_Attribute *
1099  {
1100  return myWeightAttrib;
1101  }
1102 
1103  const GA_AIFNumericArray*
1104  indexArray() const
1105  {
1106  return myIndexArray;
1107  }
1108 
1110  nameArray() const
1111  {
1112  return myNameArray;
1113  }
1114 
1115  const GA_AIFNumericArray*
1116  weightArray() const
1117  {
1118  return myWeightArray;
1119  }
1120 
1122  {
1125  : nullptr;
1128  : nullptr;
1129 
1132  : nullptr;
1133  }
1134 
1135 protected:
1136  bool bindImpl(
1137  GEO_Detail &detail,
1138  GA_AttributeOwner attrib_owner,
1139  const UT_StringHolder &key_attrib_name,
1140  const UT_StringHolder &weight_attrib_name)
1141  {
1142  GA_Attribute *weight_attrib, *key_attrib;
1143 
1144  weight_attrib =
1145  SYSconst_cast(detail.findFloatArray(attrib_owner, weight_attrib_name));
1146  key_attrib =
1147  SYSconst_cast(detail.findStringArray(attrib_owner, key_attrib_name));
1148 
1149  if (!key_attrib)
1150  {
1151  key_attrib =
1152  SYSconst_cast(detail.findIntArray( attrib_owner, key_attrib_name));
1153  }
1154 
1155  if (!key_attrib || !weight_attrib)
1156  return false;
1157 
1158  myWeightAttrib = weight_attrib;
1159  myKeyAttrib = key_attrib;
1160  setAIFArrays();
1161 
1162  return true;
1163  }
1164 
1165  void bindImpl(
1166  GA_Attribute *key_attrib,
1167  GA_Attribute *weight_attrib)
1168  {
1169  myKeyAttrib = key_attrib;
1170  myWeightAttrib = weight_attrib;
1171 
1172  setAIFArrays();
1173  }
1174 
1178 
1181 };
1182 
1184 {
1185 public:
1186  GU_RWWeightArrayPairHandle() = default;
1187 
1189  GEO_Detail &detail,
1190  GA_AttributeOwner attrib_owner,
1191  const UT_StringHolder &key_attrib_name,
1192  const UT_StringHolder &weight_attrib_name)
1193  {
1194  bind(detail, attrib_owner, key_attrib_name, weight_attrib_name);
1195  }
1196 
1197  bool bind(
1198  GEO_Detail &detail,
1199  GA_AttributeOwner attrib_owner,
1200  const UT_StringHolder &key_attrib_name,
1201  const UT_StringHolder &weight_attrib_name)
1202  {
1203  return bindImpl(detail, attrib_owner, key_attrib_name, weight_attrib_name);
1204  }
1205 
1206  void bind(
1207  GA_Attribute *key_attrib,
1208  GA_Attribute *weight_attrib)
1209  {
1210  bindImpl(key_attrib, weight_attrib);
1211  }
1212 
1213  bool
1214  isValid() const
1215  {
1216  return myKeyAttrib && myWeightAttrib;
1217  }
1218 
1219  GA_Attribute *
1220  keyAttrib() const
1221  {
1222  return myKeyAttrib;
1223  }
1224 
1225  GA_Attribute *
1227  {
1228  return myWeightAttrib;
1229  }
1230 
1231  void set(
1232  GA_Offset primoff,
1233  const UT_StringArray &names,
1234  const UT_FloatArray &weights)
1235  {
1236  nameArray()->set(keyAttrib(), primoff, names);
1237  weightArray()->set(weightAttrib(), primoff, weights);
1238  }
1239 
1241  {
1242  if (myKeyAttrib != nullptr)
1244 
1245  if (myWeightAttrib != nullptr)
1247  }
1248 };
1249 
1251 {
1252 public:
1253  struct TempData
1254  {
1258 
1261  };
1262 
1264  const GEO_Detail &weightgeo)
1265  : myWeightGeo(weightgeo)
1266  {
1267  }
1268 
1270  const GEO_Detail &weightgeo,
1271  GA_AttributeOwner attrib_owner,
1272  const UT_StringRef &key_attrib_name,
1273  const UT_StringRef &weight_attrib_name)
1274  : myWeightGeo(weightgeo)
1275  {
1276  myInputAttribs.bind(
1277  myWeightGeo,
1278  attrib_owner,
1279  key_attrib_name,
1280  weight_attrib_name);
1281  }
1282 
1284  const GEO_Detail &weightgeo,
1285  const GA_Attribute &keyattrib,
1286  const GA_Attribute &weightattrib)
1287  : myWeightGeo(weightgeo)
1288  {
1289  myInputAttribs.bind(
1290  &keyattrib,
1291  &weightattrib);
1292  }
1293 
1295  GA_AttributeOwner attrib_owner,
1296  const UT_StringRef &key_attrib_name,
1297  const UT_StringRef &weight_attrib_name)
1298  {
1299  return myInputAttribs.bind(
1300  myWeightGeo,
1301  attrib_owner,
1302  key_attrib_name,
1303  weight_attrib_name);
1304  }
1305 
1306  bool
1307  isValid() const
1308  {
1309  return myInputAttribs.keyAttrib() && myInputAttribs.weightAttrib();
1310  }
1311 
1312  const GA_Attribute *
1313  keyAttrib() const
1314  {
1315  return myInputAttribs.keyAttrib();
1316  }
1317 
1318  const GA_Attribute *
1320  {
1321  return myInputAttribs.weightAttrib();
1322  }
1323 
1324  void
1326  GU_Detail &gdp,
1327  GA_AttributeOwner owner)
1328  {
1329  bool key_is_string = false;
1330 
1331  if (!isValid())
1332  return;
1333 
1334  const UT_StringHolder key_name = keyAttrib()->getName();
1335  const UT_StringHolder weight_name = weightAttrib()->getName();
1336 
1337  key_is_string = keyAttrib()->getAIFSharedStringArray() != nullptr;
1338 
1339  GA_Attribute *keyattrib = nullptr;
1340  GA_Attribute *weightattrib = nullptr;
1341 
1342  if (key_is_string)
1343  {
1344  UTlhsTuple(keyattrib, weightattrib) =
1346  gdp, owner, key_name, weight_name);
1347  }
1348  else
1349  {
1350  UTlhsTuple(keyattrib, weightattrib) =
1352  gdp, owner, key_name, weight_name);
1353  }
1354 
1355  myOutputAttribs.bind(keyattrib, weightattrib);
1356  }
1357 
1359  const GA_OffsetArray &offsets,
1360  const UT_FloatArray &weights,
1361  GA_Offset &out_offset,
1362  TempData &tempdata) const
1363  {
1364  bool success = false;
1365  if (myInputAttribs.nameArray() != nullptr)
1366  {
1367  interpolate(
1368  tempdata.outnames,
1369  tempdata.outweights,
1370  offsets,
1371  weights,
1372  tempdata.tempnameset);
1373 
1374  myOutputAttribs.nameArray()->set(
1375  myOutputAttribs.keyAttrib(), out_offset, tempdata.outnames);
1376 
1377  success = true;
1378  }
1379  else if (myInputAttribs.indexArray())
1380  {
1381  interpolate(
1382  tempdata.outindices,
1383  tempdata.outweights,
1384  offsets,
1385  weights,
1386  tempdata.tempindexset);
1387 
1388  myOutputAttribs.indexArray()->set(
1389  myOutputAttribs.keyAttrib(), out_offset, tempdata.outindices);
1390 
1391  success = true;
1392  }
1393 
1394  if (success)
1395  {
1396  myOutputAttribs.weightArray()->set(
1397  myOutputAttribs.weightAttrib(), out_offset, tempdata.outweights);
1398  }
1399  }
1400 
1401  template<typename C>
1402  void
1404  C &out_keys,
1405  UT_Array<float> &out_weights,
1406  const GA_OffsetArray &offsets,
1407  const UT_FloatArray &weights,
1408  UT_Map<typename C::value_type, float> &blended_weights_set) const
1409  {
1410  using T = typename C::value_type;
1411 
1412  blended_weights_set.clear();
1413 
1414  float pw_sum(0.0f);
1415 
1416  for (int i=0; i<offsets.size(); ++i)
1417  {
1418  GA_Offset offset = offsets[i];
1419  float pw = weights[i];
1420 
1421  if (pw < SYS_FTOLERANCE)
1422  continue;
1423 
1424  if constexpr(SYS_IsSame_v<C, UT_StringArray>)
1425  myInputAttribs.nameArray()->get(myInputAttribs.keyAttrib(), offset, out_keys);
1426  else
1427  myInputAttribs.indexArray()->get(myInputAttribs.keyAttrib(), offset, out_keys);
1428 
1429  myInputAttribs.weightArray()->get(myInputAttribs.weightAttrib(), offset, out_weights);
1430 
1431  int count = SYSmin(out_keys.size(), out_weights.size());
1432 
1433  for (int j=0; j<count; ++j)
1434  {
1435  T key = out_keys[j];
1436  float w = out_weights[j];
1437 
1438  blended_weights_set[key] =
1439  blended_weights_set.get(key, 0.0f) + pw * w;
1440  }
1441 
1442  pw_sum += pw;
1443  }
1444 
1445  float inv_pw_sum = SYSsaferecip(pw_sum);
1446 
1447  out_keys.setSize(0);
1448  out_weights.setSize(0);
1449  for (auto &wpair : blended_weights_set)
1450  {
1451  out_keys.append(wpair.first);
1452  out_weights.append(inv_pw_sum * wpair.second);
1453  }
1454  }
1455 
1456  void
1458  const GU_Detail &geo,
1459  const GA_Attribute &prim_attrib,
1460  const GA_Attribute &primuv_attrib,
1461  GA_Attribute &key_attrib,
1462  GA_Attribute &weight_attrib) const
1463  {
1464  const GA_AIFNumericArray *index_array = key_attrib.getAIFNumericArray();
1465  const GA_AIFNumericArray *weight_array = weight_attrib.getAIFNumericArray();
1466 
1467  const GA_Size num_weight_prims = myWeightGeo.getNumPrimitives();
1468 
1469  GA_ROHandleI prim_handle(&prim_attrib);
1470  GA_ROHandleV2 primuv_handle(&primuv_attrib);
1471 
1473  [&](const GA_SplittableRange &r)
1474  {
1475  GA_Offset startptoff;
1476  GA_Offset endptoff;
1477 
1478  GA_OffsetArray pt_offsets;
1479  UT_FloatArray pt_weights;
1480 
1482  UT_ValArray<float> weights;
1483 
1484  UT_Map<GA_Size, float> temp_set;
1485 
1486  for (GA_Iterator ptit(r); ptit.blockAdvance(startptoff, endptoff); )
1487  {
1488  for (GA_Offset ptoff = startptoff; ptoff < endptoff; ++ptoff)
1489  {
1490  GA_Index skinprimindex = prim_handle.get(ptoff);
1491 
1492  if (skinprimindex < 0 || skinprimindex >= num_weight_prims)
1493  continue;
1494 
1495  GA_Offset primoff = myWeightGeo.primitiveOffset(skinprimindex);
1496  UT_Vector2 primuv = primuv_handle.get(ptoff);
1497 
1498  auto skinprim = myWeightGeo.getGEOPrimitive(primoff);
1499  skinprim->computeInteriorPointWeights(
1500  pt_offsets, pt_weights,
1501  primuv.x(),
1502  primuv.y(),
1503  0.0f);
1504 
1505  if (myInputAttribs.weightAttrib()->getOwner() != GA_ATTRIB_VERTEX)
1506  for (int i=0; i<pt_offsets.size(); ++i)
1507  pt_offsets[i] = myWeightGeo.vertexPoint(pt_offsets[i]);
1508 
1509  interpolate(
1510  indices, weights,
1511  pt_offsets, pt_weights,
1512  temp_set);
1513 
1514  index_array->set(&key_attrib, ptoff, indices);
1515  weight_array->set(&weight_attrib, ptoff, weights);
1516  }
1517  }
1518  });
1519  }
1520 
1521 private:
1522  const GEO_Detail &myWeightGeo;
1523 
1524  GU_ROWeightArrayPairHandle myInputAttribs;
1525  GU_RWWeightArrayPairHandle myOutputAttribs;
1526 };
1527 
1528 #endif
GU_GroomCurveAttribSampler(GU_Detail &dstgdp, const GU_Detail *srcgdp=nullptr)
#define SYSmax(a, b)
Definition: SYS_Math.h:1538
SYS_FORCE_INLINE void bumpDataId()
Definition: GA_Attribute.h:306
SYS_FORCE_INLINE const GA_Detail & getDetail() const
Definition: GA_Attribute.h:208
void interpolate(const GA_OffsetArray &offsets, const UT_FloatArray &weights, GA_Offset &out_offset, TempData &tempdata) const
SYS_FORCE_INLINE const GA_PrimitiveGroup * findPrimitiveGroup(const UT_StringRef &name) const
Definition: GA_Detail.h:1253
Definition of a geometry attribute.
Definition: GA_Attribute.h:198
void UTparallelFor(const Range &range, const Body &body, const int subscribe_ratio=2, const int min_grain_size=1, const bool force_use_task_scope=true)
SYS_FORCE_INLINE GA_Offset getPrimitiveVertexOffset(GA_Offset primoff, GA_Size i) const
Definition: GA_Primitive.h:900
GU_GroomSourceAttribList(GU_Detail *dest, const GU_Detail *source, const GA_AttributeOwner destowner)
bool set(GA_Attribute *attrib, GA_Offset o, const UT_StringArray &v) const
Definition: UT_Set.h:58
UT_Map< GA_Size, float > tempindexset
GU_WeightArrayInterpolate(const GEO_Detail &weightgeo, GA_AttributeOwner attrib_owner, const UT_StringRef &key_attrib_name, const UT_StringRef &weight_attrib_name)
GLsizei GLenum const void * indices
Definition: glcorearb.h:406
Generic Attribute Interface class to access an attribute as a array.
GLenum GLint * range
Definition: glcorearb.h:1925
const GA_AIFNumericArray * weightArray() const
GA_Attribute * keyAttrib() const
Iteration over a range of elements.
Definition: GA_Iterator.h:29
bool bindInputAttribs(GA_AttributeOwner attrib_owner, const UT_StringRef &key_attrib_name, const UT_StringRef &weight_attrib_name)
static GA_Attribute * findOrCreateIntArrayAttribute(GU_Detail &gdp, GA_AttributeOwner owner, const UT_StringRef &name, int tsize, GA_Storage storage=GA_STORE_INT32)
Definition: GU_GroomUtils.h:73
Class which stores the default values for a GA_Attribute.
Definition: GA_Defaults.h:35
GU_GroomSkinIntersect(const GU_RayIntersect &rayintersect, const GA_Attribute &normal)
void bindImpl(GA_Attribute *key_attrib, GA_Attribute *weight_attrib)
virtual void computeInteriorPointWeights(UT_Array< GA_Offset > &vtxlist, UT_Array< float > &weightlist, fpreal u, fpreal v, fpreal w) const
getFileOption("OpenEXR:storage") storage
Definition: HDK_Image.dox:276
const DataType & getData() const
static GA_PrimitiveGroup * findGroup(GU_Detail &gdp)
GA_Offset getLineOffset1(int id) const
SYS_FORCE_INLINE const GA_IndexMap & getIndexMap() const
Definition: GA_Attribute.h:207
bool blockAdvance(GA_Offset &start, GA_Offset &end)
GLsizei const GLfloat * value
Definition: glcorearb.h:824
SYS_FORCE_INLINE bool closestPos(UT_Vector3 &pos, GU_MinInfo &mininfo, GU_GroomInterpCoords &interpcoords)
void mapAndCreateNonRealAttribs(GA_AttributeRefMap &map, const UT_ValArray< AttribChange > *changes) const
SYS_FORCE_INLINE T * SYSconst_cast(const T *foo)
Definition: SYS_Types.h:136
SYS_FORCE_INLINE UT_Vector3 interpP(const GU_GroomInterpCoords &interpcoords) const
SYS_FORCE_INLINE bool isConstant()
int64 exint
Definition: SYS_Types.h:125
GU_GroomPartingLineLookup(unsigned int maxpartlines, GU_GroomSkinIntersect *skinintersect)
SYS_FORCE_INLINE void setValue(int pointindex, int attribindex, int guideindex, UT_QuaternionF &quat)
GU_WeightArrayInterpolate(const GEO_Detail &weightgeo, const GA_Attribute &keyattrib, const GA_Attribute &weightattrib)
void build(const GEO_Detail *gdp, const GA_PointGroup *ptgroup=NULL, bool enable_multithreading=true)
std::pair< GA_AttributeOwner, UT_StringHolder > AttribMatchTuple
SYS_FORCE_INLINE void setDim(int pointcount, int attribcount, int guidecount)
SYS_FORCE_INLINE const GA_PrimitiveTypeId & getTypeId() const
Definition: GA_Primitive.h:177
exint UT_PageNum
Definition: UT_PageArray.h:35
void setPageConstant(GA_PageNum pagenum, const BASETYPE *values) const
Definition: GA_Handle.h:480
GEO_ConstPrimitiveP myPrim
static UT_Tuple< GA_Attribute *, GA_Attribute * > createNameAndWeightArrayAttributes(GU_Detail &gdp, GA_AttributeOwner owner, const UT_StringHolder &name_attrib_name, const UT_StringHolder &weight_attrib_name)
GEO_ConstPrimitiveP prim
static GA_PrimitiveGroup & findOrCreateGroup(GU_Detail &gdp)
const GU_RayIntersect & rayIntersect()
void createOutputAttribs(GU_Detail &gdp, GA_AttributeOwner owner)
#define UTmakeTuple
Definition: UT_Tuple.h:59
GA_OffsetArray offsets
const GA_Attribute * weightAttrib() const
GA_Attribute * addStringArray(GA_AttributeOwner owner, GA_AttributeScope scope, const UT_StringHolder &name, int tuple_size=1, const UT_Options *creation_args=0, const GA_AttributeOptions *attribute_options=0, GA_Storage storage=GA_STORE_STRING, const GA_ReuseStrategy &reuse=GA_ReuseStrategy())
GA_Offset getLineOffset2(int id) const
SYS_FORCE_INLINE const UT_QuaternionFArray & getData()
std::tuple< Types...> UT_Tuple
Definition: UT_Tuple.h:53
void addAttrib(const UT_StringRef &name)
void mapAndCreateAttribs(GA_AttributeRefMap &map) const
bool bind(const GEO_Detail &detail, GA_AttributeOwner attrib_owner, const UT_StringHolder &key_attrib_name, const UT_StringHolder &weight_attrib_name)
UT_Matrix2T< T > SYSlerp(const UT_Matrix2T< T > &v1, const UT_Matrix2T< T > &v2, S t)
Definition: UT_Matrix2.h:675
void clear()
Definition: UT_Map.h:184
const GA_Attribute * weightAttrib() const
UT_UniquePtr< GU_GroomPartingLineAttribs > gu_PartingLineAttribsUPtr
V get(const key_type &key, const V &defval) const
Definition: UT_Map.h:169
GU_RWWeightArrayPairHandle()=default
static SYS_FORCE_INLINE void computeVertWeights(const GU_MinInfo &mininfo, GU_GroomInterpCoords &interpcoords)
exint size() const
Definition: UT_Array.h:646
uint64 value_type
Definition: GA_PrimCompat.h:29
void setSize(exint newsize)
Definition: UT_Array.h:666
exint GA_Size
Defines the bit width for index and offset types in GA.
Definition: GA_Types.h:235
#define GA_INVALID_OFFSET
Definition: GA_Types.h:678
A range of elements in an index-map.
Definition: GA_Range.h:42
bool bindImpl(GEO_Detail &detail, GA_AttributeOwner attrib_owner, const UT_StringHolder &key_attrib_name, const UT_StringHolder &weight_attrib_name)
GA_PrimitiveGroup * newPrimitiveGroup(const UT_StringHolder &name)
Definition: GA_Detail.h:1296
std::unique_ptr< T, Deleter > UT_UniquePtr
A smart pointer for unique ownership of dynamically allocated objects.
Definition: UT_UniquePtr.h:39
void mapAndCreateAttribs(GA_AttributeRefMap &map, const UT_ValArray< AttribChange > *changes) const
GLuint GLsizei const GLuint const GLintptr * offsets
Definition: glcorearb.h:2621
SYS_FORCE_INLINE const UT_StringHolder & getName() const
Definition: GA_Attribute.h:283
const GA_AIFNumericArray * myIndexArray
const GA_Attribute * findIntArray(GA_AttributeOwner owner, GA_AttributeScope scope, const UT_StringRef &name, int min_size=1, int max_size=-1) const
SYS_FORCE_INLINE GEO_Primitive * getGEOPrimitive(GA_Offset primoff)
Definition: GEO_Detail.h:1177
GA_Attribute * addFloatArray(GA_AttributeOwner owner, GA_AttributeScope scope, const UT_StringHolder &name, int tuple_size=1, const UT_Options *creation_args=0, const GA_AttributeOptions *attribute_options=0, GA_Storage storage=GA_STORE_REAL32, const GA_ReuseStrategy &reuse=GA_ReuseStrategy())
const GA_ATINumeric * getAttribute() const
Definition: GA_Handle.h:166
constexpr SYS_FORCE_INLINE T & x() noexcept
Definition: UT_Vector2.h:423
GA_Size GA_Offset
Definition: GA_Types.h:641
void mapAndCreateAttribs(GA_AttributeRefMap &map, const UT_ValArray< AttribChange > *changes, const std::function< bool(const GA_Attribute &)> &filter) const
static bool checkSkinPrimIndices(const GA_ROHandleI &skinprimattrib, const GU_Detail &skingdp, const GA_ElementGroup *group=nullptr)
vint4 blend(const vint4 &a, const vint4 &b, const vbool4 &mask)
Definition: simd.h:4784
static SYS_FORCE_INLINE GA_Offset primVertexOffset(const GU_Detail &gdp, GA_Offset primoff, GA_Size index=0)
static SYS_FORCE_INLINE void computeVertWeights(const GU_RayInfo &hitinfo, GU_GroomInterpCoords &interpcoords)
GA_Attribute * addIntArray(GA_AttributeOwner owner, GA_AttributeScope scope, const UT_StringHolder &name, int tuple_size=1, const UT_Options *creation_args=0, const GA_AttributeOptions *attribute_options=0, GA_Storage storage=GA_STORE_INT32, const GA_ReuseStrategy &reuse=GA_ReuseStrategy())
GU_ROWeightArrayPairHandle(const GEO_Detail &detail, GA_AttributeOwner attrib_owner, const UT_StringHolder &key_attrib_name, const UT_StringHolder &weight_attrib_name)
GLdouble n
Definition: glcorearb.h:2008
GLfloat f
Definition: glcorearb.h:1926
const GA_Attribute * findStringArray(GA_AttributeOwner owner, GA_AttributeScope scope, const UT_StringRef &name, int min_size=1, int max_size=-1) const
GA_Range getPointRange(const GA_PointGroup *group=0) const
Get a range of all points in the detail.
Definition: GA_Detail.h:1730
void addLengthScaledAttrib(const UT_StringRef &name)
GLintptr offset
Definition: glcorearb.h:665
bool operator!=(const GU_GroomFastRamp &ramp) const
void sampleAttribs(const GEO_PrimPoly &dstprimpoly, GA_Offset sourceprimoff, float blend)
static SYS_FORCE_INLINE UT_PageNum numPages(IDX_T nelements)
const GA_Attribute * keyAttrib() const
const GA_Attribute * keyAttrib() const
SYS_FORCE_INLINE const UT_QuaternionF & getValue(int pointindex, int attribindex, int guideindex)
#define UTlhsTuple
Definition: UT_Tuple.h:61
#define SYS_FORCE_INLINE
Definition: SYS_Inline.h:45
UT_Vector3T< T > SYSclamp(const UT_Vector3T< T > &v, const UT_Vector3T< T > &min, const UT_Vector3T< T > &max)
Definition: UT_Vector3.h:1057
GLsizei GLsizei GLchar * source
Definition: glcorearb.h:803
GA_API const UT_StringHolder perimeter
A specialization of GA_AIFStringArray to access "shared strings".
long long int64
Definition: SYS_Types.h:116
A handle to simplify manipulation of multiple attributes.
static float openCurveUnitToReal(int n, float u_unit)
virtual const GA_AIFSharedStringArray * getAIFSharedStringArray() const
Return the attribute's shared string array interface or NULL.
SYS_FORCE_INLINE int getLinearIndex(int pointindex, int attribindex, int guideindex)
SYS_FORCE_INLINE T get(GA_Offset off, int comp=0) const
Definition: GA_Handle.h:203
SYS_FORCE_INLINE GA_Offset vertexPoint(GA_Offset vertex) const
Given a vertex, return the point it references.
Definition: GA_Detail.h:529
UT_Map< UT_StringHolder, float > tempnameset
#define GU_API
Definition: GU_API.h:14
T interpAttrib(const GA_ROHandleT< T > &attrib, const GU_GroomInterpCoords &interpcoords) const
GLuint const GLchar * name
Definition: glcorearb.h:786
void build(const GEO_Detail *gdp, const GA_PointGroup *ptgroup, bool enable_multithreading=true)
void interpolate(const GU_Detail &geo, const GA_Attribute &prim_attrib, const GA_Attribute &primuv_attrib, GA_Attribute &key_attrib, GA_Attribute &weight_attrib) const
GA_Size GA_Index
Define the strictness of GA_Offset/GA_Index.
Definition: GA_Types.h:635
static fpreal computeNewLength(fpreal prevlength, SetLengthMode mode, fpreal value)
SYS_FORCE_INLINE UT_Vector3 interpN(const GU_GroomInterpCoords &interpcoords) const
exint append()
Definition: UT_Array.h:142
bool bind(GEO_Detail &detail, GA_AttributeOwner attrib_owner, const UT_StringHolder &key_attrib_name, const UT_StringHolder &weight_attrib_name)
void interpolate(C &out_keys, UT_Array< float > &out_weights, const GA_OffsetArray &offsets, const UT_FloatArray &weights, UT_Map< typename C::value_type, float > &blended_weights_set) const
GLsizei samples
Definition: glcorearb.h:1298
static UT_Tuple< UT_Vector2, UT_Vector2i > openCurvePointWeights(int n, fpreal u)
SYS_FORCE_INLINE const GU_Detail & detail()
GLenum mode
Definition: glcorearb.h:99
GU_GroomPartingLineLookup(unsigned int maxpartlines)
GU_GroomFastRamp(int numsamples=1000)
GLint j
Definition: glad.h:2733
const GA_AIFSharedStringArray * nameArray() const
GLsizeiptr size
Definition: glcorearb.h:664
GA_AttributeOwner
Definition: GA_Types.h:34
int64 getMemoryUsage(bool inclusive) const
const GA_AIFNumericArray * myWeightArray
void build(const GEO_Detail *gdp, const GA_PointGroup *ptgroup, const char *attrib, bool enable_multithreading=true)
GU_RWWeightArrayPairHandle(GEO_Detail &detail, GA_AttributeOwner attrib_owner, const UT_StringHolder &key_attrib_name, const UT_StringHolder &weight_attrib_name)
virtual bool get(const GA_Attribute *attrib, GA_Offset ai, UT_Array< fpreal16 > &data) const =0
static SYS_FORCE_INLINE GA_Offset primPointOffset(const GU_Detail &gdp, GA_Offset primoff, GA_Size index=0)
GLenum GLsizei GLsizei GLint * values
Definition: glcorearb.h:1602
const UT_StringHolder & attribMissingWarning()
bool operator==(const GU_GroomFastRamp &ramp) const
fpreal64 fpreal
Definition: SYS_Types.h:277
GA_Attribute * weightAttrib() const
GU_ROWeightArrayPairHandle()=default
SYS_FORCE_INLINE GA_Offset primitiveOffset(GA_Index index) const
Given a primitive's index (in append order), return its data offset.
Definition: GA_Detail.h:419
GA_Size GA_PageNum
Definition: GA_Types.h:644
Utility class for containing a color ramp.
Definition: UT_Ramp.h:88
virtual bool set(GA_Attribute *attrib, GA_Offset ai, const UT_Span< const fpreal16 > &data) const =0
GLuint index
Definition: glcorearb.h:786
const GA_AIFNumericArray * indexArray() const
bool get(const GA_Attribute *attrib, GA_Offset o, UT_StringArray &v) const
UT_ValArray< GA_Size > outindices
SYS_FORCE_INLINE GA_Size getNumPrimitives() const
Return the number of primitives.
Definition: GA_Detail.h:408
UT_FloatArray weights
SYS_FORCE_INLINE float lookup(float u) const
const GA_Attribute * findFloatArray(GA_AttributeOwner owner, GA_AttributeScope scope, const UT_StringRef &name, int min_size=1, int max_size=-1) const
SYS_FORCE_INLINE GA_AttributeOwner getOwner() const
Definition: GA_Attribute.h:210
const GA_AIFSharedStringArray * myNameArray
static fpreal getIndices(fpreal c, int &c1, int &c2, int max_index, int wrap)
#define SYS_FTOLERANCE
Definition: SYS_Types.h:208
GLubyte GLubyte GLubyte GLubyte w
Definition: glcorearb.h:857
static T interpAttrib(const GA_ROHandleT< T > &attrib, const GA_Offset &primoff, const GA_OffsetArray &vertoffsets, const UT_FloatArray &vertweights, const T defaultvalue=T(0.0f))
static GA_Attribute * findOrCreateStringArrayAttribute(GU_Detail &gdp, GA_AttributeOwner owner, const UT_StringRef &name, int tsize)
Definition: GU_GroomUtils.h:58
#define UT_ASSERT(ZZ)
Definition: UT_Assert.h:156
Definition: core.h:1131
static const GA_PrimitiveGroup * findGroup(const GU_Detail &gdp)
void set(GA_Offset primoff, const UT_StringArray &names, const UT_FloatArray &weights)
GLboolean r
Definition: glcorearb.h:1222
static void setPagesConstant(GA_RWHandleF attribhandle, float value)
GLuint attribindex
Definition: glcorearb.h:2746
void mapAndCreateRealAttribs(GA_AttributeRefMap &map, const UT_ValArray< AttribChange > *changes) const
#define SYSmin(a, b)
Definition: SYS_Math.h:1539
static UT_Tuple< GA_Attribute *, GA_Attribute * > createIndexAndWeightArrayAttributes(GU_Detail &gdp, GA_AttributeOwner owner, const UT_StringHolder &name_attrib_name, const UT_StringHolder &weight_attrib_name)
GA_Storage
Definition: GA_Types.h:50
static GA_Attribute * findOrCreateFloatArrayAttribute(GU_Detail &gdp, GA_AttributeOwner owner, const UT_StringRef &name, int tsize, GA_Storage storage=GA_STORE_REAL32)
Definition: GU_GroomUtils.h:89
constexpr SYS_FORCE_INLINE T & y() noexcept
Definition: UT_Vector2.h:425
GU_WeightArrayInterpolate(const GEO_Detail &weightgeo)
GLint GLsizei count
Definition: glcorearb.h:405
SYS_FORCE_INLINE bool hitPointInfo(UT_Vector3 pos, UT_Vector3 dir, GU_RayInfo &info)
SYS_FORCE_INLINE GA_Offset offsetSize() const
Definition: GA_IndexMap.h:97
SYS_FORCE_INLINE bool closestPointInfo(const UT_Vector3 &pos, GU_MinInfo &mininfo) const
void bind(GA_Attribute *key_attrib, GA_Attribute *weight_attrib)
SYS_FORCE_INLINE float lookupNearest(float u) const
GU_GroomSkinIntersect(const GU_RayIntersect &rayintersect)
GLint GLint GLint GLint GLint GLint GLint GLbitfield GLenum filter
Definition: glcorearb.h:1297
void bind(const GA_Attribute *key_attrib, const GA_Attribute *weight_attrib)
virtual const GA_AIFNumericArray * getAIFNumericArray() const
Return the attribute's arraydata interface or NULL.