HDK
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
GU_Path.h
Go to the documentation of this file.
1  /*
2  * PROPRIETARY INFORMATION. This software is proprietary to
3  * Side Effects Software Inc., and is not to be reproduced,
4  * transmitted, or disclosed in any way without written permission.
5  *
6  * NAME: GU_Path.h (GEO Utility library, C++)
7  *
8  * COMMENTS: This class implements the utilities for the path. Path
9  * is a curve that behaves like a rope or semi-flexible string
10  * (but the behaviour of the path may be extended in the future
11  * to incorporate other behaviours). Path curve has normal
12  * attribute (and potentially a twist attribute) to define
13  * the orientation of the rope, so that it can simulate
14  * the twisting behavoiur in addition to the bending behaviour.
15  *
16  * Primary use of this class is intended for the object level
17  * path normal computation (which is used when generating
18  * bones on the path and solving them in follow curve IK chop).
19  * We are primarily interested in the normals at sample points.
20  * The sample points are taken from the Bezier or NURBS curve.
21  * The setup of the object level path is such that only
22  * breakpoints are intended for maniputaling curve (via
23  * object level Path CVs). Thus the GU_Path, obtains
24  * the breakpoint data (normals, twists, etc) and uses it
25  * for interpolating the brakpoint normals among the sampled
26  * points. So, Bezier segments are preferable inputs to the
27  * GU_Path, but NRBS curves are also handled: the breakpoint
28  * data is evaluated from the CVs and then used as for Bezier
29  * curves.
30  */
31 
32 #ifndef __GU_Path_H__
33 #define __GU_Path_H__
34 
35 
36 #include "GU_API.h"
37 // includes
38 #include <UT/UT_Vector3Array.h>
39 #include <UT/UT_IntArray.h>
40 #include <UT/UT_Vector3.h>
41 #include <UT/UT_VectorTypes.h>
42 
43 // class declarations
44 class GA_ROAttributeRef;
45 class GEO_PrimPoly;
46 class GEO_Primitive;
47 class GEO_Curve;
48 class GU_Detail;
49 
50 
51 // Path class
53 {
54 public:
55 
56  // the calculation method of the normals
58  {
59  GU_CALC_DEFAULT, // default
60  GU_CALC_NONE, // no normals are computed
61  GU_CALC_QUAT, // interpolating with quaternions
62  GU_CALC_TWIST_SHORT,// interpolating with twist angles in 0..180 range
63  GU_CALC_TWIST_FULL // interpolating with twist angles in any range
64  };
65 
66  // constructor
67  GU_Path();
68 
69  // destructor
70  ~GU_Path();
71 
72  // Calculate the path object from the curve object.
73  // Normals associated with the curve's breakpoints (!)
74  // are retargeted for the path object, if curve has normal attribute.
75  // Otherwise path object will not
76  // have normals. If curve has twist attribute, the normals for the path
77  // are interpolated according to the angle around the path (like a twisted
78  // rope or string), otherwise a quaternion interpolation of curve normals
79  // is used.
80  // INPUT:
81  // curve - the detail whose first primitive is a curve.
82  // It may have normal attribute
83  // and twist attribute. Twist is the angle of rotation
84  // around the path (synonims: curve, rope) measured from
85  // its natural "rest" orientation (presumably defined
86  // at the path creation time). If
87  // mat - the matrix used to transform the curve's sampled points,
88  // before assigning them to the path.
89  // normal_comp_type - a method for interpolating the normals at
90  // the breakpoints. Default uses best method for which
91  // we have enough information.
92  // RETURN:
93  // true on success, false if failed
94  bool computePathFromCurve(
95  const GU_Detail * curve,
96  const UT_DMatrix4 & mat,
97  gu_CalcMethod normal_comp_type = GU_CALC_DEFAULT,
98  int prim_num = 0);
99 
100  // Calculate the path from detail object containing a curve.
101  // Normals for the path are calculated so that they flow naturally
102  // without any twist differences between breakpoints.
103  // INPUT:
104  // curve - detail containing a curve
105  // normal - a normal to match on cv_index-th breakpoint of the curve
106  // cv_index - index of the breakpoint whose normal should be the same
107  // as 'normal' argument
108  // RETURN:
109  // true on success, false if failed
110  bool computeNaturalPathFromCurve( const GU_Detail * curve,
111  const UT_Vector3& normal,
112  int cv_index = 0);
113 
114  // calculates the positions of the joints along the path.
115  // The joints mark uniform arc length segments along the path.
116  // INPUT:
117  // num_of_segments - number of segments (n+1 sample points) for resampling
118  // OUTPUT:
119  // joints - array of vertices that resample the path
120  // normals - array of normals associated with joints. This array
121  // is set to empty if path has no normals.
122  void resamplePath( int num_of_segments,
123  UT_Vector3Array & joints,
124  UT_Vector3Array & normals ) const;
125 
126  // obtains the twist angles between path's breakpoint normals
127  // and the vectors passed in
128  // INPUT:
129  // vectors - vectors against which to compute twist angles. Should
130  // be the same size as the array returned by getBreakpointNormals()
131  // OUTPUT:
132  // angles - angles in degrees by which i-th breakpoint normal needs to be
133  // rotated while traversing the path to match the i+1-th vector.
134  // The angles are in the interval [-180, 180].
135  // RETURN:
136  // true on success, false on failure
137  bool getBreakpointTwists( const UT_Vector3Array & vectors,
138  UT_FloatArray & angles );
139 
140  // do a spherical linear interpolation (slerp) between two vectors
141  // using t = [0, 1] as a blending factor
142  static UT_Vector3 slerp( const UT_Vector3 & v0, const UT_Vector3 & v1,
143  double t );
144 
145  // obtains path's vertices
146  const UT_Vector3Array & getVertices() const
147  {
148  return myVertices;
149  }
150 
151  // obtains path's normals
152  const UT_Vector3Array & getNormals() const
153  {
154  return myNormals;
155  }
156 
157  // obtains path breakpoints' normals
159  {
160  return myBreakpointNormals;
161  }
162 
163  // true if path is closed
164  bool isClosed() const
165  {
166  return myIsClosed;
167  }
168 
169  // obtains a tangent at the path start point
171  {
172  return myHeadTangent;
173  }
174 
175  // obtains a tangent at the path end point
177  {
178  return myTailTangent;
179  }
180 
181 private: // methods
182 
183  // suck data from the poly and transfer it to ourselves. Curve
184  // is used for finding and interpolating the attributes like
185  // the normals. If it is NULL, then no normals will be computed
186  // for the path object. Otherwise the normal_comp_type determines
187  // the method for interpolating the normals (provided enough
188  // information is given in curve)
189  void getDataFromPoly( const GU_Detail * detail,
190  const GEO_PrimPoly * poly,
191  const GEO_Curve * curve,
192  const UT_DMatrix4 & mat,
193  gu_CalcMethod normal_comp_type =
194  GU_CALC_DEFAULT );
195 
196  // construct the path from poly, and assign natually flowing normals
197  // to the vertices. If curve is not NULL, also the breakpoint normals
198  // for that curve are computed and stored in member data field.
199  void computeNaturalPathFromPoly(const GEO_PrimPoly * poly,
200  const GEO_Curve * curve,
201  const UT_Vector3& normal, int cv_index );
202 
203  // interpolate normals between the breakpoints of the curve and
204  // set them for our path object
205  // (i.e., for each verex in myVertices compute appropriate normal
206  // in myNormals)
207  // NB: curve must have the normal attribute
208  void setInterpolatedNormals( const GU_Detail * detail,
209  const GEO_Curve * curve );
210 
211  // for each vertex in myVertices interpolate twist (rotation angle
212  // around the curve) between the breakpoints of the curve and
213  // use this twist to find the normal (and set it in myNormals).
214  // If clamp_range is true, the twist between the breakpoints
215  // is going to be within [-180, 180]. Otherwise the twist is unlimited
216  // in its range
217  // NB: curve must have the normal attribute
218  // NB: all the breakpoints of the curve, must have a corresponding point
219  // in vertices array myVertices that have the same position.
220  void setTwistedNormals( const GU_Detail * detail,
221  const GEO_Curve * curve,
222  bool clamp_range = false);
223 
224  // for each vertex in myVertices assign a normal (stored in myNormals)
225  // using the natural flow. If curve is not null then its index-th control
226  // will have the 'normal' orientation. If curve is null the index-th
227  // vertex will have the orientation alligned with normal.
228  void setNaturalNormals( const GEO_Curve *curve,
229  const UT_Vector3& normal, int index );
230 
231  // sets our normals from the poly. It is one to one correspondence
232  // with the poly (the normals), thus the poly must have the same
233  // number of vertices as we do.
234  void setPolyNormals( const GU_Detail *detail,
235  const GEO_PrimPoly * poly );
236 
237  // calculates length as a sum of distances between 'points'. Points
238  // should have at least 2 entries. Additionally, if curve and
239  // break_arc_lengts are not null, break_arc_lengths will be filled
240  // with arc length parameter for each of curve's breakpoint measured
241  // along the points. All curve's breakpoint locations must coincide
242  // with some of the points (up to tollerance level). If
243  // vertex_indices is not null it is filled with vertex indices that
244  // coincide with the curve's breakpoints.
245  float calculateLength( const UT_Vector3Array & points,
246  const GEO_Curve * curve = NULL,
247  UT_FloatArray * break_arc_lengths = NULL,
248  UT_IntArray * break_vertex_indices =NULL)const;
249 
250  // returns the angular twist (radians) difference around the curve. That is,
251  // the angle by which the normal n0 needs to be rotated, as we traverse
252  // down the curve, to allign it with n1. index0 and index1 are point indices
253  // corresponing to the normals n0 and n1.
254  // RETURNS:
255  // the twist angle between points index0 and index1 that alligns
256  // the normals
257  float calculateTwistDelta( int index0, int index1,
258  const UT_Vector3 & n0, const UT_Vector3 & n1,
259  const UT_Vector3Array & points ) const;
260 
261  // rotates to_transform according to the quaternion rotation of the from
262  // vector to the to vector
263  void rotateVector( UT_Vector3 from, UT_Vector3 to,
264  UT_Vector3 & to_transform ) const;
265 
266  // rotates to_transform vector around about vector by the angle
267  void rotateVector( UT_Vector3 about, float angle,
268  UT_Vector3 & to_transform ) const;
269 
270  // pushes the normal forward along the points preserwing zero twist
271  // INPUTS:
272  // from_index - the vertex index from which to move normal
273  // normal - normal to move ( associated with from_index-th vertex )
274  // reuse_direction - the normalized direction from vertex from_index
275  // to vertex from_index+1. If vector is zero, it is
276  // computed internaly. This is intended for reuse during
277  // forward traversals.
278  // OUTPUTS:
279  // normal - moved and transformed normal
280  // reuse_direction - the normalized direction from vertex from_index+1
281  // to vertex from_index+2. If no vertices of such indecis
282  // it is set to zero.
283  void moveNormalForward( const UT_Vector3Array & vertices,
284  int from_index, UT_Vector3 & reuse_direction,
285  UT_Vector3 & normal ) const;
286 
287  // pushes the normal backward along the points preserving zero twist
288  // INPUTS:
289  // from_index - the vertex index from which to move normal
290  // normal - normal to move ( associated with from_index-th vertex )
291  // reuse_direction - the normalized direction from vertex from_index
292  // to vertex from_index-1. If vector is zero, it is
293  // computed internaly. This is intended for reuse during
294  // backward traversals.
295  // OUTPUTS:
296  // normal - moved and transformed normal
297  // reuse_direction - the normalized direction from vertex from_index-1
298  // to vertex from_index-2. If no vertices of such indecis
299  // it is set to zero.
300  void moveNormalBackward( const UT_Vector3Array & vertices,
301  int from_index, UT_Vector3 & reuse_direction,
302  UT_Vector3 & normal ) const;
303 
304  // calculates the start and end tangents of a prim and set them
305  // as the path front and back tangents
306  void setTangents( const GEO_Primitive * prim, const UT_DMatrix4 & mat );
307 
308 
309 private: // data
310 
311  bool myIsClosed; // true if path is a closed loop
312  UT_Vector3Array myVertices; // vertices of the path (sampled rope)
313  UT_Vector3Array myNormals; // normals of the vertices
314  UT_Vector3Array myBreakpointNormals; // normals of breakpoint
315  // contol vertices
316  UT_IntArray myBreakpointIndices; // indices to myVertices for each
317  // breakpoint
318  UT_Vector3 myHeadTangent; // tangent at the path start point
319  UT_Vector3 myTailTangent; // tangent at the path end point
320 };
321 
322 #endif // __GU_Path_H__
bool isClosed() const
Definition: GU_Path.h:164
const UT_Vector3Array & getBreakpointNormals() const
Definition: GU_Path.h:158
3D Vector class.
Quat< T > slerp(const Quat< T > &q1, const Quat< T > &q2, T t)
Definition: ImathQuat.h:495
This class provides a way to manage a reference to an attribute permitting Read-Only access...
const UT_Vector3Array & getNormals() const
Definition: GU_Path.h:152
T angle(const Vec2< T > &v1, const Vec2< T > &v2)
Definition: Vec2.h:472
UT_Vector3 getHeadTangent() const
Definition: GU_Path.h:170
const UT_Vector3Array & getVertices() const
Definition: GU_Path.h:146
#define GU_API
Definition: GU_API.h:12
UT_Vector3 getTailTangent() const
Definition: GU_Path.h:176
GLfloat v0
Definition: glcorearb.h:815
GLuint index
Definition: glcorearb.h:785
GLfloat GLfloat v1
Definition: glcorearb.h:816
gu_CalcMethod
Definition: GU_Path.h:57