dWorldID world; // ワールド dJointGroupID contactjointGroup; // 接触ジョイントのジョイント グループ
// 衝突検出時に呼び出されるコールバック関数 void nearCallback( void *data, dGeomID o1, dGeomID o2 ) { // o1、o2のいずれかがスペースであるか判定する if( dGeomIsSpace( o1 ) || dGeomIsSpace( o2 ) ) { // o1、o2が異なるスペースであることも考慮して、衝突検出を行う dSpaceCollide2( o1, o2, data, &nearCallback ); if( dGeomIsSpace( o1 ) ) { // o1がスペースならば、そこに含まれるすべてのジオメトリを対象に衝突検出をする dSpaceCollide( o1, data, &nearCallback ); } if( dGeomIsSpace( o2 ) ) { // o2がスペースならば、そこに含まれるすべてのジオメトリを対象に衝突検出をする dSpaceCollide( o2, data, &nearCallback ); } } else { const int max_contacts = 256; dContact contact[ max_contacts ]; // 接触情報を格納する配列 // ジオメトリo1、o2の間の接触情報を作成する intnum_contact = dCollide( o1, o2, max_contacts, // 接触点の最大数 &contact[ 0 ].geom, // 接触情報を格納するdContactGeom構造体 sizeof( dContact ) ); for( int i = 0; i < intnum_contact; i++ ) { // 接触面の性質を設定する contact[ i ].surface.mode = dContactBounce; contact[ i ].surface.bounce = 1.0; contact[ i ].surface.bounce_vel = 0.0; // 接触ジョイントを作成する dJointID joint = dJointCreateContact( world, contactjointGroup, &contact[ i ] // 接触情報 ); // 接触情報に含まれれるジオメトリのボディを取得する dBodyID body1 = dGeomGetBody( contact[ i ].geom.g1 ); dBodyID body2 = dGeomGetBody( contact[ i ].geom.g2 ); // 接触したボディを接触ジョイントにより接続する dJointAttach( joint, body1, body2 ); } } }※コールバック関数内では、スペースに変更を加えてはなりません。
// シミュレーションのステップごとに、トップレベルのスペースを対象に // すべてのジオメトリ同士の衝突をテストする dSpaceCollide( top_level_space, 0, &nearCallback ); // シミュレーションのステップを進める dWorldStep( world, 0.01 ); // 接触ジョイントのグループに含まれるすべてのジョイントを破棄する dJointGroupEmpty( contactjointGroup );
ジョイントの破棄は処理の最後に行います。さもなくばシミュレーションを終了するときに、「destroying world containing grouped joints」との警告が表示されます。