HOME > natural science Laboratory > コンピュータ・シミュレーション講座 > ODE入門

Open Dynamics Engine 入門
【1日目】球の描画と衝突判定

文責:遠藤 理平 (2011年2月11日) カテゴリ:ODE入門(9)仮想物理実験室(325)

Open Dynamics Engine の利用方法

ODEのインストールから、コンパイル方法は、次のページに非常に詳しく紹介されていますので参照ください。
2. インストールと開発/demura.net: ロボットの開発と教育

球の描画と衝突判定

ボールを空から落下させるプログラムです。

プログラムソース

以下のプログラムソースは、demura.net: ロボットの開発と教育にて公開されているソースを利用させていただいております。

#include <ode/ode.h>
#include <drawstuff/drawstuff.h>
#include <time.h>

#ifdef dDOUBLE
#define dsDrawSphere dsDrawSphereD
#endif
int WindowWidth  = 352; //ウィンドウの幅
int WindowHeight = 288; //ウィンドウの高さ

static dWorldID world; //ODE世界のID
static dSpaceID space; //衝突空間のID(同じ衝突空間内のオブジェクトのみが衝突する)
static dGeomID  ground;//地面との衝突判定のID
static dJointGroupID contactgroup; //ジョイントグループID
dsFunctions fn;

const int N = 200;//描画する球の数
const dReal   radius = 0.2;//球の半径
const dReal   mass   = 1.0;//球の質量

typedef struct {//球の構造体
  dBodyID body; //動力学計算用のボディ
  dGeomID geom; //衝突計算用のジオメトリ
} MyObject;
MyObject ball[N];//球を描画するための配列

static void nearCallback(void *data, dGeomID o1, dGeomID o2)//2つのオブジェクトに衝突可能性がある場合に呼び出される
{
  const int N = 10;
  dContact contact[N];

  //地面との衝突であるかどうかの判定
  int isGround = ((ground == o1) || (ground == o2));

  //衝突の判定を実際に行う関数 3つ目の引数に衝突の情報を格納する
  int n =  dCollide(o1,o2,N,&contact[0].geom,sizeof(dContact));


  //if (isGround)  {//もし地面との衝突だけを考える場合にはコメントアウトをはずす
    for (int i = 0; i < n; i++) {
      contact[i].surface.mode = dContactBounce;  //衝突モード
      contact[i].surface.mu   = dInfinity;       // 摩擦係数
      contact[i].surface.bounce     = 0.5;       // 反発係数(0 ~ 1)
      contact[i].surface.bounce_vel = 0.0;       // 最低反射速度
      dJointID c = dJointCreateContact(world,contactgroup,&contact[i]);
      dJointAttach (c,dGeomGetBody(contact[i].geom.g1),dGeomGetBody(contact[i].geom.g2));
    }
  //}
}


static void simLoop (int pause)//無限ループ
{
  const dReal *pos,*R;

  dSpaceCollide(space,0,&nearCallback); //衝突判定用の関数
  dWorldStep(world, 0.01);//世界の時間を進める
  dJointGroupEmpty(contactgroup);//ジョイントグループを初期化
  //球の描画を行う
  for(int i=0;i<N;i++){
    dsSetColor(1.0, 0.0, 0.0);            //オブジェクトの色の設定
    pos = dBodyGetPosition(ball[i].body); //オブジェクトの位置情報(posは配列)
    R   = dBodyGetRotation(ball[i].body); //オブジェクトの回転情報(Rは配列)
    dsDrawSphere(pos,R,radius);           //オブジェクトの描画
  }
}

void start() //初期設定
{
  static float xyz[3] = {0.0,-3.0,1.0}; //カメラの位置
  static float hpr[3] = {90.0,0.0,0.0}; //カメラの方向
  //(z軸, y軸, x軸)における回転角度({0.0,0.0,0.0}でx軸方向を向いている)
  //上の場合は、y軸の方向を向いている
  dsSetViewpoint (xyz,hpr); //カメラの設定
}

void  prepDrawStuff() {   //描画の初期化
  fn.version = DS_VERSION; 
  fn.start   = &start;
  fn.step    = &simLoop;
  fn.command = NULL;
  fn.stop    = NULL;
  fn.path_to_textures = "C:/ode-0.11.1/drawstuff/textures";
}

//いよいよメイン関数
int main (int argc, char *argv[])
{
  srand(time(NULL)); //rand()の種
  dReal x0 = 0.0, y0 = 0.0, z0 = 3.0;
  dMass m1;

  prepDrawStuff();

  dInitODE();
  world = dWorldCreate();      //世界の誕生(IDをworldに代入)
  space = dHashSpaceCreate(0); //衝突空間の生成(IDをspaceに代入)
  contactgroup = dJointGroupCreate(0); //ジョイント空間の生成(IDをcontactgroupに代入)

  dWorldSetGravity(world,0,0,-0.5);//世界の重力加速度を指定

  //地面との衝突判定用ジオメトリの生成(描画なし)
  ground = dCreatePlane(space,0,0,1,0);

  //ボールの生成
  for(int i=0;i<N;i++){
    ball[i].body = dBodyCreate(world);     //動力学計算用ボディのIDを取得
    dMassSetZero(&m1);                     //基本形状構造体の初期化
    dMassSetSphereTotal(&m1, mass ,radius);//基本形状構造体に重心、慣性テンソルのパラメータをセットする(この場合は球)
    dBodySetMass(ball[i].body,&m1);        //生成したオブジェクトと基本形状構造体とリンクさせる
    //生成したオブジェクトの初期位置を設定
    dBodySetPosition(ball[i].body, x0+ double(rand()-rand())/double(RAND_MAX*10)  , y0 + double(rand()-rand())/double(RAND_MAX*10) , z0 + double(i)/2.0);

    ball[i].geom = dCreateSphere(space,radius); //衝突計算用ジオメトリのIDを取得
    dGeomSetBody(ball[i].geom,ball[i].body);    //衝突計算用ジオメトリのIDと動力学計算用ボディのIDをリンク
  }
  dsSimulationLoop (argc,argv,WindowWidth, WindowHeight,&fn); //シミュレーション用の無限ループ

  dWorldDestroy (world);
  dCloseODE();

  return 0;
}

参考ページ

demura.net: ロボットの開発と教育(出村 公成 氏)
ODE (Open Dynamics Engine) プログラミング解説(Crystal-Creation 氏)



▲このページのトップNPO法人 natural science トップ

関連記事

ODE入門

仮想物理実験室







▲このページのトップNPO法人 natural science トップ




Warning: mysqli_connect(): (28000/1045): Access denied for user 'xsvx1015071_ri'@'sv102.xserver.jp' (using password: YES) in /home/xsvx1015071/include/natural-science/include_counter-d.php on line 8
MySQL DBとの接続に失敗しました