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
00029 #include "ODESimulator.h"
00030 #include "../ShapeData.h"
00031
00032 using namespace std;
00033
00034 namespace opal
00035 {
00036 OPAL_EXPORT_FUNCTION opal::Simulator* OPAL_CALL createSimulator( )
00037 {
00038
00039 if ( sizeof( real ) != sizeof( dReal ) )
00040 {
00041 OPAL_LOGGER( "warning" ) << "The size of data types (OPAL) real "
00042 << "and (ODE) dReal do not match. Make sure these "
00043 << "libraries are built using the same floating point "
00044 << "precision (float or double)." << std::endl;
00045 }
00046
00047 opal::ODESimulator * sim = new opal::ODESimulator( );
00048 sim->initData( opal::SimulatorData() );
00049 return sim;
00050 }
00051
00052 OPAL_EXPORT_FUNCTION opal::Simulator* OPAL_CALL createCustomSimulator( opal::SimulatorData & data )
00053 {
00054
00055 if ( sizeof( real ) != sizeof( dReal ) )
00056 {
00057 OPAL_LOGGER( "warning" ) << "The size of data types (OPAL) real "
00058 << "and (ODE) dReal do not match. Make sure these "
00059 << "libraries are built using the same floating point "
00060 << "precision (float or double)." << std::endl;
00061 }
00062
00063 opal::ODESimulator * sim = new opal::ODESimulator( );
00064 sim->initData( data );
00065 return sim;
00066 }
00067
00068 void ODESimulator::initData( SimulatorData data )
00069 {
00070 Simulator::initData( data );
00071
00072
00073 mWorldID = dWorldCreate();
00074
00075
00076 setGravity( defaults::gravity );
00077
00078
00079
00080
00081
00082
00083
00084 if ( data.useOctreeInsteadHash )
00085 {
00086 dVector3 center = { data.worldCenter[ 0 ],
00087 data.worldCenter[ 1 ],
00088 data.worldCenter[ 2 ] };
00089 dVector3 extents = { data.worldSize[ 0 ],
00090 data.worldSize[ 1 ],
00091 data.worldSize[ 2 ] };
00092 mRootSpaceID = dQuadTreeSpaceCreate( 0, center, extents, data.octreeDepth );
00093 }
00094 else
00095 {
00096 mRootSpaceID = dHashSpaceCreate( 0 );
00097 dHashSpaceSetLevels( mRootSpaceID, data.hashMinLevel, data.hashMaxLevel );
00098 }
00099
00100 mRootSpace = new ODESpace( mRootSpaceID );
00101
00102
00103 mContactJointGroupID = dJointGroupCreate( 0 );
00104
00105
00106
00107
00108
00109
00110 dWorldSetCFM( mWorldID, defaults::ode::globalCFM );
00111
00112
00113
00114
00115
00116 dWorldSetERP( mWorldID, ( real ) 0.5 * ( defaults::ode::maxERP +
00117 defaults::ode::minERP ) );
00118
00119 dWorldSetContactSurfaceLayer( mWorldID, defaults::ode::surfaceLayer );
00120
00121 setSolverAccuracy( defaults::solverAccuracy );
00122 mCollisionCount = 0;
00123
00124 mSensorSolid = NULL;
00125 mRayContactGroup = defaults::shape::contactGroup;
00126 }
00127
00128 ODESimulator::ODESimulator( )
00129 {
00130
00131 }
00132
00133 ODESimulator::~ODESimulator()
00134 {
00135
00136 }
00137
00138 void ODESimulator::setMaxCorrectingVel( real vel )
00139 {
00140 Simulator::setMaxCorrectingVel( vel );
00141 dWorldSetContactMaxCorrectingVel( mWorldID, vel );
00142 }
00143
00144 Solid* ODESimulator::createSolid()
00145 {
00146 Solid * newSolid = new ODESolid( mWorldID, mRootSpaceID );
00147 addSolid( newSolid );
00148 return newSolid;
00149 }
00150
00151 Space* ODESimulator::createSpace()
00152 {
00153 ODESpace * newSpace = new ODESpace();
00154
00155
00156 dSpaceAdd( mRootSpaceID, ( dGeomID ) newSpace->internal_getSpaceID() );
00157
00158 addSpace( newSpace );
00159 return newSpace;
00160 }
00161
00162 Joint* ODESimulator::createJoint()
00163 {
00164 Joint * newJoint = new ODEJoint( mWorldID );
00165 addJoint( newJoint );
00166 return newJoint;
00167 }
00168
00169 void ODESimulator::destroy()
00170 {
00171
00172
00173
00174 dSpaceID rootSpaceID = mRootSpaceID;
00175 dWorldID worldID = mWorldID;
00176 dJointGroupID contactJointGroupID = mContactJointGroupID;
00177
00178 delete this;
00179
00180
00181
00182
00183 dSpaceDestroy( rootSpaceID );
00184 dWorldDestroy( worldID );
00185 dJointGroupDestroy( contactJointGroupID );
00186 dCloseODE();
00187 }
00188
00189 void ODESimulator::stepPhysics()
00190 {
00191
00192
00193
00194 std::vector<Solid*>::iterator iter;
00195 for ( iter = mSolidList.begin(); iter != mSolidList.end(); ++iter )
00196 {
00197 ODESolid* solid = ( ODESolid* ) ( *iter );
00198
00199 if ( !solid->isStatic() )
00200 {
00201 if ( solid->isSleeping() )
00202 {
00203
00204
00205
00206
00207
00208 dBodyID bodyID = ( ( ODESolid* ) solid ) ->internal_getBodyID();
00209 dBodySetLinearVel( bodyID, 0, 0, 0 );
00210 dBodySetAngularVel( bodyID, 0, 0, 0 );
00211 dBodySetForce( bodyID, 0, 0, 0 );
00212 dBodySetTorque( bodyID, 0, 0, 0 );
00213 }
00214 else
00215 {
00216
00217
00218
00219
00220
00221
00222
00223
00224
00225 dBodyID bodyID = solid->internal_getBodyID();
00226 dMass mass;
00227 dBodyGetMass( bodyID, &mass );
00228
00229
00230
00231
00232
00233
00234
00235
00236
00237
00238
00239
00240
00241
00242 real linearDamping = solid->getLinearDamping();
00243 if ( 0 != linearDamping )
00244 {
00245 const dReal * lVelGlobal = dBodyGetLinearVel( bodyID );
00246
00247
00248
00249
00250 dReal dampingFactor = -linearDamping * mass.mass;
00251 dVector3 dampingForce = {
00252 dampingFactor * lVelGlobal[ 0 ],
00253 dampingFactor * lVelGlobal[ 1 ],
00254 dampingFactor * lVelGlobal[ 2 ] };
00255
00256
00257
00258 dBodyAddForce( bodyID, dampingForce[ 0 ],
00259 dampingForce[ 1 ], dampingForce[ 2 ] );
00260 }
00261
00262
00263 real angularDamping = solid->getAngularDamping();
00264 if ( 0 != angularDamping )
00265 {
00266 const dReal * aVelGlobal = dBodyGetAngularVel( bodyID );
00267 dVector3 aVelLocal;
00268 dBodyVectorFromWorld( bodyID, aVelGlobal[ 0 ],
00269 aVelGlobal[ 1 ], aVelGlobal[ 2 ], aVelLocal );
00270
00271
00272
00273
00274
00275 dReal dampingFactor = -angularDamping;
00276 dVector3 aMomentum;
00277
00278
00279 dMULTIPLYOP0_331( aMomentum, = , mass.I, aVelLocal );
00280 dVector3 dampingTorque = {
00281 dampingFactor * aMomentum[ 0 ],
00282 dampingFactor * aMomentum[ 1 ],
00283 dampingFactor * aMomentum[ 2 ] };
00284
00285
00286
00287 dBodyAddRelTorque( bodyID, dampingTorque[ 0 ],
00288 dampingTorque[ 1 ], dampingTorque[ 2 ] );
00289 }
00290
00291
00292
00293
00294
00295
00296
00299
00300
00301
00302
00303
00304
00305
00306
00307
00308
00309
00310
00311
00312 }
00313 }
00314 }
00315
00316
00317 dSpaceCollide( mRootSpaceID, this,
00318 &ode_hidden::internal_collisionCallback );
00319
00320
00321 if ( SOLVER_QUICKSTEP == mSolverType )
00322 {
00323 dWorldQuickStep( mWorldID, mStepSize );
00324 }
00325 else
00326 {
00327 dWorldStep( mWorldID, mStepSize );
00328 }
00329
00330
00331 dJointGroupEmpty( mContactJointGroupID );
00332
00333
00334
00335 for ( iter = mSolidList.begin(); iter != mSolidList.end(); ++iter )
00336 {
00337 ODESolid* s = ( ODESolid* ) ( *iter );
00338 if ( !s->isSleeping() && !s->isStatic() )
00339 {
00340 s->internal_doAngularVelFix();
00341 }
00342 }
00343 }
00344
00345 namespace ode_hidden
00346 {
00347 void internal_collisionCallback( void *data, dGeomID o0, dGeomID o1 )
00348 {
00349 if ( dGeomIsSpace( o0 ) || dGeomIsSpace( o1 ) )
00350 {
00351
00352 dSpaceCollide2( o0, o1, data, &internal_collisionCallback );
00353
00354 if ( dGeomIsSpace( o0 ) )
00355 {
00356
00357 dSpaceCollide( ( dSpaceID ) o0, data,
00358 &internal_collisionCallback );
00359 }
00360
00361 if ( dGeomIsSpace( o1 ) )
00362 {
00363
00364 dSpaceCollide( ( dSpaceID ) o1, data,
00365 &internal_collisionCallback );
00366 }
00367 }
00368 else
00369 {
00370
00371
00372
00373
00374
00375
00376
00377
00378
00379
00380
00381
00382
00383
00384
00385
00386
00387
00388
00389
00390
00391
00392
00393
00394
00395
00396
00397
00398
00399
00400
00401
00402
00403
00404
00405 dBodyID o0BodyID = dGeomGetBody( o0 );
00406 dBodyID o1BodyID = dGeomGetBody( o1 );
00407 bool solid0Static = ( 0 == o0BodyID );
00408 bool solid1Static = ( 0 == o1BodyID );
00409
00410
00411 bool bothHaveBodies = true;
00412 if ( 0 == o0BodyID || 0 == o1BodyID )
00413 {
00414 bothHaveBodies = false;
00415 }
00416
00417
00418
00419 Joint* commonJoint = NULL;
00420 if ( bothHaveBodies && dAreConnectedExcluding( o0BodyID,
00421 o1BodyID, dJointTypeContact ) )
00422 {
00423
00424
00425 commonJoint = internal_getCommonJoint( o0BodyID, o1BodyID );
00426 }
00427
00428
00429 GeomData* geomData0 = ( GeomData* ) dGeomGetData( o0 );
00430 GeomData* geomData1 = ( ( GeomData* ) dGeomGetData( o1 ) );
00431
00432
00433 const ShapeData* shape0 = geomData0->shape;
00434 const ShapeData* shape1 = geomData1->shape;
00435
00436
00437 ODESimulator* sim = ( ODESimulator* ) data;
00438
00439
00440
00441 bool makeContacts = sim->groupsMakeContacts(
00442 shape0->contactGroup, shape1->contactGroup );
00443
00444
00445
00446 bool ignoreStaticSleepingContacts =
00447 !sim->areStaticSleepingContactsEnabled();
00448
00449
00450 Solid* solid0 = geomData0->solid;
00451 Solid* solid1 = geomData1->solid;
00452
00453
00454
00455
00456 CollisionEventHandler* handler0 =
00457 solid0->getCollisionEventHandler();
00458 CollisionEventHandler* handler1 =
00459 solid1->getCollisionEventHandler();
00460
00461 bool neitherHasEventHandler = !( handler0 || handler1 );
00462
00463 bool hasNoGlobalHandler = sim->getNumGlobalCollisionEventHandlers() == 0;
00464
00465
00466
00467
00468
00469 bool case1 = neitherHasEventHandler && hasNoGlobalHandler
00470 && solid0Static && solid1Static;
00471
00472 bool case3 = bothHaveBodies && !dBodyIsEnabled( o0BodyID )
00473 && !dBodyIsEnabled( o1BodyID );
00474 bool case4 = commonJoint &&
00475 commonJoint->getType() == FIXED_JOINT;
00476 bool case5 = commonJoint
00477 && !commonJoint->areContactsEnabled();
00478 bool case6 = solid0Static && 0 != o1BodyID
00479 && !dBodyIsEnabled( o1BodyID )
00480 && ignoreStaticSleepingContacts
00481 && neitherHasEventHandler && hasNoGlobalHandler;
00482 bool case7 = solid1Static && 0 != o0BodyID
00483 && !dBodyIsEnabled( o0BodyID )
00484 && ignoreStaticSleepingContacts
00485 && neitherHasEventHandler && hasNoGlobalHandler;
00486 bool case8 = !makeContacts && neitherHasEventHandler
00487 && hasNoGlobalHandler;
00488
00489 if ( case1 || case3 || case4 || case5 || case6 || case7 || case8 )
00490 return ;
00491
00492
00493
00494 dWorldID theWorldID = sim->internal_getWorldID();
00495 dJointGroupID theJointGroupID =
00496 sim->internal_getJointGroupID();
00497 dContactGeom contactArray[ globals::maxMaxContacts ];
00498 int numContacts = dCollide( o0, o1, sim->getMaxContacts(),
00499 contactArray, sizeof( dContactGeom ) );
00500
00501
00502
00503 if ( 0 == numContacts )
00504 {
00505 return ;
00506 }
00507
00508
00509
00510 if ( handler0 || handler1 || !hasNoGlobalHandler )
00511 {
00512
00513
00514
00515
00516
00517
00518
00519 CollisionEvent e;
00520 e.thisSolid = solid0;
00521 e.otherSolid = solid1;
00522 e.pos[ 0 ] = ( real ) contactArray[ 0 ].pos[ 0 ];
00523 e.pos[ 1 ] = ( real ) contactArray[ 0 ].pos[ 1 ];
00524 e.pos[ 2 ] = ( real ) contactArray[ 0 ].pos[ 2 ];
00525 e.normal[ 0 ] = ( real ) contactArray[ 0 ].normal[ 0 ];
00526 e.normal[ 1 ] = ( real ) contactArray[ 0 ].normal[ 1 ];
00527 e.normal[ 2 ] = ( real ) contactArray[ 0 ].normal[ 2 ];
00528 e.depth = ( real ) contactArray[ 0 ].depth;
00529
00530 if ( handler0 )
00531 {
00532 handler0->internal_pushCollisionEvent( e );
00533 }
00534
00535 if ( handler1 )
00536 {
00537
00538
00539 e.normal *= -1;
00540 e.thisSolid = solid1;
00541 e.otherSolid = solid0;
00542 handler1->internal_pushCollisionEvent( e );
00543 }
00544
00545 sim->internal_recordCollision( e );
00546 }
00547
00548
00550
00551
00552
00553
00554
00555
00556
00557
00558
00559
00560
00561
00562
00563
00564
00565
00566
00567
00568
00569
00570
00571
00572
00573
00574
00575
00576
00577
00578
00579
00580
00581
00582
00583
00584
00585
00586
00587
00588
00589
00590
00591 if ( makeContacts )
00592 {
00593
00594 ( ( ODESolid* ) solid0 ) ->internal_setFreelySpinning( false );
00595 ( ( ODESolid* ) solid1 ) ->internal_setFreelySpinning( false );
00596
00597 for ( int i = 0; i < numContacts; ++i )
00598 {
00599 const Material* m0 = &( shape0->material );
00600 const Material* m1 = &( shape1->material );
00601
00602 dContact tempContact;
00603 tempContact.surface.mode = dContactBounce |
00604 dContactSoftERP;
00605
00606
00607 assert( m0->hardness >= 0 && m0->hardness <= 1
00608 && m1->hardness >= 0 && m1->hardness <= 1 );
00609 real hardness = ( m0->hardness + m1->hardness ) *
00610 ( real ) 0.5;
00611
00612
00613
00614 tempContact.surface.soft_erp = hardness *
00615 ( defaults::ode::maxERP - defaults::ode::minERP ) +
00616 defaults::ode::minERP;
00617
00618
00619
00620
00621
00622
00623
00624
00625
00626 assert( m0->friction >= 0 && m0->friction <= 1
00627 && m1->friction >= 0 && m1->friction <= 1 );
00628 if ( 1.0 == m0->friction && 1.0 == m1->friction )
00629 {
00630 tempContact.surface.mu = dInfinity;
00631 }
00632 else
00633 {
00634 tempContact.surface.mu =
00635 sqrt( m0->friction * m1->friction ) *
00636 defaults::ode::maxFriction;
00637 }
00638
00639
00640 assert( m0->bounciness >= 0 && m0->bounciness <= 1
00641 && m1->bounciness >= 0 && m1->bounciness <= 1 );
00642 real bounciness = ( m0->bounciness + m1->bounciness ) *
00643 ( real ) 0.5;
00644
00645
00646 tempContact.surface.bounce = bounciness;
00647
00648
00649
00650
00651 tempContact.surface.bounce_vel =
00652 defaults::bounceThreshold;
00653
00654
00655
00656
00657
00658
00659
00660
00661
00662
00663 tempContact.geom = contactArray[ i ];
00664 dJointID contactJoint = dJointCreateContact(
00665 theWorldID, theJointGroupID, &tempContact );
00666
00667
00668
00669
00670
00671
00672 dJointAttach( contactJoint, o0BodyID, o1BodyID );
00673
00674
00675
00676
00677
00678
00679
00680
00681
00682
00683
00684
00685
00686
00687
00688
00689
00690
00691
00692
00693
00694
00695
00696
00697
00698
00699
00700
00701
00702
00703
00704
00705
00706
00707
00708
00709
00710
00711
00712
00713
00714
00715
00716
00717
00718
00719
00720
00721
00722
00723
00724
00725
00726
00727
00728
00729
00730
00731
00732
00733
00734
00735
00736
00737
00738
00739
00740
00741
00742
00743
00744
00745
00746
00747
00748
00749
00750
00751
00752
00753
00754
00755
00756
00757
00758
00759
00760
00761
00762
00763
00764
00765
00766
00767
00768
00769
00770
00771
00772
00773
00774
00775
00776
00777
00778
00779
00780
00781
00782
00783
00784
00785
00786
00787
00788
00789
00790
00791
00792 }
00793 }
00794 }
00795 }
00796
00797 Joint* internal_getCommonJoint( dBodyID body0, dBodyID body1 )
00798 {
00799
00800
00801
00802
00803
00804 int numJoints0 = dBodyGetNumJoints( body0 );
00805 dJointID theJoint = 0;
00806
00807
00808 int i = 0;
00809 for ( i = 0; i < numJoints0; ++i )
00810 {
00811 dJointID currentJoint = dBodyGetJoint( body0, i );
00812 dBodyID jointBody0 = dJointGetBody( currentJoint, 0 );
00813 dBodyID jointBody1 = dJointGetBody( currentJoint, 1 );
00814
00815 if ( ( jointBody0 == body0 && jointBody1 == body1 ) ||
00816 ( jointBody0 == body1 && jointBody1 == body0 ) )
00817 {
00818
00819
00820
00821 theJoint = currentJoint;
00822 }
00823 }
00824
00825
00826
00827 assert( theJoint );
00828
00829
00830 return ( Joint* ) dJointGetData( theJoint );
00831 }
00832
00833 void internal_volumeCollisionCallback( void* data, dGeomID o0,
00834 dGeomID o1 )
00835 {
00836 if ( dGeomIsSpace( o0 ) || dGeomIsSpace( o1 ) )
00837 {
00838
00839 dSpaceCollide2( o0, o1, data,
00840 &internal_volumeCollisionCallback );
00841 }
00842 else
00843 {
00844
00845
00846
00847
00848
00849
00850
00851
00852
00853
00854
00855
00856
00857
00858
00859
00860
00861
00862
00863
00864
00865 ODESimulator* sim = ( ODESimulator* ) data;
00866
00867
00868
00869 const GeomData* geomData0 = ( ( GeomData* ) dGeomGetData( o0 ) );
00870 const GeomData* geomData1 = ( ( GeomData* ) dGeomGetData( o1 ) );
00871 assert( geomData0 != NULL );
00872 assert( geomData1 != NULL );
00873
00874
00875 const ShapeData* shape0 = geomData0->shape;
00876 const ShapeData* shape1 = geomData1->shape;
00877
00878
00879
00880 bool makeContacts = sim->groupsMakeContacts(
00881 shape0->contactGroup, shape1->contactGroup );
00882 if ( !makeContacts )
00883 {
00884 return ;
00885 }
00886
00887
00888
00889 dContactGeom contactArray[ 1 ];
00890 int numContacts = dCollide( o0, o1, 1, contactArray,
00891 sizeof( dContactGeom ) );
00892
00893 if ( 0 == numContacts )
00894 {
00895 return ;
00896 }
00897 else
00898 {
00899
00900
00901
00902 Solid* solid0 = geomData0->solid;
00903 Solid* solid1 = geomData1->solid;
00904
00905
00906
00907
00908
00909
00910 sim->internal_addCollidedSolid( solid0 );
00911 sim->internal_addCollidedSolid( solid1 );
00912 }
00913 }
00914 }
00915
00916 void internal_raycastCollisionCallback( void* data, dGeomID o0,
00917 dGeomID o1 )
00918 {
00919 if ( dGeomIsSpace( o0 ) || dGeomIsSpace( o1 ) )
00920 {
00921
00922 dSpaceCollide2( o0, o1, data,
00923 &internal_raycastCollisionCallback );
00924 }
00925 else
00926 {
00927
00928
00929
00930
00931 if ( o0 == o1 )
00932 {
00933 return ;
00934 }
00935
00936
00937 ODESimulator* sim = ( ODESimulator* ) data;
00938
00939
00940
00941
00942 GeomData* geomData0 = ( ( GeomData* ) dGeomGetData( o0 ) );
00943 GeomData* geomData1 = ( ( GeomData* ) dGeomGetData( o1 ) );
00944
00945
00946 unsigned int geomContactGroup = defaults::shape::contactGroup;
00947 if ( geomData0 )
00948 {
00949 geomContactGroup = geomData0->shape->contactGroup;
00950 }
00951 else
00952 {
00953 geomContactGroup = geomData1->shape->contactGroup;
00954 }
00955
00956
00957
00958 bool makeContacts = sim->groupsMakeContacts(
00959 geomContactGroup, sim->internal_getRayContactGroup() );
00960 if ( !makeContacts )
00961 {
00962 return ;
00963 }
00964
00965
00966
00967 dContactGeom contactArray[ defaults::ode::maxRaycastContacts ];
00968 int numContacts = dCollide( o0, o1,
00969 defaults::ode::maxRaycastContacts, contactArray,
00970 sizeof( dContactGeom ) );
00971
00972 if ( 0 == numContacts )
00973 {
00974 return ;
00975 }
00976 else
00977 {
00978
00979
00980 int closest = 0;
00981 for (int i = 0; i < numContacts; ++i)
00982 {
00983 if (contactArray[i].depth < contactArray[closest].depth)
00984 {
00985 closest = i;
00986 }
00987 }
00988
00989
00990
00991 Solid* solid = NULL;
00992 if ( geomData0 )
00993 {
00994 solid = geomData0->solid;
00995 }
00996 else
00997 {
00998 solid = geomData1->solid;
00999 }
01000
01001 Point3r intersection( ( real ) contactArray[ closest ].pos[ 0 ],
01002 ( real ) contactArray[ closest ].pos[ 1 ],
01003 ( real ) contactArray[ closest ].pos[ 2 ] );
01004 Vec3r normal( ( real ) contactArray[ closest ].normal[ 0 ],
01005 ( real ) contactArray[ closest ].normal[ 1 ],
01006 ( real ) contactArray[ closest ].normal[ 2 ] );
01007
01008 sim->internal_addRaycastResult( solid, intersection,
01009 normal, ( real ) contactArray[ closest ].depth );
01010 }
01011 }
01012 }
01013 }
01014
01015 void ODESimulator::internal_addCollidedSolid( Solid* solid )
01016 {
01017
01018
01019 if ( mSensorSolid == solid )
01020 {
01021 return ;
01022 }
01023
01024 ODESolid* solidPtr = ( ( ODESolid* ) solid );
01025
01026 if ( solidPtr->internal_getCollisionCount() != mCollisionCount )
01027 {
01028 mVolumeQueryResult.internal_addSolid( solid );
01029 solidPtr->internal_setCollisionCount( mCollisionCount );
01030 }
01031 }
01032
01033 void ODESimulator::internal_addRaycastResult( Solid* solid,
01034 const Point3r& intersection, const Vec3r& normal, real depth )
01035 {
01036
01037
01038 if ( mSensorSolid == solid )
01039 {
01040 return ;
01041 }
01042
01043
01044 RaycastResult result;
01045 result.solid = solid;
01046 result.intersection = intersection;
01047 result.normal = normal;
01048 result.distance = depth;
01049 mRaycastResults.push_back( result );
01050 }
01051
01052 unsigned int ODESimulator::internal_getRayContactGroup()
01053 {
01054 return mRayContactGroup;
01055 }
01056
01057
01058
01059
01060
01061
01062
01063
01064
01065
01066
01068
01069
01070
01071
01072
01073
01074
01075
01076
01077 vector<RaycastResult> & ODESimulator::internal_fireRay( const Rayr& r,
01078 real length, const Solid* attachedSolid,
01079 unsigned int rayContactGroup )
01080 {
01081 Point3r origin = r.getOrigin();
01082 Vec3r dir = r.getDir().unit();
01083
01084 mRaycastResults.clear();
01085 mSensorSolid = attachedSolid;
01086 mRayContactGroup = rayContactGroup;
01087
01088
01089
01090
01091 dGeomID rayGeomID = dCreateRay( mRootSpaceID, length );
01092 dGeomRaySet( rayGeomID, origin[ 0 ], origin[ 1 ], origin[ 2 ], dir[ 0 ],
01093 dir[ 1 ], dir[ 2 ] );
01094 dGeomSetData( rayGeomID, NULL );
01095
01096
01097
01098 dSpaceCollide2( rayGeomID, ( dGeomID ) mRootSpaceID, this,
01099 &ode_hidden::internal_raycastCollisionCallback );
01100
01101
01102 dGeomDestroy( rayGeomID );
01103
01104 return mRaycastResults;
01105 }
01106
01107 const VolumeQueryResult& ODESimulator::internal_queryVolume(
01108 const Solid* volume, const Solid* attachedSolid )
01109 {
01110 mSensorSolid = attachedSolid;
01111 mCollisionCount++;
01112 mVolumeQueryResult.internal_clearSolids();
01113 const std::vector<GeomData*>* geomList =
01114 ( ( ODESolid* ) volume ) ->internal_getGeomDataList();
01115
01116
01117
01118
01119 std::vector<GeomData*>::const_iterator iter;
01120 for ( iter = geomList->begin(); iter != geomList->end(); ++iter )
01121 {
01122 dGeomID geomID = ( *iter ) ->geomID;
01123 if ( ( *iter ) ->transformID )
01124 {
01125
01126 geomID = ( *iter ) ->transformID;
01127 }
01128
01129 dSpaceCollide2( geomID, ( dGeomID ) mRootSpaceID, this,
01130 &ode_hidden::internal_volumeCollisionCallback );
01131 }
01132
01133
01134 mVolumeQueryResult.internal_removeSolid( volume );
01135
01136 return mVolumeQueryResult;
01137 }
01138
01139 void ODESimulator::setGravity( const Vec3r& gravity )
01140 {
01141 dWorldSetGravity( mWorldID, gravity[ 0 ], gravity[ 1 ], gravity[ 2 ] );
01142 }
01143
01144 Vec3r ODESimulator::getGravity() const
01145 {
01146 dVector3 g;
01147 dWorldGetGravity( mWorldID, g );
01148 Vec3r gravity( ( real ) g[ 0 ], ( real ) g[ 1 ], ( real ) g[ 2 ] );
01149 return gravity;
01150 }
01151
01152 void ODESimulator::setSolverAccuracy( SolverAccuracyLevel level )
01153 {
01154 Simulator::setSolverAccuracy( level );
01155
01156 switch ( level )
01157 {
01158 case SOLVER_ACCURACY_VERY_LOW:
01159 mSolverType = SOLVER_QUICKSTEP;
01160 dWorldSetQuickStepNumIterations( mWorldID, 5 );
01161 break;
01162 case SOLVER_ACCURACY_LOW:
01163 mSolverType = SOLVER_QUICKSTEP;
01164 dWorldSetQuickStepNumIterations( mWorldID, 10 );
01165 break;
01166 case SOLVER_ACCURACY_MEDIUM:
01167 mSolverType = SOLVER_QUICKSTEP;
01168
01169 dWorldSetQuickStepNumIterations( mWorldID, 20 );
01170 break;
01171 case SOLVER_ACCURACY_HIGH:
01172 mSolverType = SOLVER_QUICKSTEP;
01173 dWorldSetQuickStepNumIterations( mWorldID, 40 );
01174 break;
01175 case SOLVER_ACCURACY_VERY_HIGH:
01176 mSolverType = SOLVER_WORLDSTEP;
01177 break;
01178 default:
01179 assert( false );
01180 break;
01181 }
01182 }
01183
01184 dWorldID ODESimulator::internal_getWorldID() const
01185 {
01186 return mWorldID;
01187 }
01188
01189 dSpaceID ODESimulator::internal_getSpaceID() const
01190 {
01191 return mRootSpaceID;
01192 }
01193
01194 dJointGroupID ODESimulator::internal_getJointGroupID() const
01195 {
01196 return mContactJointGroupID;
01197 }
01198 }