00001 #ifndef CURVE_H
00002 #define CURVE_H
00003
00004 #include "Types.h"
00005 #include "AbstractCurve.h"
00006
00007 namespace RenderTools {
00008
00009 using namespace std;
00010
00013 template<class T = Vec3>
00014 class Curve : public AbstractCurve {
00015 public:
00016
00017 Curve( void );
00018 virtual ~Curve( void );
00019
00020 static PropertyPtr create( const XMLNodePtr & xml = XMLNodePtr() );
00021 virtual void createProperties( void );
00022 virtual const string getTypeName( bool ofComponent = false ) const;
00023
00024 virtual void onUpdate( void );
00025 virtual void clear( void );
00026 void addKnot( const T & knot, int index = -1, bool rebuild = true );
00027 void removeKnot( unsigned int index, bool rebuild = true );
00028 T & getKnot( unsigned int index );
00029 const T & getKnot( unsigned int index ) const;
00030 unsigned int getNumKnots( void ) const;
00031 vector< T > & getKnots( void );
00032 const vector< T > & getKnots( void ) const;
00033 T & getPoint( unsigned int index );
00034 const T & getPoint( unsigned int index ) const;
00035 unsigned int getNumPoints( void ) const;
00036 vector< T > & getPoints( void );
00037 const vector< T > & getPoints( void ) const;
00038 T & getTangent( unsigned int index );
00039 const T & getTangent( unsigned int index ) const;
00040 unsigned int getNumTangents( void ) const;
00041 vector< T > & getTangents( void );
00042 const vector< T > & getTangents( void ) const;
00043
00044 protected:
00045 vector<T> m_knots;
00046 vector<T> m_points;
00047 vector<T> m_tangents;
00048
00049 };
00050
00051 template< class T >
00052 Curve< T >::Curve( void ):
00053 AbstractCurve(){
00054 }
00055
00056 template< class T >
00057 Curve< T >::~Curve( void ){
00058
00059 }
00060
00061 template< class T >
00062 void Curve< T >::createProperties( void ){
00063 AbstractCurve::createProperties();
00064 createProperty( this, "points", & m_knots );
00065 }
00066
00067 template< class T >
00068 const string Curve< T >::getTypeName( bool ofComponent ) const {
00069 if( ! ofComponent ){
00070 return( "Curve" );
00071 }
00072 else{
00073 T t;
00074 return( RenderTools::getTypeName( t ) );
00075 }
00076 }
00077
00078 template< class T >
00079 void Curve< T >::addKnot( const T & knot, int index, bool doRebuild ){
00080 if( index < 0 ){
00081 m_knots.push_back( knot );
00082 }
00083 else if( index >= 0 && index < (int)m_knots.size() ){
00084 m_knots.insert( m_knots.begin() + index, knot );
00085 }
00086 else{
00087 Error::error( Error::INDEX_OUT_OF_BOUNDS, __FILE__, __LINE__ );
00088 }
00089 if( doRebuild ){
00090 update( true );
00091 }
00092 }
00093
00094 template< class T >
00095 void Curve< T >::removeKnot( unsigned int index, bool doRebuild ){
00096 if( index >= 0 && index < m_knots.size() ){
00097 m_knots.erase( m_knots.begin() + index );
00098 }
00099 else{
00100 Error::error( Error::INDEX_OUT_OF_BOUNDS, __FILE__, __LINE__ );
00101 }
00102 if( doRebuild ){
00103 update( true );
00104 }
00105 }
00106
00107 template< class T >
00108 void Curve< T >::clear( void ){
00109 m_knots.clear();
00110 m_points.clear();
00111 m_tangents.clear();
00112 }
00113
00114 template< class T >
00115 const T & Curve< T >::getKnot( unsigned int index ) const {
00116 if( index >= 0 && index < m_knots.size() ){
00117 return( m_knots[ index ] );
00118 }
00119 else{
00120 Error::error( Error::INDEX_OUT_OF_BOUNDS, __FILE__, __LINE__ );
00122 static const T v;
00123 return( v );
00124 }
00125 }
00126
00127 template< class T >
00128 T & Curve< T >::getKnot( unsigned int index ){
00129 if( index >= 0 && index < m_knots.size() ){
00130 return( m_knots[ index ] );
00131 }
00132 else{
00133 Error::error( Error::INDEX_OUT_OF_BOUNDS, __FILE__, __LINE__ );
00135 static T v;
00136 return( v );
00137 }
00138 }
00139
00140 template< class T >
00141 unsigned int Curve< T >::getNumKnots( void ) const {
00142 return( m_knots.size() );
00143 }
00144
00145 template< class T >
00146 const vector< T > & Curve< T >::getKnots( void ) const {
00147 return( m_knots );
00148 }
00149
00150 template< class T >
00151 unsigned int Curve< T >::getNumPoints( void ) const {
00152 return( m_points.size() );
00153 }
00154
00155 template< class T >
00156 const vector< T > & Curve< T >::getPoints( void ) const {
00157 return( m_points );
00158 }
00159
00160 template< class T >
00161 const T & Curve< T >::getPoint( unsigned int index ) const {
00162 if( index >= 0 && index < m_points.size() ){
00163 return( m_points[ index ] );
00164 }
00165 else{
00166 Error::error( Error::INDEX_OUT_OF_BOUNDS, __FILE__, __LINE__ );
00168 static const T v;
00169 return( v );
00170 }
00171 }
00172
00173 template< class T >
00174 T & Curve< T >::getPoint( unsigned int index ){
00175 if( index >= 0 && index < m_points.size() ){
00176 return( m_points[ index ] );
00177 }
00178 else{
00179 Error::error( Error::INDEX_OUT_OF_BOUNDS, __FILE__, __LINE__ );
00181 static T v;
00182 return( v );
00183 }
00184 }
00185
00186 template< class T >
00187 unsigned int Curve< T >::getNumTangents( void ) const {
00188 return( m_tangents.size() );
00189 }
00190
00191 template< class T >
00192 const vector< T > & Curve< T >::getTangents( void ) const {
00193 return( m_tangents );
00194 }
00195
00196 template< class T >
00197 const T & Curve< T >::getTangent( unsigned int index ) const {
00198 if( index >= 0 && index < m_tangents.size() ){
00199 return( m_tangents[ index ] );
00200 }
00201 else{
00202 Error::error( Error::INDEX_OUT_OF_BOUNDS, __FILE__, __LINE__ );
00204 static const T v;
00205 return( v );
00206 }
00207 }
00208
00209 template< class T >
00210 T & Curve< T >::getTangent( unsigned int index ){
00211 if( index >= 0 && index < m_tangents.size() ){
00212 return( m_tangents[ index ] );
00213 }
00214 else{
00215 Error::error( Error::INDEX_OUT_OF_BOUNDS, __FILE__, __LINE__ );
00217 static T v;
00218 return( v );
00219 }
00220 }
00221
00222 template< class T >
00223 void Curve< T >::onUpdate( void ){
00224
00225 if( m_closed && m_knots.size() <= 2 ){
00227 T t;
00228 t[0] = 1.0f;
00229 m_tangents.push_back( t );
00230 m_points = m_knots;
00231 return;
00232 }
00233 else if( m_knots.size() <= 1 ){
00234 m_points = m_knots;
00235 T t;
00236 t[0] = 1.0f;
00237 m_tangents.push_back( t );
00238 return;
00239 }
00240
00242 m_points.clear();
00243 m_tangents.clear();
00244
00245 switch( m_interpolationType ){
00246 case LINEAR:
00247 if( m_subdiv == 0 ){
00249 m_points = m_knots;
00251 if( m_closed ){
00252 m_points.push_back( m_knots[ 0 ] );
00253 }
00254 }
00255 else{
00257 vector<T> newCurve;
00258 vector<T> prevCurve = m_knots;
00259 if( m_closed ){
00260 prevCurve.insert( prevCurve.begin(), m_knots[ m_knots.size() - 1 ] );
00261 prevCurve.push_back( m_knots[ 0 ] );
00262 }
00263 for( unsigned int i = 0; i < m_subdiv; i++ ){
00265 newCurve.clear();
00266
00267 if( ! m_closed ){
00268
00269 newCurve.push_back( prevCurve[0] );
00270 }
00271 for( unsigned int j = 0; j < prevCurve.size() - 1; j++ ) {
00272 const T & p0 = prevCurve[ j ];
00273 const T & p1 = prevCurve[ j + 1 ];
00274
00275 newCurve.push_back( mix( p0, p1, 0.25f ) );
00276 newCurve.push_back( mix( p0, p1, 0.75f ) );
00277 }
00278
00279 if( ! m_closed ){
00281 newCurve.push_back( prevCurve[ prevCurve.size() - 1 ] );
00282 }
00284 prevCurve = newCurve;
00285 }
00286
00288 m_points = newCurve;
00289
00291 for( unsigned int i = 0; i < m_points.size(); i++ ){
00292 unsigned int i1 = i;
00293 unsigned int i2 = i + 1;
00294 if( i == m_points.size() - 1 ){
00295 if( m_closed ){
00296 i2 = 0;
00297 }
00298 else{
00299 i1 = m_points.size() - 2;
00300 i2 = m_points.size() - 1;
00301 }
00302 }
00303 m_tangents.push_back( normalize( m_points[ i2 ] - m_points[ i1 ] ) );
00304 }
00305 }
00306 break;
00307 case HERMITE:
00309 for( unsigned int i = 0; i < m_knots.size(); i++ ){
00310
00312 T v0, v1, v2, v3;
00313
00315 int i1 = i, i2 = i + 1;
00316
00317 if( i == m_knots.size() - 1 ){
00319 if( m_closed ){
00321 i2 = 0;
00322 }
00323 else{
00325 break;
00326 }
00327 }
00328
00330 if( i1 == 0 ){
00331 if( m_closed ){
00333 v0 = m_knots[ m_knots.size() - 1 ];
00334 }
00335 else{
00337 v0 = m_knots[ 0 ] - ( m_knots[ 1 ] - m_knots[ 0 ] );
00338 }
00339 }
00340 else{
00342 v0 = m_knots[ i1 - 1 ];
00343 }
00344
00346 v1 = m_knots[ i1 ];
00347 v2 = m_knots[ i2 ];
00348
00350 if( i2 == m_knots.size() - 1 ){
00351 if( m_closed ){
00353 v3 = m_knots[ 0 ];
00354 }
00355 else{
00357 v3 = m_knots[ m_knots.size() - 1 ] + ( m_knots[ m_knots.size() - 1 ] - m_knots[ m_knots.size() - 2 ] );
00358 }
00359 }
00360 else{
00362 v3 = m_knots[ i2 + 1 ];
00363 }
00364
00366 for( unsigned int j = 0; j <= m_subdiv; j++ ){
00367 float f = (float)j / (float)m_subdiv;
00368
00370 if( j == m_subdiv ){
00372 if( ! ( ( ( ! m_closed ) && i == m_knots.size() - 2 ) || \
00373 ( m_closed && i == m_knots.size() - 1 ) ) ){
00374 break;
00375 }
00376 }
00377
00379 T s0, s1;
00380 float f2, f3;
00381 float a0, a1, a2, a3;
00382
00383 f2 = f * f;
00384 f3 = f2 * f;
00385
00386 T v01 = ( v1 - v0 );
00387 T v12 = ( v2 - v1 );
00388 T v23 = ( v3 - v2 );
00389
00390 s0 = v01 * 0.25f;
00391 s0 += v12 * 0.25f;
00392 s1 = v12 * 0.25f;
00393 s1 += v23 * 0.25f;
00394
00395 a0 = 2.0f * f3 - 3.0f * f2 + 1.0f;
00396 a1 = f3 - 2.0f * f2 + f;
00397 a2 = f3 - f2;
00398 a3 = -2.0f * f3 + 3.0f * f2;
00399
00400 m_points.push_back( a0 * v1 + a1 * s0 + a2 * s1 + a3 * v2 );
00401
00403 T t1 = normalize( v01 );
00404 T t2 = normalize( v12 );
00405 T t3 = normalize( v23 );
00407 m_tangents.push_back( normalize( mix( ( t1 + t2 ) * 0.5f, ( t2 + t3 ) * 0.5f, f ) ) );
00408 }
00409 }
00410 break;
00411 }
00412 }
00413
00414 };
00415
00416 #endif