00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028 #include "Joint.h"
00029 #include "Solid.h"
00030
00031 namespace opal
00032 {
00033 Joint::Joint()
00034 {
00035
00036 setJointBreakEventHandler( NULL );
00037 setUserData( NULL );
00038 mInitCalled = false;
00039 mNumAxes = 0;
00040 mAxisRotational[ 0 ] = false;
00041 mAxisRotational[ 1 ] = false;
00042 mAxisRotational[ 2 ] = false;
00043 }
00044
00045 Joint::~Joint()
00046 {}
00047
00048 void Joint::internal_destroy()
00049 {
00050 delete this;
00051 }
00052
00053 void Joint::init( const JointData& data )
00054 {
00055 mData = data;
00056 }
00057
00058 const JointData& Joint::getData()
00059 {
00060
00061 for ( int i = 0; i < mNumAxes; ++i )
00062 {
00063 mData.axis[ i ] = getAxis( i );
00064 }
00065
00066 mData.anchor = getAnchor();
00067
00068 return mData;
00069 }
00070
00071 void Joint::setName( const std::string& name )
00072 {
00073 mData.name = name;
00074 }
00075
00076 const std::string& Joint::getName() const
00077 {
00078 return mData.name;
00079 }
00080
00081 void Joint::setContactsEnabled( bool e )
00082 {
00083 mData.contactsEnabled = e;
00084 }
00085
00086 bool Joint::areContactsEnabled() const
00087 {
00088 return mData.contactsEnabled;
00089 }
00090
00091 JointType Joint::getType() const
00092 {
00093 return mData.getType();
00094 }
00095
00096 void Joint::setBreakParams( JointBreakMode mode, real breakThresh,
00097 real accumThresh )
00098 {
00099 mData.breakMode = mode;
00100 mData.breakThresh = breakThresh;
00101 mData.accumThresh = accumThresh;
00102 }
00103
00104 bool Joint::isBroken() const
00105 {
00106 return mData.isBroken;
00107 }
00108
00109 JointBreakMode Joint::getBreakingMode() const
00110 {
00111 return mData.breakMode;
00112 }
00113
00114 real Joint::getBreakThresh() const
00115 {
00116 return mData.breakThresh;
00117 }
00118
00119 real Joint::getAccumulatedDamage() const
00120 {
00121 return mData.accumDamage;
00122 }
00123
00124 real Joint::getAccumulatedThresh() const
00125 {
00126 return mData.accumThresh;
00127 }
00128
00129 void Joint::repairAccumDamage()
00130 {
00131 mData.accumDamage = 0;
00132
00133 }
00134
00135
00136
00137
00138
00139
00140 void Joint::setJointBreakEventHandler(
00141 JointBreakEventHandler* eventHandler )
00142 {
00143 mJointBreakEventHandler = eventHandler;
00144 }
00145
00146 JointBreakEventHandler* Joint::getJointBreakEventHandler() const
00147 {
00148 return mJointBreakEventHandler;
00149 }
00150
00151 void Joint::setLimitsEnabled( int axisNum, bool e )
00152 {
00153 assert( axisNum >= 0 && axisNum < mNumAxes );
00154 mData.axis[ axisNum ].limitsEnabled = e;
00155 }
00156
00157 bool Joint::areLimitsEnabled( int axisNum )
00158 {
00159 assert( axisNum >= 0 && axisNum < mNumAxes );
00160 return mData.axis[ axisNum ].limitsEnabled;
00161 }
00162
00163
00164
00165
00166
00167
00168
00169
00170
00171
00172
00173
00174
00175
00176
00177 void Joint::setLimitRange( int axisNum, real low, real high )
00178 {
00179 assert( high >= low );
00180 assert( axisNum >= 0 && axisNum < mNumAxes );
00181 mData.axis[ axisNum ].limits.low = low;
00182 mData.axis[ axisNum ].limits.high = high;
00183 }
00184
00185 real Joint::getLowLimit( int axisNum ) const
00186 {
00187 assert( axisNum >= 0 && axisNum < mNumAxes );
00188 return mData.axis[ axisNum ].limits.low;
00189 }
00190
00191 real Joint::getHighLimit( int axisNum ) const
00192 {
00193 assert( axisNum >= 0 && axisNum < mNumAxes );
00194 return mData.axis[ axisNum ].limits.high;
00195 }
00196
00197 void Joint::setLimitHardness( int axisNum, real h )
00198 {
00199 assert( h >= 0 && h <= 1 );
00200 assert( axisNum >= 0 && axisNum < mNumAxes );
00201 mData.axis[ axisNum ].limits.hardness = h;
00202 }
00203
00204 real Joint::getLimitHardness( int axisNum ) const
00205 {
00206 assert( axisNum >= 0 && axisNum < mNumAxes );
00207 return mData.axis[ axisNum ].limits.hardness;
00208 }
00209
00210 void Joint::setLimitBounciness( int axisNum, real b )
00211 {
00212 assert( b >= 0 && b <= 1 );
00213 assert( axisNum >= 0 && axisNum < mNumAxes );
00214 mData.axis[ axisNum ].limits.bounciness = b;
00215 }
00216
00217 real Joint::getLimitBounciness( int axisNum ) const
00218 {
00219 assert( axisNum >= 0 && axisNum < mNumAxes );
00220 return mData.axis[ axisNum ].limits.bounciness;
00221 }
00222
00223 void Joint::addForce( int axisNum, real magnitude, real duration,
00224 bool singleStep )
00225 {
00226 assert( axisNum >= 0 && axisNum < mNumAxes );
00227
00228 if ( mData.enabled )
00229 {
00230 Force f;
00231 f.singleStep = singleStep;
00232
00233
00234
00235 if ( !f.singleStep )
00236 {
00237 f.duration = duration;
00238 }
00239
00240 f.type = LOCAL_FORCE;
00241 Vec3r direction = mData.axis[ axisNum ].direction;
00242 f.vec = magnitude * direction;
00243
00244 if ( mData.solid0 )
00245 {
00246 mData.solid0->addForce( f );
00247 }
00248
00249 f.vec *= ( real ) - 1.0;
00250
00251 if ( mData.solid1 )
00252 {
00253 mData.solid1->addForce( f );
00254 }
00255 }
00256 }
00257
00258 void Joint::addTorque( int axisNum, real magnitude, real duration,
00259 bool singleStep )
00260 {
00261 assert( axisNum >= 0 && axisNum < mNumAxes );
00262
00263 if ( mData.enabled )
00264 {
00265 Force f;
00266 f.singleStep = singleStep;
00267
00268
00269
00270 if ( !f.singleStep )
00271 {
00272 f.duration = duration;
00273 }
00274
00275 f.type = LOCAL_TORQUE;
00276 Vec3r axis = mData.axis[ axisNum ].direction;
00277 f.vec = magnitude * axis;
00278
00279 if ( mData.solid0 )
00280 {
00281 mData.solid0->addForce( f );
00282 }
00283
00284 f.vec *= ( real ) - 1.0;
00285
00286 if ( mData.solid1 )
00287 {
00288 mData.solid1->addForce( f );
00289 }
00290 }
00291 }
00292
00293 void Joint::wakeSolids()
00294 {
00295 if ( mData.solid0 )
00296 mData.solid0->setSleeping( false );
00297 if ( mData.solid1 )
00298 mData.solid1->setSleeping( false );
00299 }
00300
00301 void Joint::setSolids( Solid* s0, Solid* s1 )
00302 {
00303 mData.solid0 = s0;
00304 mData.solid1 = s1;
00305 }
00306
00307 Solid* Joint::getSolid0() const
00308 {
00309 return mData.solid0;
00310 }
00311
00312 Solid* Joint::getSolid1() const
00313 {
00314 return mData.solid1;
00315 }
00316
00317 void Joint::setAxis( int axisNum, const JointAxis& axis )
00318 {
00319 assert( axisNum >= 0 && axisNum < mNumAxes );
00320 mData.axis[ axisNum ] = axis;
00321 }
00322
00323 int Joint::getNumAxes() const
00324 {
00325 return mNumAxes;
00326 }
00327
00328 void Joint::setAnchor( const Point3r& anchor )
00329 {
00330 mData.anchor = anchor;
00331 }
00332
00333 bool Joint::isEnabled() const
00334 {
00335 return mData.enabled;
00336 }
00337
00338 void Joint::setEnabled( bool e )
00339 {
00340 if ( !mInitCalled )
00341 {
00342 return ;
00343 }
00344
00345 mData.enabled = e;
00346 }
00347
00348 bool Joint::isRotational( int axisNum ) const
00349 {
00350 assert( axisNum >= 0 && axisNum < mNumAxes );
00351 return mAxisRotational[ axisNum ];
00352 }
00353
00354 void Joint::setUserData( void* data )
00355 {
00356 mUserData = data;
00357 }
00358
00359 void* Joint::getUserData()
00360 {
00361 return mUserData;
00362 }
00363
00364 bool Joint::internal_dependsOnSolid( Solid* s )
00365 {
00366 if ( s == mData.solid0 || s == mData.solid1 )
00367 {
00368 return true;
00369 }
00370 else
00371 {
00372 return false;
00373 }
00374 }
00375
00376 void Joint::updateDamage( real currentStress )
00377 {
00378 switch ( mData.breakMode )
00379 {
00380 case UNBREAKABLE_MODE:
00381
00382 break;
00383 case THRESHOLD_MODE:
00384 {
00385 if ( currentStress >= mData.breakThresh )
00386 {
00387 mData.isBroken = true;
00388 }
00389 break;
00390 }
00391 case ACCUMULATED_MODE:
00392 {
00393 if ( currentStress >= mData.accumThresh )
00394 {
00395 mData.accumDamage += currentStress;
00396 }
00397
00398 if ( mData.accumDamage >= mData.breakThresh )
00399 {
00400 mData.isBroken = true;
00401 }
00402 break;
00403 }
00404 default:
00405 assert( false );
00406 }
00407
00408 if ( mData.isBroken )
00409 {
00410 setEnabled( false );
00411 if ( mJointBreakEventHandler )
00412 {
00413 mJointBreakEventHandler->handleJointBreakEvent( this );
00414 }
00415 }
00416 }
00417 }