36 #include "SOP_SweepHDK.proto.h" 
   41 #include "../SOP_OrientAlongCurve/GU_CurveFrame.h" 
   42 #include "../SOP_CopyToPoints/GEO_BuildPrimitives.h" 
   43 #include "../SOP_CopyToPoints/GU_Copy2.h" 
   85 using namespace UT::Literal;
 
   87 namespace HDK_Sample {
 
   93 constexpr 
static int theUComponent = 0;
 
   94 constexpr 
static int theVComponent = 1;
 
   96 constexpr 
static int theCurveInput = 0;
 
   97 constexpr 
static int theCrossSectionInput = 1;
 
  100 struct CrossSectionAttribMatchData
 
  151     sop_SweepGrid(
const sop_SweepGrid &that)
 
  171         if (that.mySingleCrossSection)
 
  178     sop_SweepGrid(sop_SweepGrid &&that)
 
  198         if (that.mySingleCrossSection)
 
  203             that.mySingleCrossSection = 
true;
 
  208     sop_SweepGrid &
operator=(
const sop_SweepGrid &that)
 
  221         if (that.mySingleCrossSection)
 
  241     sop_SweepGrid &
operator=(sop_SweepGrid &&that)
 
  254         if (that.mySingleCrossSection)
 
  259             that.mySingleCrossSection = 
true;
 
  308         myPrevCurvePrimListDataID(-1),
 
  309         myPrevCurveTopologyDataID(-1),
 
  310         myPrevOutputDetailID(-1),
 
  311         myPrevCopyOrder(SOP_SweepHDKEnums::
CopyOrder::CYCLEVTX),
 
  312         myPrevSurfaceType(SOP_SweepHDKEnums::
SurfaceType::POINTS),
 
  313         myPrevPrimType(SOP_SweepHDKEnums::
PrimType::AUTO),
 
  314         myPrevSurfaceShape(SOP_SweepHDKEnums::
SurfaceShape::INPUT),
 
  316         myPrevEndCapType(SOP_SweepHDKEnums::
EndCapType::NONE),
 
  317         myPrevEndCapDivs(-1),
 
  318         myPrevCrossSectionPrimListDataID(-1),
 
  319         myPrevCrossSectionTopologyDataID(-1),
 
  320         myPrevUnrollClosedRowCol(false),
 
  321         myPrevCloseIfNoCurveInput(false),
 
  322         myPrevTriangularPoles(false),
 
  323         myPrevSwapRowCol(false),
 
  324         myPrevCrossSectCurveAttribDataId(-1),
 
  325         myPrevCrossSectPrimAttribDataId(-1)
 
  384         return SYSisSame<T,double>()
 
  386             : 
reinterpret_cast<const UT_Vector3T<T> *
>(myTranslatef);
 
  396         return SYSisSame<T,double>()
 
  398             : 
reinterpret_cast<const UT_Matrix3T<T> *
>(myInverse3f);
 
  408         return SYSisSame<T,double>()
 
  410             : 
reinterpret_cast<const UT_Matrix3T<T> *
>(myMatrix3f);
 
  420         return SYSisSame<T,double>()
 
  422             : 
reinterpret_cast<const UT_QuaternionT<T> *
>(myQuaternionf);
 
  445     void cook(
const CookParms &cookparms) 
const override;
 
  461 const UT_StringHolder SOP_SweepHDKVerb::theSOPTypeName(
"hdk_sweep"_sh);
 
  483         mySopFlags.setManagesDataIDs(
true);
 
  493         return cookMyselfAsVerb(context);
 
  502             case 0:     
return "Backbone Curves";
 
  503             case 1:     
return "Cross Section(s)";
 
  504             default:    
return "Invalid Source";
 
  516         return (i == 0 || i == 1);
 
  534     return SOP_SweepHDKVerb::theVerb.get();
 
  562 namespace HDK_Sample {
 
  565 SOP_SweepHDK::cookInputGroups(
OP_Context &context, 
int alone)
 
  572     const GU_Detail *curve_input = inputGeo(theCurveInput);
 
  574     OP_ERROR ret = cookInputPrimitiveGroups(context, curve_group, alone, 
true, 0, -1, 
true, 
false, 
GroupCreator(curve_input));
 
  578     const GU_Detail *cross_section_input = inputGeo(theCrossSectionInput);
 
  580     ret = cookInputPrimitiveGroups(context, cross_section_group, alone, 
true, 1, -1, 
true, 
false, 
GroupCreator(cross_section_input));
 
  589 const char *
const SOP_SweepHDKVerb::theDsFile = R
"THEDSFILE( 
  595         label   "Backbone Curve Group" 
  598         parmtag { "script_action" "import soputils\nkwargs['geometrytype'] = (hou.geometryType.Primitives,)\nkwargs['inputindex'] = 0\nsoputils.selectGroupParm(kwargs)" } 
  599         parmtag { "script_action_help" "Select geometry from an available viewport.\nShift-click to turn on Select Groups." } 
  600         parmtag { "script_action_icon" "BUTTONS_reselect" } 
  603         name    "crosssectiongroup" 
  604         cppname "CrossSectionGroup" 
  605         label   "Cross Section Group" 
  608         parmtag { "script_action" "import soputils\nkwargs['geometrytype'] = (hou.geometryType.Primitives,)\nkwargs['inputindex'] = 1\nsoputils.selectGroupParm(kwargs)" } 
  609         parmtag { "script_action_help" "Select geometry from an available viewport.\nShift-click to turn on Select Groups." } 
  610         parmtag { "script_action_icon" "BUTTONS_reselect" } 
  619         name    "surface_folder" 
  623             cppname "SurfaceShape" 
  624             label   "Surface Shape" 
  626             default { "0" }     // Default to first entry in menu, "input" 
  628                 "input"     "Second Input Cross Sections" 
  630                 "square"    "Square Tube" 
  636             cppname "SurfaceType" 
  639             default { "5" }     // Default to menu entry "quads" 
  644                 "rowcol"    "Rows and Columns" 
  646                 "quads"     "Quadrilaterals" 
  647                 "alttris"   "Alternating Triangles" 
  648                 "revtris"   "Reverse Triangles" 
  653             label   "Scale Cross Sections" 
  657             disablewhen "{ surfaceshape != input }" 
  658             hidewhen    "{ surfaceshape != input }" 
  666             disablewhen "{ surfaceshape == input }" 
  667             hidewhen    "{ surfaceshape == input }" 
  675             parmtag { "units" "m1" } 
  676             disablewhen "{ surfaceshape != tube }" 
  677             hidewhen    "{ surfaceshape != tube }" 
  685             parmtag { "units" "m1" } 
  686             disablewhen "{ surfaceshape != ribbon surfaceshape != square }" 
  687             hidewhen    "{ surfaceshape != ribbon surfaceshape != square }" 
  690             name    "reversecrosssections" 
  691             cppname "ReverseCrossSections" 
  692             label   "Reverse Cross Sections" 
  697             name    "stretcharoundturns" 
  698             cppname "StretchAroundTurns" 
  699             label   "Stretch Around Turns" 
  704             name    "maxstretcharoundturns" 
  705             cppname "MaxStretchAroundTurns" 
  710             disablewhen "{ stretcharoundturns == 0 }" 
  713             name    "endcaps_folder" 
  720                 default { "0" }     // Default to menu entry "none" 
  723                     "single"    "Single Polygon" 
  725                     "sidesingle" "Side Single Polygon" 
  731                 label   "Cap Divisions" 
  735                 disablewhen "{ endcaptype == none } { endcaptype == single } { endcaptype == sidesingle }" 
  736                 hidewhen "{ endcaptype == none } { endcaptype == single } { endcaptype == sidesingle }" 
  740                 name    "triangularpoles" 
  741                 cppname "TriangularPoles" 
  742                 label   "Triangular Poles" 
  745                 disablewhen "{ endcaptype == none } { endcaptype == single } { endcaptype == sidesingle }" 
  746                 hidewhen "{ endcaptype == none } { endcaptype == single } { endcaptype == sidesingle }" 
  751                 label   "End Cap Scale" 
  755                 disablewhen "{ endcaptype == none } { endcaptype == single } { endcaptype == sidesingle }" 
  756                 hidewhen "{ endcaptype == none } { endcaptype == single } { endcaptype == sidesingle }" 
  760                 cppname "CapRoundness" 
  761                 label   "End Cap Roundness" 
  765                 disablewhen "{ endcaptype == none } { endcaptype == single } { endcaptype == sidesingle }" 
  766                 hidewhen "{ endcaptype == none } { endcaptype == single } { endcaptype == sidesingle }" 
  769                 name    "addendcapsgroup" 
  770                 cppname "AddEndCapsGroup" 
  771                 label   "Add End Caps Group" 
  779                 cppname "EndCapsGroup" 
  780                 label   "End Caps Group" 
  782                 default { "endcaps" } 
  783                 disablewhen "{ addendcapsgroup == 0 }" 
  792                 label   "Apply Scale Along Curve" 
  803                 disablewhen "{ applyscale == 0 }" 
  804                 parmtag     { "rampfloatdefault" "1pos ( 0 ) 1value ( 1 ) 1interp ( linear ) 2pos ( 1 ) 2value ( 1 ) 2interp ( linear )" } 
  808             name    "rotation_folder" 
  815                 // NOTE: The default rotation order X,Y,Z is semi-arbitrary, but Z 
  816                 //       should probably be last, since it always needs to twist 
  817                 //       around the curve tangent.  The X and Y rotations may have 
  818                 //       just been to reorient a cross-section before copying. 
  821                     "xyz"   "Pitch, Yaw, Roll" 
  822                     "xzy"   "Pitch, Roll, Yaw" 
  823                     "yxz"   "Yaw, Pitch, Roll" 
  824                     "yzx"   "Yaw, Roll, Pitch" 
  825                     "zxy"   "Roll, Pitch, Yaw" 
  826                     "zyx"   "Roll, Yaw, Pitch" 
  832                 label   "Apply Roll or Twist" 
  842                 hidewhen "{ applyroll == 0 }" 
  851                 hidewhen "{ applyroll == 0 }" 
  856                 label   "Partial Twist" 
  860                 hidewhen "{ applyroll == 0 }" 
  868                 default { "4" }     // Default to "fulldistance" entry in menu 
  871                     "distance"      "Per Unit Distance" 
  872                     "attrib"        "Scale by Attribute" 
  873                     "fulledges"     "Per Full Curve by Edges" 
  874                     "fulldistance"  "Per Full Curve by Distance" 
  876                 hidewhen "{ applyroll == 0 }" 
  881                 label   "Twist Ramp Attribute" 
  884                 disablewhen "{ applyroll == 0 } { applyroll == 1 rollper != attrib }" 
  885                 hidewhen    "{ applyroll == 0 } { applyroll == 1 rollper != attrib }" 
  892                 hidewhen "{ applyroll == 0 }" 
  907                 hidewhen "{ applyyaw == 0 }" 
  912                 label   "Incremental Yaw" 
  916                 hidewhen "{ applyyaw == 0 }" 
  924                 default { "4" }     // Default to "fulldistance" entry in menu 
  927                     "distance"      "Per Unit Distance" 
  928                     "attrib"        "Scale By Attribute" 
  929                     "fulledges"     "Per Full Curve by Edges" 
  930                     "fulldistance"  "Per Full Curve by Distance" 
  932                 hidewhen "{ applyyaw == 0 }" 
  937                 label   "Yaw Ramp Attribute" 
  940                 disablewhen "{ applyyaw == 0 } { applyyaw == 1 yawper != attrib }" 
  941                 hidewhen    "{ applyyaw == 0 } { applyyaw == 1 yawper != attrib }" 
  948                 hidewhen "{ applyyaw == 0 }" 
  963                 hidewhen "{ applypitch == 0 }" 
  968                 label   "Incremental Pitch" 
  972                 hidewhen "{ applypitch == 0 }" 
  980                 default { "4" }     // Default to "fulldistance" entry in menu 
  983                     "distance"      "Per Unit Distance" 
  984                     "attrib"        "Scale By Attribute" 
  985                     "fulledges"     "Per Full Curve by Edges" 
  986                     "fulldistance"  "Per Full Curve by Distance" 
  988                 hidewhen "{ applypitch == 0 }" 
  992                 cppname "PitchAttrib" 
  993                 label   "Pitch Ramp Attribute" 
  996                 disablewhen "{ applypitch == 0 } { applypitch == 1 pitchper != attrib }" 
  997                 hidewhen    "{ applypitch == 0 } { applypitch == 1 pitchper != attrib }" 
 1006         name    "construction_folder" 
 1007         label   "Construction" 
 1009             name    "cross_sections_folder" 
 1010             label   "Cross Sections" 
 1014                 label   "Cross Section Order" 
 1016                 default { "1" }     // Default to third entry in menu, "each" 
 1018                     "all"   "All Cross Sections At Each Curve Vertex" 
 1019                     "each"  "Each Cross Section At All Curve Vertices" 
 1020                     "cyclevtx" "Cycle Through Cross Section Primitives per Vertex" 
 1021                     "cyclepr" "Cycle Through Cross Section Primitives per Curve" 
 1022                     "attrib" "Choose Cross Section Primitives by Attribute" 
 1024                 disablewhen "{ surfaceshape != input }" 
 1027                 name    "crosssectionattrib" 
 1028                 cppname "CrossSectionAttrib" 
 1029                 label   "Cross Section Attribute" 
 1031                 default { "variant" } 
 1032                 disablewhen "{ surfaceshape != input } { copyorder != attrib }" 
 1033                 hidewhen    "{ surfaceshape != input } { copyorder != attrib }" 
 1038                 label   "Primitive Type" 
 1040                 default { "0" }     // Default to menu entry "auto" 
 1044                     "mesh"      "Bilinear Mesh" 
 1045                     "nurbs"     "NURBS Surface" 
 1046                     "bezier"    "Bezier Surface" 
 1047                     "polysoup"  "Polygon Soup" 
 1049                 disablewhen "{ surfacetype == points }" 
 1052                 name    "unrollclosedrowcol" 
 1053                 cppname "UnrollClosedRowCol" 
 1054                 label   "Ensure Unique Seam Vertices" 
 1057                 disablewhen "{ surfacetype == points }" 
 1061                 cppname "SwapRowCol" 
 1062                 label   "Swap Rows and Columns" 
 1067                 name    "closeifnocurveinput" 
 1068                 cppname "CloseIfNoCurveInput" 
 1069                 label   "Close Implicit Backbone Curve if No Curve Input" 
 1072                 disablewhen "{ surfacetype == points } { surfacetype == rows } { hasinput(0) != 0 }" 
 1076             //    cppname "SegDivs" 
 1077             //    label   "Segment Divisions" 
 1088                 cppname "UpVectorType" 
 1089                 label   "Target Up Vector" 
 1091                 default { "0" } // Default to first entry in menu, "normal" 
 1093                     "normal"    "Curve Normal" 
 1097                     "attrib"    "Attribute" 
 1100                 disablewhen "{ tangenttype == none }" 
 1103             //    name    "usenormalup" 
 1104             //    cppname "UseNormalUp" 
 1105             //    label   "Use Curve Normal as Up Vector (When Valid)" 
 1108             //    disablewhen "{ tangenttype == none }" 
 1111                 name    "upvectoratstart" 
 1112                 cppname "UpVectorAtStart" 
 1113                 label   "Target Up Vector at Start (else Average)" 
 1116                 disablewhen "{ tangenttype == none }" 
 1119                 name    "useendupvector" 
 1120                 cppname "UseEndUpVector" 
 1121                 label   "Use Target End Up Vector" 
 1124                 disablewhen "{ tangenttype == none } { upvectoratstart == 0 }" 
 1127                 name    "upvectorattrib" 
 1128                 cppname "UpVectorAttrib" 
 1129                 label   "Start Up Attribute" 
 1131                 default { "start_up" } 
 1132                 disablewhen "{ tangenttype == none } { upvectortype != attrib }" 
 1133                 hidewhen "{ tangenttype == none } { upvectortype != attrib }" 
 1136                 name    "endupvectorattrib" 
 1137                 cppname "EndUpVectorAttrib" 
 1138                 label   "End Up Attribute" 
 1140                 default { "end_up" } 
 1141                 disablewhen "{ tangenttype == none } { upvectortype != attrib } { useendupvector == 0 } { upvectoratstart == 0 }" 
 1142                 hidewhen "{ tangenttype == none } { upvectortype != attrib } { useendupvector == 0 } { upvectoratstart == 0 }" 
 1147                 label   "Start Up Vector" 
 1150                 default { "0" "1" "0" } 
 1151                 disablewhen "{ tangenttype == none } { upvectortype != custom }" 
 1152                 hidewhen "{ tangenttype == none } { upvectortype != custom }" 
 1156                 cppname "EndUpVector" 
 1157                 label   "End Up Vector" 
 1160                 default { "0" "1" "0" } 
 1161                 disablewhen "{ tangenttype == none } { upvectortype != custom } { useendupvector == 0 } { upvectoratstart == 0 }" 
 1162                 hidewhen "{ tangenttype == none } { upvectortype != custom } { useendupvector == 0 } { upvectoratstart == 0 }" 
 1166             name    "tangents_folder" 
 1170                 cppname "TangentType" 
 1171                 label   "Tangent Type" 
 1173                 default { "0" } // Default to first entry in menu, "avgdir" 
 1175                     "avgdir"    "Average of Edge Directions" 
 1176                     "diff"      "Central Difference" 
 1177                     "prev"      "Previous Edge" 
 1179                     "none"      "Z Axis (Ignore Curve)" 
 1183                 name    "continuousclosed" 
 1184                 cppname "ContinuousClosed" 
 1185                 label   "Make Closed Curve Orientations Continuous" 
 1188                 disablewhen "{ tangenttype == none }" 
 1191                 name    "extrapolateendtangents" 
 1192                 cppname "ExtrapolateEndTangents" 
 1193                 label   "Extrapolate End Tangents" 
 1196                 disablewhen "{ tangenttype == none }" 
 1199                 name    "transformbyattribs" 
 1200                 cppname "TransformByAttribs" 
 1201                 label   "Transform Using Curve Point Attributes" 
 1213         label   "UVs and Attributes" 
 1216             label   "UV Coordinates" 
 1219                 cppname "ComputeUVs" 
 1225                 name    "overrideexistinguvs" 
 1226                 cppname "OverrideExistingUVs" 
 1227                 label   "Override Any Existing UVs" 
 1230                 disablewhen "{ computeuvs == 0 }" 
 1233                 name    "lengthweighteduvs" 
 1234                 cppname "LengthWeightedUVs" 
 1235                 label   "Length-Weighted UVs" 
 1238                 disablewhen "{ computeuvs == 0 }" 
 1242                 cppname "NormalizeU" 
 1243                 label   "Normalize Computed Us" 
 1246                 disablewhen "{ computeuvs == 0 } { lengthweighteduvs == 0 }" 
 1250                 cppname "NormalizeV" 
 1251                 label   "Normalize Computed Vs" 
 1254                 disablewhen "{ computeuvs == 0 } { lengthweighteduvs == 0 }" 
 1259                 label   "Flip Computed Us" 
 1262                 disablewhen "{ computeuvs == 0 }" 
 1265                 name    "uvscale_folder" 
 1267                 grouptag { "group_type" "collapsible" } 
 1268                 parmtag { "group_default" "0" } 
 1276                     disablewhen "{ computeuvs == 0 }" 
 1279                     name    "usemeshedgelengths" 
 1280                     cppname "UseMeshEdgeLengths" 
 1281                     label   "Use Mesh Edge Lengths Instead of Curve Edge Lengths" 
 1284                     disablewhen "{ computeuvs == 0 } { lengthweighteduvs == 0 }" 
 1287                     name    "propscalepercurve" 
 1288                     cppname "PropScalePerCurve" 
 1289                     label   "Use Max Cross Section Length per Curve for Proportional Scale" 
 1292                     disablewhen "{ computeuvs == 0 } { lengthweighteduvs == 0 } { normalizeu != 1 } { normalizev != 0 }" 
 1296                 name    "uvseams_folder" 
 1298                 grouptag { "group_type" "collapsible" } 
 1299                 parmtag { "group_default" "0" } 
 1303                     label   "Snap U to Nearest Tile Boundary" 
 1306                     disablewhen "{ computeuvs == 0 } { lengthweighteduvs == 0 } { normalizeu == 1 }" 
 1311                     label   "Snap V to Nearest Tile Boundary" 
 1314                     disablewhen "{ computeuvs == 0 } { lengthweighteduvs == 0 } { normalizev == 1 }" 
 1319             name    "attributes_folder" 
 1321             grouptag { "group_type" "collapsible" } 
 1322             parmtag { "group_default" "0" } 
 1327                     name    "attribsfrombackbone" 
 1328                     cppname "AttribsFromBackbone" 
 1329                     label   "From Backbone Curves" 
 1331                     default { "* ^P ^N ^up ^pscale ^scale ^orient ^rot ^pivot ^trans ^transform" } 
 1334                     name    "attribsfromcrosssection" 
 1335                     cppname "AttribsFromCrossSection" 
 1336                     label   "From Cross Sections" 
 1342                 name    "output_folder" 
 1346                     cppname "AddPointRow" 
 1347                     label   "Add Point Row Attribute" 
 1355                     cppname "PtRowAttrib" 
 1356                     label   "Point Row Attribute" 
 1359                     disablewhen "{ addptrow == 0 }" 
 1363                     cppname "AddPointCol" 
 1364                     label   "Add Point Col Attribute" 
 1372                     cppname "PtColAttrib" 
 1373                     label   "Point Col Attribute" 
 1376                     disablewhen "{ addptcol == 0 }" 
 1380                     cppname "AddPrimRow" 
 1381                     label   "Add Prim Row Attribute" 
 1388                     name    "primrowattrib" 
 1389                     cppname "PrimRowAttrib" 
 1390                     label   "Prim Row Attribute" 
 1392                     default { "primrow" } 
 1393                     disablewhen "{ addprimrow == 0 }" 
 1397                     cppname "AddPrimCol" 
 1398                     label   "Add Prim Col Attribute" 
 1405                     name    "primcolattrib" 
 1406                     cppname "PrimColAttrib" 
 1407                     label   "Prim Col Attribute" 
 1409                     default { "primcol" } 
 1410                     disablewhen "{ addprimcol == 0 }" 
 1413                     name    "addcrosssectionnum" 
 1414                     cppname "AddCrossSectionNum" 
 1415                     label   "Add Cross Section Num Attribute" 
 1422                     name    "crosssectionnumattrib" 
 1423                     cppname "CrossSectionNumAttrib" 
 1424                     label   "Cross Section Num Attribute" 
 1426                     default { "crossnum" } 
 1427                     disablewhen "{ addcrosssectionnum == 0 }" 
 1431                     cppname "AddCurveNum" 
 1432                     label   "Add Curve Num Attribute" 
 1439                     name    "curvenumattrib" 
 1440                     cppname "CurveNumAttrib" 
 1441                     label   "Curve Num Attribute" 
 1443                     default { "curvenum" } 
 1444                     disablewhen "{ addcurvenum == 0 }" 
 1446                 // TODO: Add option to compute vertex normals with cusp angle. 
 1457 using namespace SOP_SweepHDKEnums;
 
 1458 using namespace GU_CurveFrame;
 
 1464 template<
typename T>
 
 1466 insertIntoIntervals(
 
 1467     const T *
const edge_lengths,
 
 1468     const T total_length,
 
 1470     const exint ninsertions,
 
 1471     exint *
const ninsertions_per_edge)
 
 1473     UT_ASSERT(nedges >= 1 && ninsertions >= 0);
 
 1474     exint ninsertions_so_far = 0;
 
 1475     for (
exint i = 0; i < nedges; ++i)
 
 1477         T portion = (total_length > 0) ? (edge_lengths[i]/total_length) : (
T(1)/
T(nedges));
 
 1484         ki = 
SYSmin(ki, ninsertions-ninsertions_so_far);
 
 1485         ninsertions_per_edge[i] = ki;
 
 1486         ninsertions_so_far += ki;
 
 1488     if (ninsertions_so_far == ninsertions)
 
 1491     struct IntervalComparator {
 
 1492         IntervalComparator(
const T *
const edge_lengths, 
const exint *
const ninsertions_per_edge) :
 
 1493             myEdgeLengths(edge_lengths),
 
 1494             myNInsertionsPerEdge(ninsertions_per_edge)
 
 1499             const T nadb = myEdgeLengths[
a]*(myNInsertionsPerEdge[
b]+1);
 
 1500             const T nbda = myEdgeLengths[
b]*(myNInsertionsPerEdge[
a]+1);
 
 1507             return nadb < nbda || (nadb == nbda && a < 
b);
 
 1509         const T *
const myEdgeLengths;
 
 1510         const exint *
const myNInsertionsPerEdge;
 
 1512     IntervalComparator comparator(edge_lengths, ninsertions_per_edge);
 
 1516     if (nedges < 20 || (ninsertions-ninsertions_so_far) < 20) {
 
 1518             exint edge_with_largest_intervals = 0;
 
 1519             for (
exint i = 1; i < nedges; ++i) {
 
 1520                 if (comparator(edge_with_largest_intervals, i)) {
 
 1521                     edge_with_largest_intervals = i;
 
 1524             ++ninsertions_per_edge[edge_with_largest_intervals];
 
 1525             ++ninsertions_so_far;
 
 1526         } 
while (ninsertions_so_far < ninsertions);
 
 1535     for (
exint i = 0; i < nedges; ++i)
 
 1538     exint *
const heap_end = heap_begin+nedges;
 
 1539     std::make_heap(heap_begin, heap_end, comparator);
 
 1544         exint edge_with_largest_intervals = heap_begin[0];
 
 1545         ++ninsertions_per_edge[edge_with_largest_intervals];
 
 1546         ++ninsertions_so_far;
 
 1547         if (ninsertions_so_far == ninsertions)
 
 1551         std::pop_heap(heap_begin, heap_end, comparator);
 
 1552         heap_end[-1] = edge_with_largest_intervals;
 
 1553         std::push_heap(heap_begin, heap_end, comparator);
 
 1562     switch (sop_primtype)
 
 1579     return (i==0) ? 0 : (n-i);
 
 1599     if (interrupt.wasInterrupted())
 
 1617             if (interrupt.wasInterrupted())
 
 1621             for (
GA_Offset primoff = start; primoff < 
end; ++primoff)
 
 1642                 if (!reverse || closed)
 
 1643                     vtxoff0 = vertices(0);
 
 1645                     vtxoff0 = vertices(n-1);
 
 1647                 bool local_by_length = by_length;
 
 1648                 if (local_by_length)
 
 1669                         local_by_length = 
false;
 
 1675                         float cur_length = 0;
 
 1683                             const float u = cur_length/
length;
 
 1689                 if (!local_by_length)
 
 1692                     GA_Size nedges = closed ? n : (n-1);
 
 1697                         const float u = i/
float(nedges);
 
 1706                 if (reverse && closed)
 
 1715 static GA_Offset lookupCrossSectionFromAttrib(
 
 1716     const CrossSectionAttribMatchData *copy_order_attrib_data,
 
 1721     if (copy_order_attrib_data->myCurveIntAttrib.isValid())
 
 1724         const exint id = copy_order_attrib_data->myCurveIntAttrib.get(curve_offset);
 
 1725         if (copy_order_attrib_data->myIsUsingMap) {
 
 1731             auto &&it = copy_order_attrib_data->myIntToPrimOff.find(
id);
 
 1732             if (it == copy_order_attrib_data->myIntToPrimOff.end()) {
 
 1743         if (cross_section_group && !cross_section_group->
contains(cross_section_primoff)) {
 
 1747         return cross_section_primoff;
 
 1751     UT_ASSERT_P(copy_order_attrib_data->myCurveStrAttrib.isValid());
 
 1752     UT_ASSERT_P(copy_order_attrib_data->myIsUsingMap);
 
 1759     auto &&it = copy_order_attrib_data->myStrToPrimOff.find(name);
 
 1760     if (it == copy_order_attrib_data->myStrToPrimOff.end()) {
 
 1771     int &primitive_type,
 
 1772     unsigned char &fallback_orderu,
 
 1793     if (pbasisu != 
nullptr)
 
 1800 computeCombinedCrossSectionProperties(
 
 1804     exint num_cross_sections,
 
 1805     exint &cross_section_nedges,
 
 1806     bool &cross_section_closed,
 
 1807     bool &cross_section_unrolled,
 
 1808     bool &varying_nedges,
 
 1810     const bool is_primtype_auto,
 
 1811     int &primitive_type,
 
 1812     unsigned char &fallback_orderu,
 
 1815     if (num_cross_sections == 0)
 
 1823     bool basis_cross_section_closed;
 
 1824     bool basis_cross_section_unrolled;
 
 1827     cross_section_nedges = -1;
 
 1828     varying_nedges = 
false;
 
 1830     for (
exint cross_sectioni = 0; cross_sectioni < num_cross_sections; ++cross_sectioni)
 
 1832         GA_Offset cross_section_primoff = *cross_section_it;
 
 1834         if (cross_section_it.
atEnd())
 
 1837             cross_section_it.
rewind();
 
 1841         cross_section_primoffs.
append(cross_section_primoff);
 
 1843         exint local_cross_section_nedges;
 
 1844         bool local_cross_section_closed;
 
 1845         bool local_cross_section_unrolled;
 
 1846         bool nonempty = 
getPolyProperties(cross_section_input, cross_section_vertices, local_cross_section_nedges, local_cross_section_closed, local_cross_section_unrolled);
 
 1852         if (cross_section_nedges == -1)
 
 1855             cross_section_closed = local_cross_section_closed;
 
 1856             cross_section_unrolled = local_cross_section_unrolled;
 
 1858         else if (!local_cross_section_closed)
 
 1862             cross_section_closed = 
false;
 
 1863             cross_section_unrolled = 
false;
 
 1865         else if (local_cross_section_unrolled && cross_section_closed && !cross_section_unrolled)
 
 1869             cross_section_unrolled = 
true;
 
 1874         bool local_varying_nedges = (cross_section_nedges != -1 && local_cross_section_nedges != cross_section_nedges);
 
 1876         varying_nedges |= local_varying_nedges;
 
 1879         if (is_primtype_auto)
 
 1881             local_primtype = updateAutoPrimType(cross_section_input, cross_section_primoff, primitive_type, fallback_orderu, 
nullptr);
 
 1885         if (local_cross_section_nedges > cross_section_nedges)
 
 1887             cross_section_nedges = local_cross_section_nedges;
 
 1889             if (is_primtype_auto && pbasisu != 
nullptr)
 
 1895                     basis_cross_section_closed = local_cross_section_closed;
 
 1896                     basis_cross_section_unrolled = local_cross_section_unrolled;
 
 1911     if (pbasisu != 
nullptr && *pbasisu != 
nullptr)
 
 1916         if (basis_primtype != primitive_type ||
 
 1917             basis_cross_section_closed != cross_section_closed ||
 
 1918             basis_cross_section_unrolled != cross_section_unrolled)
 
 1933 computeCombinedCrossSectionPropertiesAttrib(
 
 1938     const CrossSectionAttribMatchData *
const copy_order_attrib_data,
 
 1939     exint &cross_section_nedges,
 
 1940     bool &cross_section_closed,
 
 1941     bool &cross_section_unrolled,
 
 1942     bool &varying_nedges,
 
 1944     const bool is_primtype_auto,
 
 1945     int &primitive_type,
 
 1946     unsigned char &fallback_orderu,
 
 1949     exint num_vertices = curve_vertices.
size();
 
 1950     if (num_vertices == 0)
 
 1953     const GA_AttributeOwner curve_owner = copy_order_attrib_data->myCurveAttribOwner;
 
 1958     bool basis_cross_section_closed;
 
 1959     bool basis_cross_section_unrolled;
 
 1962     cross_section_nedges = -1;
 
 1963     varying_nedges = 
false;
 
 1965     for (
exint vtxi = 0; vtxi < num_vertices; ++vtxi)
 
 1967         GA_Offset curve_offset = curve_vertices[vtxi];
 
 1969             curve_offset = curve_input->
vertexPoint(curve_offset);
 
 1970         GA_Offset cross_section_primoff = lookupCrossSectionFromAttrib(copy_order_attrib_data, curve_offset, cross_section_input, cross_section_group);
 
 1977         cross_section_primoffs.
append(cross_section_primoff);
 
 1979         exint local_cross_section_nedges;
 
 1980         bool local_cross_section_closed;
 
 1981         bool local_cross_section_unrolled;
 
 1982         bool nonempty = 
getPolyProperties(cross_section_input, cross_section_vertices, local_cross_section_nedges, local_cross_section_closed, local_cross_section_unrolled);
 
 1988         if (cross_section_nedges == -1)
 
 1991             cross_section_closed = local_cross_section_closed;
 
 1992             cross_section_unrolled = local_cross_section_unrolled;
 
 1994         else if (!local_cross_section_closed)
 
 1998             cross_section_closed = 
false;
 
 1999             cross_section_unrolled = 
false;
 
 2001         else if (local_cross_section_unrolled && cross_section_closed && !cross_section_unrolled)
 
 2005             cross_section_unrolled = 
true;
 
 2010         bool local_varying_nedges = (cross_section_nedges != -1 && local_cross_section_nedges != cross_section_nedges);
 
 2012         varying_nedges |= local_varying_nedges;
 
 2015         if (is_primtype_auto)
 
 2017             local_primtype = updateAutoPrimType(cross_section_input, cross_section_primoff, primitive_type, fallback_orderu, 
nullptr);
 
 2021         if (local_cross_section_nedges > cross_section_nedges)
 
 2023             cross_section_nedges = local_cross_section_nedges;
 
 2025             if (is_primtype_auto && pbasisu != 
nullptr)
 
 2031                     basis_cross_section_closed = local_cross_section_closed;
 
 2032                     basis_cross_section_unrolled = local_cross_section_unrolled;
 
 2047     if (pbasisu != 
nullptr && *pbasisu != 
nullptr)
 
 2052         if (basis_primtype != primitive_type ||
 
 2053             basis_cross_section_closed != cross_section_closed ||
 
 2054             basis_cross_section_unrolled != cross_section_unrolled)
 
 2067     const bool output_points_only,
 
 2068     const bool is_primtype_auto,
 
 2069     int &primitive_type,
 
 2070     unsigned char &fallback_orderv,
 
 2080     fallback_orderv = 0;
 
 2081     if (!is_primtype_auto)
 
 2086     if (curve_input == 
nullptr)
 
 2090         fallback_orderv = 4;
 
 2097     bool is_curve = 
false;
 
 2126 computeSingleGridSetup(
 
 2130     const bool single_cross_section,
 
 2133     exint cross_section_nedges,
 
 2134     bool cross_section_closed,
 
 2135     bool cross_section_unrolled,
 
 2137     const CrossSectionAttribMatchData *
const copy_order_attrib_data,
 
 2138     bool varying_nedges_all_case,
 
 2144     const bool closed_if_no_curve_input,
 
 2148     const bool output_points_only,
 
 2149     const bool unroll_closed_row_col,
 
 2150     const bool is_primtype_auto,
 
 2152     unsigned char fallback_orderu,
 
 2153     unsigned char fallback_orderv,
 
 2156     exint cap_divisions,
 
 2159     sop_SweepGrid &grid_info,
 
 2162     const bool has_col_surface_type =
 
 2165     const bool has_row_surface_type =
 
 2168     const bool has_rowcol_surface_type =
 
 2169         has_col_surface_type || has_row_surface_type;
 
 2171     const bool is_polygon_type = (!output_points_only && primitive_type == 
GA_PRIMPOLY);
 
 2172     const bool could_add_row_seam_vertex = (has_col_surface_type || !is_polygon_type) && unroll_closed_row_col;
 
 2173     const bool could_add_col_seam_vertex = (has_row_surface_type || !is_polygon_type) && unroll_closed_row_col;
 
 2175     if (curve_input == 
nullptr)
 
 2178         UT_ASSERT(cross_section_input != 
nullptr);
 
 2180         grid_info.myCurveClosed = closed_if_no_curve_input;
 
 2181         grid_info.myCurveUnrolled = (grid_info.myCurveClosed && could_add_row_seam_vertex);
 
 2183         grid_info.myCurveNEdges = num_cross_sections - !grid_info.myCurveClosed;
 
 2185         bool varying_nedges;
 
 2187         bool is_valid_grid = computeCombinedCrossSectionProperties(
 
 2188             cross_section_input,
 
 2189             cross_section_group,
 
 2192             cross_section_nedges,
 
 2193             cross_section_closed,
 
 2194             cross_section_unrolled,
 
 2196             cross_section_primoffs,
 
 2205         grid_info.myCrossSectionNEdges = cross_section_nedges;
 
 2206         grid_info.myCrossSectionClosed = cross_section_closed;
 
 2207         grid_info.myCrossSectionUnrolled = cross_section_unrolled || (cross_section_closed && could_add_col_seam_vertex);
 
 2208         grid_info.myAllEqualNEdges = !varying_nedges;
 
 2209         grid_info.mySingleCrossSection = (cross_section_primoffs.
size() == 1);
 
 2210         if (grid_info.mySingleCrossSection)
 
 2211             grid_info.myCrossSectionPrimOff = cross_section_primoffs(0);
 
 2213             grid_info.myCrossSectionPrimOffs = 
new GA_OffsetList(std::move(cross_section_primoffs));
 
 2218         grid_info.myCurvePrimOff = curve_primoff;
 
 2222         bool curve_unrolled;
 
 2224         bool nonempty = 
getPolyProperties(curve_input, curve_vertices, curve_nedges, curve_closed, curve_unrolled);
 
 2230         grid_info.myCurveClosed = curve_closed;
 
 2231         grid_info.myCurveUnrolled = curve_unrolled || (curve_closed && could_add_row_seam_vertex);
 
 2232         grid_info.myCurveNEdges = curve_nedges;
 
 2234         if (single_cross_section)
 
 2237             grid_info.myCrossSectionNEdges = cross_section_nedges;
 
 2238             grid_info.myCrossSectionClosed = cross_section_closed;
 
 2239             grid_info.myCrossSectionUnrolled = cross_section_unrolled || (cross_section_closed && could_add_col_seam_vertex);
 
 2240             grid_info.myAllEqualNEdges = 
true;
 
 2241             grid_info.mySingleCrossSection = 
true;
 
 2242             grid_info.myCrossSectionPrimOff = single_cross_section_primoff;
 
 2247                 "Other cases should have resolved to single cross section grids.");
 
 2249             bool varying_nedges = varying_nedges_all_case;
 
 2251             if (copy_order == CopyOrder::CYCLEVTX)
 
 2253                 exint num_cross_sections = curve_nedges + !curve_closed;
 
 2254                 bool is_valid_grid = computeCombinedCrossSectionProperties(
 
 2255                     cross_section_input,
 
 2256                     cross_section_group,
 
 2259                     cross_section_nedges,
 
 2260                     cross_section_closed,
 
 2261                     cross_section_unrolled,
 
 2263                     cross_section_primoffs,
 
 2274                 bool is_valid_grid = computeCombinedCrossSectionPropertiesAttrib(
 
 2275                     cross_section_input,
 
 2276                     cross_section_group,
 
 2279                     copy_order_attrib_data,
 
 2280                     cross_section_nedges,
 
 2281                     cross_section_closed,
 
 2282                     cross_section_unrolled,
 
 2284                     cross_section_primoffs,
 
 2294             grid_info.myCrossSectionNEdges = cross_section_nedges;
 
 2295             grid_info.myCrossSectionClosed = cross_section_closed;
 
 2296             grid_info.myCrossSectionUnrolled = cross_section_unrolled || (cross_section_closed && could_add_col_seam_vertex);
 
 2297             grid_info.myAllEqualNEdges = !varying_nedges;
 
 2298             grid_info.mySingleCrossSection = 
false;
 
 2301                 exint ncopies = grid_info.myCurveNEdges + !grid_info.myCurveClosed;
 
 2302                 grid_info.myCurveNEdges = (ncopies * cross_section_primoffs_all_case->
size()) - !grid_info.myCurveClosed;
 
 2304                 for (
exint copyi = 0; copyi < ncopies; ++copyi)
 
 2306                     grid_info.myCrossSectionPrimOffs->append(*cross_section_primoffs_all_case);
 
 2311                 grid_info.myCrossSectionPrimOffs = 
new GA_OffsetList(std::move(cross_section_primoffs));
 
 2316     grid_info.myHasPolygonCaps =
 
 2317         !output_points_only &&
 
 2319             (end_cap_type == EndCapType::SINGLE &&
 
 2320                 (!grid_info.myCurveClosed && grid_info.myCrossSectionClosed && grid_info.myCrossSectionNEdges > 1)) ||
 
 2321             (end_cap_type == EndCapType::SIDESINGLE &&
 
 2322                 (!grid_info.myCrossSectionClosed && grid_info.myCurveClosed && grid_info.myCurveNEdges > 1))
 
 2324         !has_rowcol_surface_type;
 
 2327     grid_info.myUEndPoles = 
false;
 
 2329     grid_info.myUEndPoles =
 
 2330         !output_points_only &&
 
 2331         (end_cap_type != 
EndCapType::NONE && end_cap_type != EndCapType::SINGLE && end_cap_type != EndCapType::SIDESINGLE) &&
 
 2332         (!grid_info.myCrossSectionClosed && grid_info.myCurveClosed) &&
 
 2339     grid_info.myVEndPoles =
 
 2340         !output_points_only &&
 
 2341         (end_cap_type != 
EndCapType::NONE && end_cap_type != EndCapType::SINGLE && end_cap_type != EndCapType::SIDESINGLE) &&
 
 2342         (!grid_info.myCurveClosed) &&
 
 2345     if (grid_info.myUEndPoles)
 
 2348         grid_info.myCrossSectionNEdges += 2*cap_divisions;
 
 2351         UT_ASSERT(grid_info.myCurveNEdges >= 1);
 
 2353     else if (grid_info.myVEndPoles)
 
 2356         grid_info.myCurveNEdges += 2*cap_divisions;
 
 2358         if (!grid_info.mySingleCrossSection)
 
 2362             GA_OffsetList &primoffs = *grid_info.myCrossSectionPrimOffs;
 
 2363             for (
exint i = 0; i < cap_divisions; ++i)
 
 2364                 new_cross_section_primoffs.
append(primoffs(0));
 
 2365             new_cross_section_primoffs.
append(primoffs);
 
 2366             for (
exint i = 0; i < cap_divisions; ++i)
 
 2367                 new_cross_section_primoffs.
append(primoffs.
last());
 
 2368             primoffs = std::move(new_cross_section_primoffs);
 
 2372         UT_ASSERT(grid_info.myCrossSectionNEdges >= 1);
 
 2375     using PrimitiveType = sop_SweepGrid::PrimitiveType;
 
 2376     grid_info.myPrimitiveType = PrimitiveType::POINTS;
 
 2377     if (!output_points_only)
 
 2379         grid_info.myPrimitiveType = PrimitiveType::POLYGON;
 
 2381             grid_info.myPrimitiveType = PrimitiveType::POLYSOUP;
 
 2383             grid_info.myPrimitiveType = PrimitiveType::MESH;
 
 2385             grid_info.myPrimitiveType = PrimitiveType::NURBS;
 
 2387             grid_info.myPrimitiveType = PrimitiveType::BEZIER;
 
 2391         if (grid_info.myPrimitiveType != PrimitiveType::POLYGON &&
 
 2392             (grid_info.myCurveNEdges <= 0 || grid_info.myCrossSectionNEdges <= 0))
 
 2394             grid_info.myPrimitiveType = PrimitiveType::POLYGON;
 
 2397     if (grid_info.myPrimitiveType == PrimitiveType::NURBS)
 
 2399         if (fallback_orderv == 0)
 
 2404             fallback_orderv = (is_primtype_auto && curve_input != 
nullptr) ? 2 : 4;
 
 2406         exint curve_nvertices = grid_info.myCurveNEdges + (!grid_info.myCurveClosed || grid_info.myCurveUnrolled);
 
 2407         if (curve_nvertices < fallback_orderv)
 
 2411             fallback_orderv = 
SYSclamp(
int(curve_nvertices), 2, 3);
 
 2413         if (fallback_orderu == 0)
 
 2416             fallback_orderu = (is_primtype_auto && cross_section_input != 
nullptr) ? 2 : 4;
 
 2418         exint cross_section_nvertices = grid_info.myCrossSectionNEdges + (!grid_info.myCrossSectionClosed || grid_info.myCrossSectionUnrolled);
 
 2419         if (cross_section_nvertices < fallback_orderu)
 
 2423             fallback_orderu = 
SYSclamp(
int(cross_section_nvertices), 2, 3);
 
 2426     else if (grid_info.myPrimitiveType == PrimitiveType::BEZIER)
 
 2428         if (fallback_orderv == 0)
 
 2433             fallback_orderv = is_primtype_auto ? 2 : 4;
 
 2435         if (grid_info.myCurveNEdges % (fallback_orderv-1) != 0)
 
 2438             fallback_orderv = 2;
 
 2440         if (fallback_orderu == 0)
 
 2443             fallback_orderu = is_primtype_auto ? 2 : 4;
 
 2445         if (grid_info.myCrossSectionNEdges % (fallback_orderu-1) != 0)
 
 2448             fallback_orderu = 2;
 
 2451     grid_info.myBasisOrderCrossSection = fallback_orderu;
 
 2452     grid_info.myBasisOrderCurve = fallback_orderv;
 
 2455     num_points = (grid_info.myCurveNEdges + !grid_info.myCurveClosed - 2*
exint(grid_info.myVEndPoles))
 
 2456         * (grid_info.myCrossSectionNEdges + !grid_info.myCrossSectionClosed - 2*
exint(grid_info.myUEndPoles))
 
 2457         + 2*
exint(grid_info.myVEndPoles) + 2*
exint(grid_info.myUEndPoles);
 
 2462 template<
typename T>
 
 2465     const sop_SweepGrid &grid_info,
 
 2467     const bool output_points_only,
 
 2468     const bool triangular_poles,
 
 2469     const bool swap_row_col,
 
 2470     const T grid_start_ptnum,
 
 2476     grid.
myUnrollCurves = grid_info.myCurveUnrolled || grid_info.myCrossSectionUnrolled;
 
 2479     bool is_single_grid_prim = 
false;
 
 2480     if (output_points_only)
 
 2485         is_single_grid_prim = (grid.
myPrimitiveType != PrimitiveType::POLYGON);
 
 2494     const exint nedgerows = swap_row_col ? grid_info.myCrossSectionNEdges : grid_info.myCurveNEdges;
 
 2495     const exint nedgecols = swap_row_col ? grid_info.myCurveNEdges : grid_info.myCrossSectionNEdges;
 
 2496     bool vclosed = swap_row_col ? grid_info.myCrossSectionClosed : grid_info.myCurveClosed;
 
 2497     bool uclosed = swap_row_col ? grid_info.myCurveClosed : grid_info.myCrossSectionClosed;
 
 2498     bool uendpoles = swap_row_col ? grid_info.myVEndPoles : grid_info.myUEndPoles;
 
 2499     bool vendpoles = swap_row_col ? grid_info.myUEndPoles : grid_info.myVEndPoles;
 
 2500     if (is_single_grid_prim)
 
 2504         if (nvtxrows < 2 || nvtxcols < 2)
 
 2506             is_single_grid_prim = 
false;
 
 2511             unsigned char orderv = swap_row_col ? grid_info.myBasisOrderCrossSection : grid_info.myBasisOrderCurve;
 
 2512             unsigned char orderu = swap_row_col ? grid_info.myBasisOrderCurve : grid_info.myBasisOrderCrossSection;
 
 2520             grid.
initTorus(nedgerows, nedgecols, grid_start_ptnum);
 
 2521         else if (!uendpoles)
 
 2522             grid.
initRowTube(nedgerows, nedgecols, grid_start_ptnum);
 
 2527             const exint nmid_points = nedgerows*(nedgecols - 1);
 
 2528             grid.
initRowSphere(nedgerows, nedgecols, grid_start_ptnum, grid_start_ptnum+1+nmid_points, grid_start_ptnum+1);
 
 2536                 grid.
initColTube(nedgerows, nedgecols, grid_start_ptnum);
 
 2541                 const exint nmid_points = (nedgerows - 1)*nedgecols;
 
 2542                 grid.
initColSphere(nedgerows, nedgecols, grid_start_ptnum, grid_start_ptnum+1+nmid_points, grid_start_ptnum+1);
 
 2553                 const exint nmid_points = (nedgerows - 1)*(nedgecols+1);
 
 2554                 grid.
initSplitColSphere(nedgerows, nedgecols, grid_start_ptnum, grid_start_ptnum+1+nmid_points, grid_start_ptnum+1);
 
 2561 appendPrimTypeCountPair(
 
 2562     UT_Array<std::pair<int,exint>> &prim_type_count_pairs,
 
 2566     if (prim_type_count_pairs.isEmpty() || prim_type_count_pairs.last().first != primtype)
 
 2568         prim_type_count_pairs.append(std::pair<int,exint>(primtype, count));
 
 2572         prim_type_count_pairs.last().second += count;
 
 2585     if (!(closed_span_lengths.
size() & 1) == closed)
 
 2586         ++closed_span_lengths.
last();
 
 2588         closed_span_lengths.
append(1);
 
 2595 appendSingleGridTopology(
 
 2596     const sop_SweepGrid &grid_info,
 
 2598     const bool output_points_only,
 
 2599     const bool triangular_poles,
 
 2600     const bool single_polygon_caps,
 
 2601     const bool swap_row_col,
 
 2603     UT_Array<std::pair<int,exint>> &prim_type_count_pairs,
 
 2613     exint grid_start_ptnum = 
exint(grid_info.myStartPtOff);
 
 2615     initGUGrid(grid_info, surface_type, output_points_only, triangular_poles, swap_row_col, grid_start_ptnum, grid);
 
 2620     if (num_grid_prims == 0)
 
 2623     bool current_has_polygon_caps = grid_info.myHasPolygonCaps;
 
 2624     bool is_row_cap = current_has_polygon_caps && grid.
myNoWrapV;
 
 2625     bool is_cross_section_cap = !grid_info.myCrossSectionClosed;
 
 2626     exint cap_count = current_has_polygon_caps ? 2 : 0;
 
 2651         appendPrimTypeCountPair(prim_type_count_pairs, primtype, num_grid_prims + cap_count);
 
 2655         appendPrimTypeCountPair(prim_type_count_pairs, cap_primtype, 1);
 
 2656         appendPrimTypeCountPair(prim_type_count_pairs, primtype, num_grid_prims);
 
 2657         appendPrimTypeCountPair(prim_type_count_pairs, cap_primtype, 1);
 
 2660     exint cap_vertex_count = 0;
 
 2661     if (current_has_polygon_caps)
 
 2663     auto &&add_polygon_cap_functor = [is_row_cap,cap_vertex_count,swap_row_col,is_cross_section_cap,&grid,&vertexlistsizelist,&closed_span_lengths,&vertexpointnumbers](
bool last_cap)
 
 2665         vertexlistsizelist.append(cap_vertex_count);
 
 2668         appendClosedSpans(closed_span_lengths, 
true);
 
 2670         const exint old_size = vertexpointnumbers.
size();
 
 2671         vertexpointnumbers.
bumpSize(old_size + cap_vertex_count);
 
 2672         exint *vertexpointnumber_start = vertexpointnumbers.
getArray() + old_size;
 
 2676             exint row = last_cap ? grid.myNumEdgeRows : 0;
 
 2677             for (
exint col = 0; col < cap_vertex_count; ++col)
 
 2679                 exint point_col = ((last_cap != swap_row_col) != is_cross_section_cap) ? col : reverseVtx(col, cap_vertex_count, 
true);
 
 2680                 vertexpointnumber_start[col] = grid.getPoint(row, point_col);
 
 2686             exint col = last_cap ? grid.myNumEdgeCols : 0;
 
 2687             for (
exint row = 0; row < cap_vertex_count; ++
row)
 
 2689                 exint point_row = ((last_cap != swap_row_col) != is_cross_section_cap) ? row : reverseVtx(row, cap_vertex_count, 
true);
 
 2690                 vertexpointnumber_start[
row] = grid.getPoint(point_row, col);
 
 2694     if (current_has_polygon_caps)
 
 2697         add_polygon_cap_functor(
false);
 
 2702         [&vertexlistsizelist,&closed_span_lengths
 
 2708         UT_ASSERT_P(primnum >= 0 && primnum < num_grid_prims);
 
 2709         vertexlistsizelist.append(primvtxcount);
 
 2711         appendClosedSpans(closed_span_lengths, closed);
 
 2714     const exint old_size = vertexpointnumbers.
size();
 
 2715     vertexpointnumbers.
bumpSize(old_size + grid.myNumVertices);
 
 2716     exint *vertexpointnumber_start = vertexpointnumbers.
getArray() + old_size;
 
 2718         [vertexpointnumber_start,&grid](
exint vtxnum, 
exint row, 
exint col, 
bool isrowend, 
bool iscolend, 
exint primnum, 
exint primvtxnum)
 
 2720         UT_ASSERT_P(vtxnum >= 0 && vtxnum < grid.myNumVertices);
 
 2721         vertexpointnumber_start[vtxnum] = grid.getPoint(row+
exint(isrowend),col+
exint(iscolend));
 
 2724     if (current_has_polygon_caps)
 
 2727         add_polygon_cap_functor(
true);
 
 2732     num_grid_prims += cap_count;
 
 2733     num_grid_verts += 2*cap_vertex_count;
 
 2737 initNonPolyGridPrims(
 
 2738     const sop_SweepGrid &grid_info,
 
 2740     const bool swap_row_col,
 
 2750     GA_Offset primoff = grid_info.myStartPrimOff;
 
 2751     if (grid_info.myHasPolygonCaps)
 
 2759     const exint nvtxrows = nedgerows + 
exint(!hull_wrapv);
 
 2760     const exint nvtxcols = nedgecols + 
exint(!hull_wrapu);
 
 2767         sop_SweepGrid polygrid_info(grid_info);
 
 2768         polygrid_info.myPrimitiveType = sop_SweepGrid::PrimitiveType::POLYGON;
 
 2776             polygonsizes.
append(primvtxcount, 1);
 
 2794         exint cap_vertex_count = 0;
 
 2795         if (grid_info.myHasPolygonCaps)
 
 2797             cap_vertex_count = !grid_info.myCurveClosed ? grid_info.myCrossSectionNEdges : grid_info.myCurveNEdges;
 
 2799         const GA_Offset start_vtxoff = grid_info.myStartVtxOff + cap_vertex_count;
 
 2801             [&polygonvertexlist,start_vtxoff,&grid,has_endrow,has_endcol,nvtxcols](
exint vtxnum, 
exint row, 
exint col,
 
 2802                 bool isrowend, 
bool iscolend, 
exint primnum, 
exint primvtxnum)
 
 2819             exint soupvtxnum = row*nvtxcols + col;
 
 2820             polygonvertexlist.append(start_vtxoff + soupvtxnum);
 
 2831     hull->
initHullData(nvtxrows, nvtxcols, hull_wrapv, hull_wrapu);
 
 2835     const bool is_bezier = (grid.
myPrimitiveType == PrimitiveType::BEZIER);
 
 2836     if (!is_nurbs && !is_bezier)
 
 2845     if (source_basisu != 
nullptr && source_basisu->
getType() != basis_type)
 
 2846         source_basisu = 
nullptr;
 
 2847     if (source_basisv != 
nullptr && source_basisv->
getType() != basis_type)
 
 2848         source_basisv = 
nullptr;
 
 2851     if (source_basisu != 
nullptr)
 
 2854         basisu->copyFrom(*source_basisu);
 
 2865     if (source_basisv != 
nullptr)
 
 2885             bool interpolate_ends = !closed;
 
 2886             int extra_knots = order + (closed ? (interpolate_ends ? 1 : (order - 1)) : 0);
 
 2891                 (nvertices + extra_knots),
 
 2896         if (basisu == 
nullptr)
 
 2898             basisu = make_nurbs_basis(nvtxcols, grid.
myBasisOrderU, hull_wrapu);
 
 2902         if (basisv == 
nullptr)
 
 2904             basisv = make_nurbs_basis(nvtxrows, grid.
myBasisOrderV, hull_wrapv);
 
 2915             int extra = ((nvertices > 2 && order > 2) || (order <= 2 && closed));
 
 2917                 extra + (nvertices / (order - 1)),
 
 2920         if (basisu == 
nullptr)
 
 2922             basisu = make_bez_basis(nvtxcols, grid.
myBasisOrderU, hull_wrapu);
 
 2926         if (basisv == 
nullptr)
 
 2928             basisv = make_bez_basis(nvtxrows, grid.
myBasisOrderV, hull_wrapv);
 
 2939     if (grid_info.myHasPolygonCaps)
 
 2941         const bool side_caps = !grid_info.myCrossSectionClosed;
 
 2942         const GA_Basis *cap_source_basis = (swap_row_col != side_caps) ? basisv : basisu;
 
 2946         cap0_basis->
copyFrom(*cap_source_basis);
 
 2947         cap1_basis->copyFrom(*cap_source_basis);
 
 2952         cap1->setBasis(cap1_basis);
 
 2961     exint cross_section_nedges,
 
 2963     const CrossSectionAttribMatchData *
const copy_order_attrib_data,
 
 2967     const bool closed_if_no_curve_input,
 
 2970     const bool output_points_only,
 
 2971     const bool unroll_closed_row_col,
 
 2972     const int primitive_type,
 
 2974     const exint cap_divisions,
 
 2975     const bool triangular_poles,
 
 2976     const bool swap_row_col,
 
 2988     if (interrupt.wasInterrupted())
 
 2995     if (cross_section_input != 
nullptr && (
 
 3000         exint max_num_grids = 1;
 
 3001         if (curve_input != 
nullptr)
 
 3006     if (curve_input != 
nullptr && (
 
 3016     bool single_cross_section = 
true;
 
 3018     bool cross_section_closed = (cross_section_shape == SurfaceShape::TUBE || cross_section_shape == SurfaceShape::SQUARE);
 
 3019     bool cross_section_unrolled = 
false;
 
 3021     if (cross_section_input != 
nullptr)
 
 3024         cross_section_range = cross_section_input->
getPrimitiveRange(cross_section_group);
 
 3026         if (ncross_sections == 0)
 
 3036         if (single_cross_section)
 
 3042             single_cross_section_primoff = *it;
 
 3043             bool nonempty = 
getPolyProperties(cross_section_input, single_cross_section_primoff,
 
 3044                 cross_section_nedges, cross_section_closed, cross_section_unrolled);
 
 3051     if (!single_cross_section || curve_input == 
nullptr)
 
 3052         cross_section_it = 
GA_Iterator(cross_section_range);
 
 3054     const bool is_primtype_auto = !output_points_only && (primitive_type == 
GA_PRIMNONE);
 
 3061     closed_span_lengths.
append(0);
 
 3065     bool hassharedpoints = 
true;
 
 3066     exint total_num_points = 0;
 
 3067     exint total_num_verts = 0;
 
 3068     exint total_num_prims = 0;
 
 3069     if (curve_input == 
nullptr)
 
 3072         UT_ASSERT(cross_section_input != 
nullptr);
 
 3076         int local_primitive_type = primitive_type;
 
 3077         unsigned char fallback_orderu = 0;
 
 3078         unsigned char fallback_orderv;
 
 3082             local_primitive_type,
 
 3087         const GA_Basis **pbasisu = grid_basisus.
isEmpty() ? 
nullptr : &grid_basisus[0];
 
 3089         sop_SweepGrid grid_info;
 
 3091         bool valid_grid = computeSingleGridSetup(
 
 3092             cross_section_input,
 
 3093             cross_section_group,
 
 3097             0, 
false, 
false, CopyOrder::CYCLEVTX, 
nullptr, 
false, 
nullptr, 
 
 3099             closed_if_no_curve_input,
 
 3100             surface_type, output_points_only,
 
 3101             unroll_closed_row_col,
 
 3103             local_primitive_type,
 
 3104             fallback_orderu, fallback_orderv,
 
 3108             grid_info, num_points);
 
 3114         total_num_points = num_points;
 
 3116         exint num_grid_prims;
 
 3117         exint num_grid_verts;
 
 3118         appendSingleGridTopology(
 
 3119             grid_info, surface_type, output_points_only, triangular_poles,
 
 3120             grid_info.myHasPolygonCaps, swap_row_col,
 
 3121             prim_type_count_pairs, vertexlistsizelist, vertexpointnumbers,
 
 3122             closed_span_lengths, num_grid_prims, num_grid_verts);
 
 3125         total_num_verts = num_grid_verts;
 
 3126         grid_info.myStartPrimOff = 
GA_Offset(0);
 
 3127         total_num_prims = num_grid_prims;
 
 3128         grids.
append(std::move(grid_info));
 
 3130     else if (!single_cross_section && copy_order == CopyOrder::EACH)
 
 3134         for (; !cross_section_it.
atEnd(); ++cross_section_it)
 
 3136             GA_Offset cross_section_primoff = *cross_section_it;
 
 3139                 cross_section_nedges, cross_section_closed, cross_section_unrolled);
 
 3147                 if (interrupt.wasInterrupted())
 
 3152                 for (
GA_Offset curve_primoff = start; curve_primoff < 
end; ++curve_primoff)
 
 3155                     const GA_Basis **pbasisu = grid_basisus.
isEmpty() ? 
nullptr : &grid_basisus[gridi];
 
 3156                     const GA_Basis **pbasisv = grid_basisvs.
isEmpty() ? 
nullptr : &grid_basisvs[gridi];
 
 3158                     int local_primitive_type = primitive_type;
 
 3159                     unsigned char fallback_orderu = 0;
 
 3160                     unsigned char fallback_orderv;
 
 3164                         local_primitive_type,
 
 3171                     if (is_primtype_auto && cross_section_input != 
nullptr)
 
 3172                         updateAutoPrimType(cross_section_input, cross_section_primoff, local_primitive_type, fallback_orderu, pbasisu);
 
 3174                     sop_SweepGrid grid_info;
 
 3176                     bool valid_grid = computeSingleGridSetup(
 
 3180                         cross_section_primoff,
 
 3181                         cross_section_nedges,
 
 3182                         cross_section_closed,
 
 3183                         cross_section_unrolled,
 
 3188                         curve_input, curve_primoff,
 
 3192                         unroll_closed_row_col,
 
 3194                         local_primitive_type,
 
 3195                         fallback_orderu, fallback_orderv,
 
 3205                     grid_info.myStartPtOff = 
GA_Offset(total_num_points);
 
 3206                     total_num_points += num_points;
 
 3208                     exint num_grid_prims;
 
 3209                     exint num_grid_verts;
 
 3210                     appendSingleGridTopology(
 
 3211                         grid_info, surface_type, output_points_only, triangular_poles,
 
 3212                         grid_info.myHasPolygonCaps, swap_row_col,
 
 3213                         prim_type_count_pairs, vertexlistsizelist, vertexpointnumbers,
 
 3214                         closed_span_lengths, num_grid_prims, num_grid_verts);
 
 3216                     grid_info.myStartVtxOff = 
GA_Offset(total_num_verts);
 
 3217                     total_num_verts += num_grid_verts;
 
 3218                     grid_info.myStartPrimOff = 
GA_Offset(total_num_prims);
 
 3219                     total_num_prims += num_grid_prims;
 
 3220                     grids.
append(std::move(grid_info));
 
 3225     else if (!single_cross_section && (copy_order == CopyOrder::CYCLEPR ||
 
 3236             cross_section_primoff = lookupCrossSectionFromAttrib(copy_order_attrib_data,
 
 3242                 cross_section_nedges, cross_section_closed, cross_section_unrolled);
 
 3251             if (interrupt.wasInterrupted())
 
 3256             for (
GA_Offset curve_primoff = start; curve_primoff < 
end; ++curve_primoff)
 
 3258                 if (copy_order == CopyOrder::CYCLEPR)
 
 3260                     cross_section_primoff = *cross_section_it;
 
 3262                     if (cross_section_it.
atEnd())
 
 3264                         cross_section_it.
rewind();
 
 3270                     cross_section_primoff = lookupCrossSectionFromAttrib(copy_order_attrib_data,
 
 3271                         curve_primoff, cross_section_input, cross_section_group);
 
 3280                         cross_section_nedges, cross_section_closed, cross_section_unrolled);
 
 3286                 const GA_Basis **pbasisu = grid_basisus.
isEmpty() ? 
nullptr : &grid_basisus[gridi];
 
 3287                 const GA_Basis **pbasisv = grid_basisvs.
isEmpty() ? 
nullptr : &grid_basisvs[gridi];
 
 3289                 int local_primitive_type = primitive_type;
 
 3290                 unsigned char fallback_orderu = 0;
 
 3291                 unsigned char fallback_orderv;
 
 3295                     local_primitive_type,
 
 3302                 if (is_primtype_auto && cross_section_input != 
nullptr)
 
 3303                     updateAutoPrimType(cross_section_input, cross_section_primoff, local_primitive_type, fallback_orderu, pbasisu);
 
 3305                 sop_SweepGrid grid_info;
 
 3307                 bool valid_grid = computeSingleGridSetup(
 
 3311                     cross_section_primoff,
 
 3312                     cross_section_nedges,
 
 3313                     cross_section_closed,
 
 3314                     cross_section_unrolled,
 
 3319                     curve_input, curve_primoff,
 
 3321                     surface_type, output_points_only,
 
 3322                     unroll_closed_row_col,
 
 3324                     local_primitive_type,
 
 3325                     fallback_orderu, fallback_orderv,
 
 3329                     grid_info, num_points);
 
 3334                 grid_info.myStartPtOff = 
GA_Offset(total_num_points);
 
 3335                 total_num_points += num_points;
 
 3337                 exint num_grid_prims;
 
 3338                 exint num_grid_verts;
 
 3339                 appendSingleGridTopology(
 
 3340                     grid_info, surface_type, output_points_only, triangular_poles,
 
 3341                     grid_info.myHasPolygonCaps, swap_row_col,
 
 3342                     prim_type_count_pairs, vertexlistsizelist, vertexpointnumbers,
 
 3343                     closed_span_lengths, num_grid_prims, num_grid_verts);
 
 3345                 grid_info.myStartVtxOff = 
GA_Offset(total_num_verts);
 
 3346                 total_num_verts += num_grid_verts;
 
 3347                 grid_info.myStartPrimOff = 
GA_Offset(total_num_prims);
 
 3348                 total_num_prims += num_grid_prims;
 
 3349                 grids.
append(std::move(grid_info));
 
 3355         unsigned char fallback_orderu = 0;
 
 3356         int cross_section_primitive_type = is_primtype_auto ? 
GA_PRIMPOLY : primitive_type;
 
 3357         bool varying_nedges_all_case = 
false;
 
 3359         const bool all_case = (!single_cross_section && copy_order == 
CopyOrder::ALL);
 
 3360         const GA_Basis *all_case_grid_basisu = 
nullptr;
 
 3368             bool is_valid_grid = computeCombinedCrossSectionProperties(
 
 3369                 cross_section_input,
 
 3370                 cross_section_group,
 
 3373                 cross_section_nedges,
 
 3374                 cross_section_closed,
 
 3375                 cross_section_unrolled,
 
 3376                 varying_nedges_all_case,
 
 3377                 cross_section_primoffs_all_case,
 
 3379                 cross_section_primitive_type,
 
 3381                 &all_case_grid_basisu);
 
 3392             if (interrupt.wasInterrupted())
 
 3395             for (
GA_Offset curve_primoff = start; curve_primoff < 
end; ++curve_primoff)
 
 3398                 const GA_Basis **pbasisu = grid_basisus.
isEmpty() ? 
nullptr : &grid_basisus[gridi];
 
 3399                 const GA_Basis **pbasisv = grid_basisvs.
isEmpty() ? 
nullptr : &grid_basisvs[gridi];
 
 3401                 int local_primitive_type = primitive_type;
 
 3402                 unsigned char fallback_orderv;
 
 3406                     local_primitive_type,
 
 3413                 if (single_cross_section && is_primtype_auto && cross_section_input != 
nullptr)
 
 3414                     updateAutoPrimType(cross_section_input, single_cross_section_primoff, local_primitive_type, fallback_orderu, pbasisu);
 
 3418                         local_primitive_type = cross_section_primitive_type;
 
 3421                 if (all_case && pbasisu != 
nullptr)
 
 3425                     *pbasisu = all_case_grid_basisu;
 
 3428                 sop_SweepGrid grid_info;
 
 3430                 bool valid_grid = computeSingleGridSetup(
 
 3431                     cross_section_input,
 
 3432                     cross_section_group,
 
 3433                     single_cross_section,
 
 3435                     single_cross_section_primoff,
 
 3436                     cross_section_nedges,
 
 3437                     cross_section_closed,
 
 3438                     cross_section_unrolled,
 
 3440                     copy_order_attrib_data,
 
 3441                     varying_nedges_all_case,
 
 3442                     (cross_section_primoffs_all_case.
size() == 0) ? 
nullptr : &cross_section_primoffs_all_case,
 
 3443                     curve_input, curve_primoff,
 
 3444                     closed_if_no_curve_input,
 
 3445                     surface_type, output_points_only,
 
 3446                     unroll_closed_row_col,
 
 3448                     local_primitive_type,
 
 3449                     fallback_orderu, fallback_orderv,
 
 3453                     grid_info, num_points);
 
 3458                 grid_info.myStartPtOff = 
GA_Offset(total_num_points);
 
 3459                 total_num_points += num_points;
 
 3461                 exint num_grid_prims;
 
 3462                 exint num_grid_verts;
 
 3463                 appendSingleGridTopology(
 
 3464                     grid_info, surface_type, output_points_only, triangular_poles,
 
 3465                     grid_info.myHasPolygonCaps, swap_row_col,
 
 3466                     prim_type_count_pairs, vertexlistsizelist, vertexpointnumbers,
 
 3467                     closed_span_lengths, num_grid_prims, num_grid_verts);
 
 3469                 grid_info.myStartVtxOff = 
GA_Offset(total_num_verts);
 
 3470                 total_num_verts += num_grid_verts;
 
 3471                 grid_info.myStartPrimOff = 
GA_Offset(total_num_prims);
 
 3472                 total_num_prims += num_grid_prims;
 
 3473                 grids.
append(std::move(grid_info));
 
 3478     if (interrupt.wasInterrupted())
 
 3485     if (output_points_only)
 
 3491             prim_type_count_pairs.getArray(),
 
 3492             start_ptoff, total_num_points,
 
 3493             vertexlistsizelist, vertexpointnumbers.
getArray(),
 
 3510         for (
exint gridi = 0, num_grids = grids.
size(); gridi < num_grids; ++gridi)
 
 3512             grids[gridi].myStartPtOff += start_ptoff;
 
 3517         for (
exint gridi = 0, num_grids = grids.
size(); gridi < num_grids; ++gridi)
 
 3519             grids[gridi].myStartVtxOff += start_vtxoff;
 
 3524         for (
exint gridi = 0, num_grids = grids.
size(); gridi < num_grids; ++gridi)
 
 3526             grids[gridi].myStartPrimOff += start_primoff;
 
 3534         for (
exint gridi = 0, num_grids = grids.
size(); gridi < num_grids; ++gridi)
 
 3536             const sop_SweepGrid &grid_info = grids[gridi];
 
 3538             initGUGrid(grid_info, surface_type, output_points_only, triangular_poles, swap_row_col, grid_info.myStartPtOff, grid);
 
 3539             const GA_Basis *basisu = grid_basisus.
isEmpty() ? 
nullptr : grid_basisus[gridi];
 
 3540             const GA_Basis *basisv = grid_basisvs.
isEmpty() ? 
nullptr : grid_basisvs[gridi];
 
 3543                 initNonPolyGridPrims(grid_info, grid, swap_row_col, basisu, basisv, output_geo);
 
 3551 template<
typename FUNCTOR>
 
 3553 copyVertexCrossSectionWrapper(
 
 3555     const sop_SweepGrid &grid_info,
 
 3556     const FUNCTOR &functor)
 
 3560     exint cap_vertex_count = 0;
 
 3561     if (grid_info.myHasPolygonCaps)
 
 3568             for (
exint col = 0; col < cap_vertex_count; ++col)
 
 3571                 functor(grid_info.myStartVtxOff + col, 0, reverseVtx(col, cap_vertex_count, 
true));
 
 3579             for (
exint row = 0; row < cap_vertex_count; ++
row)
 
 3582                 functor(grid_info.myStartVtxOff + row, reverseVtx(row, cap_vertex_count, 
true), 0);
 
 3587     const GA_Offset start_vtxoff = grid_info.myStartVtxOff + cap_vertex_count;
 
 3588     auto &&functor_wrapper = [&functor,start_vtxoff](
exint vtxnum, 
exint row, 
exint col, 
bool isrowend, 
bool iscolend, 
exint primnum, 
exint primvtxnum)
 
 3590         GA_Offset output_vtxoff = start_vtxoff + vtxnum;
 
 3591         functor(output_vtxoff, row + 
exint(isrowend), col + 
exint(iscolend));
 
 3594     if (grid_info.myHasPolygonCaps)
 
 3601             for (
exint col = 0; col < cap_vertex_count; ++col)
 
 3609             for (
exint row = 0; row < cap_vertex_count; ++
row)
 
 3617 template<
typename TRANSFORM_T,GA_AttributeOwner output_attrib_owner,
bool wrap_to_inval
id=false,
typename OUTPUT_ATTRIB_T,
typename INPUT_ATTRIB_T,
typename GET_TRANSFORM_FUNCTOR,
typename TRANSFORM_FUNCTOR,
typename INTERP_FUNCTOR>
 
 3619 copyCrossSectionAttributeWrapper2(
 
 3621     const OUTPUT_ATTRIB_T &outputh,
 
 3622     const INPUT_ATTRIB_T &cross_sectionh,
 
 3625     const sop_SweepGridTransformWrapper *transforms,
 
 3626     const sop_SweepGrid &grid_info,
 
 3627     const bool reverse_cross_sections,
 
 3628     const bool swap_row_col,
 
 3629     const GET_TRANSFORM_FUNCTOR &get_transform_functor,
 
 3630     const TRANSFORM_FUNCTOR &transform_and_copy_functor,
 
 3631     const INTERP_FUNCTOR &transform_and_interp_functor)
 
 3634     UT_ASSERT(cross_section_owner == output_attrib_owner ||
 
 3638     exint prev_curve_vtxi = -1;
 
 3641     exint current_cross_section_nedges;
 
 3642     bool current_cross_section_closed;
 
 3643     bool current_cross_section_unrolled;
 
 3645     auto &&functor = [&grid_info,&outputh,&cross_sectionh,
 
 3646         cross_section_owner,
 
 3647         &get_transform_functor,&transform_and_copy_functor,
 
 3648         &transform_and_interp_functor,
 
 3649         cross_section_input,
 
 3651         reverse_cross_sections,
 
 3654         &source_cross_section_primoff,
 
 3655         &cross_section_vertices,
 
 3656         ¤t_cross_section_nedges,
 
 3657         ¤t_cross_section_closed,
 
 3658         ¤t_cross_section_unrolled,
 
 3661         exint num_curve_edges = grid_info.myCurveNEdges;
 
 3662         bool is_curve_closed = grid_info.myCurveClosed;
 
 3663         exint curve_vtxi = swap_row_col ? col : 
row;
 
 3664         exint num_cross_section_edges = grid_info.myCrossSectionNEdges;
 
 3666         exint cross_section_vtxi = swap_row_col ? row : col;
 
 3668         if (curve_vtxi != prev_curve_vtxi)
 
 3673             if (output_attrib_owner == 
GA_ATTRIB_VERTEX && is_curve_closed && curve_vtxi == num_curve_edges)
 
 3675             transform = get_transform_functor(transforms, curve_vtxi, grid_info);
 
 3676             source_cross_section_primoff =
 
 3677                 grid_info.mySingleCrossSection ?
 
 3678                 GA_Offset(grid_info.myCrossSectionPrimOff) :
 
 3683                 cross_section_vertices = cross_section_input->getPrimitiveVertexList(source_cross_section_primoff);
 
 3684                 getPolyProperties(cross_section_input, cross_section_vertices, current_cross_section_nedges, current_cross_section_closed, current_cross_section_unrolled);
 
 3686             prev_curve_vtxi = curve_vtxi;
 
 3691             transform_and_copy_functor(cross_sectionh, source_cross_section_primoff, transform, outputh, output_offset);
 
 3695         constexpr 
bool is_vertex_attrib = (output_attrib_owner == 
GA_ATTRIB_VERTEX);
 
 3697         if (current_cross_section_nedges == num_cross_section_edges)
 
 3701             if (reverse_cross_sections)
 
 3704                 cross_section_vtxi = reverseVtx(cross_section_vtxi, current_cross_section_nedges + 
exint(is_vertex_attrib || !current_cross_section_closed),
 
 3705                     !is_vertex_attrib && current_cross_section_closed);
 
 3712             if (cross_section_vtxi == cross_section_vertices.size())
 
 3714                 if (wrap_to_invalid)
 
 3721                     vtxoff = cross_section_vertices[0];
 
 3724                 vtxoff = cross_section_vertices[cross_section_vtxi];
 
 3726             transform_and_copy_functor(cross_sectionh, cross_section_offset, transform, outputh, output_offset);
 
 3733             UT_ASSERT_P(num_cross_section_edges > current_cross_section_nedges);
 
 3738             exint fine_fractions = cross_section_vtxi*current_cross_section_nedges;
 
 3739             if (reverse_cross_sections)
 
 3740                 fine_fractions = num_cross_section_edges*current_cross_section_nedges - fine_fractions;
 
 3741             exint current_cross_section_edge = fine_fractions / num_cross_section_edges;
 
 3742             exint current_cross_section_fractions = fine_fractions % num_cross_section_edges;
 
 3743             exint current_cross_section_pt = current_cross_section_fractions / current_cross_section_nedges;
 
 3744             if (current_cross_section_pt == 0)
 
 3748                 if (current_cross_section_edge == cross_section_vertices.size())
 
 3750                     if (wrap_to_invalid)
 
 3757                         vtxoff = cross_section_vertices[0];
 
 3760                     vtxoff = cross_section_vertices[current_cross_section_edge];
 
 3762                 transform_and_copy_functor(cross_sectionh, cross_section_offset, transform, outputh, output_offset);
 
 3770                 exint current_cross_section_edge_start = (current_cross_section_edge*num_cross_section_edges + current_cross_section_nedges-1) / current_cross_section_nedges;
 
 3771                 exint current_cross_section_edge_end = ((current_cross_section_edge+1)*num_cross_section_edges + current_cross_section_nedges-1) / current_cross_section_nedges;
 
 3772                 exint current_cross_section_edge_npts = current_cross_section_edge_end - current_cross_section_edge_start;
 
 3773                 double u = double(current_cross_section_pt)/double(current_cross_section_edge_npts);
 
 3777                 UT_ASSERT_P(current_cross_section_edge != current_cross_section_nedges);
 
 3778                 exint vtxi0 = current_cross_section_edge;
 
 3779                 GA_Offset vtxoff0 = cross_section_vertices[vtxi0];
 
 3782                 if (current_cross_section_edge+1 == cross_section_vertices.size())
 
 3784                     if (wrap_to_invalid)
 
 3791                         vtxoff1 = cross_section_vertices[0];
 
 3794                     vtxoff1 = cross_section_vertices[current_cross_section_edge+1];
 
 3800                     cross_section_offset0 = vtxoff0;
 
 3801                     cross_section_offset1 = vtxoff1;
 
 3805                     cross_section_offset0 = cross_section_input->vertexPoint(vtxoff0);
 
 3807                         cross_section_offset1 = cross_section_input->vertexPoint(vtxoff1);
 
 3809                         cross_section_offset1 = vtxoff1;
 
 3811                 transform_and_interp_functor(cross_sectionh, cross_section_offset0, cross_section_offset1, u, transform, outputh, output_offset);
 
 3820         copyVertexCrossSectionWrapper(grid, grid_info, functor);
 
 3827         if (grid_info.myHasPolygonCaps)
 
 3830             functor(grid_info.myStartPrimOff, 0, 0);
 
 3833         const GA_Offset start_primoff = grid_info.myStartPrimOff + 
exint(grid_info.myHasPolygonCaps);
 
 3834         auto &&functor_wrapper = [&functor,start_primoff](
exint primnum, 
exint row, 
exint col, 
exint primvtxcount, 
bool closed)
 
 3836             GA_Offset output_primoff = start_primoff + primnum;
 
 3837             functor(output_primoff, row, col);
 
 3840         if (grid_info.myHasPolygonCaps)
 
 3857 template<
typename VALUE_T,
typename TRANSFORM_T,GA_AttributeOwner attrib_owner,
typename GET_TRANSFORM_FUNCTOR,
typename TRANSFORM_FUNCTOR,
typename INTERP_FUNCTOR>
 
 3859 copyCrossSectionAttributeWrapper(
 
 3864     const sop_SweepGridTransformWrapper *transforms,
 
 3865     const sop_SweepGrid &grid_info,
 
 3866     const bool reverse_cross_sections,
 
 3867     const bool swap_row_col,
 
 3868     const GET_TRANSFORM_FUNCTOR &get_transform_functor,
 
 3869     const TRANSFORM_FUNCTOR &transform_and_copy_functor,
 
 3870     const INTERP_FUNCTOR &transform_and_interp_functor)
 
 3877     copyCrossSectionAttributeWrapper2<TRANSFORM_T,attrib_owner>(
 
 3878         grid, outputh, cross_sectionh, attrib_owner,
 
 3879         cross_section_input, transforms, grid_info,
 
 3880         reverse_cross_sections,
 
 3882         get_transform_functor,
 
 3883         transform_and_copy_functor,
 
 3884         transform_and_interp_functor);
 
 3887 template<
typename T,GA_AttributeOwner attrib_owner>
 
 3889 copyIntegerSingleGrid(
 
 3893     const sop_SweepGridTransformWrapper *transforms,
 
 3894     const sop_SweepGrid &grid_info,
 
 3896     const bool output_points_only,
 
 3897     const bool triangular_poles,
 
 3898     const bool reverse_cross_sections,
 
 3899     const bool swap_row_col)
 
 3907     initGUGrid(grid_info, surface_type, output_points_only, triangular_poles, swap_row_col, grid_info.myStartPtOff, grid);
 
 3912     auto &&get_transform = [](
const sop_SweepGridTransformWrapper *transforms, 
exint row, 
const sop_SweepGrid &grid_info) -> 
const void*
 
 3917     if (tuple_size == 1)
 
 3920         auto &&transform_and_copy = [](
 
 3925             T value = cross_sectionh.
get(cross_section_offset);
 
 3926             outputh.set(output_offset, value);
 
 3928         auto &&transform_and_interp = [](
 
 3934             GA_Offset cross_section_offset = (t < 0.5) ? cross_section_offset0 : cross_section_offset1;
 
 3935             T value = cross_sectionh.
get(cross_section_offset);
 
 3936             outputh.set(output_offset, value);
 
 3938         copyCrossSectionAttributeWrapper<T, void, attrib_owner>(grid,
 
 3939             output_attrib, cross_section_attrib, cross_section_input, transforms, grid_info,
 
 3940             reverse_cross_sections, swap_row_col,
 
 3941             get_transform, transform_and_copy, transform_and_interp);
 
 3946     auto &&transform_and_copy = [tuple_size](
 
 3951         for (
exint component = 0; component < tuple_size; ++component)
 
 3953             T value = cross_sectionh.
get(cross_section_offset, component);
 
 3954             outputh.set(output_offset, component, value);
 
 3957     auto &&transform_and_interp = [tuple_size](
 
 3963         GA_Offset cross_section_offset = (t < 0.5) ? cross_section_offset0 : cross_section_offset1;
 
 3964         for (
exint component = 0; component < tuple_size; ++component)
 
 3966             T value = cross_sectionh.
get(cross_section_offset, component);
 
 3967             outputh.set(output_offset, component, value);
 
 3970     copyCrossSectionAttributeWrapper<T, void, attrib_owner>(grid,
 
 3971         output_attrib, cross_section_attrib, cross_section_input, transforms, grid_info,
 
 3972         reverse_cross_sections, swap_row_col,
 
 3973         get_transform, transform_and_copy, transform_and_interp);
 
 3976 template<
typename T,GA_TypeInfo transform_type,GA_AttributeOwner attrib_owner>
 
 3978 copyFloatSingleGrid(
 
 3982     const sop_SweepGridTransformWrapper *transforms,
 
 3983     const sop_SweepGrid &grid_info,
 
 3984     const exint cross_sections_per_vertex,
 
 3985     const exint cap_divisions,
 
 3987     const bool output_points_only,
 
 3988     const bool triangular_poles,
 
 3989     const bool reverse_cross_sections,
 
 3990     const bool swap_row_col)
 
 3998     initGUGrid(grid_info, surface_type, output_points_only, triangular_poles, swap_row_col, grid_info.myStartPtOff, grid);
 
 4000     const exint cap_rows = (grid_info.myVEndPoles && !grid_info.myHasPolygonCaps) ? cap_divisions : 0;
 
 4001     exint last_cap_start_row = -1;
 
 4002     exint last_cap_start_transform = -1;
 
 4003     if (cross_sections_per_vertex != 1 && cap_rows > 0)
 
 4005         last_cap_start_row = grid_info.myCurveNEdges - cap_rows;
 
 4006         last_cap_start_transform = (last_cap_start_row - cap_rows)/cross_sections_per_vertex + cap_rows;
 
 4009     auto &&fix_transformi_for_all_case = [cap_rows,cross_sections_per_vertex,last_cap_start_row,last_cap_start_transform](
exint &transformi)
 
 4015             transformi /= cross_sections_per_vertex;
 
 4016         else if (transformi > cap_rows)
 
 4018             if (transformi < last_cap_start_row)
 
 4019                 transformi = (transformi - cap_rows)/cross_sections_per_vertex + cap_rows;
 
 4021                 transformi = last_cap_start_transform + (transformi - last_cap_start_row);
 
 4035             auto &&get_transform = [&
transform,cross_sections_per_vertex,&fix_transformi_for_all_case]
 
 4036                 (
const sop_SweepGridTransformWrapper *transforms, 
exint row, 
const sop_SweepGrid &grid_info) -> 
const UT_Matrix4T<T>*
 
 4039                 if (cross_sections_per_vertex != 1)
 
 4040                     fix_transformi_for_all_case(transformi);
 
 4042                 transform.
setTranslates(transforms->getTranslates<T>()[transformi]);
 
 4045             auto &&transform_and_copy = [](
 
 4052                 outputh.set(output_offset, value);
 
 4054             auto &&transform_and_interp = [](
 
 4064                 outputh.set(output_offset, value);
 
 4066             copyCrossSectionAttributeWrapper<UT_Vector3T<T>, 
UT_Matrix4T<T>, attrib_owner>(grid,
 
 4067                 output_attrib, cross_section_attrib, cross_section_input, transforms, grid_info,
 
 4068                 reverse_cross_sections, swap_row_col,
 
 4069                 get_transform, transform_and_copy, transform_and_interp);
 
 4076             auto &&get_transform = [cross_sections_per_vertex,&fix_transformi_for_all_case]
 
 4077                 (
const sop_SweepGridTransformWrapper *transforms, 
exint row, 
const sop_SweepGrid &grid_info) -> 
const UT_Matrix3T<T>*
 
 4080                 if (cross_sections_per_vertex != 1)
 
 4081                     fix_transformi_for_all_case(transformi);
 
 4082                 return &transforms->getInverse3s<
T>()[transformi];
 
 4084             auto &&transform_and_copy = [](
 
 4091                 outputh.set(output_offset, value);
 
 4093             auto &&transform_and_interp = [](
 
 4110                 if (new_length2 != 0)
 
 4111                     value *= SYSsqrt(orig_length2/new_length2);
 
 4112                 outputh.set(output_offset, value);
 
 4114             copyCrossSectionAttributeWrapper<UT_Vector3T<T>, 
UT_Matrix3T<T>, attrib_owner>(grid,
 
 4115                 output_attrib, cross_section_attrib, cross_section_input, transforms, grid_info,
 
 4116                 reverse_cross_sections, swap_row_col,
 
 4117                 get_transform, transform_and_copy, transform_and_interp);
 
 4124             auto &&get_transform = [cross_sections_per_vertex,&fix_transformi_for_all_case]
 
 4125                 (
const sop_SweepGridTransformWrapper *transforms, 
exint row, 
const sop_SweepGrid &grid_info) -> 
const UT_Matrix3T<T>*
 
 4128                 if (cross_sections_per_vertex != 1)
 
 4129                     fix_transformi_for_all_case(transformi);
 
 4130                 return &transforms->getMatrix3s<
T>()[transformi];
 
 4132             auto &&transform_and_copy = [](
 
 4139                 outputh.set(output_offset, value);
 
 4141             auto &&transform_and_interp = [](
 
 4151                 outputh.set(output_offset, value);
 
 4153             copyCrossSectionAttributeWrapper<UT_Vector3T<T>, 
UT_Matrix3T<T>, attrib_owner>(grid,
 
 4154                 output_attrib, cross_section_attrib, cross_section_input, transforms, grid_info,
 
 4155                 reverse_cross_sections, swap_row_col,
 
 4156                 get_transform, transform_and_copy, transform_and_interp);
 
 4163             auto &&get_transform = [cross_sections_per_vertex,&fix_transformi_for_all_case]
 
 4164                 (
const sop_SweepGridTransformWrapper *transforms, 
exint row, 
const sop_SweepGrid &grid_info) -> 
const UT_QuaternionT<T>*
 
 4167                 if (cross_sections_per_vertex != 1)
 
 4168                     fix_transformi_for_all_case(transformi);
 
 4169                 return &transforms->getQuaternions<
T>()[transformi];
 
 4171             auto &&transform_and_copy = [](
 
 4178                 outputh.set(output_offset, value);
 
 4180             auto &&transform_and_interp = [](
 
 4189                 value = *transform * 
value;
 
 4190                 outputh.set(output_offset, value);
 
 4192             copyCrossSectionAttributeWrapper<UT_QuaternionT<T>, 
UT_QuaternionT<T>, attrib_owner>(grid,
 
 4193                 output_attrib, cross_section_attrib, cross_section_input, transforms, grid_info,
 
 4194                 reverse_cross_sections, swap_row_col,
 
 4195                 get_transform, transform_and_copy, transform_and_interp);
 
 4200             if (tuple_size == 9)
 
 4203                 auto &&get_transform = [cross_sections_per_vertex,&fix_transformi_for_all_case]
 
 4204                     (
const sop_SweepGridTransformWrapper *transforms, 
exint row, 
const sop_SweepGrid &grid_info) -> 
const UT_Matrix3T<T>*
 
 4207                     if (cross_sections_per_vertex != 1)
 
 4208                         fix_transformi_for_all_case(transformi);
 
 4209                     return &transforms->getMatrix3s<
T>()[transformi];
 
 4211                 auto &&transform_and_copy = [](
 
 4218                     outputh.set(output_offset, value);
 
 4220                 auto &&transform_and_interp = [](
 
 4230                     outputh.set(output_offset, value);
 
 4232                 copyCrossSectionAttributeWrapper<UT_Matrix3T<T>, 
UT_Matrix3T<T>, attrib_owner>(grid,
 
 4233                     output_attrib, cross_section_attrib, cross_section_input, transforms, grid_info,
 
 4234                     reverse_cross_sections, swap_row_col,
 
 4235                     get_transform, transform_and_copy, transform_and_interp);
 
 4238             if (tuple_size == 16)
 
 4243                 auto &&get_transform = [&
transform,cross_sections_per_vertex,&fix_transformi_for_all_case]
 
 4244                     (
const sop_SweepGridTransformWrapper *transforms, 
exint row, 
const sop_SweepGrid &grid_info) -> 
const UT_Matrix4T<T>*
 
 4247                     if (cross_sections_per_vertex != 1)
 
 4248                         fix_transformi_for_all_case(transformi);
 
 4250                     transform.
setTranslates(transforms->getTranslates<T>()[transformi]);
 
 4253                 auto &&transform_and_copy = [](
 
 4260                     outputh.set(output_offset, value);
 
 4262                 auto &&transform_and_interp = [](
 
 4272                     outputh.set(output_offset, value);
 
 4274                 copyCrossSectionAttributeWrapper<UT_Matrix4T<T>, 
UT_Matrix4T<T>, attrib_owner>(grid,
 
 4275                     output_attrib, cross_section_attrib, cross_section_input, transforms, grid_info,
 
 4276                     reverse_cross_sections, swap_row_col,
 
 4277                     get_transform, transform_and_copy, transform_and_interp);
 
 4284     auto &&get_transform = [](
const sop_SweepGridTransformWrapper *transforms, 
exint row, 
const sop_SweepGrid &grid_info) -> 
const void*
 
 4290     if (tuple_size == 1)
 
 4293         auto &&transform_and_copy = [](
 
 4298             T value = cross_sectionh.
get(cross_section_offset);
 
 4299             outputh.set(output_offset, value);
 
 4301         if (is_integer_type)
 
 4303             auto &&transform_and_interp = [](
 
 4309                 GA_Offset cross_section_offset = (t < 0.5) ? cross_section_offset0 : cross_section_offset1;
 
 4310                 T value = cross_sectionh.
get(cross_section_offset);
 
 4311                 outputh.set(output_offset, value);
 
 4313             copyCrossSectionAttributeWrapper<T, void, attrib_owner>(grid,
 
 4314                 output_attrib, cross_section_attrib, cross_section_input, 
nullptr, grid_info,
 
 4315                 reverse_cross_sections, swap_row_col,
 
 4316                 get_transform, transform_and_copy, transform_and_interp);
 
 4320             auto &&transform_and_interp = [](
 
 4326                 const T value0 = cross_sectionh.
get(cross_section_offset0);
 
 4327                 const T value1 = cross_sectionh.
get(cross_section_offset1);
 
 4328                 T value = 
SYSlerp(value0, value1, t);
 
 4329                 outputh.set(output_offset, value);
 
 4331             copyCrossSectionAttributeWrapper<T, void, attrib_owner>(grid,
 
 4332                 output_attrib, cross_section_attrib, cross_section_input, 
nullptr, grid_info,
 
 4333                 reverse_cross_sections, swap_row_col,
 
 4334                 get_transform, transform_and_copy, transform_and_interp);
 
 4338     if (tuple_size == 2 && !is_integer_type)
 
 4341         auto &&transform_and_copy = [](
 
 4347             outputh.set(output_offset, value);
 
 4349         auto &&transform_and_interp = [](
 
 4358             outputh.set(output_offset, value);
 
 4360         copyCrossSectionAttributeWrapper<UT_Vector2T<T>, 
void, attrib_owner>(grid,
 
 4361             output_attrib, cross_section_attrib, cross_section_input, 
nullptr, grid_info,
 
 4362             reverse_cross_sections, swap_row_col,
 
 4363             get_transform, transform_and_copy, transform_and_interp);
 
 4366     if (tuple_size == 3 && !is_integer_type)
 
 4369         auto &&transform_and_copy = [](
 
 4375             outputh.set(output_offset, value);
 
 4377         auto &&transform_and_interp = [](
 
 4386             outputh.set(output_offset, value);
 
 4388         copyCrossSectionAttributeWrapper<UT_Vector3T<T>, 
void, attrib_owner>(grid,
 
 4389             output_attrib, cross_section_attrib, cross_section_input, 
nullptr, grid_info,
 
 4390             reverse_cross_sections, swap_row_col,
 
 4391             get_transform, transform_and_copy, transform_and_interp);
 
 4396     auto &&transform_and_copy = [tuple_size](
 
 4401         for (
exint component = 0; component < tuple_size; ++component)
 
 4403             T value = cross_sectionh.
get(cross_section_offset, component);
 
 4404             outputh.set(output_offset, component, value);
 
 4407     if (is_integer_type)
 
 4409         auto &&transform_and_interp = [tuple_size](
 
 4415             GA_Offset cross_section_offset = (t < 0.5) ? cross_section_offset0 : cross_section_offset1;
 
 4416             for (
exint component = 0; component < tuple_size; ++component)
 
 4418                 T value = cross_sectionh.
get(cross_section_offset, component);
 
 4419                 outputh.set(output_offset, component, value);
 
 4422         copyCrossSectionAttributeWrapper<T, void, attrib_owner>(grid,
 
 4423             output_attrib, cross_section_attrib, cross_section_input, 
nullptr, grid_info,
 
 4424             reverse_cross_sections, swap_row_col,
 
 4425             get_transform, transform_and_copy, transform_and_interp);
 
 4429         auto &&transform_and_interp = [tuple_size](
 
 4435             for (
exint component = 0; component < tuple_size; ++component)
 
 4437                 const T value0 = cross_sectionh.
get(cross_section_offset0, component);
 
 4438                 const T value1 = cross_sectionh.
get(cross_section_offset1, component);
 
 4439                 T value = 
SYSlerp(value0, value1, t);
 
 4440                 outputh.set(output_offset, component, value);
 
 4443         copyCrossSectionAttributeWrapper<T, void, attrib_owner>(grid,
 
 4444             output_attrib, cross_section_attrib, cross_section_input, 
nullptr, grid_info,
 
 4445             reverse_cross_sections, swap_row_col,
 
 4446             get_transform, transform_and_copy, transform_and_interp);
 
 4450 template<GA_AttributeOwner attrib_owner>
 
 4452 copyAttribSingleGrid(
 
 4456     const sop_SweepGrid &grid_info,
 
 4458     const bool output_points_only,
 
 4459     const bool triangular_poles,
 
 4460     const bool reverse_cross_sections,
 
 4461     const bool swap_row_col)
 
 4466     initGUGrid(grid_info, surface_type, output_points_only, triangular_poles, swap_row_col, grid_info.myStartPtOff, grid);
 
 4469     auto &&get_transform = [](
const sop_SweepGridTransformWrapper *transforms, 
exint row, 
const sop_SweepGrid &grid_info) -> 
const void*
 
 4474     auto &&transform_and_copy = [](
 
 4479         output_attrib->copy(output_offset, *cross_section_attrib, cross_section_offset);
 
 4481     auto &&transform_and_interp = [](
 
 4487         GA_Offset cross_section_offset = (t < 0.5) ? cross_section_offset0 : cross_section_offset1;
 
 4488         output_attrib->copy(output_offset, *cross_section_attrib, cross_section_offset);
 
 4492     copyCrossSectionAttributeWrapper2<void, attrib_owner>(grid,
 
 4493         output_attrib, cross_section_attrib, attrib_owner, cross_section_input, 
nullptr, grid_info,
 
 4494         reverse_cross_sections, swap_row_col,
 
 4495         get_transform, transform_and_copy, transform_and_interp);
 
 4498 static const sop_SweepGridTransformWrapper *
 
 4499 gridOffsetTransforms(
 
 4500     const SOP_SweepHDKCache *
const transform_cache,
 
 4501     sop_SweepGridTransformWrapper &grid_transforms,
 
 4504     if (transform_cache == 
nullptr)
 
 4507     grid_transforms.
init(*transform_cache, gridi);
 
 4509     return &grid_transforms;
 
 4512 template<GA_AttributeOwner attrib_owner>
 
 4514 copyCrossSectionAttrib2(
 
 4518     const SOP_SweepHDKCache *transform_cache,
 
 4519     const sop_SweepGrid *grids,
 
 4521     const exint cross_sections_per_vertex,
 
 4522     const exint cap_divisions,
 
 4524     const bool output_points_only,
 
 4525     const bool triangular_poles,
 
 4526     const bool reverse_cross_sections,
 
 4527     const bool swap_row_col)
 
 4532     const exint PARALLEL_THRESHOLD = 2048;
 
 4533     const bool parallel = (ngrids > 1 &&
 
 4538     if (!output_numeric)
 
 4545                 copyAttribSingleGrid<attrib_owner>(
 
 4546                     output_attrib, cross_section_attrib, cross_section_input,
 
 4548                     surface_type, output_points_only, triangular_poles,
 
 4549                     reverse_cross_sections, swap_row_col);
 
 4560             functor(grid_range);
 
 4567     if (!cross_section_numeric)
 
 4571     if (tuple_size != cross_section_numeric->
getTupleSize())
 
 4586         sop_SweepGridTransformWrapper local_grid_transforms;
 
 4587         if (tuple_size == 3)
 
 4595                         auto grid_transforms = gridOffsetTransforms(transform_cache, local_grid_transforms, gridi);
 
 4596                         copyFloatSingleGrid<fpreal64,GA_TYPE_POINT,attrib_owner>(
 
 4597                             output_numeric, cross_section_numeric, cross_section_input,
 
 4598                             grid_transforms, grids[gridi], cross_sections_per_vertex, cap_divisions,
 
 4599                             surface_type, output_points_only, triangular_poles,
 
 4600                             reverse_cross_sections, swap_row_col);
 
 4607                         auto grid_transforms = gridOffsetTransforms(transform_cache, local_grid_transforms, gridi);
 
 4608                         copyFloatSingleGrid<fpreal32,GA_TYPE_POINT,attrib_owner>(
 
 4609                             output_numeric, cross_section_numeric, cross_section_input,
 
 4610                             grid_transforms, grids[gridi], cross_sections_per_vertex, cap_divisions,
 
 4611                             surface_type, output_points_only, triangular_poles,
 
 4612                             reverse_cross_sections, swap_row_col);
 
 4623                         auto grid_transforms = gridOffsetTransforms(transform_cache, local_grid_transforms, gridi);
 
 4624                         copyFloatSingleGrid<fpreal64,GA_TYPE_NORMAL,attrib_owner>(
 
 4625                             output_numeric, cross_section_numeric, cross_section_input,
 
 4626                             grid_transforms, grids[gridi], cross_sections_per_vertex, cap_divisions,
 
 4627                             surface_type, output_points_only, triangular_poles,
 
 4628                             reverse_cross_sections, swap_row_col);
 
 4635                         auto grid_transforms = gridOffsetTransforms(transform_cache, local_grid_transforms, gridi);
 
 4636                         copyFloatSingleGrid<fpreal32,GA_TYPE_NORMAL,attrib_owner>(
 
 4637                             output_numeric, cross_section_numeric, cross_section_input,
 
 4638                             grid_transforms, grids[gridi], cross_sections_per_vertex, cap_divisions,
 
 4639                             surface_type, output_points_only, triangular_poles,
 
 4640                             reverse_cross_sections, swap_row_col);
 
 4651                         auto grid_transforms = gridOffsetTransforms(transform_cache, local_grid_transforms, gridi);
 
 4652                         copyFloatSingleGrid<fpreal64,GA_TYPE_VECTOR,attrib_owner>(
 
 4653                             output_numeric, cross_section_numeric, cross_section_input,
 
 4654                             grid_transforms, grids[gridi], cross_sections_per_vertex, cap_divisions,
 
 4655                             surface_type, output_points_only, triangular_poles,
 
 4656                             reverse_cross_sections, swap_row_col);
 
 4663                         auto grid_transforms = gridOffsetTransforms(transform_cache, local_grid_transforms, gridi);
 
 4664                         copyFloatSingleGrid<fpreal32,GA_TYPE_VECTOR,attrib_owner>(
 
 4665                             output_numeric, cross_section_numeric, cross_section_input,
 
 4666                             grid_transforms, grids[gridi], cross_sections_per_vertex, cap_divisions,
 
 4667                             surface_type, output_points_only, triangular_poles,
 
 4668                             reverse_cross_sections, swap_row_col);
 
 4674         else if (tuple_size == 4)
 
 4682                         auto grid_transforms = gridOffsetTransforms(transform_cache, local_grid_transforms, gridi);
 
 4683                         copyFloatSingleGrid<fpreal64,GA_TYPE_QUATERNION,attrib_owner>(
 
 4684                             output_numeric, cross_section_numeric, cross_section_input,
 
 4685                             grid_transforms, grids[gridi], cross_sections_per_vertex, cap_divisions,
 
 4686                             surface_type, output_points_only, triangular_poles,
 
 4687                             reverse_cross_sections, swap_row_col);
 
 4694                         auto grid_transforms = gridOffsetTransforms(transform_cache, local_grid_transforms, gridi);
 
 4695                         copyFloatSingleGrid<fpreal32,GA_TYPE_QUATERNION,attrib_owner>(
 
 4696                             output_numeric, cross_section_numeric, cross_section_input,
 
 4697                             grid_transforms, grids[gridi], cross_sections_per_vertex, cap_divisions,
 
 4698                             surface_type, output_points_only, triangular_poles,
 
 4699                             reverse_cross_sections, swap_row_col);
 
 4705         else if (tuple_size == 9 || tuple_size == 16)
 
 4713                         auto grid_transforms = gridOffsetTransforms(transform_cache, local_grid_transforms, gridi);
 
 4714                         copyFloatSingleGrid<fpreal64,GA_TYPE_TRANSFORM,attrib_owner>(
 
 4715                             output_numeric, cross_section_numeric, cross_section_input,
 
 4716                             grid_transforms, grids[gridi], cross_sections_per_vertex, cap_divisions,
 
 4717                             surface_type, output_points_only, triangular_poles,
 
 4718                             reverse_cross_sections, swap_row_col);
 
 4725                         auto grid_transforms = gridOffsetTransforms(transform_cache, local_grid_transforms, gridi);
 
 4726                         copyFloatSingleGrid<fpreal32,GA_TYPE_TRANSFORM,attrib_owner>(
 
 4727                             output_numeric, cross_section_numeric, cross_section_input,
 
 4728                             grid_transforms, grids[gridi], cross_sections_per_vertex, cap_divisions,
 
 4729                             surface_type, output_points_only, triangular_poles,
 
 4730                             reverse_cross_sections, swap_row_col);
 
 4741                 copyFloatSingleGrid<fpreal64,GA_TYPE_VOID,attrib_owner>(
 
 4742                     output_numeric, cross_section_numeric, cross_section_input,
 
 4743                     nullptr, grids[gridi], cross_sections_per_vertex, cap_divisions,
 
 4744                     surface_type, output_points_only, triangular_poles,
 
 4745                     reverse_cross_sections, swap_row_col);
 
 4752                 copyFloatSingleGrid<fpreal32,GA_TYPE_VOID,attrib_owner>(
 
 4753                     output_numeric, cross_section_numeric, cross_section_input,
 
 4754                     nullptr, grids[gridi], cross_sections_per_vertex, cap_divisions,
 
 4755                     surface_type, output_points_only, triangular_poles,
 
 4756                     reverse_cross_sections, swap_row_col);
 
 4763                 copyIntegerSingleGrid<int64,attrib_owner>(
 
 4764                     output_numeric, cross_section_numeric, cross_section_input,
 
 4765                     nullptr, grids[gridi],
 
 4766                     surface_type, output_points_only, triangular_poles,
 
 4767                     reverse_cross_sections, swap_row_col);
 
 4774                 copyIntegerSingleGrid<int32,attrib_owner>(
 
 4775                     output_numeric, cross_section_numeric, cross_section_input,
 
 4776                     nullptr, grids[gridi],
 
 4777                     surface_type, output_points_only, triangular_poles,
 
 4778                     reverse_cross_sections, swap_row_col);
 
 4786         functor(grid_range);
 
 4790 copyCrossSectionAttrib(
 
 4794     const SOP_SweepHDKCache *transform_cache,
 
 4795     const sop_SweepGrid *grids,
 
 4797     const exint cross_sections_per_vertex,
 
 4798     const exint cap_divisions,
 
 4800     const bool output_points_only,
 
 4801     const bool triangular_poles,
 
 4802     const bool reverse_cross_sections,
 
 4803     const bool swap_row_col)
 
 4810         copyCrossSectionAttrib2<GA_ATTRIB_POINT>(
 
 4811             output_attrib, cross_section_attrib, cross_section_input,
 
 4812             transform_cache, grids, ngrids, cross_sections_per_vertex, cap_divisions,
 
 4813             surface_type, output_points_only, triangular_poles,
 
 4814             reverse_cross_sections, swap_row_col);
 
 4818         copyCrossSectionAttrib2<GA_ATTRIB_VERTEX>(
 
 4819             output_attrib, cross_section_attrib, cross_section_input,
 
 4820             transform_cache, grids, ngrids, cross_sections_per_vertex, cap_divisions,
 
 4821             surface_type, output_points_only, triangular_poles,
 
 4822             reverse_cross_sections, swap_row_col);
 
 4826         copyCrossSectionAttrib2<GA_ATTRIB_PRIMITIVE>(
 
 4827             output_attrib, cross_section_attrib, cross_section_input,
 
 4828             transform_cache, grids, ngrids, cross_sections_per_vertex, cap_divisions,
 
 4829             surface_type, output_points_only, triangular_poles,
 
 4830             reverse_cross_sections, swap_row_col);
 
 4834         output_attrib->
replace(*cross_section_attrib);
 
 4838 template<
bool wrap_to_inval
id,
typename FUNCTOR>
 
 4840 copyVertexCurveAttribWrapper(
 
 4841     const sop_SweepGrid &grid_info,
 
 4844     exint cap_divisions,
 
 4845     exint cross_sections_per_vertex,
 
 4846     const bool swap_row_col,
 
 4847     const FUNCTOR ©_functor)
 
 4849     const exint curve_nedges = grid_info.myCurveNEdges;
 
 4850     const exint cross_section_nedges = grid_info.myCrossSectionNEdges;
 
 4852     const exint cap_divs = (grid_info.myVEndPoles && !grid_info.myHasPolygonCaps) ? cap_divisions : 0;
 
 4853     exint prev_vtxi = -1;
 
 4855     exint cap_vertex_count = 0;
 
 4856     if (grid_info.myHasPolygonCaps)
 
 4861             cap_vertex_count = cross_section_nedges;
 
 4866             for (
exint col = 0; col < cap_vertex_count; ++col)
 
 4868                 copy_functor(grid_info.myStartVtxOff + col, 0);
 
 4874             cap_vertex_count = curve_nedges;
 
 4876             for (
exint row = 0; row < cap_vertex_count; ++
row)
 
 4878                 copy_functor(grid_info.myStartVtxOff + row, row);
 
 4883     const GA_Offset start_vtxoff = grid_info.myStartVtxOff + cap_vertex_count;
 
 4884     const bool closed_curve = grid_info.myCurveClosed;
 
 4886         start_vtxoff, cross_sections_per_vertex, swap_row_col, closed_curve, ©_functor]
 
 4889         exint vtxi = swap_row_col ? col : 
row;
 
 4890         vtxi += 
exint(swap_row_col ? iscolend : isrowend);
 
 4891         if (vtxi != prev_vtxi)
 
 4893             curve_vtxi = vtxi - cap_divs;
 
 4894             if (cross_sections_per_vertex != 1)
 
 4895                 curve_vtxi /= cross_sections_per_vertex;
 
 4898             else if (curve_vtxi >= num_vertices)
 
 4901                     curve_vtxi = num_vertices-1;
 
 4902                 else if (wrap_to_invalid)
 
 4909         copy_functor(start_vtxoff + vtxnum, curve_vtxi);
 
 4911     if (grid_info.myHasPolygonCaps)
 
 4918             curve_vtxi = num_vertices-1;
 
 4920             for (
exint col = 0; col < cap_vertex_count; ++col)
 
 4922                 copy_functor(cap_start_vtxoff + col, curve_vtxi);
 
 4928             for (
exint row = 0; row < cap_vertex_count; ++
row)
 
 4930                 copy_functor(cap_start_vtxoff + row, row);
 
 4936 template<GA_AttributeOwner attrib_owner,
bool wrap_to_inval
id=false,
typename COPY_FUNCTOR>
 
 4941     const sop_SweepGrid *grids,
 
 4943     const exint cross_sections_per_vertex,
 
 4945     const bool output_points_only,
 
 4946     const bool triangular_poles,
 
 4947     const exint cap_divisions,
 
 4948     const bool swap_row_col,
 
 4949     const COPY_FUNCTOR ©_functor)
 
 4960             const sop_SweepGrid &grid_info = grids[gridi];
 
 4962             initGUGrid(grid_info, surface_type, output_points_only, triangular_poles, swap_row_col, grid_info.myStartPtOff, grid);
 
 4967                 copyVertexCurveAttribWrapper<wrap_to_invalid>(grid_info, grid, vertices.
size(), cap_divisions, cross_sections_per_vertex, swap_row_col,
 
 4968                     [©_functor,&vertices](
GA_Offset output_vtxoff, 
exint curve_vtxi)
 
 4971                     copy_functor(output_vtxoff, curve_vtxoff);
 
 4977                 const exint cap_divs = (grid_info.myVEndPoles && !grid_info.myHasPolygonCaps) ? cap_divisions : 0;
 
 4978                 exint prev_vtxi = -1;
 
 4981                     &curve_ptoff, curve_input, cross_sections_per_vertex, swap_row_col, ©_functor]
 
 4984                     exint vtxi = swap_row_col ? col : 
row;
 
 4985                     if (vtxi != prev_vtxi)
 
 4987                         exint curve_vtxi = vtxi - cap_divs;
 
 4988                         if (cross_sections_per_vertex != 1)
 
 4989                             curve_vtxi /= cross_sections_per_vertex;
 
 4992                         else if (curve_vtxi >= vertices.
size())
 
 4993                             curve_vtxi = vertices.
size()-1;
 
 4994                         GA_Offset curve_vtxoff = vertices(curve_vtxi);
 
 4995                         curve_ptoff = curve_input->
vertexPoint(curve_vtxoff);
 
 4998                     copy_functor(output_ptoff, curve_ptoff);
 
 5004     const exint PARALLEL_THRESHOLD = 2048;
 
 5023     const sop_SweepGrid *grids,
 
 5025     const exint cross_sections_per_vertex,
 
 5027     const bool output_points_only,
 
 5028     const bool triangular_poles,
 
 5029     const exint cap_divisions,
 
 5030     const bool swap_row_col)
 
 5037         auto &©_functor = [output_attrib,curve_attrib](
GA_Offset output_off, 
GA_Offset curve_off)
 
 5039             output_attrib->
copy(output_off, *curve_attrib, curve_off);
 
 5041         copyCurveAttrib2<GA_ATTRIB_POINT>(
 
 5042             output_attrib, curve_input,
 
 5043             grids, ngrids, cross_sections_per_vertex,
 
 5044             surface_type, output_points_only, triangular_poles, cap_divisions,
 
 5045             swap_row_col, copy_functor);
 
 5049         if (!output_points_only)
 
 5051             auto &©_functor = [output_attrib,curve_attrib](
GA_Offset output_off, 
GA_Offset curve_off)
 
 5053                 output_attrib->
copy(output_off, *curve_attrib, curve_off);
 
 5055             copyCurveAttrib2<GA_ATTRIB_VERTEX>(
 
 5056                 output_attrib, curve_input,
 
 5057                 grids, ngrids, cross_sections_per_vertex,
 
 5058                 surface_type, output_points_only, triangular_poles, cap_divisions,
 
 5059                 swap_row_col, copy_functor);
 
 5064         if (!output_points_only)
 
 5074                     const sop_SweepGrid &grid_info = grids[gridi];
 
 5076                     initGUGrid(grid_info, surface_type, output_points_only, triangular_poles, swap_row_col, grid_info.myStartPtOff, grid);
 
 5079                     const GA_Offset startprimoff = grid_info.myStartPrimOff;
 
 5081                     output_attrib->
fill(
GA_Range(output_attrib->
getIndexMap(), startprimoff, endprimoff), *curve_attrib, grid_info.myCurvePrimOff);
 
 5085             const exint PARALLEL_THRESHOLD = 2048;
 
 5101         output_attrib->
replace(*curve_attrib);
 
 5113 template<
typename T,GA_AttributeOwner output_owner>
 
 5115 copyCrossSectionUVSingleGrid(
 
 5120     const sop_SweepGrid &grid_info,
 
 5122     const bool is_cross_section_uv_computed,
 
 5123     const bool reverse_cross_sections,
 
 5124     const bool swap_row_col,
 
 5137     auto &&get_transform = [](
const sop_SweepGridTransformWrapper *transforms, 
exint row, 
const sop_SweepGrid &grid_info) -> 
const void*
 
 5147         if (tuple_size == 2)
 
 5151             auto &©_functor = [missing_input_us,&outputh,flipu,swap_row_col,uscale](
 
 5154                 const exint cross_section_vtxi = swap_row_col ? row : col;
 
 5155                 T value = (cross_section_vtxi == missing_input_us->size()) ? 
T(1.0) : (*missing_input_us)[cross_section_vtxi];
 
 5159                 output_value[theUComponent] = uscale*
value;
 
 5160                 outputh.set(output_offset, output_value);
 
 5163                 copyVertexCrossSectionWrapper(grid, grid_info, copy_functor);
 
 5167         else if (tuple_size == 3)
 
 5171             auto &©_functor = [missing_input_us,&outputh,flipu,swap_row_col,uscale](
 
 5174                 const exint cross_section_vtxi = swap_row_col ? row : col;
 
 5175                 T value = (cross_section_vtxi == missing_input_us->size()) ? 
T(1.0) : (*missing_input_us)[cross_section_vtxi];
 
 5179                 output_value[theUComponent] = uscale*
value;
 
 5180                 outputh.set(output_offset, output_value);
 
 5183                 copyVertexCrossSectionWrapper(grid, grid_info, copy_functor);
 
 5190     if (tuple_size == 2)
 
 5193         auto &&transform_and_copy = [flipu,reverse_cross_sections,uscale,is_cross_section_uv_computed](
 
 5200                 value = reverse_cross_sections ? 
T(0.0) : T(1.0);
 
 5202                 value = cross_sectionh.get(cross_section_offset);
 
 5205                 value = T(1.0)-
value;
 
 5206             if (is_cross_section_uv_computed)
 
 5209             output_value[theUComponent] = 
value;
 
 5210             outputh.set(output_offset, output_value);
 
 5212         auto &&transform_and_interp = [flipu,reverse_cross_sections,uscale,is_cross_section_uv_computed](
 
 5219             const T value0 = cross_sectionh.get(cross_section_offset0);
 
 5224                 value1 = reverse_cross_sections ? T(0.0) : T(1.0);
 
 5226                 value1 = cross_sectionh.get(cross_section_offset1);
 
 5228             T value = 
SYSlerp(value0, value1, t);
 
 5230                 value = T(1.0)-
value;
 
 5231             if (is_cross_section_uv_computed)
 
 5234             output_value[theUComponent] = 
value;
 
 5235             outputh.set(output_offset, output_value);
 
 5242         copyCrossSectionAttributeWrapper2<void, output_owner, wrap_to_invalid>(grid,
 
 5243             outputh, cross_sectionh, cross_section_owner, cross_section_input, 
nullptr, grid_info,
 
 5244             reverse_cross_sections, swap_row_col,
 
 5245             get_transform, transform_and_copy, transform_and_interp);
 
 5248     if (tuple_size == 3)
 
 5251         auto &&transform_and_copy = [flipu,reverse_cross_sections,uscale,is_cross_section_uv_computed](
 
 5258                 value = reverse_cross_sections ? T(0.0) : T(1.0);
 
 5260                 value = cross_sectionh.get(cross_section_offset);
 
 5263                 value = T(1.0)-
value;
 
 5264             if (is_cross_section_uv_computed)
 
 5267             output_value[theUComponent] = 
value;
 
 5268             outputh.set(output_offset, output_value);
 
 5270         auto &&transform_and_interp = [flipu,reverse_cross_sections,uscale,is_cross_section_uv_computed](
 
 5277             const T value0 = cross_sectionh.get(cross_section_offset0);
 
 5282                 value1 = reverse_cross_sections ? T(0.0) : T(1.0);
 
 5284                 value1 = cross_sectionh.get(cross_section_offset1);
 
 5286             T value = 
SYSlerp(value0, value1, t);
 
 5288                 value = T(1.0)-
value;
 
 5289             if (is_cross_section_uv_computed)
 
 5292             output_value[theUComponent] = 
value;
 
 5293             outputh.set(output_offset, output_value);
 
 5300         copyCrossSectionAttributeWrapper2<void, output_owner, wrap_to_invalid>(grid,
 
 5301             outputh, cross_sectionh, cross_section_owner, cross_section_input, 
nullptr, grid_info,
 
 5302             reverse_cross_sections, swap_row_col,
 
 5303             get_transform, transform_and_copy, transform_and_interp);
 
 5308 template<
typename T>
 
 5313     const exint cross_section_nedges,
 
 5314     const exint curve_row)
 
 5317     for (
exint cross_section_vtxi = 0; cross_section_vtxi < cross_section_nedges; ++cross_section_vtxi)
 
 5319         exint row = curve_row;;
 
 5320         exint col = cross_section_vtxi;
 
 5327     return sum / cross_section_nedges;
 
 5336 template<
typename T>
 
 5337 static double crossSectionLength(
 
 5341     const exint cross_section_nedges,
 
 5342     const exint curve_row,
 
 5346     double cross_section_length = 0;
 
 5347     exint row = curve_row;
 
 5354     if (dir0 != 
nullptr)
 
 5356         T d = prevpos.
dot(*dir0);
 
 5357         prevpos0 = prevpos - d*(*dir0);
 
 5358         if (dir1 != 
nullptr)
 
 5360             d = prevpos.
dot(*dir1);
 
 5361             prevpos1 = prevpos - d*(*dir1);
 
 5364     for (
exint cross_section_vtxi = 0; cross_section_vtxi < cross_section_nedges; ++cross_section_vtxi)
 
 5366         exint row = curve_row;
 
 5367         exint col = cross_section_vtxi+1;
 
 5373         if (dir0 != 
nullptr)
 
 5375             T d = nextpos.
dot(*dir0);
 
 5376             nextpos0 = nextpos - d*(*dir0);
 
 5377             T dist0 = prevpos0.
distance(nextpos0);
 
 5378             if (dir1 != 
nullptr)
 
 5380                 d = nextpos.
dot(*dir1);
 
 5381                 nextpos1 = nextpos - d*(*dir1);
 
 5383                 cross_section_length += 0.5f*(dist0 + prevpos1.
distance(nextpos1));
 
 5387                 cross_section_length += dist0;
 
 5392             cross_section_length += prevpos.
distance(nextpos);
 
 5395         if (dir0 != 
nullptr)
 
 5397             prevpos0 = nextpos0;
 
 5398             if (dir1 != 
nullptr)
 
 5399                 prevpos1 = nextpos1;
 
 5402     return cross_section_length;
 
 5405 template<
typename T, 
typename FUNCTOR>
 
 5406 static void iterateCurveEdgeLengths(
 
 5407     const exint curve_nedges,
 
 5408     const bool use_mesh_edge_lengths,
 
 5410     const exint cross_section_npts,
 
 5411     const bool swap_row_col,
 
 5415     const sop_SweepGrid &grid_info,
 
 5416     const exint cap_divisions,
 
 5423     for (
exint curve_vtxi = 0; curve_vtxi < curve_nedges; ++curve_vtxi)
 
 5425         double length_sum = 0;
 
 5426         exint length_sum_count;
 
 5427         if (use_mesh_edge_lengths)
 
 5429             length_sum_count = cross_section_npts;
 
 5430             for (
exint cross_section_vtxi = 0; cross_section_vtxi < cross_section_npts; ++cross_section_vtxi)
 
 5432                 exint col0 = swap_row_col ? curve_vtxi : cross_section_vtxi;
 
 5433                 exint col1 = swap_row_col ? curve_vtxi+1 : cross_section_vtxi;
 
 5434                 exint row0 = swap_row_col ? cross_section_vtxi : curve_vtxi;
 
 5435                 exint row1 = swap_row_col ? cross_section_vtxi : curve_vtxi+1;
 
 5443             length_sum_count = 1;
 
 5444             exint orig_curve_vtxi = curve_vtxi;
 
 5445             if (grid_info.myVEndPoles)
 
 5448                 orig_curve_vtxi -= cap_divisions;
 
 5452             exint orig_curve_vtxi1 = (curve_vertices.
getExtraFlag() && curve_vtxi+1 == curve_nedges) ? 0 : curve_vtxi+1;
 
 5453             if (grid_info.myVEndPoles)
 
 5457                 orig_curve_vtxi1 -= cap_divisions;
 
 5464         functor(curve_vtxi, length_sum, length_sum_count);
 
 5469 template<GA_AttributeOwner output_owner, 
typename T>
 
 5471 generateLengthWeightedV(
 
 5472     const sop_SweepGrid &grid_info,
 
 5474     const exint cross_sections_per_vertex,
 
 5479     bool scalevasu_usingmax,
 
 5483     bool use_mesh_edge_lengths,
 
 5488     const exint curve_nedges = grid_info.myCurveNEdges;
 
 5489     const exint cross_section_nedges = grid_info.myCrossSectionNEdges;
 
 5494     exint cap_divisions = 0;
 
 5495     if (curve_input != 
nullptr)
 
 5498         if (grid_info.myVEndPoles)
 
 5501             exint orig_curve_nedges = curve_vertices.
size() - 1;
 
 5502             cap_divisions = (grid_info.myCurveNEdges - orig_curve_nedges)/2;
 
 5505         curve_pos.
bind(curve_input->
getP());
 
 5508     bool norm_u_unnorm_v = (ustyle == UVStyle::NORMALIZED && vstyle != UVStyle::NORMALIZED);
 
 5509     bool special_case_u_division = (!scalevasu_usingmax && norm_u_unnorm_v);
 
 5513     bool prevPosValid = 
false;
 
 5515     bool currPosValid = 
false;
 
 5523     double prev_cross_section_length = 0;
 
 5524     if (special_case_u_division)
 
 5526         if (curve_input != 
nullptr)
 
 5530             if (curve_vertices.
size() >= 2)
 
 5532                 currPos = curve_pos.
get(curve_input->
vertexPoint(curve_vertices[0]));
 
 5533                 nextPos = curve_pos.
get(curve_input->
vertexPoint(curve_vertices[1]));
 
 5534                 currPosValid = 
true;
 
 5535                 if (grid_info.myCurveClosed)
 
 5539                     exint last_vtxi = curve_vertices.
size() - (unrolled ? 2 : 1);
 
 5540                     prevPos = curve_pos.
get(curve_input->
vertexPoint(curve_vertices[last_vtxi]));
 
 5541                     prevPosValid = 
true;
 
 5545         else if (curve_nedges >= 1 + (grid_info.myVEndPoles ? 2*cap_divisions : 0))
 
 5549             exint start = grid_info.myVEndPoles ? cap_divisions : 0;
 
 5550             currPos = crossSectionCenter(swap_row_col, pos, grid, cross_section_nedges, start);
 
 5551             nextPos = crossSectionCenter(swap_row_col, pos, grid, cross_section_nedges, start+1);
 
 5552             currPosValid = 
true;
 
 5553             if (grid_info.myCurveClosed)
 
 5555                 prevPos = crossSectionCenter(swap_row_col, pos, grid, cross_section_nedges, curve_nedges-1);
 
 5556                 prevPosValid = 
true;
 
 5562             dir0 = (currPos - prevPos);
 
 5563             dir1 = (nextPos - currPos);
 
 5566             if (length0 != 0 && length1 != 0)
 
 5571             else if (length0 != 0 || length1 != 0)
 
 5572                 pdir0 = (length0 != 0) ? &dir0 : &dir1;
 
 5574         else if (currPosValid)
 
 5576             dir1 = (nextPos - currPos);
 
 5582         prev_cross_section_length = crossSectionLength(swap_row_col, pos, grid, cross_section_nedges, 0, pdir0, pdir1);
 
 5591     double max_cross_section_length = 0;
 
 5592     if (need_max_cross_section_length)
 
 5594         for (
exint curve_vtxi = 0; curve_vtxi <= curve_nedges; ++curve_vtxi)
 
 5596             double cross_section_length = crossSectionLength(swap_row_col, pos, grid, cross_section_nedges, curve_vtxi, dir0, dir1);
 
 5597             max_cross_section_length = 
SYSmax(cross_section_length, max_cross_section_length);
 
 5605     double total_length_sum = 0;
 
 5606     exint curve_npts = curve_nedges + !grid_info.myCurveClosed;
 
 5607     exint cross_section_npts = cross_section_nedges + !grid_info.myCrossSectionClosed;
 
 5608     iterateCurveEdgeLengths(
 
 5610         use_mesh_edge_lengths,
 
 5620         [&](
exint curve_vtxi, 
double length_sum, 
exint length_sum_count)
 
 5622         if (special_case_u_division)
 
 5624             bool nextPosValid = 
false;
 
 5626             if (!grid_info.myVEndPoles || (curve_vtxi >= cap_divisions && curve_vtxi < curve_npts-cap_divisions))
 
 5628                 nextPosValid = 
true;
 
 5629                 if (cross_section_nedges >= 1)
 
 5631                     exint nextPosVtxi = curve_vtxi+2;
 
 5632                     exint threshold = curve_npts;
 
 5633                     if (grid_info.myVEndPoles)
 
 5635                         nextPosVtxi -= cap_divisions;
 
 5636                         threshold -= 2*cap_divisions;
 
 5638                     if (nextPosVtxi >= threshold)
 
 5640                         if (grid_info.myCurveClosed)
 
 5641                             nextPosVtxi -= curve_npts;
 
 5643                             nextPosValid = 
false;
 
 5647                         if (curve_input != 
nullptr)
 
 5650                             exint next_curve_vtxi = nextPosVtxi;
 
 5651                             if (cross_sections_per_vertex != 1)
 
 5652                                 next_curve_vtxi /= cross_sections_per_vertex;
 
 5653                             if (next_curve_vtxi < 0)
 
 5654                                 next_curve_vtxi = 0;
 
 5655                             else if (next_curve_vtxi >= curve_vertices.
size())
 
 5656                                 next_curve_vtxi = curve_vertices.
size()-1;
 
 5657                             GA_Offset curve_vtxoff = curve_vertices[next_curve_vtxi];
 
 5659                             nextPos = curve_pos.
get(curve_ptoff);
 
 5663                             nextPos = crossSectionCenter(swap_row_col, pos, grid, cross_section_nedges, nextPosVtxi);
 
 5671                     dir1 = (nextPos - currPos);
 
 5673                     if (length0 != 0 && length1 != 0)
 
 5678                     else if (length0 != 0 || length1 != 0)
 
 5679                         pdir0 = (length0 != 0) ? &dir0 : &dir1;
 
 5681                 else if (length0 != 0)
 
 5686             double next_cross_section_length = crossSectionLength(swap_row_col, pos, grid, cross_section_nedges, curve_vtxi+1, pdir0, pdir1);
 
 5694             double curr_cross_section_length_avg = 0.5*(prev_cross_section_length + next_cross_section_length);
 
 5695             if (curr_cross_section_length_avg == 0)
 
 5700                 length_sum /= (length_sum_count*curr_cross_section_length_avg);
 
 5703             prev_cross_section_length = next_cross_section_length;
 
 5708             length_sum /= length_sum_count;
 
 5711         total_length_sum += length_sum;
 
 5712         length_sums[curve_vtxi+1] = vscale*total_length_sum;
 
 5715     UT_ASSERT_MSG(total_length_sum != 0 || (vstyle != UVStyle::NORMALIZED), 
"computeGridUVScales should have fallen back to v being uniform");
 
 5717     if (vstyle == UVStyle::NORMALIZED)
 
 5720         length_sums[curve_nedges] = orig_vscale;
 
 5722         for (
exint curve_vtxi = curve_nedges-1; curve_vtxi >= 0 && length_sums[curve_vtxi] > orig_vscale; ++curve_vtxi)
 
 5724             length_sums[curve_vtxi] = orig_vscale;
 
 5727     else if (vstyle == UVStyle::ROUNDED)
 
 5730         double &rounded = length_sums[curve_nedges];
 
 5734         length_sums[curve_nedges] = rounded;
 
 5736         for (
exint curve_vtxi = curve_nedges-1; curve_vtxi >= 0 && length_sums[curve_vtxi] > rounded; ++curve_vtxi)
 
 5738             length_sums[curve_vtxi] = rounded;
 
 5745     exint cap_vertex_count = 0;
 
 5751             cap_vertex_count = cross_section_nedges;
 
 5752             for (
exint col = 0; col < cap_vertex_count; ++col)
 
 5754                 outputh.
set(grid_info.myStartVtxOff + col, theVComponent, 0);
 
 5760             cap_vertex_count = curve_nedges;
 
 5764     const GA_Offset start_vtxoff = grid_info.myStartVtxOff + cap_vertex_count;
 
 5771             exint curve_vtxi = swap_row_col ? col : 
row;
 
 5772             curve_vtxi += 
exint(swap_row_col ? iscolend : isrowend);
 
 5773             outputh.
set(start_vtxoff + vtxnum, theVComponent, length_sums[curve_vtxi]);
 
 5779         const GA_Offset start_ptoff = grid_info.myStartPtOff;
 
 5783             exint curve_vtxi = swap_row_col ? col : 
row;
 
 5784             outputh.
set(start_ptoff + ptnum, theVComponent, length_sums[curve_vtxi]);
 
 5794             for (
exint col = 0; col < cap_vertex_count; ++col)
 
 5796                 outputh.
set(cap_start_vtxoff + col, theVComponent, length_sums[curve_nedges]);
 
 5807 template<GA_AttributeOwner output_owner, 
typename T>
 
 5810     const sop_SweepGrid &grid_info,
 
 5816     const exint curve_nedges = grid_info.myCurveNEdges;
 
 5817     const exint cross_section_nedges = grid_info.myCrossSectionNEdges;
 
 5820     exint cap_vertex_count = 0;
 
 5826             cap_vertex_count = cross_section_nedges;
 
 5827             for (
exint col = 0; col < cap_vertex_count; ++col)
 
 5829                 outputh.
set(grid_info.myStartVtxOff + col, theVComponent, 0);
 
 5835             cap_vertex_count = curve_nedges;
 
 5840     const GA_Offset start_vtxoff = grid_info.myStartVtxOff + cap_vertex_count;
 
 5841     const T recip_curve_nedges = (curve_nedges == 0) ? T(0.0) : (vscale/curve_nedges);
 
 5848             exint curve_vtxi = swap_row_col ? col : 
row;
 
 5849             curve_vtxi += 
exint(swap_row_col ? iscolend : isrowend);
 
 5850             outputh.
set(start_vtxoff + vtxnum, theVComponent, T(curve_vtxi)*recip_curve_nedges);
 
 5856         const GA_Offset start_ptoff = grid_info.myStartPtOff;
 
 5860             exint curve_vtxi = swap_row_col ? col : 
row;
 
 5861             outputh.
set(start_ptoff + ptnum, theVComponent, T(curve_vtxi)*recip_curve_nedges);
 
 5871             for (
exint col = 0; col < cap_vertex_count; ++col)
 
 5873                 outputh.
set(cap_start_vtxoff + col, theVComponent, vscale);
 
 5888     const sop_SweepGrid &grid_info,
 
 5890     const bool swap_row_col,
 
 5891     const exint cross_sections_per_vertex,
 
 5892     const exint cap_divisions,
 
 5895     const bool use_mesh_edge_lengths,
 
 5896     const bool scalevasu_usingmax,
 
 5898     bool &fallback_to_uniform_v)
 
 5900     fallback_to_uniform_v = 
false;
 
 5902     const exint curve_nedges = grid_info.myCurveNEdges;
 
 5903     const exint curve_npts = curve_nedges + !grid_info.myCurveClosed;
 
 5904     const exint cross_section_nedges = grid_info.myCrossSectionNEdges;
 
 5905     exint cross_section_npts = cross_section_nedges + !grid_info.myCrossSectionClosed;
 
 5913     bool prevPosValid = 
false;
 
 5915     bool currPosValid = 
false;
 
 5917     if (curve_input != 
nullptr)
 
 5919         curve_pos.bind(curve_input->
getP());
 
 5923         if (curve_vertices.size() >= 2)
 
 5925             currPos = curve_pos.get(curve_input->
vertexPoint(curve_vertices[0]));
 
 5926             nextPos = curve_pos.get(curve_input->
vertexPoint(curve_vertices[1]));
 
 5927             currPosValid = 
true;
 
 5928             if (grid_info.myCurveClosed)
 
 5931                 bool unrolled = !curve_vertices.getExtraFlag();
 
 5932                 exint last_vtxi = curve_vertices.size() - (unrolled ? 2 : 1);
 
 5933                 prevPos = curve_pos.get(curve_input->
vertexPoint(curve_vertices[last_vtxi]));
 
 5934                 prevPosValid = 
true;
 
 5938     else if (curve_nedges >= 1 + (grid_info.myVEndPoles ? 2*cap_divisions : 0))
 
 5942         exint start = grid_info.myVEndPoles ? cap_divisions : 0;
 
 5943         currPos = crossSectionCenter(swap_row_col, pos, grid, cross_section_nedges, start);
 
 5944         nextPos = crossSectionCenter(swap_row_col, pos, grid, cross_section_nedges, start+1);
 
 5945         currPosValid = 
true;
 
 5946         if (grid_info.myCurveClosed)
 
 5948             prevPos = crossSectionCenter(swap_row_col, pos, grid, cross_section_nedges, curve_nedges-1);
 
 5949             prevPosValid = 
true;
 
 5961         dir0 = (currPos - prevPos);
 
 5962         dir1 = (nextPos - currPos);
 
 5965         if (length0 != 0 && length1 != 0)
 
 5970         else if (length0 != 0 || length1 != 0)
 
 5971             pdir0 = (length0 != 0) ? &dir0 : &dir1;
 
 5973     else if (currPosValid)
 
 5975         dir1 = (nextPos - currPos);
 
 5981     double prev_cross_section_length = crossSectionLength(swap_row_col, pos, grid, cross_section_nedges, 0, pdir0, pdir1);
 
 5988     double curve_length = 0;
 
 5989     double curve_length_per_cross_section_length_sum = 0;
 
 5990     double cross_section_length_sum = prev_cross_section_length;
 
 5991     exint cross_section_length_count = 1;
 
 5992     double cross_section_length_max = prev_cross_section_length;
 
 5993     iterateCurveEdgeLengths(
 
 5995         use_mesh_edge_lengths,
 
 6005         [&](
exint curve_vtxi, 
double length_sum, 
exint length_sum_count)
 
 6007         double curr_curve_length = (length_sum/length_sum_count);
 
 6008         curve_length += curr_curve_length;
 
 6010         bool nextPosValid = 
false;
 
 6012         if (!grid_info.myVEndPoles || (curve_vtxi >= cap_divisions && curve_vtxi < curve_npts-cap_divisions))
 
 6014             nextPosValid = 
true;
 
 6015             if (cross_section_nedges >= 1)
 
 6017                 exint nextPosVtxi = curve_vtxi+2;
 
 6018                 exint threshold = curve_npts;
 
 6019                 if (grid_info.myVEndPoles)
 
 6021                     nextPosVtxi -= cap_divisions;
 
 6022                     threshold -= 2*cap_divisions;
 
 6024                 if (nextPosVtxi >= threshold)
 
 6026                     if (grid_info.myCurveClosed)
 
 6027                         nextPosVtxi -= curve_npts;
 
 6029                         nextPosValid = 
false;
 
 6033                     if (curve_input != 
nullptr)
 
 6036                         exint next_curve_vtxi = nextPosVtxi;
 
 6037                         if (cross_sections_per_vertex != 1)
 
 6038                             next_curve_vtxi /= cross_sections_per_vertex;
 
 6039                         if (next_curve_vtxi < 0)
 
 6040                             next_curve_vtxi = 0;
 
 6041                         else if (next_curve_vtxi >= curve_vertices.size())
 
 6042                             next_curve_vtxi = curve_vertices.size()-1;
 
 6043                         GA_Offset curve_vtxoff = curve_vertices[next_curve_vtxi];
 
 6045                         nextPos = curve_pos.get(curve_ptoff);
 
 6049                         nextPos = crossSectionCenter(swap_row_col, pos, grid, cross_section_nedges, nextPosVtxi);
 
 6057                 dir1 = (nextPos - currPos);
 
 6059                 if (length0 != 0 && length1 != 0)
 
 6064                 else if (length0 != 0 || length1 != 0)
 
 6065                     pdir0 = (length0 != 0) ? &dir0 : &dir1;
 
 6067             else if (length0 != 0)
 
 6072         double next_cross_section_length = crossSectionLength(swap_row_col, pos, grid, cross_section_nedges, curve_vtxi+1, pdir0, pdir1);
 
 6081         double curr_cross_section_length_avg = 0.5*(prev_cross_section_length + next_cross_section_length);
 
 6082         if (curr_cross_section_length_avg != 0)
 
 6087             curve_length_per_cross_section_length_sum += (curr_curve_length/curr_cross_section_length_avg);
 
 6090         if (curve_vtxi+1 != curve_nedges || !grid_info.myCurveClosed)
 
 6092             cross_section_length_max = 
SYSmax(next_cross_section_length, cross_section_length_max);
 
 6093             cross_section_length_sum += next_cross_section_length;
 
 6094             ++cross_section_length_count;
 
 6095             prev_cross_section_length = next_cross_section_length;
 
 6098     double cross_section_length_avg = (cross_section_length_sum/cross_section_length_count);
 
 6102     if (ustyle == UVStyle::NORMALIZED)
 
 6106         if (vstyle == UVStyle::NORMALIZED)
 
 6109             if (curve_length == 0)
 
 6110                 fallback_to_uniform_v = 
true;
 
 6112                 uvscale[1] /= curve_length;
 
 6118             if ((scalevasu_usingmax && cross_section_length_max == 0) || (!scalevasu_usingmax && curve_length_per_cross_section_length_sum == 0))
 
 6121                 fallback_to_uniform_v = 
true;
 
 6123             else if (vstyle == UVStyle::FULL)
 
 6125                 if (scalevasu_usingmax)
 
 6126                     uvscale[1] /= cross_section_length_max;
 
 6136                 if (scalevasu_usingmax)
 
 6138                     if (curve_length == 0)
 
 6141                         fallback_to_uniform_v = 
true;
 
 6145                         double rounded = 
SYSrint(uvscale[1]*curve_length/cross_section_length_max);
 
 6148                         uvscale[1] = rounded/curve_length;
 
 6153                     UT_ASSERT(curve_length_per_cross_section_length_sum != 0);
 
 6154                     double rounded = 
SYSrint(uvscale[1]*curve_length_per_cross_section_length_sum);
 
 6157                     uvscale[1] = rounded/curve_length_per_cross_section_length_sum;
 
 6162     else if (ustyle == UVStyle::FULL)
 
 6166         uvscale[0] *= cross_section_length_avg;
 
 6168         if (vstyle == UVStyle::NORMALIZED)
 
 6171             if (curve_length == 0)
 
 6173                 fallback_to_uniform_v = 
true;
 
 6177                 uvscale[0] /= curve_length;
 
 6178                 uvscale[1] /= curve_length;
 
 6181         else if (vstyle == UVStyle::FULL)
 
 6190             if (curve_length == 0)
 
 6193                 fallback_to_uniform_v = 
true;
 
 6197                 double old_vscale = uvscale[1];
 
 6198                 double rounded = 
SYSrint(old_vscale*curve_length);
 
 6201                 uvscale[1] = rounded/curve_length;
 
 6202                 uvscale[0] *= (uvscale[1]/old_vscale);
 
 6215         if (vstyle == UVStyle::NORMALIZED)
 
 6217             if (curve_length == 0)
 
 6219                 double rounded = 
SYSrint(cross_section_length_avg*uvscale[0]);
 
 6222                 uvscale[0] = rounded;
 
 6223                 fallback_to_uniform_v = 
true;
 
 6227                 double rounded = 
SYSrint(cross_section_length_avg*uvscale[0]/curve_length);
 
 6230                 uvscale[0] = rounded;
 
 6231                 uvscale[1] /= curve_length;
 
 6236             const double old_uscale = cross_section_length_avg*uvscale[0];
 
 6237             uvscale[0] = 
SYSrint(old_uscale);
 
 6241             if (vstyle == UVStyle::FULL)
 
 6243                 if (old_uscale != 0)
 
 6244                     uvscale[1] *= (uvscale[0]/old_uscale);
 
 6249                 if (curve_length == 0)
 
 6252                     fallback_to_uniform_v = 
true;
 
 6256                     double rounded = 
SYSrint(curve_length*uvscale[1]);
 
 6259                     uvscale[1] = rounded/curve_length;
 
 6268 template<GA_AttributeOwner output_owner>
 
 6270 copyUVAttribPairPtOrVtx(
 
 6276     const sop_SweepGrid *grids,
 
 6278     const exint cross_sections_per_vertex,
 
 6280     const bool output_points_only,
 
 6281     const bool triangular_poles,
 
 6282     const exint cap_divisions,
 
 6283     const bool reverse_cross_sections,
 
 6284     const bool swap_row_col,
 
 6286     const bool length_weighted_uvs,
 
 6289     const bool use_mesh_edge_lengths,
 
 6290     const bool scalevasu_usingmax,
 
 6294     const exint PARALLEL_THRESHOLD = 2048;
 
 6295     const bool parallel = (ngrids > 1 &&
 
 6305     const bool is_cross_section_uv_computed = cross_section_attrib == 
nullptr || cross_section_attrib->
isDetached();
 
 6308     UT_ASSERT((cross_section_attrib != 
nullptr) != (missing_input_us != 
nullptr));
 
 6316             const sop_SweepGrid &grid_info = grids[gridi];
 
 6318             initGUGrid(grid_info, surface_type, output_points_only, triangular_poles, swap_row_col, grid_info.myStartPtOff, grid);
 
 6320             bool fallback_to_uniform_v = 
false;
 
 6322             if (length_weighted_uvs && (is_cross_section_uv_computed || curve_attrib == 
nullptr))
 
 6325                 grid_uvscale = computeGridUVScales(
 
 6327                     cross_section_input,
 
 6331                     cross_sections_per_vertex,
 
 6334                     use_mesh_edge_lengths,
 
 6337                     fallback_to_uniform_v);
 
 6340             UT_ASSERT((cross_section_attrib != 
nullptr) != (missing_input_us != 
nullptr));
 
 6343                 copyCrossSectionUVSingleGrid<fpreal64,output_owner>(
 
 6344                     output_attrib, cross_section_attrib, cross_section_owner, cross_section_input,
 
 6345                     grid_info, grid, is_cross_section_uv_computed,
 
 6346                     reverse_cross_sections, swap_row_col, flipu, grid_uvscale[0],
 
 6351                 copyCrossSectionUVSingleGrid<fpreal32,output_owner>(
 
 6352                     output_attrib, cross_section_attrib, cross_section_owner, cross_section_input,
 
 6353                     grid_info, grid, is_cross_section_uv_computed,
 
 6354                     reverse_cross_sections, swap_row_col, flipu, grid_uvscale[0],
 
 6358             if (curve_attrib == 
nullptr)
 
 6367                     if (length_weighted_uvs && !fallback_to_uniform_v)
 
 6368                         generateLengthWeightedV<output_owner>(grid_info, grid, cross_sections_per_vertex, outputh, pos, ustyle, vstyle,
 
 6369                             scalevasu_usingmax, grid_uvscale[1], uvscale[1], swap_row_col, use_mesh_edge_lengths, curve_input);
 
 6371                         generateUniformV<output_owner>(grid_info, grid, outputh, swap_row_col, grid_uvscale[1]);
 
 6377                     if (length_weighted_uvs && !fallback_to_uniform_v)
 
 6378                         generateLengthWeightedV<output_owner>(grid_info, grid, cross_sections_per_vertex, outputh, pos, ustyle, vstyle,
 
 6379                             scalevasu_usingmax, 
float(grid_uvscale[1]), 
float(uvscale[1]), swap_row_col, use_mesh_edge_lengths, curve_input);
 
 6381                         generateUniformV<output_owner>(grid_info, grid, outputh, swap_row_col, 
float(grid_uvscale[1]));
 
 6391         functor(grid_range);
 
 6401                 outputh.
set(output_off, theVComponent, 
GAisValid(curve_off) ? curveh.get(curve_off) : 1.0);
 
 6403             copyCurveAttrib2<output_owner,true>(
 
 6404                 output_attrib, curve_input,
 
 6405                 grids, ngrids, cross_sections_per_vertex,
 
 6406                 surface_type, output_points_only, triangular_poles, cap_divisions,
 
 6407                 swap_row_col, copy_functor);
 
 6415                 outputh.
set(output_off, theVComponent, 
GAisValid(curve_off) ? curveh.get(curve_off) : 1.0f);
 
 6417             copyCurveAttrib2<output_owner,true>(
 
 6418                 output_attrib, curve_input,
 
 6419                 grids, ngrids, cross_sections_per_vertex,
 
 6420                 surface_type, output_points_only, triangular_poles, cap_divisions,
 
 6421                 swap_row_col, copy_functor);
 
 6432             auto &©_functor = [&outputh,&curveh,curve_input](
GA_Offset output_off, 
GA_Offset curve_vtxoff)
 
 6438                     value = curveh.get(curve_off);
 
 6442                 outputh.
set(output_off, theVComponent, value);
 
 6444             copyCurveAttrib2<output_owner,true>(
 
 6445                 output_attrib, curve_input,
 
 6446                 grids, ngrids, cross_sections_per_vertex,
 
 6447                 surface_type, output_points_only, triangular_poles, cap_divisions,
 
 6448                 swap_row_col, copy_functor);
 
 6454             auto &©_functor = [&outputh,&curveh,curve_input](
GA_Offset output_off, 
GA_Offset curve_vtxoff)
 
 6460                     value = curveh.get(curve_off);
 
 6464                 outputh.
set(output_off, theVComponent, value);
 
 6466             copyCurveAttrib2<output_owner,true>(
 
 6467                 output_attrib, curve_input,
 
 6468                 grids, ngrids, cross_sections_per_vertex,
 
 6469                 surface_type, output_points_only, triangular_poles, cap_divisions,
 
 6470                 swap_row_col, copy_functor);
 
 6482     const sop_SweepGrid *grids,
 
 6484     const exint cross_sections_per_vertex,
 
 6486     const bool output_points_only,
 
 6487     const bool triangular_poles,
 
 6488     const exint cap_divisions,
 
 6489     const bool reverse_cross_sections,
 
 6490     const bool swap_row_col,
 
 6492     const bool length_weighted_uvs,
 
 6495     const bool use_mesh_edge_lengths,
 
 6496     const bool scalevasu_usingmax,
 
 6523         copyUVAttribPairPtOrVtx<GA_ATTRIB_POINT>(
 
 6525             cross_section_attrib,
 
 6526             cross_section_input,
 
 6530             cross_sections_per_vertex,
 
 6535             reverse_cross_sections,
 
 6538             length_weighted_uvs,
 
 6540             use_mesh_edge_lengths,
 
 6547     if (output_points_only)
 
 6554         copyUVAttribPairPtOrVtx<GA_ATTRIB_VERTEX>(
 
 6556             cross_section_attrib,
 
 6557             cross_section_input,
 
 6561             cross_sections_per_vertex,
 
 6566             reverse_cross_sections,
 
 6569             length_weighted_uvs,
 
 6571             use_mesh_edge_lengths,
 
 6583         const exint PARALLEL_THRESHOLD = 2048;
 
 6584         const bool parallel = (ngrids > 1 &&
 
 6606                     const sop_SweepGrid &grid_info = grids[gridi];
 
 6608                     initGUGrid(grid_info, surface_type, output_points_only, triangular_poles, swap_row_col, grid_info.myStartPtOff, grid);
 
 6610                     copyCrossSectionUVSingleGrid<fpreal64,GA_ATTRIB_PRIMITIVE>(
 
 6612                         grid_info, grid, 
false,
 
 6613                         reverse_cross_sections, swap_row_col, flipu, uvscale[0]);
 
 6615                     if (curveh.isValid() && outputh.
isValid() && outputh.getTupleSize() >= 2)
 
 6617                         const double v = curveh.get(grid_info.myCurvePrimOff);
 
 6622                             outputh.
set(grid_info.myStartPrimOff + primnum, theVComponent, v);
 
 6633                     const sop_SweepGrid &grid_info = grids[gridi];
 
 6635                     initGUGrid(grid_info, surface_type, output_points_only, triangular_poles, swap_row_col, grid_info.myStartPtOff, grid);
 
 6637                     copyCrossSectionUVSingleGrid<fpreal32,GA_ATTRIB_PRIMITIVE>(
 
 6639                         grid_info, grid, 
false,
 
 6640                         reverse_cross_sections, swap_row_col, flipu, uvscale[0]);
 
 6642                     if (curveh.isValid() && outputh.
isValid() && outputh.getTupleSize() >= 2)
 
 6644                         const float v = curveh.get(grid_info.myCurvePrimOff);
 
 6649                             outputh.
set(grid_info.myStartPrimOff + primnum, theVComponent, v);
 
 6660             functor(grid_range);
 
 6669         case SurfaceType::ROWS:
 
 6671         case SurfaceType::COLS:
 
 6673         case SurfaceType::ROWCOL:
 
 6675         case SurfaceType::QUADS:
 
 6677         case SurfaceType::TRIS:
 
 6679         case SurfaceType::REVTRIS:
 
 6681         case SurfaceType::ALTTRIS:
 
 6684         case SurfaceType::POINTS:
 
 6691 copySurfaceAttributes(
 
 6696     const exint cross_sections_per_vertex,
 
 6697     const UT_Array<std::pair<const GA_Attribute*,GA_Attribute*>> &cross_section_attribs,
 
 6698     const UT_Array<std::pair<const GA_Attribute*,GA_Attribute*>> &curve_attribs,
 
 6699     const UT_Array<std::pair<std::pair<const GA_ATINumeric*,const GA_ATINumeric*>,
GA_ATINumeric*>> &uv_attribs,
 
 6700     const SOP_SweepHDKCache *
const transform_cache,
 
 6702     const bool output_points_only,
 
 6703     const bool triangular_poles,
 
 6704     const exint cap_divisions,
 
 6705     const bool reverse_cross_sections,
 
 6706     const bool swap_row_col,
 
 6707     const exint uv_attrib_index,
 
 6709     const bool length_weighted_uvs,
 
 6712     const bool use_mesh_edge_lengths,
 
 6713     const bool scalevasu_usingmax,
 
 6718     if (interrupt.wasInterrupted())
 
 6722     for (
exint attribi = 0; attribi < cross_section_attribs.size(); ++attribi)
 
 6724         if (interrupt.wasInterrupted())
 
 6727         const GA_Attribute *cross_section_attrib = cross_section_attribs[attribi].first;
 
 6728         GA_Attribute *output_attrib = cross_section_attribs[attribi].second;
 
 6729         copyCrossSectionAttrib(
 
 6731             cross_section_attrib,
 
 6732             cross_section_input,
 
 6735             cross_sections_per_vertex, cap_divisions,
 
 6736             surface_type, output_points_only, triangular_poles,
 
 6737             reverse_cross_sections, swap_row_col);
 
 6741     for (
exint attribi = 0; attribi < curve_attribs.size(); ++attribi)
 
 6743         if (interrupt.wasInterrupted())
 
 6746         const GA_Attribute *curve_attrib = curve_attribs[attribi].first;
 
 6747         GA_Attribute *output_attrib = curve_attribs[attribi].second;
 
 6753             cross_sections_per_vertex,
 
 6754             surface_type, output_points_only, triangular_poles,
 
 6755             cap_divisions, swap_row_col);
 
 6759     for (
exint attribi = 0; attribi < uv_attribs.size(); ++attribi)
 
 6761         if (interrupt.wasInterrupted())
 
 6764         const GA_ATINumeric *cross_section_attrib = uv_attribs[attribi].first.first;
 
 6765         const GA_ATINumeric *curve_attrib = uv_attribs[attribi].first.second;
 
 6769             cross_section_attrib,
 
 6770             cross_section_input,
 
 6774             cross_sections_per_vertex,
 
 6775             surface_type, output_points_only, triangular_poles,
 
 6777             reverse_cross_sections, swap_row_col,
 
 6778             (uv_attrib_index == attribi) ? missing_input_us : 
nullptr,
 
 6779             length_weighted_uvs,
 
 6781             use_mesh_edge_lengths,
 
 6783             (uv_attrib_index == attribi) && flipu,
 
 6790 static void setupCrossSectionAttribs(
 
 6791     SOP_SweepHDKCache *sopcache,
 
 6793     const SOP_SweepHDKParms &sopparms,
 
 6794     bool &same_cross_section_data,
 
 6800     UT_ASSERT_MSG(cross_section_input && curve_input, 
"Copy order only makes sense if both inputs are present.");
 
 6802     CrossSectionAttribMatchData ©_order_attrib_data = sopcache->myCrossSectionAttribMatchData;
 
 6807     const UT_StringHolder &cross_section_attrib_name = sopparms.getCrossSectionAttrib();
 
 6818     bool string_missing_error_case = 
false;
 
 6822         same_cross_section_data &= (sopcache->myPrevCrossSectCurveAttribDataId == new_curve_data_id);
 
 6823         sopcache->myPrevCrossSectCurveAttribDataId = new_curve_data_id;
 
 6825         copy_order_attrib_data.myCurveAttribOwner = curve_attrib->
getOwner();
 
 6829         copy_order_attrib_data.myCurveIntAttrib.bind(curve_attrib);
 
 6830         if (!copy_order_attrib_data.myCurveIntAttrib.isValid()) {
 
 6831             copy_order_attrib_data.myCurveStrAttrib.bind(curve_attrib);
 
 6832             if (!copy_order_attrib_data.myCurveStrAttrib.isValid()) {
 
 6834                 curve_attrib = 
nullptr;
 
 6838                 if (!cross_section_name_attrib.isValid()) {
 
 6840                     curve_attrib = 
nullptr;
 
 6841                     copy_order_attrib_data.myCurveStrAttrib.clear();
 
 6842                     string_missing_error_case = 
true;
 
 6846                     const int64 new_cross_section_data_id = cross_section_name_attrib->getDataId();
 
 6847                     const bool same_map = (sopcache->myPrevCrossSectPrimAttribDataId == new_cross_section_data_id);
 
 6848                     same_cross_section_data &= same_map;
 
 6849                     sopcache->myPrevCrossSectPrimAttribDataId = new_cross_section_data_id;
 
 6850                     copy_order_attrib_data.myIsUsingMap = 
true;
 
 6855                         copy_order_attrib_data.myIntToPrimOff.destroy();
 
 6856                         copy_order_attrib_data.myStrToPrimOff.destroy();
 
 6862                             for (
GA_Offset primoff = start; primoff < 
end; ++primoff) {
 
 6874                                 copy_order_attrib_data.myStrToPrimOff.insert(name, primoff);
 
 6883             if (!cross_section_id_attrib.isValid()) {
 
 6885                 copy_order_attrib_data.myIsUsingMap = 
false;
 
 6886                 same_cross_section_data &= (sopcache->myPrevCrossSectPrimAttribDataId == -1);
 
 6887                 sopcache->myPrevCrossSectPrimAttribDataId = -1;
 
 6890                 copy_order_attrib_data.myIntToPrimOff.destroy();
 
 6891                 copy_order_attrib_data.myStrToPrimOff.destroy();
 
 6895                 copy_order_attrib_data.myIsUsingMap = 
true;
 
 6896                 const int64 new_cross_section_data_id = cross_section_id_attrib->getDataId();
 
 6897                 const bool same_map = (sopcache->myPrevCrossSectPrimAttribDataId == new_cross_section_data_id);
 
 6898                 same_cross_section_data &= same_map;
 
 6899                 sopcache->myPrevCrossSectPrimAttribDataId = new_cross_section_data_id;
 
 6904                     copy_order_attrib_data.myIntToPrimOff.destroy();
 
 6905                     copy_order_attrib_data.myStrToPrimOff.destroy();
 
 6911                         for (
GA_Offset primoff = start; primoff < 
end; ++primoff) {
 
 6912                             exint id = cross_section_id_attrib.get(primoff);
 
 6921                             copy_order_attrib_data.myIntToPrimOff.insert(
id, primoff);
 
 6928     if (!curve_attrib) {
 
 6931         if (!string_missing_error_case)
 
 6932             buf.
sprintf(
"Curve input geometry doesn't have an integer or string attribute named \"%s\" for selecting cross section primitives.", cross_section_attrib_name.
c_str());
 
 6934             buf.
sprintf(
"Cross section doesn't have a primitive string attribute named \"%s\" for selecting cross section primitives,", cross_section_attrib_name.
c_str());
 
 6938         copy_order = CopyOrder::CYCLEVTX;
 
 6939         same_cross_section_data = (sopcache->myPrevCopyOrder == copy_order);
 
 6940         sopcache->myPrevCrossSectCurveAttribDataId = -1;
 
 6941         sopcache->myPrevCrossSectPrimAttribDataId = -1;
 
 6942         copy_order_attrib_data.myIntToPrimOff.destroy();
 
 6943         copy_order_attrib_data.myStrToPrimOff.destroy();
 
 6948 static void removeUnnecessarySweepAttribs(
 
 6959             attribs_to_delete.
append(attrib);
 
 6961     for (
exint i = 0, n = attribs_to_delete.
size(); i < 
n; ++i)
 
 6970     attribs_to_delete.
clear();
 
 6974             attribs_to_delete.
append(attrib);
 
 6976     for (
exint i = 0, n = attribs_to_delete.
size(); i < 
n; ++i)
 
 6985     attribs_to_delete.
clear();
 
 6988         attribs_to_delete.
append(attrib);
 
 6990     for (
exint i = 0, n = attribs_to_delete.
size(); i < 
n; ++i)
 
 6999     attribs_to_delete.
clear();
 
 7002         attribs_to_delete.
append(attrib);
 
 7004     for (
exint i = 0, n = attribs_to_delete.
size(); i < 
n; ++i)
 
 7011         edge_groups_to_delete.
append(it.group());
 
 7013     for (
exint i = 0, n = edge_groups_to_delete.
size(); i < 
n; ++i)
 
 7019 static void setupSweepTransferAttribs(
 
 7025     UT_Array<std::pair<const GA_Attribute*,GA_Attribute*>> &cross_section_attribs,
 
 7026     UT_Array<std::pair<const GA_Attribute*,GA_Attribute*>> &curve_attribs,
 
 7027     UT_Array<std::pair<std::pair<const GA_ATINumeric*,const GA_ATINumeric*>,
GA_ATINumeric*>> &uv_attribs,
 
 7028     exint &uv_attrib_index,
 
 7029     const bool compute_uvs,
 
 7030     const bool override_existing_uvs)
 
 7037     UT_ASSERT(compute_uvs || !override_existing_uvs);
 
 7038     uv_attrib_index = -1;
 
 7044     if (cross_section_input)
 
 7050         auto &&clone_attrib_functor = [&cross_section_attribs,&uv_attribs,&uv_attrib_index,&
filter,output_geo,
 
 7051             curve_input,&curve_filter,override_existing_uvs,compute_uvs](
const GA_Attribute *attrib)
 
 7053             if (!filter.match(attrib))
 
 7060             const bool isuv = point_or_vertex &&
 
 7063             if ((compute_uvs && override_existing_uvs) && isuv)
 
 7079                         GA_Attribute *new_attribute = output_geo->getAttributes().cloneAttribute(
 
 7080                             output_owner, attrib->
getName(),
 
 7084                         uv_attribs.append(std::make_pair(
 
 7092                 if (isuv && compute_uvs)
 
 7096                     GA_Attribute *new_attribute = output_geo->getAttributes().cloneAttribute(
 
 7101                     uv_attrib_index = uv_attribs.size();
 
 7102                     uv_attribs.append(std::make_pair(
 
 7114                 new_attribute = output_geo->getAttributes().cloneAttribute(
 
 7122                     output_geo->getElementGroupTable(owner).newGroup(attrib->
getName()));
 
 7126                 cross_section_attribs.append(std::make_pair(attrib, new_attribute));
 
 7142         auto &&clone_attrib_functor = [&curve_attribs,&uv_attribs,&uv_attrib_index,&curve_filter,output_geo,
 
 7143             cross_section_input,override_existing_uvs,compute_uvs](
const GA_Attribute *attrib)
 
 7145             if (!curve_filter.match(attrib))
 
 7154             if (cross_section_input)
 
 7157                     output_geo->findAttribute(owner, attrib->
getScope(), attrib->
getName());
 
 7168                     old_attrib = output_geo->findAttribute(
 
 7177             const bool isuv = point_or_vertex &&
 
 7180             if ((compute_uvs && override_existing_uvs) && isuv)
 
 7188                 if (isuv && compute_uvs)
 
 7192                     GA_Attribute *new_attribute = output_geo->getAttributes().cloneAttribute(
 
 7197                     uv_attrib_index = uv_attribs.size();
 
 7198                     uv_attribs.append(std::make_pair(
 
 7209                 new_attribute = output_geo->getAttributes().cloneAttribute(
 
 7217                     output_geo->getElementGroupTable(owner).newGroup(attrib->
getName()));
 
 7221                 curve_attribs.append(std::make_pair(attrib, new_attribute));
 
 7231                 .forEachAttribute(clone_attrib_functor);
 
 7261         centre = 0.5*(p0+p1);
 
 7270                 UT_Vector3D new_normal = *out_normal - 
dot(*out_normal, diff)*diff;
 
 7273                     *out_normal = new_normal;
 
 7282     for (
exint i = 2; i < 
n; ++i)
 
 7291     covariance_matrix.
zero();
 
 7294     pdiff = p1 - pos_avg;
 
 7296     for (
exint i = 2; i < 
n; ++i)
 
 7299         pdiff = p - pos_avg;
 
 7302     const double row_length2s[] = {
 
 7303         covariance_matrix[0].length2(),
 
 7304         covariance_matrix[1].length2(),
 
 7305         covariance_matrix[2].length2()
 
 7307     const int maxrow = SYSargmax(
 
 7311     if (row_length2s[maxrow] == 0)
 
 7319     UT_Vector3D maxrow_vec = covariance_matrix[maxrow];
 
 7324     double maxrow_vec_eigen2 = (maxrow_vec*covariance_matrix).length2();
 
 7325     double other_dir0_eigen2 = (other_dir0*covariance_matrix).length2();
 
 7326     double other_dir1_eigen2 = (other_dir1*covariance_matrix).length2();
 
 7329     if (other_dir0_eigen2+other_dir1_eigen2 < 1e-8*maxrow_vec_eigen2)
 
 7331         pdiff = p0 - pos_avg;
 
 7332         double min_from_avg = pdiff.
dot(maxrow_vec);
 
 7333         double max_from_avg = min_from_avg;
 
 7334         pdiff = p1 - pos_avg;
 
 7335         double d = pdiff.
dot(maxrow_vec);
 
 7336         min_from_avg = 
SYSmin(min_from_avg, d);
 
 7337         max_from_avg = 
SYSmax(max_from_avg, d);
 
 7338         for (
exint i = 2; i < 
n; ++i)
 
 7341             pdiff = p - pos_avg;
 
 7342             d = pdiff.
dot(maxrow_vec);
 
 7343             min_from_avg = 
SYSmin(min_from_avg, d);
 
 7344             max_from_avg = 
SYSmax(max_from_avg, d);
 
 7347         radius = 0.5*(max_from_avg - min_from_avg);
 
 7348         centre = pos_avg + 0.5*(min_from_avg + max_from_avg);
 
 7351             UT_Vector3D new_normal = *out_normal - 
dot(*out_normal, maxrow_vec)*maxrow_vec;
 
 7354                 *out_normal = new_normal;
 
 7362     for (
exint i = 2; i < 
n; ++i)
 
 7365         normal += 
cross(pprev-p0, pnext-p0);
 
 7370     if (normal.length2() == 0)
 
 7375         double max_distance2 = 
distance2(centre, p0);
 
 7376         for (
exint i = 1; i < 
n; ++i)
 
 7381         radius = SYSsqrt(max_distance2);
 
 7386     double min_normal_dot = 0;
 
 7387     double max_normal_dot = 0;
 
 7388     for (
exint i = 1; i < 
n; ++i)
 
 7391         double dot = (p-p0).
dot(normal);
 
 7392         min_normal_dot = 
SYSmin(dot, min_normal_dot);
 
 7393         max_normal_dot = 
SYSmax(dot, max_normal_dot);
 
 7397     double mid_normal_dot = 0.5*(min_normal_dot+max_normal_dot);
 
 7403     tangent1 = 
cross(normal, tangent0);
 
 7409     for (
exint i = 1; i < 
n; ++i)
 
 7417     radius = SYSsqrt(radius2);
 
 7421     centre = p0 + (normal*mid_normal_dot + tangent0*centre2d[0] + tangent1*centre2d[1]);
 
 7427         if (out_normal->
dot(normal) < 0)
 
 7428             *out_normal = -normal;
 
 7430             *out_normal = normal;
 
 7435 sopPrescaleTranslate(
 
 7447         pret[0]*transform0[0][0] + pret[1]*transform0[1][0] + pret[2]*transform0[2][0] + transform0[3][0],
 
 7448         pret[0]*transform0[0][1] + pret[1]*transform0[1][1] + pret[2]*transform0[2][1] + transform0[3][1],
 
 7449         pret[0]*transform0[0][2] + pret[1]*transform0[1][2] + pret[2]*transform0[2][2] + transform0[3][2]
 
 7453         scale*transform0[0][0], scale*transform0[0][1], scale*transform0[0][2], scale*transform0[0][3],
 
 7454         scale*transform0[1][0], scale*transform0[1][1], scale*transform0[1][2], scale*transform0[1][3],
 
 7455         scale*transform0[2][0], scale*transform0[2][1], scale*transform0[2][2], scale*transform0[2][3],
 
 7456         t[0], t[1], t[2], 1.0
 
 7463     const exint cap_divisions,
 
 7471     scaled_z_dir = -scaled_z_dir;
 
 7481         ztranslate = scaled_z_dir;
 
 7485         const double scale_portion = double(capi)/double(cap_divisions);
 
 7486         const double ztranslate_portion = 1.0 - scale_portion;
 
 7492         const double theta = 
M_PI_2*ztranslate_portion;
 
 7493         const double scale_round = SYScos(theta);
 
 7494         const double ztranslate_round = SYSsin(theta);
 
 7501         const double scale_pointed = scale_portion;
 
 7502         const double ztranslate_pointed = ztranslate_portion;
 
 7505         double ztranslate_scalar;
 
 7508             scale = 
SYSlerp(scale_pointed, scale_round, roundness);
 
 7509             ztranslate_scalar = 
SYSlerp(ztranslate_pointed, ztranslate_round, roundness);
 
 7511         else if (roundness == 0)
 
 7513             scale = scale_pointed;
 
 7514             ztranslate_scalar = ztranslate_pointed;
 
 7524             scale = 
SYSlerp(scale_pointed, 1.0-ztranslate_round, -roundness);
 
 7525             ztranslate_scalar = 
SYSlerp(ztranslate_pointed, 1.0-scale_round, -roundness);
 
 7527         ztranslate = ztranslate_scalar*scaled_z_dir;
 
 7529     return sopPrescaleTranslate(scale, centre, ztranslate, transform0);
 
 7533 sopAllEndCapTransforms(
 
 7534     const sop_SweepGrid &grid,
 
 7535     const SOP_SweepHDKParms &sopparms,
 
 7539     const exint num_vertices,
 
 7542     bool use_cross_section_normal_for_z)
 
 7544     const exint cap_divisions = sopparms.getCapDivs();
 
 7555     if (grid.mySingleCrossSection && !
GAisValid(grid.myCrossSectionPrimOff))
 
 7563     else if (grid.mySingleCrossSection)
 
 7570         sopBoundingTube(cross_section_input, primoff, radius, centre,
 
 7571             use_cross_section_normal_for_z ? &normal : 
nullptr);
 
 7574         centres[0] = centre;
 
 7575         centres[1] = centre;
 
 7576         if (use_cross_section_normal_for_z)
 
 7578             normals[0] = normal;
 
 7579             normals[1] = normal;
 
 7584         GA_Offset primoff0 = (*grid.myCrossSectionPrimOffs)[0];
 
 7585         GA_Offset primoff1 = grid.myCrossSectionPrimOffs->last();
 
 7587         if (use_cross_section_normal_for_z && grid.myCrossSectionPrimOffs->size() >= 2*cap_divisions+1)
 
 7592             sopBoundingTube(cross_section_input, primoff0, radius, centreA, 
nullptr);
 
 7593             sopBoundingTube(cross_section_input, (*grid.myCrossSectionPrimOffs)[cap_divisions+1], radius, centreB, 
nullptr);
 
 7594             normals[0] = centreA-centreB;
 
 7596             sopBoundingTube(cross_section_input, primoff1, radius, centreA, 
nullptr);
 
 7597             sopBoundingTube(cross_section_input, (*grid.myCrossSectionPrimOffs)[grid.myCrossSectionPrimOffs->size()-2-cap_divisions], radius, centreB, 
nullptr);
 
 7598             normals[1] = centreB-centreA;
 
 7601         sopBoundingTube(cross_section_input, primoff0, radii[0], centres[0],
 
 7602             use_cross_section_normal_for_z ? &normals[0] : 
nullptr);
 
 7603         sopBoundingTube(cross_section_input, primoff1, radii[1], centres[1],
 
 7604             use_cross_section_normal_for_z ? &normals[1] : 
nullptr);
 
 7606     if (use_cross_section_normal_for_z)
 
 7616     const double cap_scale = sopparms.getCapScale();
 
 7617     const double cap_roundness = sopparms.getCapRoundness();
 
 7620     for (
exint i = 0; i < cap_divisions; ++i)
 
 7622         const exint row = i;
 
 7625             centres[0], (cap_scale*radii[0])*normals[0],
 
 7626             cap_roundness, transform0);
 
 7633     for (
exint i = 0; i < cap_divisions; ++i)
 
 7637         const exint row = cap_divisions+num_vertices+i;
 
 7639             cap_divisions-1-i, cap_divisions,
 
 7640             centres[1], (-cap_scale*radii[1])*normals[1],
 
 7641             cap_roundness, transform1);
 
 7649 void SOP_SweepHDKVerb::cook(
const CookParms &cookparms)
 const 
 7668     using namespace GU_Copy;
 
 7677     auto &&sopparms = cookparms.
parms<SOP_SweepHDKParms>();
 
 7684     const GU_Detail *
const cross_section_input =
 
 7685         (sopparms.getSurfaceShape() == SurfaceShape::INPUT)
 
 7686             ? cookparms.
inputGeo(theCrossSectionInput)
 
 7691     if (!cookparms.
inputGeo(theCrossSectionInput) && !curve_input)
 
 7694         output_geo->clearAndDestroy();
 
 7698     if (!cross_section_input && (sopparms.getSurfaceShape() == SurfaceShape::INPUT))
 
 7701         output_geo->clearAndDestroy();
 
 7704     if (!curve_input && (sopparms.getSurfaceShape() != SurfaceShape::INPUT))
 
 7707         output_geo->clearAndDestroy();
 
 7718         if (sopparms.getCurveGroup().isstring())
 
 7720             curve_group = group_manager.parsePrimitiveGroups(
 
 7721                 sopparms.getCurveGroup(),
 
 7724         if (curve_group == 
nullptr)
 
 7726             curve_group_list = curve_input->getPrimitiveMap().getOffsetFromIndexList();
 
 7734                 curve_group_list.setTrivialRange(curve_group_list.size(), start, end-start);
 
 7740     if (cross_section_input)
 
 7742         if (sopparms.getCrossSectionGroup().isstring())
 
 7744             cross_section_group = group_manager.parsePrimitiveGroups(
 
 7745                 sopparms.getCrossSectionGroup(),
 
 7748         if (cross_section_group == 
nullptr)
 
 7758                 cross_section_group_list.setTrivialRange(cross_section_group_list.size(), start, end-start);
 
 7771     CopyOrder copy_order = (cross_section_input && curve_input) ? sopparms.getCopyOrder() : CopyOrder::CYCLEVTX;
 
 7772     bool same_cross_section_data = (sopcache->myPrevCopyOrder == copy_order);
 
 7776         setupCrossSectionAttribs(
 
 7777             sopcache, cookparms, sopparms,
 
 7778             same_cross_section_data, copy_order,
 
 7779             cross_section_input, curve_input,
 
 7780             cross_section_group);
 
 7786     removeUnnecessarySweepAttribs(output_geo);
 
 7793     bool need_to_build_surface = 
true;
 
 7795     const bool same_output_geo_as_last_cook =
 
 7796         (output_geo->getUniqueId() == sopcache->myPrevOutputDetailID);
 
 7797     int64 new_curve_prim_list_data_id = (curve_input ? curve_input->getPrimitiveList().getDataId() : -1);
 
 7798     int64 new_curve_topology_data_id = (curve_input ? curve_input->getTopology().getDataId() : -1);
 
 7799     if (same_output_geo_as_last_cook)
 
 7801         const bool same_input_curves =
 
 7802             (new_curve_prim_list_data_id == sopcache->myPrevCurvePrimListDataID) &&
 
 7803             (new_curve_topology_data_id == sopcache->myPrevCurveTopologyDataID) &&
 
 7804             (curve_group_list.size() == sopcache->myPrevCurveGroup.size()) &&
 
 7805             (curve_group_list.isEqual(sopcache->myPrevCurveGroup, 0, curve_group_list.size()));
 
 7807         bool same_surface_parms =
 
 7808             (sopparms.getSurfaceType() == sopcache->myPrevSurfaceType) &&
 
 7809             (sopparms.getUnrollClosedRowCol() == sopcache->myPrevUnrollClosedRowCol) &&
 
 7810             (sopparms.getPrimType() == sopcache->myPrevPrimType) &&
 
 7811             (sopparms.getEndCapType() == sopcache->myPrevEndCapType) &&
 
 7812             (sopparms.getCapDivs() == sopcache->myPrevEndCapDivs) &&
 
 7813             (sopparms.getTriangularPoles() == sopcache->myPrevTriangularPoles) &&
 
 7814             (sopparms.getSwapRowCol() == sopcache->myPrevSwapRowCol);
 
 7815         if (same_surface_parms)
 
 7817             if (cross_section_input && sopcache->myPrevSurfaceShape == SurfaceShape::INPUT)
 
 7819                 same_surface_parms =
 
 7820                     (sopcache->myPrevSurfaceShape == SurfaceShape::INPUT) &&
 
 7821                     (sopcache->myPrevCloseIfNoCurveInput == sopparms.getCloseIfNoCurveInput()) &&
 
 7822                     same_cross_section_data &&
 
 7824                     (cross_section_input->
getTopology().
getDataId() == sopcache->myPrevCrossSectionTopologyDataID) &&
 
 7825                     (cross_section_group_list.size() == sopcache->myPrevCrossSectionGroup.size()) &&
 
 7826                     (cross_section_group_list.isEqual(sopcache->myPrevCrossSectionGroup, 0, cross_section_group_list.size()));
 
 7830                 same_surface_parms =
 
 7831                     (sopparms.getSurfaceShape() == sopcache->myPrevSurfaceShape) &&
 
 7832                     (sopparms.getCols() == sopcache->myPrevCols);
 
 7839         if (same_input_curves && same_surface_parms)
 
 7840             need_to_build_surface = 
false;
 
 7843     sopcache->myPrevOutputDetailID = output_geo->getUniqueId();
 
 7844     sopcache->myPrevCurvePrimListDataID = new_curve_prim_list_data_id;
 
 7845     sopcache->myPrevCurveTopologyDataID = new_curve_topology_data_id;
 
 7846     sopcache->myPrevCurveGroup = std::move(curve_group_list);
 
 7847     sopcache->myPrevSurfaceType = sopparms.getSurfaceType();
 
 7848     sopcache->myPrevUnrollClosedRowCol = sopparms.getUnrollClosedRowCol();
 
 7849     sopcache->myPrevPrimType = sopparms.getPrimType();
 
 7850     sopcache->myPrevCloseIfNoCurveInput = sopparms.getCloseIfNoCurveInput();
 
 7851     sopcache->myPrevSurfaceShape = sopparms.getSurfaceShape();
 
 7852     sopcache->myPrevCols = (cross_section_input && sopcache->myPrevSurfaceShape == SurfaceShape::INPUT) ? -1 : sopparms.getCols();
 
 7853     sopcache->myPrevEndCapType = sopparms.getEndCapType();
 
 7854     sopcache->myPrevEndCapDivs = sopparms.getCapDivs();
 
 7855     sopcache->myPrevTriangularPoles = sopparms.getTriangularPoles();
 
 7856     sopcache->myPrevSwapRowCol = sopparms.getSwapRowCol();
 
 7857     sopcache->myPrevCrossSectionPrimListDataID = cross_section_input ? cross_section_input->
getPrimitiveList().
getDataId() : -1;
 
 7858     sopcache->myPrevCrossSectionTopologyDataID = cross_section_input ? cross_section_input->
getTopology().
getDataId() : -1;
 
 7859     sopcache->myPrevCrossSectionGroup = std::move(cross_section_group_list);
 
 7860     sopcache->myPrevCopyOrder = copy_order;
 
 7863     const CrossSectionAttribMatchData *copy_order_attrib_data = (copy_order == 
CopyOrder::ATTRIB) ? &sopcache->myCrossSectionAttribMatchData : 
nullptr;
 
 7865     GEO_SurfaceType surface_type = sweepSurfaceToGeoSurface(sopparms.getSurfaceType());
 
 7866     bool output_points_only = (sopparms.getSurfaceType() == SurfaceType::POINTS);
 
 7867     exint cap_divisions =
 
 7868         (sopparms.getEndCapType() == 
EndCapType::NONE || sopparms.getEndCapType() == EndCapType::SINGLE || sopparms.getEndCapType() == EndCapType::SIDESINGLE) ? 0 : sopparms.getCapDivs();
 
 7870     if (need_to_build_surface)
 
 7872         bool finished = createGrids(
 
 7873             cross_section_input, cross_section_group,
 
 7874             sopparms.getSurfaceShape(),
 
 7875             sopparms.getCols() * ((sopparms.getSurfaceShape() == SurfaceShape::SQUARE) ? 4 : 1),
 
 7876             copy_order, copy_order_attrib_data,
 
 7877             curve_input, curve_group,
 
 7878             sopparms.getCloseIfNoCurveInput(),
 
 7879             surface_type, output_points_only, sopparms.getUnrollClosedRowCol(),
 
 7880             sopParmToPrimType(sopparms.getPrimType()),
 
 7881             sopparms.getEndCapType(), cap_divisions,
 
 7882             sopparms.getTriangularPoles(),
 
 7883             sopparms.getSwapRowCol(),
 
 7898     exint uv_attrib_index = -1;
 
 7900     setupSweepTransferAttribs(output_geo,
 
 7901         cross_section_input, sopparms.getAttribsFromCrossSection(),
 
 7902         curve_input, sopparms.getAttribsFromBackbone(),
 
 7903         cross_section_attribs,
 
 7907         sopparms.getComputeUVs(),
 
 7908         sopparms.getComputeUVs() && sopparms.getOverrideExistingUVs());
 
 7920     if (sopparms.getComputeUVs())
 
 7922         if (cross_section_input)
 
 7925             if (!sopparms.getOverrideExistingUVs())
 
 7928                 if (!input_uv_attrib.
isValid())
 
 7933             if (!input_uv_attrib.
isValid() || sopparms.getOverrideExistingUVs())
 
 7937                 detached_cross_section_uv =
 
 7940                 rw_uv_attrib.
bind(detached_cross_section_uv.get());
 
 7946                 computeCurveUVs(cross_section_input, cross_section_group, rw_uv_attrib, sopparms.getLengthWeightedUVs(), sopparms.getReverseCrossSections());
 
 7948                 if (uv_attrib_index >= 0)
 
 7951                     uv_attribs[uv_attrib_index].first.first = rw_uv_attrib.
getAttribute();
 
 7958                     uv_attrib_index = uv_attribs.size();
 
 7959                     uv_attribs.append(std::make_pair(std::make_pair(rw_uv_attrib.
getAttribute(), (
const GA_ATINumeric*)
nullptr), output_attrib));
 
 7966             exint nedgecols = sopparms.getCols();
 
 7967             if (sopparms.getSurfaceShape() == SurfaceShape::SQUARE)
 
 7969             bool closed = (sopparms.getSurfaceShape() == SurfaceShape::TUBE || sopparms.getSurfaceShape() == SurfaceShape::SQUARE);
 
 7970             exint nvertices = nedgecols + !closed;
 
 7972             for (
exint i = 0; i < nvertices; ++i)
 
 7974                 missing_input_us[i] = double(i)/double(nedgecols);
 
 7977             if (uv_attrib_index < 0)
 
 7984                 uv_attrib_index = uv_attribs.size();
 
 7985                 uv_attribs.append(std::make_pair(std::make_pair((
const GA_ATINumeric*)
nullptr, (
const GA_ATINumeric*)
nullptr), output_attrib));
 
 7995             if (!sopparms.getOverrideExistingUVs())
 
 7998                 if (!input_uv_attrib.
isValid())
 
 8003             if (!input_uv_attrib.
isValid() || sopparms.getOverrideExistingUVs())
 
 8008                 curve_uv_deleter.reset(detached_uv_attrib);
 
 8009                 rw_uv_attrib.
bind(detached_uv_attrib);
 
 8015                 computeCurveUVs(curve_input, curve_group, rw_uv_attrib, sopparms.getLengthWeightedUVs());
 
 8017                 if (uv_attrib_index >= 0)
 
 8020                     uv_attribs[uv_attrib_index].first.second = rw_uv_attrib.
getAttribute();
 
 8026                     uv_attrib_index = uv_attribs.size();
 
 8027                     uv_attribs.append(std::make_pair(std::make_pair((
const GA_ATINumeric*)
nullptr, rw_uv_attrib.
getAttribute()), output_attrib));
 
 8035             bool closed = sopparms.getCloseIfNoCurveInput();
 
 8036             exint nedgecols = num_cross_sections - !closed;
 
 8038             bool length_weighted_uvs = sopparms.getLengthWeightedUVs();
 
 8039             if (length_weighted_uvs)
 
 8047                 exint cross_section_i = 0;
 
 8048                 double total_distance = 0;
 
 8049                 for (; !cross_section_it.
atEnd(); ++cross_section_it)
 
 8055                     for (
exint i = 0; i < 
n; ++i)
 
 8058                         centroid += pos_attrib.get(ptoff);
 
 8063                     if (cross_section_i == 0)
 
 8065                         first_centroid = centroid;
 
 8072                     missing_input_us[cross_section_i] = total_distance;
 
 8075                     prev_centroid = centroid;
 
 8080                     double distance = first_centroid.distance(prev_centroid);
 
 8084                 if (total_distance == 0)
 
 8087                     length_weighted_uvs = 
false;
 
 8091                     for (
exint i = 0, n = missing_input_us.
size(); i < 
n; ++i)
 
 8093                         missing_input_us[i] /= total_distance;
 
 8099             if (!length_weighted_uvs)
 
 8102                 for (
exint i = 0; i < num_cross_sections; ++i)
 
 8104                     missing_input_us[i] = double(i)/double(nedgecols);
 
 8111     const bool computing_uvs = (uv_attrib_index >= 0);
 
 8119     exint total_transforms = 0;
 
 8120     if (curve_input != 
nullptr)
 
 8128             curve_input->createDetachedTupleAttribute(
 
 8130         GA_RWHandleM4D transform_attrib(detached_transform_attrib.get());
 
 8135         parms.myExtrapolateEndTangents = sopparms.getExtrapolateEndTangents();
 
 8136         parms.myTransformByInstanceAttribs = sopparms.getTransformByAttribs();
 
 8140         const bool applypitch = sopparms.getApplyPitch();
 
 8141         const bool applyyaw = sopparms.getApplyYaw();
 
 8142         const bool applyroll = sopparms.getApplyRoll();
 
 8144             applypitch ? SYSdegToRad(sopparms.getPitch()) : 0.0,
 
 8145             applyyaw   ? SYSdegToRad(sopparms.getYaw())   : 0.0,
 
 8146             applyroll  ? SYSdegToRad(sopparms.getRoll())  : 0.0);
 
 8147         parms.myAngles = angles;
 
 8149             applypitch ? SYSdegToRad(sopparms.getIncPitch()) : 0.0,
 
 8150             applyyaw   ? SYSdegToRad(sopparms.getIncYaw())   : 0.0,
 
 8151             applyroll  ? SYSdegToRad(sopparms.getIncRoll() + 360.0*sopparms.getFullTwists())  : 0.0);
 
 8152         parms.myIncAngles = incangles;
 
 8164             parms.myRotAttribs[0].bind(curve_input->findAttribute(sopparms.getPitchAttrib(), search_order, 4));
 
 8166             parms.myRotAttribs[1].bind(curve_input->findAttribute(sopparms.getYawAttrib(), search_order, 4));
 
 8168             parms.myRotAttribs[2].bind(curve_input->findAttribute(sopparms.getRollAttrib(), search_order, 4));
 
 8172         switch (sopparms.getUpVectorType())
 
 8180                 parms.myTargetUpVectorAttrib.bind(curve_input, GA_ATTRIB_PRIMITIVE, sopparms.getUpVectorAttrib());
 
 8181                 if (!parms.myTargetUpVectorAttrib.isValid())
 
 8183                     parms.myTargetUpVectorAttrib.bind(curve_input, 
GA_ATTRIB_DETAIL, sopparms.getUpVectorAttrib());
 
 8185                 if (parms.myTargetUpVectorAttrib.isValid() && parms.myTargetUpVectorAttrib->getOwner() == 
GA_ATTRIB_DETAIL)
 
 8188                     parms.myTargetUpVector = parms.myTargetUpVectorAttrib.get(
GA_DETAIL_OFFSET);
 
 8189                     parms.myTargetUpVectorAttrib.clear();
 
 8193                     if (!parms.myTargetUpVectorAttrib.isValid())
 
 8201             case UpVectorType::CUSTOM: parms.myTargetUpVector = sopparms.getUpVector(); 
break;
 
 8203         parms.myUseCurveNormalAsTargetUp = (sopparms.getUpVectorType() == UpVectorType::NORMAL);
 
 8204         parms.myTargetUpVectorAtStart = sopparms.getUpVectorAtStart();
 
 8205         parms.myContinuousClosedCurves = sopparms.getContinuousClosed();
 
 8207         if (parms.myTargetUpVectorAtStart && sopparms.getUseEndUpVector())
 
 8209             parms.myUseEndTargetUpVector = 
true;
 
 8212                 parms.myEndTargetUpVectorAttrib.bind(curve_input, GA_ATTRIB_PRIMITIVE, sopparms.getEndUpVectorAttrib());
 
 8213                 if (!parms.myEndTargetUpVectorAttrib.isValid())
 
 8215                     parms.myEndTargetUpVectorAttrib.bind(curve_input, 
GA_ATTRIB_DETAIL, sopparms.getEndUpVectorAttrib());
 
 8217                 if (parms.myEndTargetUpVectorAttrib.isValid() && parms.myEndTargetUpVectorAttrib->getOwner() == 
GA_ATTRIB_DETAIL)
 
 8220                     parms.myEndTargetUpVector = parms.myEndTargetUpVectorAttrib.get(
GA_DETAIL_OFFSET);
 
 8221                     parms.myEndTargetUpVectorAttrib.clear();
 
 8225                     if (!parms.myEndTargetUpVectorAttrib.isValid())
 
 8227                         cookparms.
sopAddWarning(
SOP_MESSAGE, 
"End target up vector attribute not found; defaulting to no end target up vector.");
 
 8228                         parms.myUseEndTargetUpVector = 
false;
 
 8233             else if (sopparms.getUpVectorType() == UpVectorType::CUSTOM)
 
 8235                 parms.myEndTargetUpVector = sopparms.getEndUpVector();
 
 8239                 parms.myEndTargetUpVector = parms.myTargetUpVector;
 
 8243         parms.myNormalizeScales = 
false;
 
 8245         if (sopparms.getSurfaceShape() == SurfaceShape::INPUT)
 
 8246             parms.myUniformScale = sopparms.getScale();
 
 8247         else if (sopparms.getSurfaceShape() == SurfaceShape::TUBE)
 
 8248             parms.myUniformScale = sopparms.getRadius();
 
 8250             parms.myUniformScale = 0.5*sopparms.getWidth();
 
 8252         if(sopparms.getApplyScale())
 
 8253             parms.myScaleRamp = sopparms.getScaleRamp().get();
 
 8255         parms.myStretchAroundTurns = sopparms.getStretchAroundTurns();
 
 8256         parms.myMaxStretchScale = sopparms.getMaxStretchAroundTurns();
 
 8261         total_transforms = 0;
 
 8262         for (
exint gridi = 0, ngrids = grids.
size(); gridi < ngrids; ++gridi)
 
 8264             const sop_SweepGrid &grid = grids[gridi];
 
 8265             total_transforms += grid.myCurveNEdges + !grid.myCurveClosed;
 
 8267         sopcache->myGridTransformStarts.reset(
new exint[grids.
size()]);
 
 8268         sopcache->clearTransformArrays();
 
 8269         sopcache->myTransformMatrices3D.reset(
new UT_Matrix3D[total_transforms]);
 
 8270         sopcache->myTransformTranslates3D.reset(
new UT_Vector3D[total_transforms]);
 
 8271         sopcache->myTransformCacheSize = total_transforms;
 
 8272         exint *grid_transform_starts = sopcache->myGridTransformStarts.get();
 
 8273         UT_Matrix3D *transform_matrix3ds = sopcache->myTransformMatrices3D.get();
 
 8274         UT_Vector3D *transform_translate3ds = sopcache->myTransformTranslates3D.get();
 
 8275         exint current_transform_start = 0;
 
 8276         for (
exint gridi = 0, ngrids = grids.
size(); gridi < ngrids; ++gridi)
 
 8278             const sop_SweepGrid &grid = grids[gridi];
 
 8279             grid_transform_starts[gridi] = current_transform_start;
 
 8280             current_transform_start += grid.myCurveNEdges + !grid.myCurveClosed;
 
 8283         for (
exint gridi = 0, ngrids = grids.
size(); gridi < ngrids; ++gridi)
 
 8285             const sop_SweepGrid &grid = grids[gridi];
 
 8287             const GA_Offset curve_primoff = grid.myCurvePrimOff;
 
 8288             const GA_OffsetListRef vertices = curve_input->getPrimitiveVertexList(curve_primoff);
 
 8293                 (curve_input->vertexPoint(vertices(0)) == curve_input->vertexPoint(vertices.
last()));
 
 8295             if (vertices.
size() == 1)
 
 8299                 curve_unrolled = 
false;
 
 8305             const exint grid_transform_start = grid_transform_starts[gridi];
 
 8306             UT_Matrix3D *grid_matrix3ds = transform_matrix3ds + grid_transform_start;
 
 8307             UT_Vector3D *grid_translate3ds = transform_translate3ds + grid_transform_start;
 
 8310             const exint row_start = grid.myVEndPoles ? cap_divisions : 0;
 
 8311             for (
exint i = 0; i < num_vertices; ++i)
 
 8313                 const UT_Matrix4D transform = transform_attrib.get(vertices(i));
 
 8314                 UT_ASSERT(grid_transform_start+row_start+i < total_transforms);
 
 8315                 grid_matrix3ds[row_start+i] = 
UT_Matrix3D(transform);
 
 8319             if (grid.myVEndPoles)
 
 8323                 const UT_Matrix4D transform0 = transform_attrib.get(vtxoff0);
 
 8324                 const UT_Matrix4D transform1 = transform_attrib.get(vtxoff1);
 
 8326                 sopAllEndCapTransforms(
 
 8327                     grid, sopparms, cross_section_input,
 
 8328                     transform0, transform1, num_vertices,
 
 8329                     grid_matrix3ds, grid_translate3ds,
 
 8334     else if (grids.
size() == 1 && grids[0].myVEndPoles)
 
 8338         const sop_SweepGrid &grid = grids[0];
 
 8341         total_transforms = grid.myCurveNEdges + !grid.myCurveClosed;
 
 8342         exint num_vertices = total_transforms - 2*cap_divisions;
 
 8344         sopcache->myGridTransformStarts.reset(
new exint[1]);
 
 8345         sopcache->clearTransformArrays();
 
 8346         sopcache->myTransformMatrices3D.reset(
new UT_Matrix3D[total_transforms]);
 
 8347         sopcache->myTransformTranslates3D.reset(
new UT_Vector3D[total_transforms]);
 
 8348         sopcache->myTransformCacheSize = total_transforms;
 
 8349         exint *grid_transform_starts = sopcache->myGridTransformStarts.get();
 
 8350         UT_Matrix3D *grid_matrix3ds = sopcache->myTransformMatrices3D.get();
 
 8351         UT_Vector3D *grid_translate3ds = sopcache->myTransformTranslates3D.get();
 
 8352         grid_transform_starts[0] = 0;
 
 8355         for (
exint i = 0; i < num_vertices; ++i)
 
 8357             UT_ASSERT(cap_divisions+i < total_transforms);
 
 8358             grid_matrix3ds[cap_divisions+i].
identity();
 
 8359             grid_translate3ds[cap_divisions+i] = 
UT_Vector3D(0,0,0);
 
 8363         sopAllEndCapTransforms(
 
 8364             grid, sopparms, cross_section_input,
 
 8365             identity, identity, num_vertices,
 
 8366             grid_matrix3ds, grid_translate3ds,
 
 8371         sopcache->clearTransformArrays();
 
 8378         needed_transforms[i] = 
false;
 
 8380     for (
exint attribi = 0, nattribs = cross_section_attribs.size(); attribi < nattribs; ++attribi)
 
 8382         GA_Attribute *output_attrib = cross_section_attribs[attribi].second;
 
 8384         if (output_numeric == 
nullptr)
 
 8391         using namespace NeededTransforms;
 
 8396             needed_transforms[
matrix3f] |= !double_precision;
 
 8397             needed_transforms[
translate3f] |= !double_precision;
 
 8401             needed_transforms[
matrix3f] |= !double_precision;
 
 8405             needed_transforms[
inverse3d] |= double_precision;
 
 8406             needed_transforms[
inverse3f] |= !double_precision;
 
 8410             needed_transforms[
quaterniond] |= double_precision;
 
 8411             needed_transforms[
quaternionf] |= !double_precision;
 
 8415             needed_transforms[
matrix3f] |= !double_precision;
 
 8426     const SOP_SweepHDKCache *transform_cache = (sopcache->myTransformCacheSize != 0) ? sopcache : 
nullptr;
 
 8437     if (!cross_section_input)
 
 8441         output_geo->getP()->bumpDataId();
 
 8446         const exint cross_section_nedges = sopparms.getCols();
 
 8447         if (sopparms.getSurfaceShape() == SurfaceShape::TUBE)
 
 8449             cross_section_positions.
setSize(cross_section_nedges);
 
 8450             if (cross_section_nedges == 1)
 
 8452                 cross_section_positions[0].assign(1,0,0);
 
 8456                 cross_section_positions[0].assign(1,0,0);
 
 8457                 for (
exint cross_sectioni = 1; cross_sectioni < cross_section_nedges; ++cross_sectioni)
 
 8459                     exint tcross_sectioni = cross_sectioni;
 
 8460                     if (sopparms.getReverseCrossSections())
 
 8461                         tcross_sectioni = reverseVtx(cross_sectioni, cross_section_nedges, 
true);
 
 8462                     double t = double(tcross_sectioni)/double(cross_section_nedges);
 
 8472                         double theta = (2.0*
M_PI)*t;
 
 8473                         double c = SYScos(theta);
 
 8474                         double s = SYSsin(theta);
 
 8480                     cross_section_positions[cross_sectioni] = 
v;
 
 8484         else if (sopparms.getSurfaceShape() == SurfaceShape::RIBBON)
 
 8486             cross_section_positions.setSize(cross_section_nedges+1);
 
 8489             double x0 = (sopparms.getReverseCrossSections() ? 1 : -1);
 
 8491             cross_section_positions[0].assign(x0, 0, 0);
 
 8492             for (
exint cross_sectioni = 1; cross_sectioni < cross_section_nedges; ++cross_sectioni)
 
 8494                 double t = double(cross_sectioni)/double(cross_section_nedges);
 
 8496                 cross_section_positions[cross_sectioni] = 
UT_Vector3D(x,0,0);
 
 8498             cross_section_positions.last().assign(x1,0,0);
 
 8502             UT_ASSERT(sopparms.getSurfaceShape() == SurfaceShape::SQUARE);
 
 8504             cross_section_positions.setSize(4*cross_section_nedges);
 
 8513             if (!sopparms.getReverseCrossSections())
 
 8514                 UTswap(corners[1], corners[3]);
 
 8517             for (
exint big_edgei = 0; big_edgei < 4; ++big_edgei)
 
 8520                 cross_section_positions[arrayi].assign(corners[big_edgei][0], corners[big_edgei][1], 0);
 
 8524                 UT_Vector2D next = corners[(big_edgei==3) ? 0 : (big_edgei+1)];
 
 8525                 for (
exint small_edgei = 1; small_edgei < cross_section_nedges; ++small_edgei, ++arrayi)
 
 8527                     double t = double(small_edgei)/double(cross_section_nedges);
 
 8529                     cross_section_positions[arrayi].assign(pos2d[0], pos2d[1], 0);
 
 8544                 auto grid_transforms = gridOffsetTransforms(transform_cache, local_grid_transforms, gridi);
 
 8545                 const sop_SweepGrid &grid_info = grids[gridi];
 
 8547                 initGUGrid(grid_info, surface_type, output_points_only, sopparms.getTriangularPoles(), sopparms.getSwapRowCol(), grid_info.myStartPtOff, grid);
 
 8549                 const bool swap_row_col = sopparms.getSwapRowCol();
 
 8550                 exint prev_vtxi = -1;
 
 8551                 auto&& functor = [&prev_vtxi,&cross_section_positions,swap_row_col,grid_transforms,&
transform,&outputP]
 
 8554                     const exint curve_vtxi = swap_row_col ? col : 
row;
 
 8555                     if (curve_vtxi != prev_vtxi)
 
 8557                         transform = 
UT_Matrix4D(grid_transforms->getMatrix3s<
double>()[curve_vtxi]);
 
 8558                         transform.setTranslates(grid_transforms->getTranslates<
double>()[curve_vtxi]);
 
 8559                         prev_vtxi = curve_vtxi;
 
 8564                     const exint cross_section_vtxi = swap_row_col ? row : col;
 
 8565                     const UT_Vector3D &cross_section_pos = cross_section_positions[cross_section_vtxi];
 
 8566                     outputP.set(output_offset, (cross_section_pos * transform));
 
 8573         const exint PARALLEL_THRESHOLD = 2048;
 
 8574         if (ngrids > 1 && output_geo->getNumPoints() >= PARALLEL_THRESHOLD)
 
 8577             outputP->hardenAllPages();
 
 8587     exint num_cross_sections;
 
 8588     if (cross_section_group != 
nullptr)
 
 8590         num_cross_sections = cross_section_group->
entries();
 
 8592     else if (cross_section_input != 
nullptr)
 
 8598         num_cross_sections = 1;
 
 8601     const UVStyle ustyle = (!computing_uvs || !sopparms.getLengthWeightedUVs() || sopparms.getNormalizeU()) ?
 
 8602         UVStyle::NORMALIZED :
 
 8603         (sopparms.getWrapU() ? UVStyle::ROUNDED : UVStyle::FULL);
 
 8604     const UVStyle vstyle = (!computing_uvs || !sopparms.getLengthWeightedUVs() || sopparms.getNormalizeV()) ?
 
 8605         UVStyle::NORMALIZED :
 
 8606         (sopparms.getWrapV() ? UVStyle::ROUNDED : UVStyle::FULL);
 
 8608     bool finished = copySurfaceAttributes(
 
 8609         output_geo, curve_input, cross_section_input,
 
 8611         cross_section_attribs,
 
 8612         curve_attribs, uv_attribs,
 
 8614         surface_type, output_points_only, sopparms.getTriangularPoles(), cap_divisions,
 
 8615         sopparms.getReverseCrossSections(), sopparms.getSwapRowCol(),
 
 8617         (!missing_input_us.
isEmpty()) ? &missing_input_us : 
nullptr,
 
 8618         sopparms.getLengthWeightedUVs(),
 
 8620         (curve_input == 
nullptr) || sopparms.getUseMeshEdgeLengths(),
 
 8621         sopparms.getPropScalePerCurve(),
 
 8622         computing_uvs && sopparms.getFlipU(),
 
 8623         sopparms.getUVScale());
 
 8635     if (sopparms.getAddPointRow() && sopparms.getPtRowAttrib().isstring())
 
 8640         if (attrib.isValid())
 
 8642             for (
exint gridi = 0, ngrids = grids.
size(); gridi < ngrids; ++gridi)
 
 8644                 const sop_SweepGrid &grid_info = grids[gridi];
 
 8646                 initGUGrid(grid_info, surface_type, output_points_only, sopparms.getTriangularPoles(), sopparms.getSwapRowCol(), grid_info.myStartPtOff, grid);
 
 8650                     attrib.set(output_ptoff, ptrow);
 
 8655     if (sopparms.getAddPointCol() && sopparms.getPtColAttrib().isstring())
 
 8660         if (attrib.isValid())
 
 8662             for (
exint gridi = 0, ngrids = grids.
size(); gridi < ngrids; ++gridi)
 
 8664                 const sop_SweepGrid &grid_info = grids[gridi];
 
 8666                 initGUGrid(grid_info, surface_type, output_points_only, sopparms.getTriangularPoles(), sopparms.getSwapRowCol(), grid_info.myStartPtOff, grid);
 
 8670                     attrib.set(output_ptoff, ptcol);
 
 8675     if (sopparms.getAddPrimRow() && sopparms.getPrimRowAttrib().isstring())
 
 8680         if (attrib.isValid())
 
 8682             for (
exint gridi = 0, ngrids = grids.
size(); gridi < ngrids; ++gridi)
 
 8684                 const sop_SweepGrid &grid_info = grids[gridi];
 
 8686                 initGUGrid(grid_info, surface_type, output_points_only, sopparms.getTriangularPoles(), sopparms.getSwapRowCol(), grid_info.myStartPtOff, grid);
 
 8688                 GA_Offset grid_start_primoff = grid_info.myStartPrimOff;
 
 8689                 if (grid_info.myHasPolygonCaps)
 
 8692                     attrib.set(grid_start_primoff, 0);
 
 8693                     ++grid_start_primoff;
 
 8699                     attrib.set(grid_start_primoff + primnum, primrow);
 
 8702                 if (grid_info.myHasPolygonCaps)
 
 8705                     attrib.set(grid_start_primoff + grid.
myNumPrimitives, grid_info.myCurveNEdges);
 
 8710     if (sopparms.getAddPrimCol() && sopparms.getPrimColAttrib().isstring())
 
 8715         if (attrib.isValid())
 
 8717             for (
exint gridi = 0, ngrids = grids.
size(); gridi < ngrids; ++gridi)
 
 8719                 const sop_SweepGrid &grid_info = grids[gridi];
 
 8721                 initGUGrid(grid_info, surface_type, output_points_only, sopparms.getTriangularPoles(), sopparms.getSwapRowCol(), grid_info.myStartPtOff, grid);
 
 8723                 GA_Offset grid_start_primoff = grid_info.myStartPrimOff;
 
 8724                 if (grid_info.myHasPolygonCaps)
 
 8727                     attrib.set(grid_start_primoff, 0);
 
 8728                     ++grid_start_primoff;
 
 8734                     attrib.set(grid_start_primoff + primnum, primcol);
 
 8737                 if (grid_info.myHasPolygonCaps)
 
 8745     if (sopparms.getAddCurveNum() && sopparms.getCurveNumAttrib().isstring())
 
 8750         if (attrib.isValid())
 
 8752             for (
exint gridi = 0, ngrids = grids.
size(); gridi < ngrids; ++gridi)
 
 8754                 const sop_SweepGrid &grid_info = grids[gridi];
 
 8756                 initGUGrid(grid_info, surface_type, output_points_only, sopparms.getTriangularPoles(), sopparms.getSwapRowCol(), grid_info.myStartPtOff, grid);
 
 8759                 exint curve_number = (curve_input != 
nullptr) ? 
exint(curve_input->primitiveIndex(grid_info.myCurvePrimOff)) : 0;
 
 8763                     attrib.set(output_ptoff, curve_number);
 
 8768     if (sopparms.getAddCrossSectionNum() && sopparms.getCrossSectionNumAttrib().isstring())
 
 8771         const UT_StringHolder &attribname = sopparms.getCrossSectionNumAttrib();
 
 8773         if (attrib.isValid())
 
 8775             for (
exint gridi = 0, ngrids = grids.
size(); gridi < ngrids; ++gridi)
 
 8777                 const sop_SweepGrid &grid_info = grids[gridi];
 
 8779                 initGUGrid(grid_info, surface_type, output_points_only, sopparms.getTriangularPoles(), sopparms.getSwapRowCol(), grid_info.myStartPtOff, grid);
 
 8781                 if (cross_section_input != 
nullptr)
 
 8785                         GA_Offset source_cross_section_primoff =
 
 8786                             grid_info.mySingleCrossSection ?
 
 8787                             GA_Offset(grid_info.myCrossSectionPrimOff) :
 
 8788                             (*grid_info.myCrossSectionPrimOffs)[ptrow];
 
 8790                         exint cross_section_number = cross_section_input->
primitiveIndex(source_cross_section_primoff);
 
 8792                         attrib.set(output_ptoff, cross_section_number);
 
 8800                         attrib.set(output_ptoff, 0);
 
 8806     if (sopparms.getAddEndCapsGroup() && sopparms.getEndCapsGroup().isstring())
 
 8813             for (
exint gridi = 0, ngrids = grids.
size(); gridi < ngrids; ++gridi)
 
 8815                 const sop_SweepGrid &grid_info = grids[gridi];
 
 8817                 initGUGrid(grid_info, surface_type, output_points_only, sopparms.getTriangularPoles(), sopparms.getSwapRowCol(), grid_info.myStartPtOff, grid);
 
 8819                 GA_Offset grid_start_primoff = grid_info.myStartPrimOff;
 
 8820                 if (grid_info.myHasPolygonCaps)
 
 8826                 else if (grid_info.myVEndPoles)
 
 8829                     exint last_cap_start_vtxi = grid_info.myCurveNEdges - cap_divisions;
 
 8830                     const bool swap_row_col = sopparms.getSwapRowCol();
 
 8834                         exint curve_vtxi = swap_row_col ? primcol : primrow;
 
 8835                         if (curve_vtxi < cap_divisions || curve_vtxi >= last_cap_start_vtxi)
 
 8837                             group->
addOffset(grid_start_primoff + primnum);
 
 8850     sopcache->clearTransformArrays();
 
static PRM_ChoiceList primGroupMenu
 
void destroyPrimitiveGroup(GA_PrimitiveGroup *g)
 
void initColTube(exint nedgerows, exint nedgecols, INT_TYPE start_pt=INT_TYPE(0))
 
constexpr SYS_FORCE_INLINE T length2() const noexcept
 
SYS_FORCE_INLINE void bumpDataId()
 
SYS_FORCE_INLINE const GA_Detail & getDetail() const 
 
SYS_FORCE_INLINE void forEachAttribute(FUNCTOR &&functor) const 
 
static SYS_FORCE_INLINE bool isType(const GA_Attribute *attrib)
 
Definition of a geometry attribute. 
 
UT_Matrix4T< fpreal64 > UT_Matrix4D
 
GLenum GLuint GLenum GLsizei const GLchar * buf
 
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)
 
constexpr SYS_FORCE_INLINE T dot(const UT_Vector3T &b) const noexcept
 
Data has no numeric representation. 
 
#define SYS_STATIC_ASSERT(expr)
 
int setUBasis(GA_Basis *ub)
 
SYS_FORCE_INLINE GA_Primitive * getPrimitive(GA_Offset prim_off)
 
SYS_FORCE_INLINE const GA_AttributeDict & pointAttribs() const 
 
FromType append(ToType value)
Add a single entry (may grow array) 
 
const GA_IndexMap & getPrimitiveMap() const 
 
GA_DataId getDataId() const 
 
unsigned char myBasisOrderU
 
Iteration over a range of elements. 
 
static SYS_FORCE_INLINE bool isType(const GA_Attribute *attrib)
 
int setVBasis(GA_Basis *vb)
 
void setChoiceListPtr(const UT_StringRef &name, PRM_ChoiceList *list)
 
UT_ErrorSeverity sopAddWarning(int code, const char *msg=0, const UT_SourceLocation *loc=0) const 
 
GOP_GroupParse::GroupCreator GroupCreator
 
static GA_AttributeFilter selectAnd(const GA_AttributeFilter &f0, const GA_AttributeFilter &f1, bool single_match=false)
 
void newSopOperator(OP_OperatorTable *table)
 
SYS_FORCE_INLINE int getPrimitiveTypeId(GA_Offset primoff) const 
 
Class which stores the default values for a GA_Attribute. 
 
T distance3d(const UT_Vector3T< T > &p1, const UT_Vector3T< T > &p2)
Compute the distance between two points. 
 
bool myPrevCloseIfNoCurveInput
 
getFileOption("OpenEXR:storage") storage
 
bool mySingleCrossSection
 
bool isValid() const 
Test to see whether the iterator is valid. 
 
GA_API const UT_StringHolder uv
 
bool myFirstRowIfNotWrapped
 
static GA_AttributeFilter selectPublic(bool include_noninternal_groups=true)
Select public scope attributes and non-internal groups. 
 
SYS_FORCE_INLINE const GA_IndexMap & getIndexMap() const 
 
SYS_FORCE_INLINE void colVecMult(const UT_Matrix3F &m)
 
GA_OffsetListType< GA_Size > GA_OffsetList
GA_OffsetList is a map from index to offset. 
 
UT_Vector2T< fpreal64 > UT_Vector2D
 
#define UT_ASSERT_LEVEL_PARANOID
 
bool blockAdvance(GA_Offset &start, GA_Offset &end)
 
GLsizei const GLfloat * value
 
GA_Size entries() const overridefinal
Will return the number of primary elements. 
 
bool myPrevUnrollClosedRowCol
 
void setSizeNoInit(exint newsize)
 
void clearAndDestroy()
Clear all the points/primitives out of this detail. 
 
UT_Vector3T< float > UT_Vector3
 
SYS_FORCE_INLINE bool getExtraFlag() const 
Synonym for isClosed() 
 
fpreal64 distance2(const UT_VectorD &v1, const UT_VectorD &v2)
Distance squared (L2) aka quadrance. 
 
GA_DataId getDataId() const 
Return the data ID for the topology attributes. 
 
SYS_FORCE_INLINE void initHullData(int rows, int cols, bool wrapv, bool wrapu)
 
GA_Attribute * getP()
Convenience method to access the P attribute. 
 
SYS_FORCE_INLINE const char * buffer() const 
 
GLboolean GLboolean GLboolean GLboolean a
 
bool myCurvesIfBasisRowCol
 
PUGI__FN void reverse(I begin, I end)
 
SYS_FORCE_INLINE GA_AttributeScope getScope() const 
 
GLuint GLsizei GLsizei * length
 
~SOP_SweepHDKCache() override
 
void setCapacity(exint new_capacity)
 
void destroyVertexGroup(GA_VertexGroup *g)
 
GA_EdgeGroupTable & edgeGroups()
 
SYS_FORCE_INLINE TO_T UTverify_cast(FROM_T from)
 
bool myFirstColIfNotWrapped
 
bool addOperator(OP_Operator *op, std::ostream *err=nullptr)
 
Standard user attribute level. 
 
SYS_FORCE_INLINE UT_Vector3 getPos3(GA_Offset ptoff) const 
The ptoff passed is the point offset. 
 
void arbitraryPerp(const UT_Vector3T< T > &v)
Finds an arbitrary perpendicular to v, and sets this to it. 
 
UT_Matrix2T< T > SYSlerp(const UT_Matrix2T< T > &v1, const UT_Matrix2T< T > &v2, S t)
 
UT_UniquePtr< exint[]> myGridTransformStarts
 
GA_ROHandleS myCurveStrAttrib
 
SOP_SweepHDKEnums::SurfaceShape myPrevSurfaceShape
We'll use NONE to represent using the cross section input. 
 
bool shouldInterpretAsTexCoord(bool allow_float2=false) const 
 
void appendPolygons(const GA_PolyCounts &sizes, const GA_OffsetList &vertices)
 
SYS_FORCE_INLINE bool GAisValid(GA_Size v)
 
CrossSectionAttribMatchData myCrossSectionAttribMatchData
 
void setSize(exint newsize)
 
exint GA_Size
Defines the bit width for index and offset types in GA. 
 
GA_OffsetList myPrevCurveGroup
 
GA_ATINumeric * getAttribute() const 
 
This is the SOP class definition. 
 
#define GA_INVALID_OFFSET
 
void bumpSize(exint newsize)
 
GA_Size countPrimitiveType(const GA_PrimitiveTypeId &type) const 
 
UT_ErrorSeverity sopAddError(int code, const char *msg=0, const UT_SourceLocation *loc=0) const 
 
GA_GroupTable::iterator< GA_EdgeGroup > beginTraverse() const 
 
A range of elements in an index-map. 
 
bool myCrossSectionClosed
 
std::unique_ptr< T, Deleter > UT_UniquePtr
A smart pointer for unique ownership of dynamically allocated objects. 
 
SYS_FORCE_INLINE const UT_StringHolder & getName() const 
 
#define UT_ASSERT_MSG(ZZ,...)
 
virtual bool fill(const GA_Range &destrange, GA_Offset srci)
 
virtual bool copyFrom(const GA_Basis &b, bool compatible=false)
 
SYS_FORCE_INLINE void outerproductUpdate(T b, const UT_Vector3F &v1, const UT_Vector3F &v2)
 
GA_API const UT_StringHolder scale
 
exint myCrossSectionPrimOff
 
UT_Array< sop_SweepGrid > myGrids
 
SYS_FORCE_INLINE GA_Index primitiveIndex(GA_Offset offset) const 
Given a primitive's data offset, return its index. 
 
int64 myPrevCrossSectionPrimListDataID
 
GA_ROHandleID myCurveIntAttrib
 
Constructs a PRM_Template list from an embedded .ds file or an istream. 
 
void identity()
Set the matrix to identity. 
 
void bind(const GA_Detail *gdp, GA_AttributeOwner owner, const UT_StringRef &name, int minsize=1)
 
GA_Iterator begin() const 
 
SOP_SweepHDKEnums::CopyOrder myPrevCopyOrder
 
void GUiterateGridPrimitives(const GU_GridT< INT_TYPE > &grid, FUNCTOR &&functor)
 
exint myCrossSectionNEdges
 
virtual void replace(const GA_Attribute &src)=0
 
GA_OffsetList * myCrossSectionPrimOffs
 
SYS_FORCE_INLINE GA_Offset appendPointBlock(GA_Size npoints)
Append new points, returning the first offset of the contiguous block. 
 
constexpr SYS_FORCE_INLINE void negate() noexcept
 
PRM_Template * templates() const 
 
UT_ArrayStringMap< GA_Offset > myStrToPrimOff
 
static SYS_FORCE_INLINE GA_ATINumeric * cast(GA_Attribute *attrib)
 
SOP_SweepHDKEnums::PrimType myPrevPrimType
 
SYS_FORCE_INLINE GA_OffsetListRef getPrimitiveVertexList(GA_Offset primoff) const 
 
virtual GA_BASIS_TYPE getType() const =0
Return the type of the basis. 
 
fpreal64 dot(const CE_VectorT< T > &a, const CE_VectorT< T > &b)
 
GEO_API GA_Offset GEObuildPrimitives(GEO_Detail *detail, const std::pair< int, exint > *primtype_count_pairs, const GA_Offset init_startpt, const GA_Size npoints_per_copy, const GA_PolyCounts &vertexlistsizelist, const INT_T *vertexpointnumbers, const bool hassharedpoints, const exint *closed_span_lengths, const exint ncopies=1)
 
UT_Vector3T< T > SYSclamp(const UT_Vector3T< T > &v, const UT_Vector3T< T > &min, const UT_Vector3T< T > &max)
 
void GUiterateGridVertices(const GU_GridT< INT_TYPE > &grid, FUNCTOR &&functor)
 
GA_AttributeSet & getAttributes()
 
SOP_NodeCache * allocCache() const override
 
Bezier or NURBS basis classes which maintain knot vectors. 
 
NURBS basis classes which maintain knot vectors. 
 
SOP_NodeParms * allocParms() const override
 
GU_API void computeCurveTransforms(const GEO_Detail *const geo, const GA_PrimitiveGroup *curve_group, const GA_RWHandleT< UT_Matrix4T< T >> &transform_attrib, const CurveFrameParms< T > &parms)
 
SYS_FORCE_INLINE GA_ATINumericUPtr createDetachedTupleAttribute(GA_AttributeOwner owner, GA_Storage storage, int tuple_size, const GA_Defaults &defaults=GA_Defaults(0.0f), const GA_AttributeOptions *attribute_options=nullptr) const 
 
GLdouble GLdouble GLint GLint order
 
UT::ArrayMap< exint, GA_Offset > myIntToPrimOff
 
SYS_FORCE_INLINE const char * c_str() const 
 
UT_Vector3T< fpreal64 > UT_Vector3D
 
SYS_FORCE_INLINE T get(GA_Offset off, int comp=0) const 
 
SYS_FORCE_INLINE GA_Offset vertexPoint(GA_Offset vertex) const 
Given a vertex, return the point it references. 
 
void identity()
Set the matrix to identity. 
 
int64 myPrevCrossSectCurveAttribDataId
 
SYS_API fpreal32 SYSfloor(fpreal32 val)
 
bool myPrevTriangularPoles
 
GLuint const GLchar * name
 
SYS_FORCE_INLINE GA_DataId getDataId() const 
 
UT_API T UTboundingCircle(const T *coords, exint n, T *centre_out=nullptr)
Returns radius squared. 
 
SYS_FORCE_INLINE const GA_Attribute * findAttribute(GA_AttributeScope scope, const UT_StringRef &name, const GA_AttributeOwner search_order[], int search_size) const 
 
OP_ERROR cookMySop(OP_Context &context) override
Since this SOP implements a verb, cookMySop just delegates to the verb. 
 
SYS_FORCE_INLINE bool destroyEdgeGroup(const UT_StringRef &name)
 
GLboolean GLboolean GLboolean b
 
GA_Size GA_Index
Define the strictness of GA_Offset/GA_Index. 
 
GA_API const UT_StringHolder transform
 
void GUiterateGridPoints(const GU_GridT< INT_TYPE > &grid, FUNCTOR &&functor)
 
void initColSphere(exint nedgerows, exint nedgecols, INT_TYPE start_pt=INT_TYPE(0), INT_TYPE end_pt=INT_TYPE(1), INT_TYPE start_mid_pt=INT_TYPE(2))
 
SYS_FORCE_INLINE const GA_AttributeDict & getDict(GA_AttributeOwner owner) const 
Raw access to the GA_AttributeDict for a particular owner. 
 
GEO_SurfaceType mySurfaceType
 
bool contains(const GA_Primitive *prim) const 
 
fpreal32 SYSrint(fpreal32 val)
 
GLenum GLenum GLsizei void * table
 
static UT_XformOrder::xyzOrder getRotOrder(int xyz)
Translate a XYZ parameter menu index into the UT_XformOrder type. 
 
int64 myPrevCurvePrimListDataID
 
bool myLastRowIfNotWrapped
 
UT_UniquePtr< GA_Attribute > GA_AttributeUPtr
 
void setTranslates(const UT_Vector3T< S > &translates)
 
SYS_FORCE_INLINE const GA_AttributeDict & attribs() const 
 
GA_Topology & getTopology()
 
static PRM_Template * buildTemplates()
 
int sprintf(const char *fmt,...) SYS_PRINTF_CHECK_ATTRIBUTE(2
 
SYS_FORCE_INLINE const GA_Attribute * findPrimitiveAttribute(GA_AttributeScope s, const UT_StringRef &name) const 
 
int64 myPrevCrossSectPrimAttribDataId
 
INT_TYPE getPoint(exint row, exint col) const 
 
SYS_FORCE_INLINE bool isValid() const 
 
const GA_Basis * getBasis() const 
 
ToType last() const 
Return the value of the last element. 
 
bool myLastColIfNotWrapped
 
GU_API void GUcomputeTransformTypeCaches(GU_PointTransformCache *cache, exint num_target_points, bool transforms_changed, const bool needed_transforms[NeededTransforms::num_needed_transforms])
 
PrimitiveType myPrimitiveType
 
SYS_FORCE_INLINE GA_Size getNumVertices() const 
Return the number verticies in the entire detail. 
 
Data represents a quaternion. Token "quaternion". 
 
GA_API const UT_StringHolder parms
 
IMATH_NAMESPACE::V2f IMATH_NAMESPACE::Box2i std::string this attribute is obsolete as of OpenEXR v3 float
 
void hardenAllPages(GA_Offset start_offset=GA_Offset(0), GA_Offset end_offset=GA_INVALID_OFFSET) override
Harden data pages. 
 
bool myCrossSectionUnrolled
 
SOP_SweepHDKEnums::SurfaceType myPrevSurfaceType
 
static GA_AttributeFilter selectByPattern(const char *pattern)
 
SYS_FORCE_INLINE GA_TypeInfo getTypeInfo() const 
 
SYS_FORCE_INLINE void set(GA_Offset off, const T &val) const 
 
SYS_FORCE_INLINE GA_Index indexSize() const 
 
SYS_NO_DISCARD_RESULT UT_QuaternionT< T > interpolate(const UT_QuaternionT< T > &target, T t, T b=0.0f) const 
Interpolates between this quat (t==0) and the target (t==1) 
 
SYS_FORCE_INLINE GA_Offset primitiveOffset(GA_Index index) const 
Given a primitive's index (in append order), return its data offset. 
 
GA_Size getEntries() const 
Get an accurate count of the entries in the range. 
 
virtual bool copy(GA_Offset desti, GA_Offset srci)
 
Data represents a normal vector. Token "normal". 
 
LeafData & operator=(const LeafData &)=delete
 
SYS_FORCE_INLINE const GA_AttributeDict & primitiveAttribs() const 
 
void append(GA_Size size, GA_Size count=1)
 
void destroyPointGroup(GA_PointGroup *g)
 
int setBasis(GA_Basis *ub)
 
unsigned char myBasisOrderCrossSection
 
int64 myPrevOutputDetailID
 
static const char *const theDsFile
This is the parameter interface string, below. 
 
SYS_FORCE_INLINE GA_Size getNumPrimitives() const 
Return the number of primitives. 
 
GA_AttributeOwner myCurveAttribOwner
 
Data represents a direction vector. Token "vector". 
 
const GU_Detail * inputGeo(exint idx) const 
 
const GA_PrimitiveList & getPrimitiveList() const 
 
int64 myPrevCurveTopologyDataID
 
SOP_NodeCache * cache() const 
 
void constant(const T &v)
Quickly set the array to a single value. 
 
constexpr SYS_FORCE_INLINE T distance(const UT_Vector3T &b) const noexcept
 
UT_StringHolder name() const override
 
Data represents a position in space. Token "point". 
 
SYS_FORCE_INLINE GA_AttributeOwner getOwner() const 
 
Container class for all geometry. 
 
static const SOP_NodeVerb::Register< SOP_SweepHDKVerb > theVerb
 
int64 myPrevCrossSectionTopologyDataID
 
void zero()
Set the matrix to zero. 
 
SYS_FORCE_INLINE UT_StorageMathFloat_t< T > normalize() noexcept
 
GLenum GLenum GLsizei void * row
 
void bind(GA_Detail *gdp, GA_AttributeOwner owner, const UT_StringRef &name, int minsize=1)
 
const char * inputLabel(OP_InputIdx idx) const override
These are the labels that appear when hovering over the inputs. 
 
static const UT_StringHolder theSOPTypeName
 
GA_OffsetList myPrevCrossSectionGroup
 
SYS_FORCE_INLINE GA_Offset vertexOffset(GA_Index index) const 
Given a vertex's index (in append order), return its data offset. 
 
SIM_API const UT_StringHolder distance
 
void clear()
Resets list to an empty list. 
 
int isRefInput(OP_InputIdx i) const override
 
SYS_FORCE_INLINE void setTypeInfo(GA_TypeInfo type)
 
void initRowSphere(exint nedgerows, exint nedgecols, INT_TYPE start_pt=INT_TYPE(0), INT_TYPE end_pt=INT_TYPE(1), INT_TYPE start_mid_pt=INT_TYPE(2))
 
GA_Range getPrimitiveRange(const GA_PrimitiveGroup *group=0) const 
Get a range of all primitives in the detail. 
 
CookMode cookMode(const SOP_NodeParms *parms) const override
 
virtual void hardenAllPages(GA_Offset start_offset=GA_Offset(0), GA_Offset end_offset=GA_INVALID_OFFSET)=0
 
void destroyAttribute(GA_AttributeOwner owner, GA_AttributeScope scope, const UT_StringRef &name, const GA_AttributeFilter *filter=0)
 
void bumpDataIdsForAddOrRemove(bool added_or_removed_points, bool added_or_removed_vertices, bool added_or_removed_primitives)
 
PrimitiveType myPrimitiveType
 
Bezier basis classes which maintain knot vectors. 
 
void initRowTube(exint nedgerows, exint nedgecols, INT_TYPE start_pt=INT_TYPE(0))
 
SOP_SweepHDKEnums::EndCapType myPrevEndCapType
 
static GA_Basis * newSpecies(GA_BASIS_TYPE type)
 
Data represents a transform matrix. Token "matrix". 
 
void initTorus(exint nedgerows, exint nedgecols, INT_TYPE start_pt=INT_TYPE(0))
 
SIM_DerVector3 cross(const SIM_DerVector3 &lhs, const SIM_DerVector3 &rhs)
 
GA_Basis * getUBasis() const 
 
GU_API bool getPolyProperties(const GEO_Detail *geometry, const GA_OffsetListRef &vertices, exint &nedges, bool &closed, bool &unrolled)
 
SYS_FORCE_INLINE void addOffset(GA_Offset ai)
 
static OP_Node * myConstructor(OP_Network *net, const char *name, OP_Operator *op)
 
GU_DetailHandle & gdh() const 
The initial state of gdh depends on the cookMode() 
 
GA_OffsetList getOffsetFromIndexList() const 
 
bool fullBlockAdvance(GA_Offset &start, GA_Offset &end)
 
SYS_FORCE_INLINE bool isstring() const 
 
unsigned char myBasisOrderCurve
 
int getOrder() const 
Return the order of the basis. 
 
SYS_FORCE_INLINE FromType size() const 
Returns the number of used elements in the list (always <= capacity()) 
 
unsigned char myBasisOrderV
 
void getTranslates(UT_Vector3T< S > &translates) const 
 
void initSingleGrid(exint nedgerows, exint nedgecols, INT_TYPE start_pt=INT_TYPE(0))
 
SOP_SweepHDK(OP_Network *net, const char *name, OP_Operator *op)
 
SYS_FORCE_INLINE const GA_AttributeDict & vertexAttribs() const 
 
void setSurfaceType(GEO_SurfaceType t)
 
UT_Matrix3T< fpreal64 > UT_Matrix3D
 
GLint GLint GLint GLint GLint GLint GLint GLbitfield GLenum filter
 
void initSplitColSphere(exint nedgerows, exint nedgecols, INT_TYPE start_pt=INT_TYPE(0), INT_TYPE end_pt=INT_TYPE(1), INT_TYPE start_mid_pt=INT_TYPE(2))
 
bool isEmpty() const 
Returns true iff there are no occupied elements in the array. 
 
GA_Storage getStorage() const 
 
GA_Basis * getVBasis() const