ODEJoint.cpp

Go to the documentation of this file.
00001 /*************************************************************************
00002 *                                                                       *
00003 * Open Physics Abstraction Layer                                        *
00004 * Copyright (C) 2004-2005                                               *
00005 * Alan Fischer  alan.fischer@gmail.com                                  *
00006 * Andres Reinot  andres@reinot.com                                      *
00007 * Tyler Streeter  tylerstreeter@gmail.com                               *
00008 * All rights reserved.                                                  *
00009 * Web: opal.sourceforge.net                                             *
00010 *                                                                       *
00011 * This library is free software; you can redistribute it and/or         *
00012 * modify it under the terms of EITHER:                                  *
00013 *   (1) The GNU Lesser General Public License as published by the Free  *
00014 *       Software Foundation; either version 2.1 of the License, or (at  *
00015 *       your option) any later version. The text of the GNU Lesser      *
00016 *       General Public License is included with this library in the     *
00017 *       file license-LGPL.txt.                                          *
00018 *   (2) The BSD-style license that is included with this library in     *
00019 *       the file license-BSD.txt.                                       *
00020 *                                                                       *
00021 * This library is distributed in the hope that it will be useful,       *
00022 * but WITHOUT ANY WARRANTY; without even the implied warranty of        *
00023 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files    *
00024 * license-LGPL.txt and license-BSD.txt for more details.                *
00025 *                                                                       *
00026 *************************************************************************/
00027 
00028 #include "ODEJoint.h" 
00029 //#include "ODETools.h"
00030 
00031 namespace opal
00032 {
00033     ODEJoint::ODEJoint( dWorldID worldID )
00034     {
00035         mJointID = NULL;
00036         mAMotorID = NULL;
00037         mWorldID = worldID;
00038     }
00039 
00040     ODEJoint::~ODEJoint()
00041     {
00042         dJointDestroy( mJointID );
00043         if ( mAMotorID )
00044         {
00045             dJointDestroy( mAMotorID );
00046         }
00047     }
00048 
00049     void ODEJoint::init( const JointData& data )
00050     {
00051         if ( mInitCalled )
00052         {
00053             // If this Joint has already been initialized, destroy the ODE
00054             // Joint ID.
00055             dJointDestroy( mJointID );
00056             if ( mAMotorID )
00057             {
00058                 dJointDestroy( mAMotorID );
00059             }
00060 
00061             // Reset event handler.
00062             mJointBreakEventHandler = NULL;
00063         }
00064 
00065         Joint::init( data );
00066         mInitCalled = true;
00067 
00068         switch ( data.getType() )
00069         {
00070         case HINGE_JOINT:
00071             // Create an ODE hinge Joint.
00072             mJointID = dJointCreateHinge( mWorldID, 0 );
00073             mNumAxes = 1;
00074 
00075             // Set the rotational property of each axis.
00076             mAxisRotational[ 0 ] = true;
00077             mAxisRotational[ 1 ] = false;
00078             mAxisRotational[ 2 ] = false;
00079 
00080             // Set the ODE fudge factor for each axis.
00081             setJointParam( dParamFudgeFactor,
00082                            defaults::ode::jointFudgeFactor );
00083             break;
00084         case UNIVERSAL_JOINT:
00085             // Create an ODE universal Joint.
00086             mJointID = dJointCreateUniversal( mWorldID, 0 );
00087             mNumAxes = 2;
00088 
00089             // Set the rotational property of each axis.
00090             mAxisRotational[ 0 ] = true;
00091             mAxisRotational[ 1 ] = true;
00092             mAxisRotational[ 2 ] = false;
00093 
00094             // Set the ODE fudge factor for each axis.
00095             setJointParam( dParamFudgeFactor,
00096                            defaults::ode::jointFudgeFactor );
00097             setJointParam( dParamFudgeFactor2,
00098                            defaults::ode::jointFudgeFactor );
00099             break;
00100         case BALL_JOINT:
00101             // Create an ODE ball Joint.
00102             mJointID = dJointCreateBall( mWorldID, 0 );
00103             mNumAxes = 3;
00104 
00105             // Set the rotational property of each axis.
00106             mAxisRotational[ 0 ] = true;
00107             mAxisRotational[ 1 ] = true;
00108             mAxisRotational[ 2 ] = true;
00109 
00110             // ODE ball Joints need this special "angular motor" to
00111             // restrain their movement e.g. when limits are used.
00112             mAMotorID = dJointCreateAMotor( mWorldID, 0 );
00113             dJointSetAMotorMode( mAMotorID, dAMotorEuler );
00114 
00115             // Set the ODE fudge factor for each axis.
00116             setJointParam( dParamFudgeFactor,
00117                            defaults::ode::jointFudgeFactor );
00118             setJointParam( dParamFudgeFactor2,
00119                            defaults::ode::jointFudgeFactor );
00120             setJointParam( dParamFudgeFactor3,
00121                            defaults::ode::jointFudgeFactor );
00122             break;
00123         case SLIDER_JOINT:
00124             // Create an ODE slider Joint.
00125             mJointID = dJointCreateSlider( mWorldID, 0 );
00126             mNumAxes = 1;
00127 
00128             // Set the rotational property of each axis.
00129             mAxisRotational[ 0 ] = false;
00130             mAxisRotational[ 1 ] = false;
00131             mAxisRotational[ 2 ] = false;
00132 
00133             // Set the ODE fudge factor for each axis.
00134             setJointParam( dParamFudgeFactor,
00135                            defaults::ode::jointFudgeFactor );
00136             break;
00137         case WHEEL_JOINT:
00138             // Create an ODE hinge2 Joint.
00139             mJointID = dJointCreateHinge2( mWorldID, 0 );
00140             mNumAxes = 2;
00141 
00142             // Set the rotational property of each axis.
00143             mAxisRotational[ 0 ] = true;
00144             mAxisRotational[ 1 ] = true;
00145             mAxisRotational[ 2 ] = false;
00146 
00147             // Set the ODE fudge factor for each axis.
00148             setJointParam( dParamFudgeFactor,
00149                            defaults::ode::jointFudgeFactor );
00150             setJointParam( dParamFudgeFactor2,
00151                            defaults::ode::jointFudgeFactor );
00152             break;
00153         case FIXED_JOINT:
00154             // Create an ODE fixed Joint.
00155             mJointID = dJointCreateFixed( mWorldID, 0 );
00156             mNumAxes = 0;
00157 
00158             // Set the rotational property of each axis.
00159             mAxisRotational[ 0 ] = false;
00160             mAxisRotational[ 1 ] = false;
00161             mAxisRotational[ 2 ] = false;
00162             break;
00163         default:
00164             assert( false );
00165             break;
00166         }
00167 
00168         // Tell ODE about the JointFeedback struct for this Joint.
00169         // TODO: for ball joints, should this get the joint id or the
00170         // amotor id?
00171         mJointFeedback.f1[ 0 ] = 0;
00172         mJointFeedback.f1[ 1 ] = 0;
00173         mJointFeedback.f1[ 2 ] = 0;
00174         mJointFeedback.t1[ 0 ] = 0;
00175         mJointFeedback.t1[ 1 ] = 0;
00176         mJointFeedback.t1[ 2 ] = 0;
00177         mJointFeedback.f2[ 0 ] = 0;
00178         mJointFeedback.f2[ 1 ] = 0;
00179         mJointFeedback.f2[ 2 ] = 0;
00180         mJointFeedback.t2[ 0 ] = 0;
00181         mJointFeedback.t2[ 1 ] = 0;
00182         mJointFeedback.t2[ 2 ] = 0;
00183         dJointSetFeedback( mJointID, &mJointFeedback );
00184 
00185         // Setup the Solids.
00186         filterSolidForStaticness( data.solid0, data.solid1 );
00187 
00188         if ( !mData.isBroken )
00189         {
00190             // Attach the Joint to the ODE bodies.
00191             attachODEBodies( mData.solid0, mData.solid1 );
00192         }
00193 
00194         // Setup the Joint's anchor.
00195         setAnchor( data.anchor );
00196 
00197         // Setup the Joint's axes.
00198         setAxis( 0, data.axis[ 0 ] );
00199         setAxis( 1, data.axis[ 1 ] );
00200         setAxis( 2, data.axis[ 2 ] );
00201 
00202         // Set the ODE joint's userdata pointer.
00203         if ( BALL_JOINT == mData.getType() )
00204         {
00205             dJointSetData( mAMotorID, this );
00206         }
00207         else
00208         {
00209             dJointSetData( mJointID, this );
00210         }
00211     }
00212 
00213     void ODEJoint::filterSolidForStaticness( Solid* s0, Solid* s1 )
00214     {
00215         Solid * temp0 = s0;
00216         Solid * temp1 = s1;
00217         mData.enabled = true;
00218         if ( s0 == s1 )
00219         {
00220             temp0 = NULL;
00221             temp1 = NULL;
00222             mData.enabled = false;
00223         }
00224         else
00225         {
00226             if ( s0 && s0->isStatic() )
00227                 temp0 = NULL;
00228             if ( s1 && s1->isStatic() )
00229                 temp1 = NULL;
00230 
00231             if ( temp0 == NULL && temp1 == NULL )
00232                 mData.enabled = false;
00233         }
00234 
00235         // now we can safely set
00236         Joint::setSolids( temp0, temp1 );
00237     }
00238 
00239     real ODEJoint::getAngle( int axisNum ) const
00240     {
00241         assert( axisNum >= 0 && axisNum < mNumAxes );
00242 
00243         real value = 0;
00244 
00245         switch ( mData.getType() )
00246         {
00247         case HINGE_JOINT:
00248             value = radToDeg( ( real ) dJointGetHingeAngle( mJointID ) );
00249             break;
00250         case UNIVERSAL_JOINT:
00251             if ( 0 == axisNum )
00252             {
00253                 value =
00254                     radToDeg( ( real ) dJointGetUniversalAngle1( mJointID ) );
00255             }
00256             else
00257             {
00258                 value =
00259                     radToDeg( ( real ) dJointGetUniversalAngle2( mJointID ) );
00260             }
00261             break;
00262         case BALL_JOINT:
00263             value =
00264                 radToDeg( ( real ) dJointGetAMotorAngle( mAMotorID, axisNum ) );
00265             break;
00266         case SLIDER_JOINT:
00267             value = 0;
00268             break;
00269         case WHEEL_JOINT:
00270             if ( 0 == axisNum )
00271             {
00272                 value = radToDeg( ( real ) dJointGetHinge2Angle1( mJointID ) );
00273             }
00274             else
00275             {
00276                 // ODE does not give us axis 1 angle.
00277                 assert( false );
00278             }
00279             break;
00280         case FIXED_JOINT:
00281             // Fixed Joints don't have any kind of state info.
00282             assert( false );
00283             break;
00284         default:
00285             assert( false );
00286             break;
00287         }
00288 
00289         return value;
00290     }
00291 
00292     real ODEJoint::getDistance( int axisNum ) const
00293     {
00294         assert( axisNum >= 0 && axisNum < mNumAxes );
00295 
00296         real value = 0;
00297 
00298         switch ( mData.getType() )
00299         {
00300         case HINGE_JOINT:
00301             value = 0;
00302             break;
00303         case UNIVERSAL_JOINT:
00304             value = 0;
00305             break;
00306         case BALL_JOINT:
00307             value = 0;
00308             break;
00309         case SLIDER_JOINT:
00310             value = ( real ) dJointGetSliderPosition( mJointID );
00311             break;
00312         case WHEEL_JOINT:
00313             value = 0;
00314             break;
00315         case FIXED_JOINT:
00316             // Fixed Joints don't have any kind of state info.
00317             assert( false );
00318             break;
00319         default:
00320             assert( false );
00321             break;
00322         }
00323 
00324         return value;
00325     }
00326 
00327     real ODEJoint::getVelocity( int axisNum ) const
00328     {
00329         assert( axisNum >= 0 && axisNum < mNumAxes );
00330 
00331         real value = 0;
00332 
00333         switch ( mData.getType() )
00334         {
00335         case HINGE_JOINT:
00336             value = radToDeg( ( real ) dJointGetHingeAngleRate( mJointID ) );
00337             break;
00338         case UNIVERSAL_JOINT:
00339             if ( 0 == axisNum )
00340             {
00341                 value = radToDeg(
00342                             ( real ) dJointGetUniversalAngle1Rate( mJointID ) );
00343             }
00344             else
00345             {
00346                 value = radToDeg(
00347                             ( real ) dJointGetUniversalAngle2Rate( mJointID ) );
00348             }
00349             break;
00350         case BALL_JOINT:
00351             value = radToDeg(
00352                         ( real ) dJointGetAMotorAngleRate( mAMotorID, axisNum ) );
00353             break;
00354         case SLIDER_JOINT:
00355             value = ( real ) dJointGetSliderPositionRate( mJointID );
00356             break;
00357         case WHEEL_JOINT:
00358             if ( 0 == axisNum )
00359             {
00360                 value = radToDeg(
00361                             ( real ) dJointGetHinge2Angle1Rate( mJointID ) );
00362             }
00363             else
00364             {
00365                 value = radToDeg(
00366                             ( real ) dJointGetHinge2Angle2Rate( mJointID ) );
00367             }
00368             break;
00369         case FIXED_JOINT:
00370             // Fixed Joints don't have rates.
00371             assert( false );
00372             break;
00373         default:
00374             assert( false );
00375             break;
00376         }
00377 
00378         return value;
00379     }
00380 
00381     //void ODEJoint::setLimits(int axisNum, JointLimits l)
00382     //{
00383 
00384     //}
00385 
00386     //const JointLimits& ODEJoint::getLimits(int axisNum)const
00387     //{
00388 
00389     //}
00390 
00391     void ODEJoint::setLimitHardness( int axisNum, real h )
00392     {
00393         Joint::setLimitHardness( axisNum, h );
00394 
00395         // Calculate the ODE ERP value by scaling hardness by a normalized
00396         // ERP range.
00397         real value = h * ( defaults::ode::maxERP - defaults::ode::minERP ) +
00398                      defaults::ode::minERP;
00399 
00400         // Set the ODE ERP parameter.
00401         switch ( axisNum )
00402         {
00403         case 0:
00404             setJointParam( dParamStopERP, value );
00405             break;
00406         case 1:
00407             setJointParam( dParamStopERP2, value );
00408             break;
00409         case 2:
00410             setJointParam( dParamStopERP3, value );
00411             break;
00412         default:
00413             assert( false );
00414             break;
00415         }
00416 
00417         // ODE's Hinge2 Joint also has a suspension parameter.  Use axis 1
00418         // for this since axis 1 doesn't use limits anyway.
00419         if ( 1 == axisNum && WHEEL_JOINT == mData.getType() )
00420         {
00421             setJointParam( dParamSuspensionERP, value );
00422         }
00423     }
00424 
00425     void ODEJoint::setLimitBounciness( int axisNum, real b )
00426     {
00427         Joint::setLimitBounciness( axisNum, b );
00428 
00429         // Calculate the ODE bounce value by scaling hardness by a
00430         // normalized ERP range.
00431         real value = b * ( defaults::ode::maxERP - defaults::ode::minERP ) +
00432                      defaults::ode::minERP;
00433 
00434         // Set the ODE bounce parameter.
00435         switch ( axisNum )
00436         {
00437         case 0:
00438             setJointParam( dParamBounce, value );
00439             break;
00440         case 1:
00441             setJointParam( dParamBounce2, value );
00442             break;
00443         case 2:
00444             setJointParam( dParamBounce3, value );
00445             break;
00446         default:
00447             assert( false );
00448             break;
00449         }
00450     }
00451 
00452     JointAxis ODEJoint::getAxis( int axisNum ) const
00453     {
00454         // Silently ignore invalid axes.
00455         if ( axisNum < 0 || axisNum >= mNumAxes )
00456         {
00457             return JointAxis();
00458         }
00459 
00460         // First we need to get an updated direction vector from ODE.
00461         dVector3 direction;
00462 
00463         switch ( mData.getType() )
00464         {
00465         case HINGE_JOINT:
00466             dJointGetHingeAxis( mJointID, direction );
00467             break;
00468         case UNIVERSAL_JOINT:
00469             if ( 0 == axisNum )
00470             {
00471                 dJointGetUniversalAxis1( mJointID, direction );
00472             }
00473             else
00474             {
00475                 dJointGetUniversalAxis2( mJointID, direction );
00476             }
00477             break;
00478         case BALL_JOINT:
00479             if ( 0 == axisNum )
00480             {
00481                 dJointGetAMotorAxis( mAMotorID, 0, direction );
00482             }
00483             else if ( 1 == axisNum )
00484             {
00485                 dJointGetAMotorAxis( mAMotorID, 1, direction );
00486             }
00487             else
00488             {
00489                 dJointGetAMotorAxis( mAMotorID, 2, direction );
00490             }
00491             break;
00492         case SLIDER_JOINT:
00493             dJointGetSliderAxis( mJointID, direction );
00494             break;
00495         case WHEEL_JOINT:
00496             if ( 0 == axisNum )
00497             {
00498                 dJointGetHinge2Axis1( mJointID, direction );
00499             }
00500             else
00501             {
00502                 dJointGetHinge2Axis2( mJointID, direction );
00503             }
00504             break;
00505         case FIXED_JOINT:
00506             // Fixed Joints don't have any axes.
00507             break;
00508         default:
00509             assert( false );
00510             break;
00511         }
00512 
00513         JointAxis axis = mData.axis[ axisNum ];
00514 
00515         // All data in this JointAxis is valid except for the direction
00516         // vector.
00517         axis.direction.set( ( real ) direction[ 0 ],
00518                             ( real ) direction[ 1 ],
00519                             ( real ) direction[ 2 ] );
00520 
00521         return axis;
00522     }
00523 
00524     Point3r ODEJoint::getAnchor() const
00525     {
00526         // We need to get an updated anchor point from ODE.
00527         dVector3 anchor;
00528 
00529         switch ( mData.getType() )
00530         {
00531         case HINGE_JOINT:
00532             dJointGetHingeAnchor( mJointID, anchor );
00533             break;
00534         case UNIVERSAL_JOINT:
00535             dJointGetUniversalAnchor( mJointID, anchor );
00536             break;
00537         case BALL_JOINT:
00538             dJointGetBallAnchor( mJointID, anchor );
00539             break;
00540         case SLIDER_JOINT:
00541             // Slider Joints don't have an anchor point.
00542             break;
00543         case WHEEL_JOINT:
00544             dJointGetHinge2Anchor( mJointID, anchor );
00545             break;
00546         case FIXED_JOINT:
00547             // Fixed Joints don't have an anchor point.
00548             break;
00549         default:
00550             assert( false );
00551             break;
00552         }
00553 
00554         return Point3r( ( real ) anchor[ 0 ], ( real ) anchor[ 1 ], ( real ) anchor[ 2 ] );
00555     }
00556 
00557     void ODEJoint::internal_update()
00558     {
00559         if ( mData.enabled )
00560         {
00561             // Update the Joint's damage status.
00562             updateDamage( calcStress() );
00563         }
00564     }
00565 
00566     void ODEJoint::internal_setDesiredVel( int axisNum, real value )
00567     {
00568         assert( axisNum >= 0 && axisNum < mNumAxes );
00569 
00570         switch ( axisNum )
00571         {
00572         case 0:
00573             setJointParam( dParamVel, value );
00574             break;
00575         case 1:
00576             setJointParam( dParamVel2, value );
00577             break;
00578         case 2:
00579             setJointParam( dParamVel3, value );
00580             break;
00581         default:
00582             assert( false );
00583             break;
00584         }
00585     }
00586 
00587     void ODEJoint::internal_setMaxTorque( int axisNum, real value )
00588     {
00589         assert( axisNum >= 0 && axisNum < mNumAxes );
00590 
00591         switch ( axisNum )
00592         {
00593         case 0:
00594             setJointParam( dParamFMax, value );
00595             break;
00596         case 1:
00597             setJointParam( dParamFMax2, value );
00598             break;
00599         case 2:
00600             setJointParam( dParamFMax3, value );
00601             break;
00602         default:
00603             assert( false );
00604             break;
00605         }
00606     }
00607 
00608     void ODEJoint::setAxis( int axisNum, const JointAxis& axis )
00609     {
00610         // Silently ignore invalid axes.
00611         //assert(axisNum >= 0 && axisNum < mNumAxes);
00612         if ( axisNum < 0 || axisNum >= mNumAxes )
00613         {
00614             return ;
00615         }
00616 
00617         // Normalize the direction vector.
00618         JointAxis normAxis = axis;
00619         normAxis.direction.normalize();
00620 
00621         // Store the axis (with normalized direction vector).
00622         Joint::setAxis( axisNum, normAxis );
00623 
00624         // Create an ODE-style vector for the direction vector.
00625         dVector3 newAxis = {( dReal ) normAxis.direction[ 0 ],
00626                             ( dReal ) normAxis.direction[ 1 ], ( dReal ) normAxis.direction[ 2 ] };
00627 
00628         // Set the ODE Joint axis direction vector.
00629         switch ( mData.getType() )
00630         {
00631         case HINGE_JOINT:
00632             dJointSetHingeAxis( mJointID, newAxis[ 0 ], newAxis[ 1 ],
00633                                 newAxis[ 2 ] );
00634             break;
00635         case UNIVERSAL_JOINT:
00636             if ( 0 == axisNum )
00637             {
00638                 dJointSetUniversalAxis1( mJointID, newAxis[ 0 ], newAxis[ 1 ],
00639                                          newAxis[ 2 ] );
00640             }
00641             else
00642             {
00643                 dJointSetUniversalAxis2( mJointID, newAxis[ 0 ], newAxis[ 1 ],
00644                                          newAxis[ 2 ] );
00645             }
00646             break;
00647         case BALL_JOINT:
00648             // From ODE docs:
00649             // For dAMotorEuler mode:
00650             // 1. Only axes 0 and 2 need to be set. Axis 1 will be
00651             //  determined automatically at each time step.
00652             // 2. Axes 0 and 2 must be perpendicular to each other.
00653             // 3. Axis 0 must be anchored to the first body, axis 2 must
00654             //  be anchored to the second body.
00655 
00656             if ( 0 == axisNum )
00657             {
00658                 dJointSetAMotorAxis( mAMotorID, 0, 1, newAxis[ 0 ],
00659                                      newAxis[ 1 ], newAxis[ 2 ] );
00660             }
00661             else if ( 2 == axisNum )
00662             {
00663                 dJointSetAMotorAxis( mAMotorID, 2, 2, newAxis[ 0 ],
00664                                      newAxis[ 1 ], newAxis[ 2 ] );
00665             }
00666             break;
00667         case SLIDER_JOINT:
00668             dJointSetSliderAxis( mJointID, newAxis[ 0 ], newAxis[ 1 ],
00669                                  newAxis[ 2 ] );
00670             break;
00671         case WHEEL_JOINT:
00672             if ( 0 == axisNum )
00673             {
00674                 dJointSetHinge2Axis1( mJointID, newAxis[ 0 ], newAxis[ 1 ],
00675                                       newAxis[ 2 ] );
00676             }
00677             else
00678             {
00679                 dJointSetHinge2Axis2( mJointID, newAxis[ 0 ], newAxis[ 1 ],
00680                                       newAxis[ 2 ] );
00681             }
00682             break;
00683         case FIXED_JOINT:
00684             // Fixed Joints don't have any axes.
00685             break;
00686         default:
00687             assert( false );
00688             break;
00689         }
00690 
00691         // Set whether the axis limits are enabled.
00692         setLimitsEnabled( axisNum, normAxis.limitsEnabled );
00693 
00694         // Set the axis' limit range.
00695         setLimitRange( axisNum, normAxis.limits.low, normAxis.limits.high );
00696 
00697         // Set the limits' hardness.
00698         setLimitHardness( axisNum, normAxis.limits.hardness );
00699 
00700         // Set the limits' bounciness.
00701         setLimitBounciness( axisNum, normAxis.limits.bounciness );
00702     }
00703 
00704     void ODEJoint::setAnchor( const Point3r& anchor )
00705     {
00706         Joint::setAnchor( anchor );
00707         dVector3 newAnchor = {( dReal ) anchor[ 0 ], ( dReal ) anchor[ 1 ],
00708                               ( dReal ) anchor[ 2 ] };
00709 
00710         switch ( mData.getType() )
00711         {
00712         case HINGE_JOINT:
00713             dJointSetHingeAnchor( mJointID, newAnchor[ 0 ], newAnchor[ 1 ],
00714                                   newAnchor[ 2 ] );
00715             break;
00716         case UNIVERSAL_JOINT:
00717             dJointSetUniversalAnchor( mJointID, newAnchor[ 0 ],
00718                                       newAnchor[ 1 ], newAnchor[ 2 ] );
00719             break;
00720         case BALL_JOINT:
00721             dJointSetBallAnchor( mJointID, newAnchor[ 0 ], newAnchor[ 1 ],
00722                                  newAnchor[ 2 ] );
00723             break;
00724         case SLIDER_JOINT:
00725             // Slider Joints don't have an anchor point.
00726             break;
00727         case WHEEL_JOINT:
00728             dJointSetHinge2Anchor( mJointID, newAnchor[ 0 ], newAnchor[ 1 ],
00729                                    newAnchor[ 2 ] );
00730             break;
00731         case FIXED_JOINT:
00732             // Fixed Joints don't have an anchor point.
00733             break;
00734         default:
00735             assert( false );
00736             break;
00737         }
00738     }
00739 
00740     void ODEJoint::setLimitsEnabled( int axisNum, bool e )
00741     {
00742         Joint::setLimitsEnabled( axisNum, e );
00743 
00744         if ( e )
00745         {
00746             real low = mData.axis[ axisNum ].limits.low;
00747             real high = mData.axis[ axisNum ].limits.high;
00748 
00749             if ( isRotational( axisNum ) )
00750             {
00751                 low = degToRad( low );
00752                 high = degToRad( high );
00753             }
00754 
00755             switch ( axisNum )
00756             {
00757             case 0:
00758                 // Both limits must be set twice because of a ODE bug in
00759                 // the limit setting function.
00760                 setJointParam( dParamLoStop, low );
00761                 setJointParam( dParamHiStop, high );
00762                 setJointParam( dParamLoStop, low );
00763                 setJointParam( dParamHiStop, high );
00764                 break;
00765             case 1:
00766                 // Both limits must be set twice because of a ODE bug in
00767                 // the limit setting function.
00768                 setJointParam( dParamLoStop2, low );
00769                 setJointParam( dParamHiStop2, high );
00770                 setJointParam( dParamLoStop2, low );
00771                 setJointParam( dParamHiStop2, high );
00772                 break;
00773             case 2:
00774                 // Both limits must be set twice because of a ODE bug in
00775                 // the limit setting function.
00776                 setJointParam( dParamLoStop3, low );
00777                 setJointParam( dParamHiStop3, high );
00778                 setJointParam( dParamLoStop3, low );
00779                 setJointParam( dParamHiStop3, high );
00780                 break;
00781             default:
00782                 assert( false );
00783                 break;
00784             }
00785         }
00786         else
00787         {
00788             switch ( axisNum )
00789             {
00790             case 0:
00791                 // Both limits must be set twice because of a ODE bug in
00792                 // the limit setting function.
00793                 setJointParam( dParamLoStop, -dInfinity );
00794                 setJointParam( dParamHiStop, dInfinity );
00795                 setJointParam( dParamLoStop, -dInfinity );
00796                 setJointParam( dParamHiStop, dInfinity );
00797                 break;
00798             case 1:
00799                 // Both limits must be set twice because of a ODE bug in
00800                 // the limit setting function.
00801                 setJointParam( dParamLoStop2, -dInfinity );
00802                 setJointParam( dParamHiStop2, dInfinity );
00803                 setJointParam( dParamLoStop2, -dInfinity );
00804                 setJointParam( dParamHiStop2, dInfinity );
00805                 break;
00806             case 2:
00807                 // Both limits must be set twice because of a ODE bug in
00808                 // the limit setting function.
00809                 setJointParam( dParamLoStop3, -dInfinity );
00810                 setJointParam( dParamHiStop3, dInfinity );
00811                 setJointParam( dParamLoStop3, -dInfinity );
00812                 setJointParam( dParamHiStop3, dInfinity );
00813                 break;
00814             default:
00815                 assert( false );
00816                 break;
00817             }
00818         }
00819     }
00820 
00821     void ODEJoint::setEnabled( bool e )
00822     {
00823         if ( !mInitCalled )
00824         {
00825             return ;
00826         }
00827 
00828         // if are enabling a joint, we need to properly alter the solids
00829         if ( e == true )
00830             filterSolidForStaticness( mData.solid0, mData.solid1 );
00831 
00832         if ( NULL == mData.solid0 && NULL == mData.solid1 )
00833         {
00834             return ;
00835         }
00836         else
00837         {
00838             Joint::setEnabled( e );
00839 
00840             if ( e )
00841             {
00842                 // Enable the joint.
00843                 attachODEBodies( mData.solid0, mData.solid1 );
00844             }
00845             else
00846             {
00847                 // Disable the joint by setting both bodies to 0.
00848                 attachODEBodies( NULL, NULL );
00849             }
00850         }
00851     }
00852 
00853     void ODEJoint::setLimitRange( int axisNum, real low, real high )
00854     {
00855         Joint::setLimitRange( axisNum, low, high );
00856 
00857         // If this axis is rotational, convert the limit angles from
00858         // degrees to radians.
00859         if ( isRotational( axisNum ) )
00860         {
00861             low = degToRad( low );
00862             high = degToRad( high );
00863         }
00864 
00865         // Only set the ODE limits if the limits for this particular axis
00866         // are enabled.
00867         switch ( axisNum )
00868         {
00869         case 0:
00870             if ( mData.axis[ axisNum ].limitsEnabled )
00871             {
00872                 // Both limits must be set twice because of a ODE bug in
00873                 // the limit setting function.
00874                 setJointParam( dParamLoStop, low );
00875                 setJointParam( dParamHiStop, high );
00876                 setJointParam( dParamLoStop, low );
00877                 setJointParam( dParamHiStop, high );
00878             }
00879             break;
00880         case 1:
00881             if ( mData.axis[ axisNum ].limitsEnabled )
00882             {
00883                 // Both limits must be set twice because of a ODE bug in
00884                 // the limit setting function.
00885                 setJointParam( dParamLoStop2, low );
00886                 setJointParam( dParamHiStop2, high );
00887                 setJointParam( dParamLoStop2, low );
00888                 setJointParam( dParamHiStop2, high );
00889             }
00890             break;
00891         case 2:
00892             if ( mData.axis[ axisNum ].limitsEnabled )
00893             {
00894                 // Both limits must be set twice because of a ODE bug in
00895                 // the limit setting function.
00896                 setJointParam( dParamLoStop3, low );
00897                 setJointParam( dParamHiStop3, high );
00898                 setJointParam( dParamLoStop3, low );
00899                 setJointParam( dParamHiStop3, high );
00900             }
00901             break;
00902         default:
00903             assert( false );
00904             break;
00905         }
00906     }
00907 
00908     void ODEJoint::setJointParam( int parameter, dReal value )
00909     {
00910         switch ( mData.getType() )
00911         {
00912         case HINGE_JOINT:
00913             dJointSetHingeParam( mJointID, parameter, value );
00914             break;
00915         case UNIVERSAL_JOINT:
00916             dJointSetUniversalParam( mJointID, parameter, value );
00917             break;
00918         case BALL_JOINT:
00919             dJointSetAMotorParam( mAMotorID, parameter, value );
00920             break;
00921         case SLIDER_JOINT:
00922             dJointSetSliderParam( mJointID, parameter, value );
00923             break;
00924         case WHEEL_JOINT:
00925             dJointSetHinge2Param( mJointID, parameter, value );
00926             break;
00927         case FIXED_JOINT:
00928             assert( false );
00929             break;
00930         default:
00931             assert( false );
00932             break;
00933         }
00934     }
00935 
00936     //real ODEJoint::getJointParam(int parameter)const
00937     //{
00938     //  real value = 0;
00939 
00940     //  switch(mData.type)
00941     //  {
00942     //          case HINGE_JOINT:
00943     //                  value = (real)dJointGetHingeParam(mJointID, parameter);
00944     //                  break;
00945     //          case UNIVERSAL_JOINT:
00946     //                  value = (real)dJointGetUniversalParam(mJointID, parameter);
00947     //                  break;
00948     //          case BALL_JOINT:
00949     //                  value = (real)dJointGetAMotorParam(mAMotorID, parameter);
00950     //                  break;
00951     //          case SLIDER_JOINT:
00952     //                  value = (real)dJointGetSliderParam(mJointID, parameter);
00953     //                  break;
00954     //          case WHEEL_JOINT:
00955     //                  value = (real)dJointGetHinge2Param(mJointID, parameter);
00956     //                  break;
00957     //          case FIXED_JOINT:
00958     //                  assert(false);
00959     //                  break;
00960     //          default:
00961     //                  assert(false);
00962     //                  break;
00963     //  }
00964 
00965     //  return value;
00966     //}
00967 
00968     real ODEJoint::calcStress()
00969     {
00970         // TODO: the damage calculations here should probably be sped up
00971         // somehow.
00972 
00973         real currentStress = 0;
00974 
00975         switch ( mData.breakMode )
00976         {
00977         case UNBREAKABLE_MODE:
00978             // Nothing to do.
00979             break;
00980         case THRESHOLD_MODE:
00981             // Fall through...
00982         case ACCUMULATED_MODE:
00983             {
00984                 dJointFeedback* jf = dJointGetFeedback( mJointID );
00985                 Vec3r f1( ( real ) jf->f1[ 0 ], ( real ) jf->f1[ 1 ], ( real ) jf->f1[ 2 ] );
00986                 Vec3r t1( ( real ) jf->t1[ 0 ], ( real ) jf->t1[ 1 ], ( real ) jf->t1[ 2 ] );
00987                 Vec3r f2( ( real ) jf->f2[ 0 ], ( real ) jf->f2[ 1 ], ( real ) jf->f2[ 2 ] );
00988                 Vec3r t2( ( real ) jf->t2[ 0 ], ( real ) jf->t2[ 1 ], ( real ) jf->t2[ 2 ] );
00989 
00990                 f1 -= f2;
00991                 t1 -= t2;
00992 
00993                 // This is a simplification, but it should still work.
00994                 currentStress = f1.length() + t1.length();
00995                 break;
00996             }
00997         default:
00998             assert( false );
00999         }
01000 
01001         return ( currentStress );
01002     }
01003 
01004     dJointID ODEJoint::internal_getJointID() const
01005     {
01006         if ( BALL_JOINT == mData.getType() )
01007         {
01008             return mAMotorID;
01009         }
01010         else
01011         {
01012             return mJointID;
01013         }
01014     }
01015 
01016     void ODEJoint::attachODEBodies( Solid* s0, Solid* s1 )
01017     {
01018         ODESolid * solid0 = ( ODESolid* ) s0;
01019         ODESolid* solid1 = ( ODESolid* ) s1;
01020 
01021         if ( NULL == solid0 && NULL == solid1 )
01022         {
01023             dJointAttach( mJointID, 0, 0 );
01024             if ( BALL_JOINT == mData.getType() )
01025             {
01026                 dJointAttach( mAMotorID, 0, 0 );
01027             }
01028         }
01029         else
01030         {
01031             if ( NULL == solid0 )
01032             {
01033                 dJointAttach( mJointID, 0, solid1->internal_getBodyID() );
01034                 if ( BALL_JOINT == mData.getType() )
01035                 {
01036                     dJointAttach( mAMotorID, 0, solid1->internal_getBodyID() );
01037                 }
01038             }
01039             else if ( NULL == solid1 )
01040             {
01041                 dJointAttach( mJointID, solid0->internal_getBodyID(), 0 );
01042                 if ( BALL_JOINT == mData.getType() )
01043                 {
01044                     dJointAttach( mAMotorID, solid0->internal_getBodyID(), 0 );
01045                 }
01046             }
01047             else
01048             {
01049                 dJointAttach( mJointID, solid0->internal_getBodyID(),
01050                               solid1->internal_getBodyID() );
01051                 if ( BALL_JOINT == mData.getType() )
01052                 {
01053                     dJointAttach( mAMotorID, solid0->internal_getBodyID(),
01054                                   solid1->internal_getBodyID() );
01055                 }
01056             }
01057 
01058             // Special call for fixed Joints so they remember the current
01059             // relationship between the Solids or between a Solid and the
01060             // static environment.
01061             if ( FIXED_JOINT == mData.getType() )
01062             {
01063                 dJointSetFixed( mJointID );
01064             }
01065         }
01066     }
01067 }

Generated on Tue May 16 17:49:51 2006 for OPAL by  doxygen 1.4.6-NO