HDK
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
GU_CurveFrame.h
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2024
3  * Side Effects Software Inc. All rights reserved.
4  *
5  * Redistribution and use of Houdini Development Kit samples in source and
6  * binary forms, with or without modification, are permitted provided that the
7  * following conditions are met:
8  * 1. Redistributions of source code must retain the above copyright notice,
9  * this list of conditions and the following disclaimer.
10  * 2. The name of Side Effects Software may not be used to endorse or
11  * promote products derived from this software without specific prior
12  * written permission.
13  *
14  * THIS SOFTWARE IS PROVIDED BY SIDE EFFECTS SOFTWARE `AS IS' AND ANY EXPRESS
15  * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
16  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
17  * NO EVENT SHALL SIDE EFFECTS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,
18  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
19  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
20  * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
21  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
22  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
23  * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24  *
25  *----------------------------------------------------------------------------
26  * Declarations of functions for computing reference frames
27  * for curve vertices.
28  */
29 
30 #pragma once
31 
32 #include <GEO/GEO_Detail.h>
33 #include <GA/GA_ElementGroup.h>
34 #include <GA/GA_Handle.h>
35 #include <GA/GA_Iterator.h>
36 #include <GA/GA_OffsetList.h>
37 #include <GA/GA_SplittableRange.h>
38 #include <GA/GA_Types.h>
39 #include <UT/UT_Interrupt.h>
40 #include <UT/UT_ParallelUtil.h>
41 #include <UT/UT_Matrix4.h>
42 #include <UT/UT_Vector3.h>
43 #include <UT/UT_Vector4.h>
44 #include <SYS/SYS_Inline.h>
45 #include <SYS/SYS_Types.h>
46 
47 class GA_PrimitiveGroup;
48 
49 namespace HDK_Sample {
50 
51 namespace GU_CurveFrame {
52 
53 static constexpr int theCurveUVComponent = 0; // u. FIXME: Should this be v?
54 static constexpr int theCrossSectionUVComponent = 1; // v. FIXME: Should this be u?
55 
57 {
58  /// Average of normalized direction vectors of adjacent edges.
59  /// Extrapolation rotates tangent from prev/next edge as much
60  /// as prev/next tangent rotated to that edge.
62 
63  /// Central difference of (unnormalized) adjacent edges, e.g.
64  /// computing velocity from motion trails.
65  /// This is the tangent that a subdivision curve would have at each point.
66  /// Extrapolation applies half the difference between the two
67  /// prev/next edges to the prev/next edge to get the tangent.
69 
70  /// Tangent is the previous edge.
71  /// Extrapolation (only back from the beginning of the curve) applies the
72  /// negative difference between the two next edges to the next edge.
74 
75  /// Tangent is the next edge.
76  /// Extrapolation (only forward from the end of the curve) applies the
77  /// difference between the two prev edges to the prev edge.
79 
80  /// Tangent is the Z axis (ignoring the curve tangent).
81  /// Extrapolation does nothing.
83 };
84 
86 {
87  /// Apply angle increment to each edge on top of previous edge's rotation
89 
90  /// Apply angle increment times edge length to each edge on top of previous
91  /// edge's rotation.
93 
94  /// Apply angle increment times rotation ramp attribute value on top of
95  /// starting rotation of the primitive.
97 
98  /// Apply (angle increment / num edges) to each edge on top of previous
99  /// edge's rotation.
101 
102  /// Apply (angle increment * edge length / total length) to each edge on
103  /// top of previous edge's rotation.
105 };
106 
107 bool
109  const GEO_Detail *geometry,
110  const GA_OffsetListRef &vertices,
111  exint &nedges,
112  bool &closed,
113  bool &unrolled);
114 
115 SYS_FORCE_INLINE bool
117  const GEO_Detail *geometry,
118  const GA_Offset primoff,
119  exint &nedges,
120  bool &closed,
121  bool &unrolled)
122 {
123  const GA_OffsetListRef vertices = geometry->getPrimitiveVertexList(primoff);
124  return getPolyProperties(geometry, vertices, nedges, closed, unrolled);
125 }
126 
127 template<typename T>
129 {
132 
133  /// Use incoming N, up, rot, orient, pscale, scale, pivot, trans, transform.
135 
139  /// NOTE: myIncAnglePer[2] will also be used for ensuring closed curve continuity.
141  /// Component of myRotAttribs being read. (default 0)
143  /// "pitch" (X), "yaw" (Y), and "roll" (Z) attributes to add
144  /// to rotation angles, to be multiplied by myIncAngles if myIncAnglePer is ATTRIB,
145  /// and they can be vertex, point, primitive, or detail attributes.
147 
153  /// When true, the target up vector will be used as the starting up vector.
154  /// When false, it will be used as the *average* up vector.
156  /// NOTE: This should only be true if myTargetUpVectorAtStart is true.
157  /// It also only applies to open curves.
159 
160  /// When true, transformations for closed curves (and for "unrolled" curves
161  /// that share a first and last point) will have an incremental roll added
162  /// to ensure that any net roll introduced by non-planarity of the curve
163  /// will be spread out, instead of being all cancelled in the very last
164  /// edge. When false, this roll will be uncorrected, so there can be
165  /// a large roll around the last edge.
166  ///
167  /// This is important to turn off if, for example,
168  /// myRotRampAttrib already accounts for this extra roll.
169  ///
170  /// If this is enabled and myIncAngles[2] is non-zero, the total roll
171  /// around the curve, including the inherent roll, will be rounded to
172  /// be a multiple of a full turn to ensure continuity. If myIncAnglePer[2]
173  /// is ATTRIB, the full range of the attribute along the curve is assumed to
174  /// be 0-1, so if this is not the true range, that roll may need to be
175  /// applied separately.
177 
180  UT_Ramp *myScaleRamp = nullptr;
183 };
184 
185 /// Computes transforms for vertex attribute transform_attrib based on
186 /// primitives (assumed to be polygon primitives if not NURBS or Bezier)
187 /// in geo and based on settings in parms.
188 ///
189 /// NOTE: End vertices on unrolled curves are not written-to.
190 /// Use extractAttribFromTransform to extract values to a more permanent
191 /// vertex attribute.
192 ///
193 /// This is instantiated for fpreal32 and fpreal64.
194 template<typename T>
195 void
197  const GEO_Detail *const geo,
198  const GA_PrimitiveGroup *curve_group,
199  const GA_RWHandleT<UT_Matrix4T<T>> &transform_attrib,
200  const CurveFrameParms<T> &parms);
201 
202 template<typename T,typename OUTPUT_T,typename FUNCTOR>
203 void
205  GEO_Detail *geo,
206  const GA_PrimitiveGroup *curve_group,
207  const GA_ROHandleT<UT_Matrix4T<T>> &transform_attrib,
208  const GA_RWHandleT<OUTPUT_T> &output_attrib,
209  FUNCTOR &&extract_functor)
210 {
211  // Start an interruptible block. The message will appear in the status bar
212  // if wasInterrupted() is called after about a second of cooking.
213  UT_AutoInterrupt interrupt("Writing curve transforms");
214  if (interrupt.wasInterrupted()) {
215  return;
216  }
217 
218  // We're going to be writing to axis_attrib in parallel, and although
219  // we're using GA_SplittableRange, we're splitting over primitive pages,
220  // not vertex pages, so we have to harden in advance.
221  output_attrib->hardenAllPages();
222 
223  // Loop over primitives in parallel, using a splittable range and a lambda functor.
225  [geo,&transform_attrib,&interrupt,&output_attrib,&extract_functor](const GA_SplittableRange &r) {
226 
227  // Inside the functor, we have a sub-range of primitives, so loop over that range.
228  // We use blockAdvance, instead of !it.atEnd() and ++it, for less looping overhead.
230  for (GA_Iterator it(r); it.blockAdvance(start,end); ) {
231  // We probably don't need to check for interruption on every curve,
232  // (unless people put in a curve with millions of vertices), so we
233  // can check it once for every contiguous block of up to GA_PAGE_SIZE
234  // primitive offsets.
235  if (interrupt.wasInterrupted()) {
236  return;
237  }
238 
239  // Loop over all primitives in this contiguous block of offsets.
240  for (GA_Offset primoff = start; primoff < end; ++primoff) {
241  const GA_OffsetListRef vertices = geo->getPrimitiveVertexList(primoff);
242  GA_Size nedges;
243  bool closed;
244  bool unrolled;
245  bool nonempty = getPolyProperties(geo, vertices, nedges, closed, unrolled);
246  const GA_Size npoints = nedges + !closed;
247 
248  // Nothing to do if no vertices
249  if (!nonempty) {
250  continue;
251  }
252 
253  // NOTE: Although we're really iterating over vertices,
254  // we didn't write to the last vertex of unrolled curves
255  // (open but last point same as first).
256  for (GA_Size i = 0; i < npoints; ++i) {
257  GA_Offset vtxoff = vertices(i);
258  output_attrib.set(vtxoff, extract_functor(transform_attrib.get(vtxoff)));
259  }
260  if (unrolled) {
261  GA_Offset dest_vtxoff = vertices(npoints);
262  GA_Offset src_vtxoff = vertices(0);
263  output_attrib.set(dest_vtxoff, extract_functor(transform_attrib.get(src_vtxoff)));
264  }
265  }
266  }
267  });
268 }
269 
270 /// This works for AXIS == 0 (x), 1 (y), 2 (z), and 3 (translation).
271 template<int AXIS,typename T,typename OUTPUT_T>
272 void
274  GEO_Detail *geo,
275  const GA_PrimitiveGroup *curve_group,
276  const GA_ROHandleT<UT_Matrix4T<T>> &transform_attrib,
277  const GA_RWHandleT<UT_Vector3T<OUTPUT_T>> &axis_attrib)
278 {
279  extractAttribFromTransform(geo, curve_group, transform_attrib, axis_attrib,
281  return UT_Vector3T<OUTPUT_T>(transform[AXIS]);
282  });
283 }
284 
285 }
286 
287 } // End of HDK_Sample namespace
Apply angle increment to each edge on top of previous edge's rotation.
Definition: GU_CurveFrame.h:88
Iteration over a range of elements.
Definition: GA_Iterator.h:29
GA_ROHandleT< UT_Vector3T< T > > myTargetUpVectorAttrib
bool blockAdvance(GA_Offset &start, GA_Offset &end)
GLuint start
Definition: glcorearb.h:475
int64 exint
Definition: SYS_Types.h:125
void extractAttribFromTransform(GEO_Detail *geo, const GA_PrimitiveGroup *curve_group, const GA_ROHandleT< UT_Matrix4T< T >> &transform_attrib, const GA_RWHandleT< OUTPUT_T > &output_attrib, FUNCTOR &&extract_functor)
void UTparallelForLightItems(const Range &range, const Body &body, const bool force_use_task_scope=true)
3D Vector class.
void extractAxisAttrib(GEO_Detail *geo, const GA_PrimitiveGroup *curve_group, const GA_ROHandleT< UT_Matrix4T< T >> &transform_attrib, const GA_RWHandleT< UT_Vector3T< OUTPUT_T >> &axis_attrib)
This works for AXIS == 0 (x), 1 (y), 2 (z), and 3 (translation).
exint GA_Size
Defines the bit width for index and offset types in GA.
Definition: GA_Types.h:235
int myRotAttribComponent
Component of myRotAttribs being read. (default 0)
GA_ROHandleT< UT_Vector3T< T > > myEndTargetUpVectorAttrib
GA_Size GA_Offset
Definition: GA_Types.h:641
SYS_FORCE_INLINE GA_OffsetListRef getPrimitiveVertexList(GA_Offset primoff) const
Definition: GA_Primitive.h:886
GLuint GLuint end
Definition: glcorearb.h:475
#define SYS_FORCE_INLINE
Definition: SYS_Inline.h:45
GA_API const UT_StringHolder transform
void computeCurveTransforms(const GEO_Detail *const geo, const GA_PrimitiveGroup *curve_group, const GA_RWHandleT< UT_Matrix4T< T >> &transform_attrib, const CurveFrameParms< T > &parms)
bool myTransformByInstanceAttribs
Use incoming N, up, rot, orient, pscale, scale, pivot, trans, transform.
void hardenAllPages(GA_Offset start_offset=GA_Offset(0), GA_Offset end_offset=GA_INVALID_OFFSET) override
Harden data pages.
SYS_FORCE_INLINE void set(GA_Offset off, const T &val) const
Definition: GA_Handle.h:354
Utility class for containing a color ramp.
Definition: UT_Ramp.h:88
bool getPolyProperties(const GEO_Detail *geometry, const GA_OffsetListRef &vertices, exint &nedges, bool &closed, bool &unrolled)
GLboolean r
Definition: glcorearb.h:1222
GA_Range getPrimitiveRange(const GA_PrimitiveGroup *group=0) const
Get a range of all primitives in the detail.
Definition: GA_Detail.h:1733
RotationPer myIncAnglePer[3]
NOTE: myIncAnglePer[2] will also be used for ensuring closed curve continuity.