00001 /* 00002 * PROPRIETARY INFORMATION. This software is proprietary to 00003 * Side Effects Software Inc., and is not to be reproduced, 00004 * transmitted, or disclosed in any way without written permission. 00005 * 00006 * Produced by: 00007 * Rafal Jaroszkiewicz 00008 * Side Effects Software Inc 00009 * 477 Richmond Street West 00010 * Toronto, Ontario 00011 * Canada M5V 3E7 00012 * 416-504-9876 00013 * 00014 * NAME: GU_Path.h (GEO Utility library, C++) 00015 * 00016 * COMMENTS: This class implements the utilities for the path. Path 00017 * is a curve that behaves like a rope or semi-flexible string 00018 * (but the behaviour of the path may be extended in the future 00019 * to incorporate other behaviours). Path curve has normal 00020 * attribute (and potentially a twist attribute) to define 00021 * the orientation of the rope, so that it can simulate 00022 * the twisting behavoiur in addition to the bending behaviour. 00023 * 00024 * Primary use of this class is intended for the object level 00025 * path normal computation (which is used when generating 00026 * bones on the path and solving them in follow curve IK chop). 00027 * We are primarily interested in the normals at sample points. 00028 * The sample points are taken from the Bezier or NURBS curve. 00029 * The setup of the object level path is such that only 00030 * breakpoints are intended for maniputaling curve (via 00031 * object level Path CVs). Thus the GU_Path, obtains 00032 * the breakpoint data (normals, twists, etc) and uses it 00033 * for interpolating the brakpoint normals among the sampled 00034 * points. So, Bezier segments are preferable inputs to the 00035 * GU_Path, but NRBS curves are also handled: the breakpoint 00036 * data is evaluated from the CVs and then used as for Bezier 00037 * curves. 00038 */ 00039 00040 #ifndef __GU_Path_H__ 00041 #define __GU_Path_H__ 00042 00043 00044 #include "GU_API.h" 00045 // includes 00046 #include <UT/UT_Vector3Array.h> 00047 #include <UT/UT_IntArray.h> 00048 #include <UT/UT_Vector3.h> 00049 00050 // class declarations 00051 class GEO_PrimPoly; 00052 class GEO_Primitive; 00053 class GEO_Curve; 00054 class GU_Detail; 00055 class UT_DMatrix4; 00056 class UT_FloatArray; 00057 00058 00059 // Path class 00060 class GU_API GU_Path 00061 { 00062 public: 00063 00064 // the calculation method of the normals 00065 enum gu_CalcMethod 00066 { 00067 GU_CALC_DEFAULT, // default 00068 GU_CALC_NONE, // no normals are computed 00069 GU_CALC_QUAT, // interpolating with quaternions 00070 GU_CALC_TWIST_SHORT,// interpolating with twist angles in 0..180 range 00071 GU_CALC_TWIST_FULL // interpolating with twist angles in any range 00072 }; 00073 00074 // constructor 00075 GU_Path(); 00076 00077 // destructor 00078 ~GU_Path(); 00079 00080 // Calculate the path object from the curve object. 00081 // Normals associated with the curve's breakpoints (!) 00082 // are retargeted for the path object, if curve has normal attribute. 00083 // Otherwise path object will not 00084 // have normals. If curve has twist attribute, the normals for the path 00085 // are interpolated according to the angle around the path (like a twisted 00086 // rope or string), otherwise a quaternion interpolation of curve normals 00087 // is used. 00088 // INPUT: 00089 // curve - the detail whose first primitive is a curve. 00090 // It may have normal attribute 00091 // and twist attribute. Twist is the angle of rotation 00092 // around the path (synonims: curve, rope) measured from 00093 // its natural "rest" orientation (presumably defined 00094 // at the path creation time). If 00095 // mat - the matrix used to transform the curve's sampled points, 00096 // before assigning them to the path. 00097 // normal_comp_type - a method for interpolating the normals at 00098 // the breakpoints. Default uses best method for which 00099 // we have enough information. 00100 // RETURN: 00101 // true on success, false if failed 00102 bool computePathFromCurve( const GU_Detail * curve, 00103 const UT_DMatrix4 & mat, 00104 gu_CalcMethod normal_comp_type = 00105 GU_CALC_DEFAULT ); 00106 00107 // Calculate the path from detail object containing a curve. 00108 // Normals for the path are calculated so that they flow naturally 00109 // without any twist differences between breakpoints. 00110 // INPUT: 00111 // curve - detail containing a curve 00112 // normal - a normal to match on cv_index-th breakpoint of the curve 00113 // cv_index - index of the breakpoint whose normal should be the same 00114 // as 'normal' argument 00115 // RETURN: 00116 // true on success, false if failed 00117 bool computeNaturalPathFromCurve( const GU_Detail * curve, 00118 const UT_Vector3& normal, 00119 int cv_index = 0); 00120 00121 // calculates the positions of the joints along the path. 00122 // The joints mark uniform arc length segments along the path. 00123 // INPUT: 00124 // num_of_segments - number of segments (n+1 sample points) for resampling 00125 // OUTPUT: 00126 // joints - array of vertices that resample the path 00127 // normals - array of normals associated with joints. This array 00128 // is set to empty if path has no normals. 00129 void resamplePath( int num_of_segments, 00130 UT_Vector3Array & joints, 00131 UT_Vector3Array & normals ) const; 00132 00133 // obtains the twist angles between path's breakpoint normals 00134 // and the vectors passed in 00135 // INPUT: 00136 // vectors - vectors against which to compute twist angles. Should 00137 // be the same size as the array returned by getBreakpointNormals() 00138 // OUTPUT: 00139 // angles - angles in degrees by which i-th breakpoint normal needs to be 00140 // rotated while traversing the path to match the i+1-th vector. 00141 // The angles are in the interval [-180, 180]. 00142 // RETURN: 00143 // true on success, false on failure 00144 bool getBreakpointTwists( const UT_Vector3Array & vectors, 00145 UT_FloatArray & angles ); 00146 00147 // do a spherical linear interpolation (slerp) between two vectors 00148 // using t = [0, 1] as a blending factor 00149 static UT_Vector3 slerp( const UT_Vector3 & v0, const UT_Vector3 & v1, 00150 double t ); 00151 00152 // obtains path's vertices 00153 const UT_Vector3Array & getVertices() const 00154 { 00155 return myVertices; 00156 } 00157 00158 // obtains path's normals 00159 const UT_Vector3Array & getNormals() const 00160 { 00161 return myNormals; 00162 } 00163 00164 // obtains path breakpoints' normals 00165 const UT_Vector3Array & getBreakpointNormals() const 00166 { 00167 return myBreakpointNormals; 00168 } 00169 00170 // true if path is closed 00171 bool isClosed() const 00172 { 00173 return myIsClosed; 00174 } 00175 00176 // obtains a tangent at the path start point 00177 UT_Vector3 getHeadTangent() const 00178 { 00179 return myHeadTangent; 00180 } 00181 00182 // obtains a tangent at the path end point 00183 UT_Vector3 getTailTangent() const 00184 { 00185 return myTailTangent; 00186 } 00187 00188 private: // methods 00189 00190 // suck data from the poly and transfer it to ourselves. Curve 00191 // is used for finding and interpolating the attributes like 00192 // the normals. If it is NULL, then no normals will be computed 00193 // for the path object. Otherwise the normal_comp_type determines 00194 // the method for interpolating the normals (provided enough 00195 // information is given in curve) 00196 void getDataFromPoly( const GU_Detail * detail, 00197 const GEO_PrimPoly * poly, 00198 const GEO_Curve * curve, 00199 const UT_DMatrix4 & mat, 00200 gu_CalcMethod normal_comp_type = 00201 GU_CALC_DEFAULT ); 00202 00203 // construct the path from poly, and assign natually flowing normals 00204 // to the vertices. If curve is not NULL, also the breakpoint normals 00205 // for that curve are computed and stored in member data field. 00206 void computeNaturalPathFromPoly(const GEO_PrimPoly * poly, 00207 const GEO_Curve * curve, 00208 const UT_Vector3& normal, int cv_index ); 00209 00210 // interpolate normals between the breakpoints of the curve and 00211 // set them for our path object 00212 // (i.e., for each verex in myVertices compute appropriate normal 00213 // in myNormals) 00214 // NB: curve must have the normal attribute 00215 void setInterpolatedNormals( const GU_Detail * detail, 00216 const GEO_Curve * curve ); 00217 00218 // for each vertex in myVertices interpolate twist (rotation angle 00219 // around the curve) between the breakpoints of the curve and 00220 // use this twist to find the normal (and set it in myNormals). 00221 // If clamp_range is true, the twist between the breakpoints 00222 // is going to be within [-180, 180]. Otherwise the twist is unlimited 00223 // in its range 00224 // NB: curve must have the normal attribute 00225 // NB: all the breakpoints of the curve, must have a corresponding point 00226 // in vertices array myVertices that have the same position. 00227 void setTwistedNormals( const GU_Detail * detail, 00228 const GEO_Curve * curve, 00229 bool clamp_range = false); 00230 00231 // for each vertex in myVertices assign a normal (stored in myNormals) 00232 // using the natural flow. If curve is not null then its index-th control 00233 // will have the 'normal' orientation. If curve is null the index-th 00234 // vertex will have the orientation alligned with normal. 00235 void setNaturalNormals( const GEO_Curve *curve, 00236 const UT_Vector3& normal, int index ); 00237 00238 // sets our normals from the poly. It is one to one correspondence 00239 // with the poly (the normals), thus the poly must have the same 00240 // number of vertices as we do. 00241 void setPolyNormals( const GU_Detail *detail, 00242 const GEO_PrimPoly * poly ); 00243 00244 // calculates length as a sum of distances between 'points'. Points 00245 // should have at least 2 entries. Additionally, if curve and 00246 // break_arc_lengts are not null, break_arc_lengths will be filled 00247 // with arc length parameter for each of curve's breakpoint measured 00248 // along the points. All curve's breakpoint locations must coincide 00249 // with some of the points (up to tollerance level). If 00250 // vertex_indices is not null it is filled with vertex indices that 00251 // coincide with the curve's breakpoints. 00252 float calculateLength( const UT_Vector3Array & points, 00253 const GEO_Curve * curve = NULL, 00254 UT_FloatArray * break_arc_lengths = NULL, 00255 UT_IntArray * break_vertex_indices =NULL)const; 00256 00257 // returns the angular twist (radians) difference around the curve. That is, 00258 // the angle by which the normal n0 needs to be rotated, as we traverse 00259 // down the curve, to allign it with n1. index0 and index1 are point indices 00260 // corresponing to the normals n0 and n1. 00261 // RETURNS: 00262 // the twist angle between points index0 and index1 that alligns 00263 // the normals 00264 float calculateTwistDelta( int index0, int index1, 00265 const UT_Vector3 & n0, const UT_Vector3 & n1, 00266 const UT_Vector3Array & points ) const; 00267 00268 // returns the offset to the normals, or -1 if not found 00269 int findNormalAttributeOffset( const GU_Detail * detail ) const; 00270 00271 // returns the offset to the twist attribute or -1 if not found 00272 int findTwistAttributeOffset( const GU_Detail * detail ) const; 00273 int findInitialTwistAttributeOffset(const GU_Detail * detail )const; 00274 00275 00276 // rotates to_transform according to the quaternion rotation of the from 00277 // vector to the to vector 00278 void rotateVector( UT_Vector3 from, UT_Vector3 to, 00279 UT_Vector3 & to_transform ) const; 00280 00281 // rotates to_transform vector around about vector by the angle 00282 void rotateVector( UT_Vector3 about, float angle, 00283 UT_Vector3 & to_transform ) const; 00284 00285 // pushes the normal forward along the points preserwing zero twist 00286 // INPUTS: 00287 // from_index - the vertex index from which to move normal 00288 // normal - normal to move ( associated with from_index-th vertex ) 00289 // reuse_direction - the normalized direction from vertex from_index 00290 // to vertex from_index+1. If vector is zero, it is 00291 // computed internaly. This is intended for reuse during 00292 // forward traversals. 00293 // OUTPUTS: 00294 // normal - moved and transformed normal 00295 // reuse_direction - the normalized direction from vertex from_index+1 00296 // to vertex from_index+2. If no vertices of such indecis 00297 // it is set to zero. 00298 void moveNormalForward( const UT_Vector3Array & vertices, 00299 int from_index, UT_Vector3 & reuse_direction, 00300 UT_Vector3 & normal ) const; 00301 00302 // pushes the normal backward along the points preserving zero twist 00303 // INPUTS: 00304 // from_index - the vertex index from which to move normal 00305 // normal - normal to move ( associated with from_index-th vertex ) 00306 // reuse_direction - the normalized direction from vertex from_index 00307 // to vertex from_index-1. If vector is zero, it is 00308 // computed internaly. This is intended for reuse during 00309 // backward traversals. 00310 // OUTPUTS: 00311 // normal - moved and transformed normal 00312 // reuse_direction - the normalized direction from vertex from_index-1 00313 // to vertex from_index-2. If no vertices of such indecis 00314 // it is set to zero. 00315 void moveNormalBackward( const UT_Vector3Array & vertices, 00316 int from_index, UT_Vector3 & reuse_direction, 00317 UT_Vector3 & normal ) const; 00318 00319 // calculates the start and end tangents of a prim and set them 00320 // as the path front and back tangents 00321 void setTangents( const GEO_Primitive * prim, const UT_DMatrix4 & mat ); 00322 00323 00324 private: // data 00325 00326 bool myIsClosed; // true if path is a closed loop 00327 UT_Vector3Array myVertices; // vertices of the path (sampled rope) 00328 UT_Vector3Array myNormals; // normals of the vertices 00329 UT_Vector3Array myBreakpointNormals; // normals of breakpoint 00330 // contol vertices 00331 UT_IntArray myBreakpointIndices; // indices to myVertices for each 00332 // breakpoint 00333 UT_Vector3 myHeadTangent; // tangent at the path start point 00334 UT_Vector3 myTailTangent; // tangent at the path end point 00335 }; 00336 00337 #endif // __GU_Path_H__
1.5.9