ODE講座7:ジョイント(関節)

金沢もã™ã£ã‹ã‚Šå¯’ããªã‚Šãšã‚ã„ガニã€é¦™ç®±ã‚¬ãƒ‹ï¼ˆæ³¨1)ãŒè§£ç¦ã•れã€å¯’鰤(ã‹ã‚“ã¶ã‚Šï¼šæ³¨2)ã¨åœ°é…’(注3ï¼‰ãŒæ—¨ã„å£ç¯€ã«ãªã£ã¦ã¾ã„りã¾ã—ãŸã€‚
ゲーム開発やãƒãƒœãƒƒãƒˆã®ç ”究者ã«ã‚‚使ã‚れã¦ã„るオープンソースã®ç‰©ç†è¨ˆç®—エンジンODE(Open Dynamics Engineã€ã‚ªãƒ¼ãƒ—ン ダイナミクスエンジン)をå¦ã¶ODE講座ã®ç¬¬ï¼—回目ã§ã™ã€‚
今回ã¯ã‚¸ãƒ§ã‚¤ãƒ³ãƒˆï¼ˆé–¢ç¯€ï¼‰ã«ã¤ã„ã¦ãŠè©±ã—ã—ã¾ã™ã€‚ å‰å›žèª²é¡ŒãŒå‡ºã¦ã¦ã„ã¾ã—ãŸãŒã§ãã¾ã—ãŸã‹ï¼Ÿã€€ç”ãˆã¯ã€nearCallback関数ã®ä¸ã«ã‚ã‚‹
contact[i].surface.bounce = 0.0; // (0.0~1.0) å発係数ã¯0ã‹ã‚‰1ã¾ã§
contact[i].surface.bounce_vel = 0.0; //  跳ã返りã«å¿…è¦ãªé€Ÿåº¦
ã®å€¤ã‚’0.0より大ãã1.0以下ã«ã™ã‚Œã°ã‚ˆã„ã®ã§ã™ã€‚å発係数ã¯è¡çªå‰ã¨è¡çªå¾Œã®é€Ÿåº¦æ¯”ã§ã—ãŸã。
ã§ã¯ã€ã‚¸ãƒ§ã‚¤ãƒ³ãƒˆã«ã¤ã„ã¦èª¬æ˜Žã—ã¾ã™ã€‚ã‚¸ãƒ§ã‚¤ãƒ³ãƒˆã¯æˆ‘々ã®å‘¨ã‚Šã§ã¯ã€æŠ˜ç•³ã¿æºå¸¯ã®ãƒ’ンジやドアã®è¶ç•ªã«ç›¸å½“ã—ã¾ã™ã€‚å°é›£ã—ãã„ã†ã¨ã€ï¼’ã¤ã®ãƒœãƒ‡ã‚£ã®ä½ç½®ã‚„姿勢をã‚る一定ã®é–¢ä¿‚ã«ä¿ã¤æ‹˜æŸãŒã‚¸ãƒ§ã‚¤ãƒ³ãƒˆã¨ãªã®ã§ã™ã€‚ODEã§ã¯ã‚¸ãƒ§ã‚¤ãƒ³ãƒˆã¨æ‹˜æŸã‚’åŒã˜æ„味ã§ä½¿ã£ã¦ã„ã¾ã™ã€‚
ジョイントã®ä½¿ã„æ–¹ã¯ä»¥ä¸‹ã®ã‚ˆã†ã«ãªã‚Šã¾ã™ã€‚
- ***ジョイントã®ç”Ÿæˆã€€ã€€ã€€ã€€ã€€ã€€dJointCreate***()
- ***ジョイントã¨ãƒœãƒ‡ã‚£ã®çµåˆã€€dJointAttach()
- ***ジョイントã®ä¸å¿ƒç‚¹ã‚’è¨å®šã€€dJointSet***Anchor()
- ***ジョイントã®å›žè»¢è»¸ã‚’è¨å®šã€€dJointSet***Axis()
上ã§***ã«ã¯ã‚¸ãƒ§ã‚¤ãƒ³ãƒˆã®ã‚¿ã‚¤ãƒ—ãŒå…¥ã‚Šã¾ã™ã€‚タイプã«ã¯Hinge(ヒンジ)ã€Ball(ボール)ã€Slider(スライダー)ã€Universal(ユニãƒãƒ¼ã‚µãƒ«)ç‰ãŒã‚りã¾ã™ã€‚詳ã—ã„ä½¿ã„æ–¹ã¯ãƒžãƒ‹ãƒ¥ã‚¢ãƒ«ã‚’å‚ç…§ã—ã¦ãã ã•ã„。
ã•ã£ãã上図ã«ç¤ºã—ã¦ã„る玉ã¨å††æŸ±ã‚’ヒンジジョイントã§çµåˆã—ã¦ã„るオブジェクトãŒãƒã‚¦ãƒ³ãƒ‰ã™ã‚‹ã‚½ãƒ¼ã‚¹ã‚³ãƒ¼ãƒ‰ã‚’以下ã«ç¤ºã—ã¾ã™ã€‚ãªãŠã€å‰å›žã¾ã§ã¨åŒã˜é–¢æ•°ã‚„宣言ã¯çœç•¥ã—ã¦ã„ã¾ã™ã€‚
注1:香箱ガニã¯ãšã‚ã„ガニã®ãƒ¡ã‚¹ã§ã™ã€‚体ã¯ã¨ã¦ã‚‚å°ã•ã„ã®ã§ã™ãŒã€åµãŒè©°ã¾ã£ã¦ã„ã¦è¶…美味ã§ã™ã€‚
注2:脂ãŒä¹—ã£ã¦ç¾Žå‘³ã€‚甘エビもãŠã„ã—ã„ã§ã™ã。
注3:石å·ã§ã¯èŠå§«ã€å¤©ç‹—舞ã€ä¸‡æ³æ¥½ãªã©ãŒå¥½ãã§ã™ãŒã€ç¦äº•ã®é»’é¾ã¯æœ¬å½“ã«è¶…ãŠå‹§ã‚ã§ã™ã€‚ã ã¾ã•れãŸã¨æ€ã£ã¦ã‚¤ãƒ³ã‚¿ãƒ¼ãƒãƒƒãƒˆã§æ³¨æ–‡ã—ã¦ã¿ã¦ã¯ã„ã‹ãŒã§ã™ã‹ï¼Ÿ
[cpp]
// sample3.cpp by ã§ã‚€
#ifdef dDOUBLE
#define dsDrawSphere dsDrawSphereD // å˜ç²¾åº¦ã¨å€ç²¾åº¦ã®æç”»é–¢æ•°ã«å¯¾å¿œã™ã‚‹ãŠã¾ã˜ãªã„
#define dsDrawCapsule dsDrawCapsuleD
#endif
typedef struct {
dBodyID body; //  ボディ(剛体)
dGeomID geom; // ジオメトリ(形状)
dReal radius, length, mass; // åŠå¾„[m]ã€ã€€é•·ã•[m]ã€ã€€è³ªé‡[kg]
} myLink;
myLink ball, pole;
// simLoopã¯ã“ã®ã‚½ãƒ¼ã‚¹ã§ã¯ã‚ã‹ã‚‰ãªã„ãŒwhileループã«å…¥ã£ã¦ã„ã¦ã€ã‚·ãƒŸãƒ¥ãƒ¬ãƒ¼ã‚·ãƒ§ãƒ³ã®å„ステップã§å®Ÿè¡Œã•れる。
static void simLoop (int pause)
{
const dReal *pos1,*R1,*pos2,*R2; // é…列ã¸ã®ãƒã‚¤ãƒ³ã‚¿ãŒä»£å…¥ã•れる
dSpaceCollide(space,0,&nearCallback);  // è¡çªæ¤œå‡ºè¨ˆç®—
dWorldStep(world,0.01); // 動力å¦è¨ˆç®—を1ステップ(ã“ã“ã§ã¯0.01秒)進ã‚ã‚‹
dJointGroupEmpty(contactgroup); //  接触点グループã®å¾Œå§‹æœ«
// ãƒœãƒ¼ãƒ«ã®æç”»
dsSetColor(1.0,0.0,0.0);  // 赤色ã®è¨å®š
pos1 = dBodyGetPosition(ball.body); // pos1(ä½ç½®ï¼‰ã¯é…列ã®ãƒã‚¤ãƒ³ã‚¿ãƒ¼ã«ãªã£ã¦ã„ã‚‹
R1 = dBodyGetRotation(ball.body); // 回転行列ã®å–å¾—
dsDrawSphere(pos1,R1,ball.radius); // çƒã®æç”»
// å††æŸ±ã®æç”»
pos2 = dBodyGetPosition(pole.body); // ä½ç½®ã®å–å¾—
R2 = dBodyGetRotation(pole.body); // å§¿å‹¢ã®å–å¾—
dsDrawCapsule(pos2,R2,pole.length,pole.radius); // ã‚«ãƒ—ã‚»ãƒ«ã®æç”»
}
// オブジェクトã®ä½œæˆ
void createBallPole() {
dMass m1;
dReal x0 = 0.0, y0 = 0.0, z0 = 2.5;
//玉
ball.radius = 0.2; ball.mass = 1.0;
ball.body = dBodyCreate(world);
dMassSetZero(&m1);
dMassSetSphereTotal(&m1,ball.mass,ball.radius);
dBodySetMass(ball.body,&m1);
dBodySetPosition(ball.body, x0, y0, z0);
ball.geom = dCreateSphere(space,ball.radius);
dGeomSetBody(ball.geom,ball.body);
//  カプセル
pole.radius = 0.025; pole.length = 1.0; pole.mass = 1.0;
pole.body = dBodyCreate(world);
dMassSetZero(&m1);
dMassSetCapsuleTotal(&m1,pole.mass,3,pole.radius,pole.length);
dBodySetMass(pole.body,&m1);
dBodySetPosition(pole.body, x0, y0, z0 - 0.5 * pole.length);
pole.geom = dCreateCapsule(space,pole.radius,pole.length);
dGeomSetBody(pole.geom,pole.body);
// ヒンジジョイント
joint = dJointCreateHinge(world, 0);           // ヒンジジョイントã®ç”Ÿæˆ
dJointAttach(joint, ball.body,pole.body);      // 玉ã®ãƒœãƒ‡ã‚£ã¨å††æŸ±ã®ãƒœãƒ‡ã‚£ã‚’ジョイントã§çµåˆ
dJointSetHingeAnchor(joint, x0, y0, z0 - ball.radius); // ヒンジジョイントã®ã‚¢ãƒ³ã‚«ãƒ¼(ä¸å¿ƒç‚¹ï¼‰ã‚’è¨å®š
dJointSetHingeAxis(joint, 1, 0, 0);            // ヒンジジョイントã®å›žè»¢è»¸ãƒ™ã‚¯ãƒˆãƒ«ã‚’è¨å®š(1,0,0)
}
int main (int argc, char **argv)
{
setDrawStuff();  // æç”»é–¢æ•°ã®è¨å®š
world = dWorldCreate(); // 動力å¦ãƒ¯ãƒ¼ãƒ«ãƒ‰ã®ç”Ÿæˆ
space = dHashSpaceCreate(0); // è¡çªè¨ˆç®—スペースã®ç”Ÿæˆ
contactgroup = dJointGroupCreate(0); // 接触点グループã®ç”Ÿæˆ
dWorldSetGravity(world,0,0,-9.8); // é‡åŠ›åŠ é€Ÿåº¦ã®è¨å®š
ground = dCreatePlane(space,0,0,1,0); // 地é¢ç”¨å¹³é¢ã‚¸ã‚ªãƒ¡ãƒˆãƒªã®ç”Ÿæˆ
createBallPole(); // 玉ã¨ã‚«ãƒ—セルã®ç”Ÿæˆ
dsSimulationLoop (argc,argv,352,288,&fn); // シミュレーションループ
dWorldDestroy (world); // ワールドã®ç ´å£Š
return 0;
}
[/cpp]
ã“ã®ä¾‹ã§ã¯çމã¨å††æŸ±ã®ãƒœãƒ‡ã‚£ã‚’ヒンジジョイントã§çµã³ã¤ã‘ã¦ã„ã¾ã™ã€‚
ã§ã¯ã‚½ãƒ¼ã‚¹ã‚³ãƒ¼ãƒ‰ã‚’èªã¿ã¾ã—ょã†ã€‚createBallandPall関数ã§ã¯ã¾ãšçŽ‰ã‚’ä½œã‚Šã€ãã®å¾Œã€å††æŸ±ã‚’作りã€ãれã‹ã‚‰ãƒ’ンジジョイントを dJointCreateHinge()㧠生æˆã—ã€dJointAttach()ã§ï¼’ã¤ã®ãƒœãƒ‡ã‚£ã‚’ヒンジジョイントã§çµåˆã—ã¾ã™ã€‚ãã®å¾Œã®dSetHingeAnchor()ã¯ã‚¸ãƒ§ã‚¤ãƒ³ãƒˆã®å›žè»¢ä¸ 心点ã®ä½ç½®ã‚’è¨å®šã—ã€dJointSetHingeAxis()ã§å›žè»¢è»¸ãƒ™ã‚¯ãƒˆãƒ« ã‚’è¨å®šã—ã¾ã™ã€‚ã“ã®ä¾‹ã§ã¯å›žè»¢è»¸ãƒ™ã‚¯ãƒˆãƒ«ã¯(1,0,0)ãªã®ã§ï½˜è»¸æ–¹å‘ã¨ãªã‚Šã¾ã™ã€‚詳ã—ãã¯ãƒžãƒ‹ãƒ¥ã‚¢ãƒ«ã‚’å‚照。
ã“れã§ã‚¸ãƒ§ã‚¤ãƒ³ãƒˆã®ç”Ÿæˆã¯çµ‚ã‚りã§ã™ã€‚今回ã¯ç°¡å˜ã®ãŸã‚ã«ã‚¸ãƒ§ã‚¤ãƒ³ãƒˆã®ãƒ‘ラメータをè¨å®šã—ã¾ã›ã‚“ã§ã—ãŸãŒã€å¯å‹•åŸŸã‚„æœ€å¤§ãƒˆãƒ«ã‚¯ã€æœ€å¤§è§’速度ã®è¨å®šãªã©ã‚‚å¯èƒ½ã§ã™ã€‚ã“ã“をクリックã—ã¦ã‚µãƒ³ãƒ—ルプãƒã‚°ãƒ©ãƒ をダウンãƒãƒ¼ãƒ‰ã—ã¦éŠã‚“ã§ãã ã•ã„。
次回ã¯é–¢ç¯€ã®å‹•ã‹ã—方やパラメータã®è¨å®šæ–¹æ³•を説明ã—ã¾ã™ã€‚ãªãŠã€èª¬æ˜Žã§ã‚ã‹ã‚Šãšã‚‰ã„箇所や質å•ãŒã‚れã°ã‚³ãƒ¡ãƒ³ãƒˆã‚’投稿ã—ã¦ãã ã•ã„。
ä»Šå›žç™»å ´ã—ãŸAPI
- void dJointAttach(dJointID joint, dBodyID body1, dBodyID dBody2)
剛体body1ã¨body2ã«ã‚¸ãƒ§ã‚¤ãƒ³ãƒˆjointã‚’å–り付ã‘ã‚‹ - dJointID dJointCreateHinge(dWorldID world, dJointGroupID)
worldã«ãƒ’ンジジョイントを生æˆã—ã€ãã®ï¼©ï¼¤ç•ªå·ã‚’è¿”ã™ã€‚dJointGroupIDã«ã¯0を入れる。 - void dJointSetHingeAnchor(dJointID joint, dReal x, dReal y, dReal z)
ヒンジジョイントã®å›žè»¢è»¸ã®ä¸å¿ƒç‚¹(x,y,z)ã‚’è¨å®šã™ã‚‹ã€‚ - void dJointSetHingeAxis(dJointID joint, dReal x, dReal y, dReal z)
ヒンジジョイントã®å›žè»¢è»¸ãƒ™ã‚¯ãƒˆãƒ«(x,y,z)ã‚’è¨å®šã™ã‚‹ã€‚
æ›´æ–°å±¥æ´
2007-1-22: 本文ã®èª¬æ˜Žã‚’強化ã—ã€ã‚µãƒ³ãƒ—ルプãƒã‚°ãƒ©ãƒ ã§æ–°ã—ãç™»å ´ã—ãŸAPI集を掲載ã—ãŸã€‚