00001 #ifndef MASS_SPRING_ENGINE_INL
00002 #define MASS_SPRING_ENGINE_INL
00003
00004 #include "massSpringEngine.h"
00005 #include <animal/linear.h>
00006 #include <animal/massspringsolver.inl>
00007 #include <animal/container_traits.h>
00008 #include <animal/picking.h>
00009 #include <animal/value.h>
00010
00011 #include <iostream>
00012 #include <vector>
00013 using std::cerr;
00014 using std::endl;
00015
00016 namespace animal
00017 {
00018
00020 template< class Inv_Masses,
00021 class Velocities,
00022 class SpringStiffness,
00023 class IndexedSprings,
00024 class Points,
00025 class Real >
00026 MassSpringEngine< Inv_Masses, Velocities, SpringStiffness, IndexedSprings, Points, Real >
00027 ::MassSpringEngine()
00028 : _velocities(0)
00029 , _points(0)
00030 , _pointSize(8)
00031 , _lineWidth(4)
00032 {
00033 compressed_ok = false;
00034 elongated_ok = false;
00035 displayMassSpring = true;
00036 }
00037
00039 template< class Inv_Masses,
00040 class Velocities,
00041 class SpringStiffness,
00042 class IndexedSprings,
00043 class Points,
00044 class Real >
00045 MassSpringEngine< Inv_Masses, Velocities, SpringStiffness, IndexedSprings, Points, Real >
00046 ::~MassSpringEngine()
00047 {}
00048
00049
00050
00051
00052
00054 template< class Inv_Masses,
00055 class Velocities,
00056 class SpringStiffness,
00057 class IndexedSprings,
00058 class Points,
00059 class Real >
00060 void MassSpringEngine< Inv_Masses, Velocities, SpringStiffness, IndexedSprings, Points, Real >
00061 ::reset()
00062 {
00063
00064 if (_points && _velocities)
00065 {
00066 v_eq(*_points, _initialPoints);
00067 v_eq(*_velocities, _initialVelocities);
00068 resize(elongation,size(*_stiffnesses));
00069 resize(colours,size(*_stiffnesses));
00070 for(unsigned i=0;i<size(*_links);i+=2)
00071 {
00072 elongation[i/2]=v_norm((*_points)[(*_links)[i]]-(*_points)[(*_links)[i+1]]) - (*get_rest_lengths())[i/2];
00073 colours[i/2].r=0.0;
00074 colours[i/2].g=0.0;
00075 colours[i/2].b=0.0;
00076 }
00077 }
00078 }
00079
00080 template< class Inv_Masses,
00081 class Velocities,
00082 class SpringStiffness,
00083 class IndexedSprings,
00084 class Points,
00085 class Real >
00086 void MassSpringEngine< Inv_Masses, Velocities, SpringStiffness, IndexedSprings, Points, Real >
00087 ::draw()
00088 {
00089 if (get_displayMassSpring())
00090 {
00091
00092 glPushAttrib(GL_LIGHTING_BIT | GL_POINT_BIT| GL_LINE_BIT);
00093 glDisable(GL_LIGHTING);
00094 glLineWidth(_lineWidth);
00095 if( _links )
00096 {
00097 glBegin(GL_LINES);
00098 unsigned i=0;
00099
00100 Index p1=0;
00101
00102 Index p2=0;
00103 float elong;
00104
00105
00106 while(i<size(*_links)-1)
00107 {
00108 float r,g,b;
00109 p1=(*_links)[i];
00110 p2=(*_links)[i+1];
00111 elong = v_norm((*_points)[p1]-(*_points)[p2]) - (*get_rest_lengths())[i/2];
00112
00113
00114 if(elongation[i/2]>elong && compressed_ok)
00115 {
00116 r=0.0;
00117 g=1.0;
00118 b=0.0;
00119 glColor3f(r,g,b);
00120 elongation[i/2]=elong;
00121 colours[i/2].r=r;
00122 colours[i/2].g=g;
00123 colours[i/2].b=b;
00124 }
00125
00126 else if(elongation[i/2]<elong && elongated_ok)
00127 {
00128 r=1.0;
00129 g=0.0;
00130 b=1.0;
00131 glColor3f(r,g,b);
00132 elongation[i/2]=elong;
00133 colours[i/2].r=r;
00134 colours[i/2].g=g;
00135 colours[i/2].b=b;
00136 }
00137
00138 else
00139 {
00140 glColor3f(0,0,0);
00141 elongation[i/2]=elong;
00142 }
00143 glVertex3f((*_points)[p1].x,(*_points)[p1].y,(*_points)[p1].z);
00144 glVertex3f((*_points)[p2].x,(*_points)[p2].y,(*_points)[p2].z);
00145 i=i+2;
00146 }
00147 glEnd();
00148 }
00149
00150
00151 glDisable(GL_POINT_SMOOTH);
00152 glPointSize(_pointSize);
00153 glBegin(GL_POINTS);
00154 glColor3f(1,1,1);
00155 for( unsigned int i=0; i<size(*_points); ++i )
00156 {
00157 glVertex3f((*_points)[i].x,(*_points)[i].y,(*_points)[i].z);
00158 }
00159 glEnd();
00160 glPopAttrib();
00161 }
00162 }
00163
00165 template< class Inv_Masses,
00166 class Velocities,
00167 class SpringStiffness,
00168 class IndexedSprings,
00169 class Points,
00170 class Real >
00171 void MassSpringEngine< Inv_Masses, Velocities, SpringStiffness, IndexedSprings, Points, Real >
00172 ::move(double dt)
00173 {
00174 Velocities force;
00175 resize(force, size(*_velocities));
00176 if (_points && _velocities)
00177 {
00178 this->_MassSpringSolver::solveODE( *_points, *_velocities, dt );
00179
00180 if (get_displayMassSpring())
00181 this->_MassSpringSolver::computeForces(force,*_points,*_velocities);
00182
00183 }
00184 }
00185
00187 template< class Inv_Masses,
00188 class Velocities,
00189 class SpringStiffness,
00190 class IndexedSprings,
00191 class Points,
00192 class Real >
00193 void MassSpringEngine< Inv_Masses, Velocities, SpringStiffness, IndexedSprings, Points, Real >
00194 ::getBoundingBox(float &minX, float &minY, float &minZ, float &maxX, float &maxY, float &maxZ)
00195 {
00196 if(_points->size()==0 )
00197 {
00198 cerr<<"MassSpringEngine::getBoundingBox can not find bounding box because there are no particles" << endl;
00199 return;
00200 }
00201 minX=maxX=(*_points)[0].x;
00202 minY=maxY=(*_points)[1].y;
00203 minZ=maxZ=(*_points)[2].z;
00204 for( unsigned i=1; i<_points->size(); ++i )
00205 {
00206 if( (*_points)[i].x<minX )
00207 minX=(*_points)[i].x;
00208 if( (*_points)[i].x>maxX )
00209 maxX=(*_points)[i].x;
00210 if( (*_points)[i].y<minY )
00211 minY=(*_points)[i].y;
00212 if( (*_points)[i].y>maxY )
00213 maxY=(*_points)[i].y;
00214 if( (*_points)[i].z<minZ )
00215 minZ=(*_points)[i].z;
00216 if( (*_points)[i].z>maxZ )
00217 maxZ=(*_points)[i].z;
00218 }
00219
00220 }
00221
00223 template< class Inv_Masses,
00224 class Velocities,
00225 class SpringStiffness,
00226 class IndexedSprings,
00227 class Points,
00228 class Real >
00229 void MassSpringEngine< Inv_Masses, Velocities, SpringStiffness, IndexedSprings, Points, Real >
00230 ::mousePressEvent( MouseEvent* )
00231 {
00232
00233 }
00234
00235
00236
00238 template< class Inv_Masses,
00239 class Velocities,
00240 class SpringStiffness,
00241 class IndexedSprings,
00242 class Points,
00243 class Real >
00244 MassSpringEngine< Inv_Masses, Velocities, SpringStiffness, IndexedSprings, Points, Real >
00245 ::ConstrainedPoint::ConstrainedPoint( MassSpringEngine* mse, int index )
00246 : _mse(mse)
00247 , _index(index)
00248 , invmass( (*mse->_invMasses)[index] )
00249 {
00250
00251 }
00252
00254 template< class Inv_Masses,
00255 class Velocities,
00256 class SpringStiffness,
00257 class IndexedSprings,
00258 class Points,
00259 class Real >
00260 void MassSpringEngine< Inv_Masses, Velocities, SpringStiffness, IndexedSprings, Points, Real >
00261 ::ConstrainedPoint::getPoint( float& x, float& y, float& z ) const
00262 {
00263 x= (*_mse->_points)[_index].x;
00264 y= (*_mse->_points)[_index].y;
00265 z= (*_mse->_points)[_index].z;
00266 }
00267
00269 template< class Inv_Masses,
00270 class Velocities,
00271 class SpringStiffness,
00272 class IndexedSprings,
00273 class Points,
00274 class Real >
00275 void MassSpringEngine< Inv_Masses, Velocities, SpringStiffness, IndexedSprings, Points, Real >
00276 ::ConstrainedPoint::moveTo( float x, float y, float z ) const
00277 {
00278 (*_mse->_points)[_index].x = x;
00279 (*_mse->_points)[_index].y = y;
00280 (*_mse->_points)[_index].z = z;
00281 (*_mse->_invMasses)[_index] = 0.0;
00282 typedef typename container_traits<Velocities>::value_type Velocity;
00283 (*_mse->_velocities)[_index] = Value<Velocity>::zero() ;
00284
00285
00286 }
00287
00289 template< class Inv_Masses,
00290 class Velocities,
00291 class SpringStiffness,
00292 class IndexedSprings,
00293 class Points,
00294 class Real >
00295 void MassSpringEngine< Inv_Masses, Velocities, SpringStiffness, IndexedSprings, Points, Real >
00296 ::ConstrainedPoint::print() const
00297 {
00298
00299 }
00300
00302 template< class Inv_Masses,
00303 class Velocities,
00304 class SpringStiffness,
00305 class IndexedSprings,
00306 class Points,
00307 class Real >
00308 MassSpringEngine< Inv_Masses, Velocities, SpringStiffness, IndexedSprings, Points, Real >
00309 ::ConstrainedPoint::~ConstrainedPoint()
00310 {
00311 (*_mse->_invMasses)[_index] = invmass;
00312 }
00313
00315 template< class Inv_Masses,
00316 class Velocities,
00317 class SpringStiffness,
00318 class IndexedSprings,
00319 class Points,
00320 class Real >
00321 bool MassSpringEngine< Inv_Masses, Velocities, SpringStiffness, IndexedSprings, Points, Real >
00322 ::ConstrainedPoint::operator == ( const ConstrainedItem* it ) const
00323 {
00324 const ConstrainedPoint* ptr_item = dynamic_cast<const ConstrainedPoint*>(it);
00325 if( ptr_item )
00326 {
00327 if(ptr_item->_mse == this->_mse)
00328 {
00329
00330 }
00331 return (ptr_item->_mse == this->_mse) && (ptr_item->_index == this->_index);
00332 }
00333 else
00334 return false;
00335
00336 }
00337
00339 template< class Inv_Masses,
00340 class Velocities,
00341 class SpringStiffness,
00342 class IndexedSprings,
00343 class Points,
00344 class Real >
00345 ConstrainedItem* MassSpringEngine< Inv_Masses, Velocities, SpringStiffness, IndexedSprings, Points, Real >
00346 ::pickPoint( float origin[3], float direction[3], float threshold )
00347 {
00348
00349 int index;
00350 float distance;
00351 typedef typename container_traits<Points>::value_type Vect;
00352 Vect lineOrigin(origin[0], origin[1], origin[2]);
00353 Vect lineDirection(direction[0],direction[1],direction[2]);
00354 if( findClosestPointToLine( index, distance, *_points, lineOrigin, lineDirection, threshold ) )
00355 return new ConstrainedPoint(this,index);
00356 else
00357 return 0;
00358 }
00359
00360
00361
00363 template< class Inv_Masses,
00364 class Velocities,
00365 class SpringStiffness,
00366 class IndexedSprings,
00367 class Points,
00368 class Real >
00369 bool MassSpringEngine< Inv_Masses, Velocities, SpringStiffness, IndexedSprings, Points, Real >
00370 ::get_compressed_ok()
00371 {
00372 return compressed_ok;
00373 }
00374
00376 template< class Inv_Masses,
00377 class Velocities,
00378 class SpringStiffness,
00379 class IndexedSprings,
00380 class Points,
00381 class Real >
00382 void MassSpringEngine< Inv_Masses, Velocities, SpringStiffness, IndexedSprings, Points, Real >
00383 ::set_compressed_ok(bool ok)
00384 {
00385 compressed_ok = ok;
00386 }
00387
00389 template< class Inv_Masses,
00390 class Velocities,
00391 class SpringStiffness,
00392 class IndexedSprings,
00393 class Points,
00394 class Real >
00395 bool MassSpringEngine< Inv_Masses, Velocities, SpringStiffness, IndexedSprings, Points, Real >
00396 ::get_elongated_ok()
00397 {
00398 return elongated_ok;
00399 }
00400
00402 template< class Inv_Masses,
00403 class Velocities,
00404 class SpringStiffness,
00405 class IndexedSprings,
00406 class Points,
00407 class Real >
00408 void MassSpringEngine< Inv_Masses, Velocities, SpringStiffness, IndexedSprings, Points, Real >
00409 ::set_elongated_ok(bool ok)
00410 {
00411 elongated_ok = ok;
00412 }
00413
00415 template< class Inv_Masses,
00416 class Velocities,
00417 class SpringStiffness,
00418 class IndexedSprings,
00419 class Points,
00420 class Real >
00421 bool MassSpringEngine< Inv_Masses, Velocities, SpringStiffness, IndexedSprings, Points, Real >
00422 ::get_displayMassSpring()
00423 {
00424 return displayMassSpring;
00425 }
00426
00428 template< class Inv_Masses,
00429 class Velocities,
00430 class SpringStiffness,
00431 class IndexedSprings,
00432 class Points,
00433 class Real >
00434 void MassSpringEngine< Inv_Masses, Velocities, SpringStiffness, IndexedSprings, Points, Real >
00435 ::set_displayMassSpring(bool display)
00436 {
00437 displayMassSpring=display;
00438 }
00439
00440
00442 template< class Inv_Masses,
00443 class Velocities,
00444 class SpringStiffness,
00445 class IndexedSprings,
00446 class Points,
00447 class Real >
00448 int MassSpringEngine< Inv_Masses, Velocities, SpringStiffness, IndexedSprings, Points, Real >
00449 ::get_pointSize() const
00450 {
00451 return _pointSize;
00452 }
00453
00455 template< class Inv_Masses,
00456 class Velocities,
00457 class SpringStiffness,
00458 class IndexedSprings,
00459 class Points,
00460 class Real >
00461 void MassSpringEngine< Inv_Masses, Velocities, SpringStiffness, IndexedSprings, Points, Real >
00462 ::set_pointSize(int s)
00463 {
00464 _pointSize=s;
00465 }
00466
00468 template< class Inv_Masses,
00469 class Velocities,
00470 class SpringStiffness,
00471 class IndexedSprings,
00472 class Points,
00473 class Real >
00474 int MassSpringEngine< Inv_Masses, Velocities, SpringStiffness, IndexedSprings, Points, Real >
00475 ::get_lineWidth() const
00476 {
00477 return _lineWidth;
00478 }
00479
00481 template< class Inv_Masses,
00482 class Velocities,
00483 class SpringStiffness,
00484 class IndexedSprings,
00485 class Points,
00486 class Real >
00487 void MassSpringEngine< Inv_Masses, Velocities, SpringStiffness, IndexedSprings, Points, Real >
00488 ::set_lineWidth(int s)
00489 {
00490 _lineWidth=s;
00491 }
00492
00493
00494
00495
00497
00498
00499
00500
00501
00502
00503
00504
00505
00506
00507
00508
00509
00510
00511
00512
00513
00514
00515
00516
00517
00518
00519
00520
00521
00522
00523
00524
00525
00526
00527
00528
00529
00530
00531
00532
00533
00534
00535
00536
00537
00538
00539
00540
00541
00542
00543
00544
00545
00546 }
00547
00548 #endif //MASS_SPRING_ENGINE_INL