CG¥¥ã¥é¥¯¥¿¥¢¥Ë¥á¡¼¥·¥ç¥ó¤Ë´ØÏ¢¤¹¤ë¥×¥í¥°¥é¥àºîÀ®¤ä¸¦µæ¤Ë·È¤ï¤Ã¤Æ¤¤¤ë¤È¡¤¤Û¤Ü´Ö°ã¤¤¤Ê¤¯¥¯¥©¡¼¥¿¥Ë¥ª¥ó¡ÊQuaternion¡Ë¤È¤¤¤¦²óžɽ¸½Ë¡¤òÌܤˤ·¤Þ¤¹¡¥¤µ¤é¤Ë¡¤µåÌÌÀþ·ÁÊä´Ö¤Ê¤É¥¯¥©¡¼¥¿¥Ë¥ª¥ó¤Î±þÍÑË¡¤òÃΤë²áÄø¤Ç¡¤¡Ö¥¯¥©¡¼¥¿¥Ë¥ª¥ó¤ò»È¤Ã¤¿¥¤¥ó¥Ð¡¼¥¹¥¥Í¥Þ¥Æ¥£¥¯¥¹¤ò¼Â¸½¤Ç¤¤Ê¤¤¤À¤í¤¦¤«¡©¡×¤È¤¤¤¦¶½Ì£¤òÊú¤¯¤³¤È¤â¤¢¤ë¤È»×¤¤¤Þ¤¹¡¥
Ëܵ»ö¤Ç¤Ï¤½¤Î°ì¤Ä¤Î²ò¤È¤·¤Æ¡¤Âпô¥¯¥©¡¼¥¿¥Ë¥ª¥ó¤òÍѤ¤¤¿¿ôÃÍŪµÕ±¿Æ°³ØË¡¡Ê¥¤¥ó¥Ð¡¼¥¹¥¥Í¥Þ¥Æ¥£¥¯¥¹¡¤Inverse Kinematics¡¤IK¡Ë¤ò²òÀ⤷¤Þ¤¹¡¥
¥ä¥³¥Ó¥¢¥ó¤òÍѤ¤¤¿µÕ±¿Æ°³Ø ¤Ç¤Ï¡¤²óž¹ÔÎó¤Î¥ª¥¤¥é¡¼³Ñɽ¸½¤òÍѤ¤¤¿ IK ¤ò¾Ò²ð¤·¤Þ¤·¤¿¡¥¤½¤ÎÊýË¡¤Ç¤Ï¡¤Â¿¥ê¥ó¥¯·Ï¤Î³Æ´ØÀá¤ÎÈù¾®³ÑÊѰÌÎ̤ȥ¨¥Õ¥§¥¯¥¿¤ÎÊѰÌÎ̤Ȥδط¸¤òɽ¤¹¥ä¥³¥Ó¥¢¥ó¹ÔÎó¤òƳ½Ð¤·¡¤¤½¤ÎµÕ¼ÌÁü¤Ë¤è¤Ã¤Æ¥¨¥Õ¥§¥¯¥¿¤òǤ°ÕÊý¸þ¤ËÈù¾®°Üư¤µ¤»¤ë¤¿¤á¤Î´ØÀá³ÑÊѰÌÎ̤ò»»½Ð¤·¤Þ¤·¤¿¡¥
°ìÊý¡¤º£²ó¤ÎÊýË¡¤Ç¤Ï¡¤ËܼÁŪ¤Ê½èÍý¼ê½ç¤Ï¤½¤Î¤Þ¤Þ¤Ë¡¤²óž¹ÔÎó¤Î¥ª¥¤¥é¡¼³Ñɽ¸½¡Ê¥Ñ¥é¥á¡¼¥¿¿ô£³¡Ë¤ÎÂØ¤ï¤ê¤ËÂпô¥¯¥©¡¼¥¿¥Ë¥ª¥ó¡ÊƱ¤¸¤¯¥Ñ¥é¥á¡¼¥¿¿ô£³¡Ë¤òÍøÍѤ·¤Þ¤¹¡¥¤Ä¤Þ¤ê¡¤Âпô¶õ´Ö¤Ë¼ÌÁü¤µ¤ì¤¿¥¯¥©¡¼¥¿¥Ë¥ª¥ó¤Î¥Ñ¥é¥á¡¼¥¿ÊѲ½¤È¥¨¥Õ¥§¥¯¥¿¤ÎÈù¾®ÊѰÌÎ̤Ȥδط¸¤òɽ¤¹¥ä¥³¥Ó¥¢¥ó¹ÔÎó¤òƳ½Ð¤·¡¤¤½¤ÎµÕ¼ÌÁü¤Ë¤è¤Ã¤Æ¥¨¥Õ¥§¥¯¥¿¤òǤ°ÕÊý¸þ¤ËÈù¾®°Üư¤µ¤»¤ë¤¿¤á¤Î¥¯¥©¡¼¥¿¥Ë¥ª¥ó¤ÎÊѲ½Î̤ò»»½Ð¤·¤Þ¤¹¡¥
Fig.1 ¥¹¥Ê¥Ã¥×¥·¥ç¥Ã¥È¡§¥ª¥¤¥é¡¼³ÑIK¡ÊÀ֡ˤȥ¯¥©¡¼¥¿¥Ë¥ª¥óIK¡ÊÇò¡Ë
»²¹Íʸ¸¥ †
¥µ¥ó¥×¥ë¥×¥í¥°¥é¥à †
¥µ¥ó¥×¥ë¥×¥í¥°¥é¥à¤Ï¡¤VisualC++ 2005 + DirectX SDK Update December 2006 ¤Î´Ä¶²¼¤Ç MFC ¤È GSL1.9 ¤òÍѤ¤¤ÆºîÀ®¤·¡¤WinVista(64bit)¾å¤Ç¤Î¤ß¼Â¹Ô¥Æ¥¹¥È¤·¤Æ¤¤¤Þ¤¹¡¥¤¿¤À¤·¡¤¥Ð¥¤¥Ê¥ê¥Ç¡¼¥¿¤Ï32bitÈǤǤ¹¡¥
¥×¥í¥°¥é¥à¤ò¼Â¹Ô¤¹¤ë¤È¡¤5 ¤Ä¤Î¥ê¥ó¥¯¤ò»ý¤Ä¥¢¡¼¥à¤¬É½¼¨¤µ¤ì¤Þ¤¹¡¥¥á¥Ë¥å¡¼¤Î [¥Æ¥¹¥È]¢ª[View] ¤ò¼Â¹Ô¤¹¤ë¤È¡¤¥¨¥Õ¥§¥¯¥¿¤¬Å¬Åö¤ÊľÀþµ°Æ»¾å¤ò±ýÉü¤¹¤ë¤è¤¦¤Ë¡¤Çò¤ÈÀ֤Υê¥ó¥¯¥¢¡¼¥à¤¬±¿Æ°¤¹¤ë¤Ï¤º¤Ç¤¹¡¥¤³¤³¤Ç¡¤ÀÖ¥ê¥ó¥¯¤Ï¥ª¥¤¥é¡¼³ÑÅÙ¤òÍøÍѤ·¤¿ IK ¡¤Çò¥ê¥ó¥¯¤¬¥¯¥©¡¼¥¿¥Ë¥ª¥ó IK ¤òÍøÍѤ·¤¿·ë²Ì¤Ç¤¹¡¥[¥Æ¥¹¥È][View] ¤ò¼Â¹Ô¤¹¤ë¤¿¤Ó¤Ëµ°Æ»¤¬¥é¥ó¥À¥à¤ËÊѲ½¤·¤Þ¤¹¤Î¤Ç¡¤¹ÈÇò¤Î¥ê¥ó¥¯¤Î±¿Æ°¤òÈæ³Ó¤·¤Æ¤ß¤Æ¤¯¤À¤µ¤¤¡¥
¥ê¥ó¥¯¥¢¡¼¥à¤ÎºîÀ®¤È¥Õ¥©¥ï¡¼¥É¥¥Í¥Þ¥Æ¥£¥¯¥¹ †
¥¤¥ó¥Ð¡¼¥¹¥¥Í¥Þ¥Æ¥£¥¯¥¹¤ÎÀâÌÀ¤ËÆþ¤ëÁ°¤Ë¡¤¥ê¥ó¥¯¥¢¡¼¥à¤ÎºîÀ®¡¤ÉÁ²è¡¤¤½¤·¤Æ¥Õ¥©¥ï¡¼¥É¥¥Í¥Þ¥Æ¥£¥¯¥¹¤Ë¤è¤ë¥¨¥Õ¥§¥¯¥¿°ÌÃ֤λ»½ÐÊýË¡¤ò¤Þ¤È¤á¤Æ¤ª¤¤Þ¤¹¡¥
¤Þ¤º¡¤¥ê¥ó¥¯¥¢¡¼¥à¤Î»ÑÀª¾ðÊó¤ò³ÊǼ¤¹¤ë¥á¥ó¥ÐÊÑ¿ô¤ò¼¡¤Î¥³¡¼¥É¤Ë¼¨¤·¤Þ¤¹¡¥NUM_LINKS ¤Î¥ê¥ó¥¯¿ô¤ò»ý¤Ä¥¢¡¼¥à¤Ë¤Ä¤¤¤Æ¡¤³Æ¥ê¥ó¥¯¤ÎŤµ¤È½é´üÊý¸þ¤ò»ØÄꤹ¤ë¥ª¥Õ¥»¥Ã¥È¥Ù¥¯¥È¥ë¤ò m_pOffset ÇÛÎó¤Ë³ÊǼ¤·¤Þ¤¹¡¥¥ê¥ó¥¯´Ö¤Î´ØÀá²óž¹ÔÎó¤ò³ÊǼ¤¹¤ëÇÛÎó¤ÏÆó¼ïÎàÍѰդ·¡¤¤½¤ì¤¾¤ì¥ª¥¤¥é¡¼³Ñ IK ¤È¥¯¥©¡¼¥¿¥Ë¥ª¥ó IK ¤Ë¤è¤ë·×»»»ÑÀª¤ò³ÊǼ¤¹¤ë¤¿¤áÍøÍѤ·¤Þ¤¹¡¥
1
2
3
4
5
| -
!
-
!
| D3DXVECTOR3 m_pOffset[NUM_LINKS];
D3DXMATRIX m_pEulerPose[NUM_LINKS];
D3DXMATRIX m_pQuatPose[NUM_LINKS];
|
¾åµ¤ÎÊÑ¿ô¤Ï¥³¥ó¥¹¥È¥é¥¯¥¿Æâ¤Ç½é´ü²½¤·¤Þ¤¹¡¥Á´¤Æ¤Î´ØÀá²óž¹ÔÎó¤Ïñ°Ì¹ÔÎó¤Ë¡¤¥ª¥Õ¥»¥Ã¥È¥Ù¥¯¥È¥ë¤Ï Z Êý¸þ¤Ë¿¤Ó¤ëñ°Ì¥Ù¥¯¥È¥ë¤È¤·¤Þ¤·¤¿¡¥
1
2
3
4
5
6
7
8
| -
!
-
|
|
|
!
| ¡¦¡¦¡¦¡¦¡¦¡¦
for (size_t i = 0;i < NUM_LINKS;++i) {
D3DXMatrixIdentity(&m_pEulerPose[i]);
D3DXMatrixIdentity(&m_pQuatPose[i]);
m_pOffset[i] = D3DXVECTOR3(0, 0, 1.0f);
}
|
¼¡¤Ë¡¤»ØÄꤵ¤ì¤¿´ØÀá²óž¹ÔÎó¤ò¤â¤È¤Ë¥¨¥Õ¥§¥¯¥¿°ÌÃÖ¤ò·×»»¤¹¤ë¡¤¥Õ¥©¥ï¡¼¥É¥¥Í¥Þ¥Æ¥£¥¯¥¹´Ø¿ô¤ò¼¨¤·¤Þ¤¹¡¥¥ê¥ó¥¯¥¢¡¼¥à¤Î¥ë¡¼¥È¤«¤éÀèü¤Ë¸þ¤«¤Ã¤Æ¡¤¥È¥é¥ó¥¹¥Õ¥©¡¼¥à¹ÔÎó¤ò²Ã»»¤¹¤ë¤À¤±¤Î¥³¡¼¥É¤Ç¤¹¡¥¤¿¤À¤·¡¤¥ª¥Õ¥»¥Ã¥È¥Ù¥¯¥È¥ë¤«¤é¥ª¥Õ¥»¥Ã¥È¹ÔÎó¤òºîÀ®¡¤¾è»»¤¹¤ëÉôʬ¤ò¡¤ÌµÍý¤ä¤ê¤Ê¥¥ã¥¹¥È¤ò»È¤Ã¤Æ¥Ù¥¯¥È¥ë¤Î²Ã»»¤ËÃÖ¤´¹¤¨¤Æ¤¤¤Þ¤¹¡¥ÊÖ¤êÃͤˤĤ¤¤Æ¤âƱÍͤˡ¤¥¼¥í¥Ù¥¯¥È¥ë¤È¤Î¾è»»¤ò̵Íý¤ä¤ê¥¥ã¥¹¥È¤Ë¤è¤Ã¤Æ´Êά²½¤·¤Æ¤¤¤Þ¤¹¡¥
1
2
3
4
5
6
7
8
9
10
11
|
-
|
|
-
|
|
|
!
|
!
| D3DXVECTOR3 CSceneView::EffectorPos(const D3DXMATRIX pose[])
{
D3DXMATRIX m, om;
D3DXMatrixIdentity(&m);
for (int i = NUM_LINKS - 1;i >= 0;--i) {
D3DXMatrixIdentity(&om);
*reinterpret_cast(&om._41) = m_pOffset[i];
m *= om * pose[i];
}
return *reinterpret_cast(&m._41);
}
|
ºÇ¸å¤Ë¡¤¥ê¥ó¥¯¥¢¡¼¥à¤ÎÉÁ²è´Ø¿ô¤ò¼¨¤·¤Þ¤¹¡¥¥ª¥¤¥é¡¼³Ñ IK¡¤¥¯¥©¡¼¥¿¥Ë¥ª¥ó IK ¤Î·ë²Ì¤òƱ»þ¤ËÉÁ²è¤·¤Þ¤¹¡¥
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
|
-
|
|
|
|
|
-
!
|
-
|
|
|
|
|
!
|
-
!
|
-
|
|
|
|
|
!
|
|
!
| HRESULT CSceneView::DrawLinks(void)
{
D3DXMATRIX m, mt;
m_pEffect->SetTechnique(m_hTechPhong);
m_pEffect->SetVector("g_vAmbiColor", &D3DXVECTOR4(1.0f, 1.0f, 1.0f, 1.0f));
m_pEffect->SetVector("g_vDiffColor", &D3DXVECTOR4(0.6f, 0.0f, 0.0f, 1.0f));
D3DXMatrixIdentity(&m);
for (size_t i = 0;i < NUM_LINKS;++i) {
D3DXMatrixTranslation(&mt, m_pOffset[i].x / 2.0f, m_pOffset[i].y / 2.0f, m_pOffset[i].z / 2.0f);
m = mt * m_pEulerPose[i] * m;
DrawMeshSub(m_pConeMesh, 0, m);
m = mt * m;
}
m_pEffect->SetVector("g_vDiffColor", &D3DXVECTOR4(0.6f, 0.6f, 0.6f, 1.0f));
D3DXMatrixIdentity(&m);
for (size_t i = 0;i < NUM_LINKS;++i) {
D3DXMatrixTranslation(&mt, m_pOffset[i].x / 2.0f, m_pOffset[i].y / 2.0f, m_pOffset[i].z / 2.0f);
m = mt * m_pQuatPose[i] * m;
DrawMeshSub(m_pConeMesh, 0, m);
m = mt * m;
}
return S_OK;
}
|
¥ä¥³¥Ó¥¢¥ó¹ÔÎó¤òÍѤ¤¤¿¥¤¥ó¥Ð¡¼¥¹¥¥Í¥Þ¥Æ¥£¥¯¥¹ †
¿ôÃÍ·×»»¤Ë¤è¤ëµÕ±¿Æ°³Ø·×»»Ë¡¤Ç¤Ï¡¤¥¨¥Õ¥§¥¯¥¿¤Î°ÌÃÖ¤äÊý¸þ¢Î´ØÀá²óžÎ̤δط¸¤òɽ¤¹¥ä¥³¥Ó¥¢¥ó¹ÔÎó¤¬ÍѤ¤¤é¤ì¤Þ¤¹¡¥¤Þ¤¿¡¤¥ä¥³¥Ó¥¢¥ó¤òÍѤ¤¤¿µÕ±¿Æ°³Ø¤Ç²òÀ⤷¤¿¤è¤¦¤Ë¡¤´ØÀá²óžÎ̤òɽ¤¹¥Ñ¥é¥á¡¼¥¿¤Ë¤Ï¥ª¥¤¥é¡¼³Ñɽ¸½¤¬¹¤¯ÍøÍѤµ¤ì¤Æ¤¤¤Þ¤¹¡¥¤³¤ì¤Ï¡¤µÕ±¿Æ°³Ø·×»»Ë¡¤¬³«È¯¤µ¤ì¤¿¥í¥Ü¥Ã¥È¹©³ØÊ¬Ìî¤Ë¤ª¤¤¤Æ¡¤¼Â¥í¥Ü¥Ã¥ÈÀ©¸æ¤ÈÁêÀ¤¬Îɤ¤¥ª¥¤¥é¡¼³Ñɽ¸½¤¬¹¤¯ÍøÍѤµ¤ì¤Æ¤¤¤ëÅÀ¤Ëµ¯°ø¤·¤Æ¤¤¤ë¤È»×¤ï¤ì¤Þ¤¹¡¥¤·¤«¤·¡¤CG¥¥ã¥é¥¯¥¿¤Ï³Æ´ØÀἫͳÅÙ¤ò¥â¡¼¥¿¶îư¤µ¤»¤ëɬÍפâ¤Ê¤¤¤Î¤Ç¡¤¼ÂºÝ¤Ë¤Ï¥ª¥¤¥é¡¼³Ñ°Ê³°¤ÎÍÍ¡¹¤Ê3¼¡¸µ²óžÎÌɽ¸½¤ò»È¤¨¤ë¤Ï¤º¤Ç¤¹¡¥¤½¤³¤Ç¡¤¤Þ¤º¥ä¥³¥Ó¥¢¥ó¹ÔÎó¤Î·×»»ÊýË¡¤òǤ°Õ¤Î²óž¥Ñ¥é¥á¡¼¥¿É½¸½¤Ë¤Ä¤¤¤Æ°ìÈ̲½¤·¤Þ¤¹¡¥
¿¥ê¥ó¥¯¥¢¡¼¥à¤ò¹½À®¤¹¤ë
¼«Í³Å٤δØÀá²óžÎ̤ò
¡¤¤½¤Î¤È¤¤Î¥¢¡¼¥àÀèü¡Ê¥¨¥Õ¥§¥¯¥¿¡Ë°ÌÃÖ¤ò
¤È¤·¡¤Èù¾®²óžÎÌ
¤ò²Ã¤¨¤¿»þ¤Î¥¨¥Õ¥§¥¯¥¿°ÌÃÖ¤ÎÈù¾®ÊѰ̤ò
¤Èɽ¤·¤Þ¤¹¡¥¤³¤³¤Ç¡¤Á°µ»ö¤Ç¤Ï¡¤´ØÀá²óžÎÌ
¤ò¥ª¥¤¥é¡¼³Ñ¤Î³Æ¥Ñ¥é¥á¡¼¥¿¤Ç¹½À®¤·¤Þ¤·¤¿¡¥¤³¤Î¤È¤¡¤¥ª¥¤¥é¡¼³Ñ¤ÎÈù¾®²óžÎÌ
¤È ¥¨¥Õ¥§¥¯¥¿Èù¾®ÊѰÌ
¤È¤Î´Ø·¸¤Ï¼¡¤Î¼°¤Çɽ¤µ¤ì¤Þ¤¹¡¥
¤³¤³¤Ç¹ÔÎó
¤Ï¡¤
¤«¤é
¤Ø¤Î¼ÌÁü¤òÍ¿¤¨¤ë¥ä¥³¥Ó¥¢¥ó¹ÔÎó¤È¸Æ¤Ð¤ì¤ë¹ÔÎó¤Ç¡¤³Æ¥ª¥¤¥é¡¼³Ñ¥Ñ¥é¥á¡¼¥¿¤Ë´Ø¤¹¤ë¥¨¥Õ¥§¥¯¥¿ÊѰ̥٥¯¥È¥ë³ÆÀ®Ê¬¤ÎÊÐÈùʬ·¸¿ô¤Ç¹½À®¤µ¤ì¤Þ¤¹¡¥
·«¤êÊÖ¤·¤Ë¤Ê¤ê¤Þ¤¹¤¬¡¤´ØÀá¤Î²óžÎÌ
¤¬ÆÃ¤Ë¥ª¥¤¥é¡¼³Ñ¤Ç¤¢¤ëɬÍפϤ¢¤ê¤Þ¤»¤ó¡¥¤Ä¤Þ¤ê¡¤¥ä¥³¥Ó¥¢¥ó¹ÔÎó
¤Î·×»»¤Ë»Ù¾ã¤¬¤Ê¤±¤ì¤Ð¡¤
¤ÎÍ×ÁǤ¬¥¯¥©¡¼¥¿¥Ë¥ª¥ó¤Î 4 ¤Ä¤Î¥Ñ¥é¥á¡¼¥¿¤Ç¤â¡¤Axis-Angle ɽ¸½¤Î 4 ¤Ä¤Î¥Ñ¥é¥á¡¼¥¿¤Ç¤âÌäÂê¤Ê¤¤¤Ï¤º¤Ç¤¹¡¥¤¹¤Ê¤ï¤Á
¤Î³ÆÍ×ÁǤ¬²óžÎ̤òɽ¤¹¥Ñ¥é¥á¡¼¥¿¤Ç¤¢¤ë¸Â¤ê¡¤¾å¼°¤ÏǤ°Õ¤Î²óžÎÌɽ¸½¤Ë¤Ä¤¤¤Æ°ìÈ̲½¤Ç¤¤Þ¤¹¡¥¤³¤³¤Ç¡¤¡Ö¥ä¥³¥Ó¥¢¥ó¹ÔÎó
¤Î·×»»¤Ë»Ù¾ã¤¬¤Ê¤±¤ì¤Ð¡×¤È¤¤¤¦¾ò·ï¤Ï¡¤¡Ö
¤Î³ÆÍ×ÁǤ¬¸ß¤¤¤ËÆÈΩ¤Ç¤¢¤ë¡×¤È¤¤¤¦À©Ìó¤ËÂбþ¤·¤Þ¤¹¡¥¤Ä¤Þ¤ê¡¤
¤ÎÊѲ½¤Ë¤è¤Ã¤Æ
¤ä
¤ÎÃͤ¬ÊѲ½¤·¤Æ¤Ï¤Ê¤é¤Ê¤¤¤È¤¤¤¦À©Ìó¤Ç¤¹¡¥¤³¤ì¤Ï¡¤¥Ñ¥é¥á¡¼¥¿¤¬½¾Â°´Ø·¸¤Ë¤¢¤ë¤È¡¤¥ä¥³¥Ó¥¢¥ó¹ÔÎó³ÆÍ×ÁǤÎÊÐÈùʬ¤¬·×»»¤Ç¤¤Ê¤¤¤³¤È¤ò°ÕÌ£¤·¤Þ¤¹¡¥Î㤨¤Ð¡¤´Ø¿ô
¤ÎÊÐÈùʬ¤Ë¤ª¤¤¤Æ
¤È
¤¬¸ß¤¤¤Ë½¾Â°¤À¤È¡¤¹çÀ®´Ø¿ô¤ÎÊÐÈùʬ¤ÎÄêµÁ¤«¤é
¤ÈƲ¡¹½ä¤ê¤Ë¤Ê¤ë¤³¤È¤«¤éÌÀ¤é¤«¤Ç¤¹¡¥
¥ª¥¤¥é¡¼³Ñɽ¸½¤ÏÁ´¤Æ¤Î¥Ñ¥é¥á¡¼¥¿¤¬ÆÈΩ¤Ê¤Î¤Ç¡¤¥ä¥³¥Ó¥¢¥ó¹ÔÎó¤ò·×»»¤Ç¤¤Þ¤¹¡¥¤·¤«¤·¡¤¥¯¥©¡¼¥¿¥Ë¥ª¥ó¤ä Axis-Angle ɽ¸½¤Ï¤³¤Î²¾Äê¤òËþ¤¿¤·¤Þ¤»¤ó¡¥¤³¤ì¤Ï¡¤²óžÎ̤òɽ¤¹¥¯¥©¡¼¥¿¥Ë¥ª¥ó¤Ïñ°Ì¥¯¥©¡¼¥¿¥Ë¥ª¥ó¤Ç¤Ê¤±¤ì¤Ð¤Ê¤é¤Ê¤¤ÅÀ¤ä¡¤Axis-Angle ɽ¸½¤Ë¤ª¤±¤ë²óž¼´¥Ù¥¯¥È¥ë¤¬Ã±°Ì¥Ù¥¯¥È¥ë¤Ç¤Ê¤±¤ì¤Ð¤Ê¤é¤Ê¤¤ÅÀ¤Ë¸¶°ø¤¬¤¢¤ê¤Þ¤¹¡¥Î㤨¤Ð¡¤²óžÎÌ¥¼¥í¤Î¥¯¥©¡¼¥¿¥Ë¥ª¥ó
¤ËÈù¾®ÊѲ½
¤¬²Ã¤ï¤ê¡¤
¤Ë¤Ê¤Ã¤¿¾ì¹ç¤ò¹Í¤¨¤Þ¤¹¡¥²Ã»»¸å¤Î¥¯¥©¡¼¥¿¥Ë¥ª¥ó¤Ï
¤òËþ¤¿¤µ¤º¡¤Ã±°Ì¥¯¥©¡¼¥¿¥Ë¥ª¥ó¤Ç¤Ï¤Ê¤¤¤Î¤Ç3¼¡¸µ²óžÎ̤òɽ¤·¤Þ¤»¤ó¡¥¤·¤¿¤¬¤Ã¤Æ¡¤
¤È¤Ê¤ë¤è¤¦¤ËÀµµ¬²½¤¹¤ëɬÍפ¬¤¢¤ê¤Þ¤¹¤¬¡¤¤½¤Î·ë²Ì¤Ï
¤È¤Ê¤ê¤Þ¤¹¡¥¤³¤³¤Ç¡¤
¤ÎÃͤ¬ÊѲ½¤·¤Æ¤¤¤ë¤Î¤Ï¤â¤Á¤í¤ó¡¤Áàºî¤·¤¿
¤ÎÃͤ½¤Î¤â¤Î¤â¸º¾¯¤·¤Æ¤·¤Þ¤¤¤Þ¤¹¡¥¤³¤ÎÌäÂê¤Ï Axis-Angle ɽ¸½¤Î²óž¼´¥Ù¥¯¥È¥ë¤Ë¤Ä¤¤¤Æ¤âƱÍͤËȯÀ¸¤·¤Þ¤¹¡¥¤³¤Î¤è¤¦¤Ë¡¤¥¯¥©¡¼¥¿¥Ë¥ª¥ó¤ä Axis-Angle ɽ¸½¤Î¥Ñ¥é¥á¡¼¥¿¤Ï¸ß¤¤¤Ë½¾Â°¤Ç¤¢¤ë¤¿¤á¡¤¥ä¥³¥Ó¥¢¥ó¹ÔÎó¤ò·×»»¤Ç¤¤Þ¤»¤ó¡¥
¤·¤¿¤¬¤Ã¤Æ¡¤¡Ö²óžÎ̤òɽ¤·¡×¤Ä¤Ä¡Ö³Æ¥Ñ¥é¥á¡¼¥¿¤¬ÆÈΩ¡×¤Ê²óžɽ¸½·Á¼°¤Ç¤¢¤ëÂпô¥¯¥©¡¼¥¿¥Ë¥ª¥ó¤òÍѤ¤¤ë¤³¤È¤Ë¤·¤Þ¤¹¡¥
3¼¡¸µ²óžɽ¸½¤ÎÁê¸ßÊÑ´¹ †
¥¢¥ë¥´¥ê¥º¥à¤Î²òÀâ¤ËɬÍפʻöÁ°Ãμ±¤È¤·¤Æ¡¤²óž¹ÔÎó
¡¤¥¯¥©¡¼¥¿¥Ë¥ª¥ó
¡¤Âпô¥¯¥©¡¼¥¿¥Ë¥ª¥ó
¡¤¥è¡¼¡¦¥Ô¥Ã¥Á¡¦¥í¡¼¥ë³Ñ¡Ê¥ª¥¤¥é¡¼³Ñ¡Ë
¤È¤ÎÁê¸ßÊÑ´¹ÊýË¡¤È¡¤¤½¤Î¼ÂÁõ¥³¡¼¥É¤ò¤Þ¤È¤á¤Þ¤¹¡¥¤Ê¤ª¡¤¤³¤³¤Ç¼¨¤¹ÊýË¡¤Ï DirectX Graphics ¤Îº¸¼ê·Ïɽ¸½¤Ë½àµò¤·¤Æ¤¤¤Þ¤¹¡¥OpenGL ¤Ê¤É¤Î±¦¼ê·Ï¤Ç¤Ï·×»»Ë¡¤¬¼ã´³°Û¤Ê¤ë¤Î¤ÇÃí°Õ¤·¤Æ¤¯¤À¤µ¤¤¡¥
²óž¹ÔÎó¢Î¥¯¥©¡¼¥¿¥Ë¥ª¥ó †
¥¯¥©¡¼¥¿¥Ë¥ª¥ó¢Í¥È¥é¥ó¥¹¥Õ¥©¡¼¥à¹ÔÎó †
·ë²Ì¤À¤±¼¨¤·¤Þ¤¹¡¥
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
-
|
|
|
|
|
|
|
|
|
|
|
!
| D3DXMATRIX quat2mat(const D3DXQUATERNION &q)
{
D3DXMATRIX m(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1);
m._11 = 1.0f - 2.0f * (q.y * q.y + q.z * q.z);
m._12 = 2.0f * (q.x * q.y + q.w * q.z);
m._13 = 2.0f * (q.x * q.z - q.w * q.y);
m._21 = 2.0f * (q.x * q.y - q.w * q.z);
m._22 = 1.0f - 2.0f * (q.x * q.x + q.z * q.z);
m._23 = 2.0f * (q.y * q.z + q.w * q.x);
m._31 = 2.0f * (q.x * q.z + q.w * q.y);
m._32 = 2.0f * (q.y * q.z - q.w * q.x);
m._33 = 1.0f - 2.0f * (q.x * q.x + q.y * q.y);
return m;
}
|
²óž¹ÔÎó¢Í¥¯¥©¡¼¥¿¥Ë¥ª¥ó †
Äê¼°²½¤ÏÈÑ»¨¤Ë¤Ê¤ë¤Î¤Ç¡¤¼ÂÁõ¥³¡¼¥É¤À¤±¼¨¤·¤Þ¤¹¡¥
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
|
-
|
|
-
|
|
|
|
|
!
-
|
-
|
|
|
|
|
|
!
-
|
|
|
|
|
|
!
-
|
|
|
|
|
|
!
!
|
!
| D3DXQUATERNION mat2quat(const D3DXMATRIX &m)
{
D3DXQUATERNION q(0, 0, 0, 0);
float s, trace = m._11 + m._22 + m._33 + 1.0;
if (trace >= 1.0f) {
s = 0.5f / sqrtf(trace);
q.w = 0.25f / s;
q.x = (m._23 - m._32) * s;
q.y = (m._31 - m._13) * s;
q.z = (m._12 - m._21) * s;
}
else {
float max = m._22 > m._33 ? m._22 : m._33;
if (max < m._11) {
s = sqrtf(m._11 - (m._22 + m._33) + 1.0f);
q.x = s * 0.5f;
s = 0.5f / s;
q.y = (m._12 + m._21) * s;
q.z = (m._31 + m._13) * s;
q.w = (m._23 - m._32) * s;
}
else if (max == m._22) {
s = sqrtf(m._22 - (m._33 + m._11) + 1.0f);
q.y = s * 0.5f;
s = 0.5f / s;
q.x = (m._12 + m._21) * s;
q.z = (m._23 + m._32) * s;
q.w = (m._31 - m._13) * s;
}
else {
s = sqrtf(m._33 - (m._11 + m._22) + 1.0f);
q.z = s * 0.5f;
s = 0.5 / s;
q.x = (m._31 + m._13) * s;
q.y = (m._23 + m._32) * s;
q.w = (m._12 - m._21) * s;
}
}
return q;
}
|
¥¯¥©¡¼¥¿¥Ë¥ª¥ó¢ÎAxis-Angle †
Ëܵ»ö¤Ë¤ÏľÀÜ´Ø·¸¤¢¤ê¤Þ¤»¤ó¤¬¡¤Âпô¥¯¥©¡¼¥¿¥Ë¥ª¥ó¤ÎÀâÌÀ¤ËÊØÍø¤Ê¤Î¤Ç·ÇºÜ¤·¤Þ¤¹¡¥¤Ê¤ª¡¤²óž¼´¥Ù¥¯¥È¥ë¤ò
¡¤¤½¤Î¼´¼þ¤ê¤Î²óžÎ̤ò
¤Èɽ¤·¤Þ¤¹¡¥
¥¯¥©¡¼¥¿¥Ë¥ª¥ó¢ÍAxis-Angle †
·ë²Ì¤À¤±¼¨¤·¤Þ¤¹¡¥
1
2
3
4
5
|
-
|
|
!
| void quat2axis(D3DXVECTOR3 &v, float &a, const D3DXQUATERNION &q)
{
a = acosf(q.w) * 2.0f;
v = D3DXVECTOR3(q.x, q.y, q.z) / sinf(a * 0.5f);
}
|
¤Ê¤ª¡¤DirectX Graphics ¤Î D3DXQuaternionToAxisAngle ´Ø¿ô¤Ï¡¤¥¯¥©¡¼¥¿¥Ë¥ª¥ó¤Î x-y-z À®Ê¬¤ò¤½¤Î¤Þ¤Þ 3 ¼¡¸µ¥Ù¥¯¥È¥ë²½¤·¤¿
¤òÊÖ¤¹¤è¤¦¤Ç¤¹¡¥¤Ä¤Þ¤ê¡¤²óž¼´¥Ù¥¯¥È¥ë¤¬Ã±°Ì¥Ù¥¯¥È¥ë¤Ç¤¢¤ëÊݾڤϤ¢¤ê¤Þ¤»¤ó¡¥¥æ¡¼¥¶ÀÕǤ¤ÇÀµµ¬²½¤¹¤ì¤Ð¤è¤¤¤À¤±¤Ç¤¹¤¬¡¤¤³¤Î¼ÂÁõ¤Ï¤Á¤ç¤Ã¤È¤É¤¦¤«¤È»×¤¤¤Þ¤¹¡¥
Axis-Angle¢Í¥¯¥©¡¼¥¿¥Ë¥ª¥ó †
·ë²Ì¤À¤±¼¨¤·¤Þ¤¹¡¥
1
2
3
4
5
|
-
|
|
!
| void axis2quat(D3DXQUATERNION &q, const D3DXVECTOR3 &v, const float &a)
{
const float sina = sinf(a * 0.5f), cosa = cosf(a * 0.5f);
q = D3DXQUATERNION(sina * v.x, sina * v.y, sina * v.z, cosa);
}
|
¥¯¥©¡¼¥¿¥Ë¥ª¥ó¢ÎÂпô¥¯¥©¡¼¥¿¥Ë¥ª¥ó †
Âпô¥¯¥©¡¼¥¿¥Ë¥ª¥ó¤È¤Ï¡¤°ì¸À¤Ç¸À¤¦¤È¡ÖAxis-Angle ɽ¸½¤Ë¤ª¤±¤ë 3 ¼¡¸µ²óž¼´¥Ù¥¯¥È¥ë
¤Î³ÆÀ®Ê¬¤Ë²óžÎÌ
¤òÀÑ»»¤·¤¿ 3 ¼¡¸µÎ̡פǤ¹¡¥¤Ê¤¼¤½¤¦ÄêµÁ¤µ¤ì¤¿¤Î¤«¤Ë¤Ä¤¤¤Æ¤Ï¡¤¿ô³Ø¤Î°Î¤¤¿Í¤Ë¿Ò¤Í¤ë¤·¤«¤¢¤ê¤Þ¤»¤ó¤Î¤Ç¡¤»äã¤Ï¤¢¤¯¤Þ¤Ç¤âÆ»¶ñ¤È¤·¤Æ°·¤¤¤Þ¤¹¡¥
¥¯¥©¡¼¥¿¥Ë¥ª¥ó¢ÍÂпô¥¯¥©¡¼¥¿¥Ë¥ª¥ó †
ľÁ°¤ÎÄêµÁ¤ËÈ¿¤·¤Þ¤¹¤¬¡¤DirectX¤Ç¤Ï¡¤Âпô¥¯¥©¡¼¥¿¥Ë¥ª¥ó¤ò¼¡¼°¤Î¤è¤¦¤ËÄêµÁ¤·¤Æ¤¤¤ë¤è¤¦¤Ç¤¹¡Ê¤¢¤¯¤Þ¤Ç¤â½èÍý·ë²Ì¤«¤é¤ÎͽÁۤǤ¹¡Ë¡¥Ëܵ»ö¤Ç¤Ï¤³¤Á¤é¤ÎÄêµÁ¤Ë±è¤Ã¤Æ¼ÂÁõ¤·¤Æ¤¤¤Þ¤¹¡¥
¤³¤Î
¤Ï Axis-Angleɽ¸½¤Ë¤ª¤±¤ë¼´¼þ¤ê²óžÎÌ
¤ÎȾʬ¤ÎÃÍ
¤Ç¤¹¡¥
¤ÏAxis-Angle ɽ¸½¤Ë¤ª¤±¤ë²óž¼´
¤ò²óžÎÌ
¤Ç¥¹¥±¡¼¥ê¥ó¥°¤·¤¿¥Ù¥¯¥È¥ë¤Ç¤¹¡¥
¤Ê¤ª¡¤»²¹Íʸ¸¥ ¤Ç¤Ï Axis-Angle ¤Î²óž¼´
¤È²óžÎÌ
¤ò¤½¤Î¤Þ¤ÞÍѤ¤¤ÆÂпô¥¯¥©¡¼¥¿¥Ë¥ª¥ó¤òÄêµÁ¤·¤Æ¤¤¤Þ¤¹¡¥¤³¤Î¤³¤È¤«¤é»¡¤¹¤ë¤Ë¡¤²óž¼´¥Ù¥¯¥È¥ë¤µ¤¨Æ±°ì¤Ç¤¢¤ì¤Ð¡¤Âпô¥¯¥©¡¼¥¿¥Ë¥ª¥ó¤ÎÄêµÁ¤Ë¤ª¤¤¤Æ¼´¼þ¤ê²óžÎ̤ÏÂ礷¤¿ÌäÂê¤Ç¤Ï¤Ê¤¤¤Î¤«¤â¤·¤ì¤Þ¤»¤ó¡¥
1
2
3
4
5
|
-
|
|
!
| D3DXQUATERNION quat_ln(const D3DXQUATERNION &q)
{
const float theta = acosf(q.w), isintheta = theta / sinf(theta);
return D3DXQUATERNION(q.x * isintheta, q.y * isintheta, q.z * isintheta, 0);
}
|
Âпô¥¯¥©¡¼¥¿¥Ë¥ª¥ó¢Í¥¯¥©¡¼¥¿¥Ë¥ª¥ó †
·ë²Ì¤À¤±¼¨¤·¤Þ¤¹¡¥
¤³¤³¤Ç¡¤
¤Î¤È¤¤Ï¥¼¥í½ü»»¤Î¤¿¤á·×»»¤Ç¤¤Þ¤»¤ó¡¥¤¿¤À¤·¡¤»²¹Íʸ¸¥¤Ë¼¨¤µ¤ì¤Æ¤¤¤ëÄ̤ꡤ¼ÂºÝ¤Ë¤Ï
¤Î¥Æ¥¤¥é¡¼Å¸³«¤òÍøÍѤ·¤Æ
¤Î¤È¤¤Î¶á»÷Ãͤò·×»»¤Ç¤¤Þ¤¹¡¥
¼ÂÁõ¥³¡¼¥É¤Ç¤Ï¥Æ¥¤¥é¡¼Å¸³«¤òÍøÍѤ·¤Ê¤¤ÊýË¡¤ò¼¨¤·¤Þ¤¹¡¥
1
2
3
4
5
|
-
|
|
!
| D3DXQUATERNION quat_exp(const D3DXQUATERNION &u)
{
const float theta = sqrtf(u.x * u.x + u.y * u.y + u.z * u.z), sintheta = sinf(theta) / theta;
return D3DXQUATERNION(u.x * sintheta, u.y * sintheta, u.z * sintheta, cosf(theta));
}
|
²óž¹ÔÎó¢Î¥ª¥¤¥é¡¼³Ñ †
¥è¡¼¡¦¥Ô¥Ã¥Á¡¦¥í¡¼¥ë·Á¼°¡Ê
¥ª¡¼¥À¡¼¤Î¥ª¥¤¥é¡¼³Ñ¡Ë
¤Ë¤Ä¤¤¤Æ¡¤²óž¹ÔÎó¤È¤ÎÁê¸ßÊÑ´¹¼°¤ò¼¨¤·¤Þ¤¹¡¥
¥è¡¼¡¦¥Ô¥Ã¥Á¡¦¥í¡¼¥ë³Ñ¢Í²óž¹ÔÎó †
½ç±¿Æ°³Ø¤Î¹à¤ò»²¾È¤·¤Æ¤¯¤À¤µ¤¤¡¥
1
2
3
4
5
6
7
|
-
|
|
|
|
!
| D3DXMATRIX ypr2mat(float yaw, float pitch, float roll)
{
D3DXMATRIX m, mt;
D3DXMatrixRotationZ(&m, roll);
m *= *D3DXMatrixRotationX(&mt, pitch);
return m * *D3DXMatrixRotationY(&mt, yaw);
}
|
²óž¹ÔÎó¢Í¥è¡¼¡¦¥Ô¥Ã¥Á¡¦¥í¡¼¥ë³Ñ †
¤³¤Á¤é¤â·ë²Ì¤À¤±¼¨¤·¤Þ¤¹¡¥Yaw-Pitch-Roll³Ñ¤«¤é²óž¹ÔÎ󤨤ÎÊÑ´¹¼°
¤òŸ³«¤·¤Æ¤¸¤Ã¤¯¤êį¤á¤ì¤Ð¡¤¤ï¤ê¤È´Êñ¤ËƳ½Ð¤Ç¤¤ë¤Ï¤º¤Ç¤¹¡¥
1
2
3
4
5
6
7
8
9
10
11
|
-
|
|
|
|
-
|
|
!
!
| void mat2ypr(float &yaw, float &pitch, float &roll, const D3DXMATRIX &m)
{
roll = atan2f(m._12, m._22);
pitch = asinf(-m._32);
yaw = atan2f(m._31, m._33);
if (fabsf(cosf(pitch)) < 1.0e-6f) {
roll += m._12 > 0.0f ? D3DX_PI : -D3DX_PI;
yaw += m._31 > 0.0f ? D3DX_PI : -D3DX_PI;
}
}
|
Âпô¥¯¥©¡¼¥¿¥Ë¥ª¥ó¤«¤é¤Î¥ä¥³¥Ó¥¢¥ó¹ÔÎóÆ³½Ð †
Âпô¥¯¥©¡¼¥¿¥Ë¥ª¥ó¤Î³Æ¥Ñ¥é¥á¡¼¥¿¤Ë´Ø¤¹¤ë²óž¹ÔÎó¤ÎÊÐÈùʬÃͤò»»½Ð¤·¡¤¥ä¥³¥Ó¥¢¥ó¹ÔÎó¤ò·×»»¤¹¤ë¼ê½ç¤òÀâÌÀ¤·¤Þ¤¹¡¥¤Þ¤º¡¤¾å½Ò¤ÎÊÑ´¹¼°¤òÍѤ¤¤ë¤³¤È¤Ç¡¤Âпô¥¯¥©¡¼¥¿¥Ë¥ª¥ó¢ª¥¯¥©¡¼¥¿¥Ë¥ª¥ó¢ª²óž¹ÔÎó¤Î½ç¤ÇÊÑ´¹¤Ç¤¤ë¤³¤È¤¬¼¨¤µ¤ì¤Þ¤·¤¿¡¥¤¹¤Ê¤ï¤Á¡¤²óž¹ÔÎó¤ÏÂпô¥¯¥©¡¼¥¿¥Ë¥ª¥ó¤Î 3 ¤Ä¤Î¥Ñ¥é¥á¡¼¥¿¤Ë¤Ä¤¤¤Æ¤Î´Ø¿ô¤È¤·¤ÆÉ½¤µ¤ì¤Þ¤¹¡¥
¤Þ¤¿¡¤¥ä¥³¥Ó¥¢¥ó¹ÔÎó¤Î
¹ÔÌܤϡ¤½ç±¿Æ°³Ø·×»»¼°¤Ë¤ª¤±¤ë´ØÀá
¤Î²óž¹ÔÎó¤ò¡¤´ØÀá
¤Î²óžÎ̤òɽ¤¹Âпô¥¯¥©¡¼¥¿¥Ë¥ª¥ó¤Î
ÈÖÌܤΥѥé¥á¡¼¥¿¤Ë´Ø¤¹¤ëÊÐÈùʬÃͤÇÃÖ¤´¹¤¨¤ë¤³¤È¤Ç·×»»¤µ¤ì¤Þ¤¹¡¥Îã¤È¤·¤Æ¡¤´ØÀá
¤ÎÂпô¥¯¥©¡¼¥¿¥Ë¥ª¥ó¥Ñ¥é¥á¡¼¥¿
¤Ë´Ø¤¹¤ë¥ä¥³¥Ó¥¢¥ó¹ÔÎó¤Î·×»»¼°¤ò¼¡¤Ë¼¨¤·¤Þ¤¹¡¥
¤¿¤À¤·¡¤Âпô¥¯¥©¡¼¥¿¥Ë¥ª¥ó¤«¤é²óž¹ÔÎ󤨤ÎÊÑ´¹´Ø¿ô¤Ï¡¤Âпô¥¯¥©¡¼¥¿¥Ë¥ª¥ó¢ª¥¯¥©¡¼¥¿¥Ë¥ª¥ó¤È¡¤¥¯¥©¡¼¥¿¥Ë¥ª¥ó¢ª²óž¹ÔÎ󤨤ÎÊÑ´¹¤È¤¤¤¦ 2 ¤Ä¤Î´Ø¿ô¤Ç¹½À®¤µ¤ì¤ë¹çÀ®´Ø¿ô¤Ç¤¹¡¥¤·¤¿¤¬¤Ã¤Æ¡¤Âпô¥¯¥©¡¼¥¿¥Ë¥ª¥ó¤Î³Æ¥Ñ¥é¥á¡¼¥¿¤Ë´Ø¤¹¤ë²óž¹ÔÎó¤ÎÊÐÈùʬ¤Ï¡¤¹çÀ®´Ø¿ô¤ÎÊÐÈùʬˡ¤Ë±è¤Ã¤Æ¼¡¼°¤Î¤è¤¦¤Ë½ñ¤´¹¤¨¤é¤ì¤Þ¤¹¡¥
¤µ¤é¤ËŸ³«¤¹¤ë¤È¡¤¼¡¼°¤¬ÆÀ¤é¤ì¤Þ¤¹¡¥¤Ê¤ª¡¤¤³¤³¤Ç¤Ï
¤ò
¤Èάµ¤·¤Þ¤¹¡¥
¤³¤Î¼ÂÁõ¥³¡¼¥É¤ò¼¨¤·¤Þ¤¹¡¥°ú¿ô q ¤ÏÂпô¥¯¥©¡¼¥¿¥Ë¥ª¥ó¤«¤éµá¤á¤é¤ì¤¿¥¯¥©¡¼¥¿¥Ë¥ª¥ó¡¤dq ¤ÏÂпô¥¯¥©¡¼¥¿¥Ë¥ª¥ó¥Ñ¥é¥á¡¼¥¿
¤Ë´Ø¤¹¤ë¥¯¥©¡¼¥¿¥Ë¥ª¥ó¤ÎÊÐÈùʬÃÍ
¤Ç¤¹¡¥
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
-
|
|
|
|
|
|
|
|
|
|
|
!
| D3DXMATRIX dr_dq(const D3DXQUATERNION &q, const D3DXQUATERNION &dq)
{
D3DXMATRIX m(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
m._11 = -4.0f * (q.y * dq.y + q.z * dq.z);
m._12 = 2.0f * (q.x * dq.y + q.y * dq.x + q.w * dq.z + q.z * dq.w);
m._13 = 2.0f * (q.x * dq.z + q.z * dq.x - q.w * dq.y - q.y * dq.w);
m._21 = 2.0f * (q.x * dq.y + q.y * dq.x - q.w * dq.z - q.z * dq.w);
m._22 = -4.0f * (q.x * dq.x + q.z * dq.z);
m._23 = 2.0f * (q.y * dq.z + q.z * dq.y + q.w * dq.x + q.x * dq.w);
m._31 = 2.0f * (q.x * dq.z + q.z * dq.x + q.w * dq.y + q.y * dq.w);
m._32 = 2.0f * (q.y * dq.z + q.z * dq.y - q.w * dq.x - q.x * dq.w);
m._33 = -4.0f * (q.x * dq.x + q.y * dq.y);
return m;
}
|
¼¡¤Ë¡¤Âпô¥¯¥©¡¼¥¿¥Ë¥ª¥ó
¤Ë´Ø¤¹¤ë¥¯¥©¡¼¥¿¥Ë¥ª¥ó¤ÎÊÐÈùʬÃÍ
¤Î»»½Ð¼°¤ò¼¨¤·¤Þ¤¹¡¥Æ³½Ð¤Î²áÄø¤Ï̵Â̤ËŤ¯¤Ê¤ë¤Î¤Ç¾Êά¤·¤Þ¤¹¡Ê¤¤¤º¤ìÉÕÏ¿¤È¤·¤Æ¤Þ¤È¤á¤ë¤«¤â¤·¤ì¤Þ¤»¤ó¡Ë¡¥
°Ê¾å¤Î 3 ¼°¤Ë¤Ï¶¦Ä̹ब¿¤¤¤Î¤Ç¡¤¤³¤ì¤é¤ÏÁ´¤Æ¤Þ¤È¤á¤Æ·×»»¤·¤Þ¤¹¡¥
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
|
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
!
| void dq_ln_domain(D3DXQUATERNION &dqx, D3DXQUATERNION &dqy, D3DXQUATERNION &dqz, const D3DXQUATERNION &lnq)
{
const double a = lnq.x, b = lnq.y, c = lnq.z;
const double theta = sqrt(a * a + b * b + c * c);
const double sint = sin(theta), cost = cos(theta);
const double itheta = 1.0 / theta;
const double it2c_it3s = cost / (theta * theta) - sint / (theta * theta * theta);
dqx.w = -a * itheta * sint;
dqx.x = a * a * it2c_it3s + itheta * sint;
dqx.y = a * b * it2c_it3s;
dqx.z = a * c * it2c_it3s;
dqy.w = -b * itheta * sint;
dqy.x = b * a * it2c_it3s;
dqy.y = b * b * it2c_it3s + itheta * sint;
dqy.z = b * c * it2c_it3s;
dqz.w = -c * itheta * sint;
dqz.x = c * a * it2c_it3s;
dqz.y = c * b * it2c_it3s;
dqz.z = c * c * it2c_it3s + itheta * sint;
}
|
¼¡¤Ë¡¤¥ä¥³¥Ó¥¢¥ó¹ÔÎó
¤Î»»½Ð¥³¡¼¥É¤ò¼¨¤·¤Þ¤¹¡¥Âпô¥¯¥©¡¼¥¿¥Ë¥ª¥ó¤Ë´Ø¤¹¤ë¥¯¥©¡¼¥¿¥Ë¥ª¥ó¤ÎÊÐÈùʬÃͤòµá¤á¡¤¥¯¥©¡¼¥¿¥Ë¥ª¥ó¤Ë´Ø¤¹¤ë²óž¹ÔÎó¤ÎÊÐÈùʬÃÍ·×»»¥ë¡¼¥Á¥ó¤ËÅϤ¹¤È¤¤¤¦½èÍý¤ò¡¤Âпô¥¯¥©¡¼¥¿¥Ë¥ª¥ó¤Î 3 ¤Ä¤Î¥Ñ¥é¥á¡¼¥¿¤Ë¤Ä¤¤¤Æ·«¤êÊÖ¤·¤Æ¤¤¤Þ¤¹¡¥
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
|
-
|
|
-
-
|
|
|
|
|
|
|
|
|
-
|
|
|
|
!
!
|
!
| CMatrix CSceneView::ComputeQuatJacobian()
{
CMatrix jm(3 * NUM_LINKS, 3);
for (size_t jid = 0;jid < NUM_LINKS;++jid) {
D3DXMATRIX dpose[NUM_LINKS];
for (size_t i = 0;i < NUM_LINKS;++i)
dpose[i] = m_pQuatPose[i];
D3DXQUATERNION q, lnq, dq[3];
D3DXQuaternionRotationMatrix(&q, &m_pQuatPose[jid]);
D3DXQuaternionLn(&lnq, &q);
dq_ln_domain(dq[0], dq[1], dq[2], lnq);
for (size_t i = 0;i < 3;++i) {
dpose[jid] = dr_dq(q, dq[i]);
D3DXVECTOR3 dp = EffectorPos(dpose);
for (size_t j = 0;j < 3;++j)
jm(3 * jid + i, j) = dp[j];
}
}
return jm;
}
|
ºÇ¸å¤Ë¡¤¥ä¥³¥Ó¥¢¥ó¹ÔÎó¤òÍѤ¤¤¿¥¤¥ó¥Ð¡¼¥¹¥¥Í¥Þ¥Æ¥£¥¯¥¹´Ø¿ô¤ò¼¨¤·¤Þ¤¹¡¥¡¥¨¥Õ¥§¥¯¥¿ÊѰ̥٥¯¥È¥ë
¤Î·×»»¡¤¢¥ä¥³¥Ó¥¢¥ó¹ÔÎó¤Îµ¼»÷µÕ¹ÔÎó
¤Î·×»»¤ÈÂпô¥¯¥©¡¼¥¿¥Ë¥ª¥óÊѰÌÎÌ
¤Î»»½Ð¡¤£Âпô¥¯¥©¡¼¥¿¥Ë¥ª¥ó¤Î½¤Àµ
¤È´ØÀá²óž¹ÔÎ󤨤ÎÊÑ´¹¡¤¤È¤¤¤¦Î®¤ì¤Ç½èÍý¤ò¿Ê¤á¤Þ¤¹¡¥
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
|
-
|
|
|
|
|
|
|
|
|
-
|
|
|
|
|
|
|
!
|
!
| bool CSceneView::UpdateQuatPose(const D3DXVECTOR3 &dest, double step)
{
D3DXVECTOR3 pv = dest - EffectorPos(m_pQuatPose);
float length = D3DXVec3Length(&pv);
if (length < step)
return false;
pv *= step / length;
CVector dv(pv);
dv = dv * ComputeQuatJacobian().PseudoInverse();
for (size_t i = 0;i < NUM_LINKS;++i) {
D3DXQUATERNION q, eq;
D3DXQuaternionRotationMatrix(&q, &m_pQuatPose[i]);
D3DXQuaternionLn(&eq, &q);
for (size_t j = 0;j < 3;++j)
eq[j] += dv[i * 3 + j];
D3DXQuaternionExp(&q, &eq);
D3DXMatrixRotationQuaternion(&m_pQuatPose[i], &q);
}
return true;
}
|
¥ª¥¤¥é¡¼³Ñ IK ¤È¤ÎÈæ³Ó †
¥¯¥©¡¼¥¿¥Ë¥ª¥ó IK ¤È¤ÎÈæ³Ó¤ËºîÀ®¤·¤¿¡¤¥ª¥¤¥é¡¼³Ñ IK ¤Î·×»»¥³¡¼¥É¤ò¼¨¤·¤Þ¤¹¡¥¥ä¥³¥Ó¥¢¥ó¤òÍѤ¤¤¿µÕ±¿Æ°³Ø¤Ç²òÀ⤷¤¿µ»½Ñ¤ò¤â¤È¤Ë¡¤¥¯¥©¡¼¥¿¥Ë¥ª¥ó IK ¤Î¥³¡¼¥Ç¥£¥ó¥°¤Ë¤½¤Ã¤ÆºîÀ®¤·¤Þ¤·¤¿¡¥°ÊÁ°¤ËÈæ¤Ù¡¤¥½¡¼¥¹¥³¡¼¥É¤Î¸«Ä̤·¤ä´Ê·é¤µ¤ò²þÁ±¤Ç¤¤¿¤È»×¤¤¤Þ¤¹¡¥ÆÃ¤ËÀâÌÀ¤¹¤Ù¤Éôʬ¤â¤Ê¤¤¤Ç¤·¤ç¤¦¤«¤é¡¤²òÀâ¤Ï¾Êά¤·¤Þ¤¹¡¥
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
|
-
|
|
|
|
|
|
|
!
-
|
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
-
-
|
|
|
!
|
|
|
!
!
|
!
-
|
|
|
|
|
|
|
|
|
-
|
|
|
|
|
!
|
!
| void dmat_euler_domain(D3DXMATRIX &dmr, D3DXMATRIX &dmp, D3DXMATRIX &dmy, float roll, float pitch, float yaw)
{
D3DXMatrixIdentity(&dmr); D3DXMatrixIdentity(&dmp); D3DXMatrixIdentity(&dmy);
dmr._11 = -sinf(roll); dmp._11 = 0; dmy._11 = -sinf(yaw);
dmr._12 = cosf(roll); dmp._22 = -sinf(pitch); dmy._13 = -cosf(yaw);
dmr._21 = -dmr._12; dmp._23 = cosf(pitch); dmy._22 = 0;
dmr._22 = dmr._11; dmp._32 = -dmp._23; dmy._31 = -dmy._13;
dmr._33 = 0; dmp._33 = dmp._22; dmy._33 = dmy._11;
dmr._44 = 0; dmp._44 = 0; dmy._44 = 0;
}
CMatrix CSceneView::ComputeEulerJacobian()
{
CMatrix jm(3 * NUM_LINKS, 3);
for (size_t jid = 0;jid < NUM_LINKS;++jid) {
D3DXMATRIX dpose[NUM_LINKS];
for (size_t i = 0;i < NUM_LINKS;++i)
dpose[i] = m_pEulerPose[i];
D3DXMATRIX dm[3], m[3];
float yaw, pitch, roll;
mat2ypr(yaw, pitch, roll, m_pEulerPose[jid]);
dmat_euler_domain(dm[0], dm[1], dm[2], roll, pitch, yaw);
D3DXMatrixRotationZ(&m[0], roll);
D3DXMatrixRotationX(&m[1], pitch);
D3DXMatrixRotationY(&m[2], yaw);
for (size_t i = 0;i < 3;++i) {
switch (i) {
case 0: dpose[jid] = dm[0] * m[1] * m[2]; break;
case 1: dpose[jid] = m[0] * dm[1] * m[2]; break;
case 2: dpose[jid] = m[0] * m[1] * dm[2]; break;
}
D3DXVECTOR3 dp = EffectorPos(dpose);
for (size_t j = 0;j < 3;++j)
jm(3 * jid + i, j) = dp[j];
}
}
return jm;
}
bool CSceneView::UpdateEulerPose(const D3DXVECTOR3 &dest, double step)
{
D3DXVECTOR3 pv = dest - EffectorPos(m_pEulerPose);
float length = D3DXVec3Length(&pv);
if (length < step)
return false;
pv *= step / length;
CVector dv(pv);
dv = dv * ComputeEulerJacobian().PseudoInverse();
for (size_t i = 0;i < NUM_LINKS;++i) {
float ra[3];
mat2ypr(ra[0], ra[1], ra[2], m_pEulerPose[i]);
for (size_t j = 0;j < 3;++j)
ra[2 - j] += dv[i * 3 + j];
m_pEulerPose[i] = ypr2mat(ra[0], ra[1], ra[2]);
}
return true;
}
|
·ë²Ì †
¥¢¥Ë¥á¡¼¥·¥ç¥ó¤Îɾ²Á¤Ë¤Ä¤¤¤Æ¤Ï¥Ç¥â¥½¥Õ¥È¤ò¤´Í÷¤¤¤¿¤À¤¯¤È¤·¤Æ¡¤¤³¤³¤Ç¤Ï IK ·×»»¤ÎÀºÅÙ¤òɾ²Á¤·¤Þ¤¹¡¥¤¹¤Ê¤ï¤Á¡¤»ØÄꤷ¤¿¥¨¥Õ¥§¥¯¥¿ÊѰÌÎ̤ȡ¤»»½Ð¤µ¤ì¤¿´ØÀá²óžÎ̤ˤè¤Ã¤ÆÈ¯À¸¤¹¤ë¥¨¥Õ¥§¥¯¥¿ÊѰÌÎ̤κ¹¤òɾ²Á¤·¤Þ¤¹¡¥¤¿¤À¤·¤³¤³¤Ç¤Ï¿¾¯¼êÈ´¤¤ò¤·¡¤ÍýÏÀŪ¤Ê·×»»·«¤êÊÖ¤·²ó¿ô¤È¡¤¥¨¥Õ¥§¥¯¥¿¤¬ÌÜɸ°ÌÃÖ¤ËÅþ㤹¤ë¤Þ¤Ç¤Î¼ÂºÝ¤Î·×»»·«¤êÊÖ¤·²ó¿ô¤Î¸íº¹¤ò»»½Ð¤·¤Þ¤·¤¿¡¥¤Ä¤Þ¤ê¡¤³Æ¥¹¥Æ¥Ã¥×¤Î¥¨¥Õ¥§¥¯¥¿ÊѰÌÎÌ¤Î¸íº¹¤Ï¹Í¤¨¤º¡¤Á´ÂΤȤ·¤Æ¤Î¥¨¥Õ¥§¥¯¥¿ÊѰÌÎ̤ÎÀºÅÙ¤òɾ²Á¤·¤Þ¤¹¡¥
ɾ²Á¥Æ¥¹¥È¤Î¼ÂÁõ¥³¡¼¥É¤ò¼¨¤·¤Þ¤¹¡¥·×»»·«¤êÊÖ¤·²ó¿ô¤ÎÍýÏÀÃͤϡ¤¡Ê|ÌÜɸ°ÌÃÖ - ½é´ü¥¨¥Õ¥§¥¯¥¿°ÌÃÖ|/¥¨¥Õ¥§¥¯¥¿°ÌÃÖ¥¹¥Æ¥Ã¥×Éý¡Ë¤Ç»»½Ð¤Ç¤¤Þ¤¹¡¥¤½¤·¤Æ¡¤¥ª¥¤¥é¡¼³Ñ IK¡¤¥¯¥©¡¼¥¿¥Ë¥ª¥ó IK ¤Î¤½¤ì¤¾¤ì¤Î·×»»·«¤êÊÖ¤·²ó¿ô¤Ë¤Ä¤¤¤Æ¡¤ÍýÏÀÃͤ«¤é¤ÎÊ¿Êýº¬Ê¿¶Ñ¼«¾è¸íº¹¡ÊRoot Mean Squared Error¡§RMS¸íº¹¡Ë¤ò 100 ²ó¤Î»î¹Ô¤Ë¤è¤Ã¤Æµá¤á¤Þ¤¹¡¥
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
|
-
|
|
-
-
|
|
!
|
|
|
|
|
|
|
|
|
|
!
|
|
|
|
!
| void CSceneView::OnTestView()
{
CWaitCursor cur;
float sum0 = 0, sum1 = 0;
for (size_t trial = 0;trial < 100;++trial) {
for (size_t i = 0;i < NUM_LINKS;++i) {
D3DXMatrixRotationYawPitchRoll(&m_pEulerPose[i], D3DX_PI * rand() / RAND_MAX, D3DX_PI * rand() / RAND_MAX, D3DX_PI * rand() / RAND_MAX);
m_pQuatPose[i] = m_pEulerPose[i];
}
D3DXVECTOR3 dest = -EffectorPos(m_pEulerPose);
int loop0, loop1;
for (loop0 = 0;loop0 < 10000 && UpdateQuatPose(dest, 0.001f);++loop0);
for (loop1 = 1;loop1 < 10000 && UpdateEulerPose(dest, 0.001f);++loop1);
int ideal = static_cast<int>(D3DXVec3Length(&dest) * 2.0f / 0.001f) + 1;
sum0 += (loop0 - ideal) * (loop0 - ideal);
sum1 += (loop1 - ideal) * (loop1 - ideal);
}
CString str;
str.Format("%f %f", sqrtf(sum0 / 100.0f), sqrtf(sum1 / 100.0f));
MessageBox(str);
}
|
ŬÅö¤Ë3²ó¤Û¤É¥Æ¥¹¥È¤·¤¿·ë²Ì¤ò²¼É½¤Ë¤Þ¤È¤á¤Þ¤¹¡¥
| »î¹Ô | ¥¯¥©¡¼¥¿¥Ë¥ª¥óIK | ¥ª¥¤¥é¡¼³ÑIK |
| A | 0.678 | 52.341 |
| B | 0.854 | 99.646 |
| C | 0.656 | 98.148 |
¥¯¥©¡¼¥¿¥Ë¥ª¥ó IK ¤Î¸íº¹¤Ï̵»ë¤Ç¤¤ëÄøÅ٤Ȥ¤¤¦¡¤Èó¾ï¤ËÍ¥Îɤʷë²Ì¤ò½Ð¤·¤Æ¤¤¤Þ¤¹¡¥°ìÊý¡¤¥ª¥¤¥é¡¼³Ñ IK ¤ÏÈó¾ï¤ËÂç¤¤Ê¸íº¹¤òÀ¸¤¸¤Æ¤¤¤Þ¤¹¡¥¸íº¹¤ÎÆâÍÆ¤ò¾Ü¤·¤¯¸«¤ë¤È¡¤¥ª¥¤¥é¡¼³Ñ IK ¤Ï»ØÄꤷ¤¿²ó¿ô°Ê¾å¤Î·×»»·«¤êÊÖ¤·¤òɬÍפȤ¹¤ë¤³¤È¤¬¤ï¤«¤ê¤Þ¤·¤¿¡¥¤³¤ì¤Ï¡¤»ØÄꤷ¤¿µ÷Î¥°Ê²¼¤·¤«¥¨¥Õ¥§¥¯¥¿¤¬°Üư¤·¤Ê¤«¤Ã¤¿¤ê¡¤»ØÄꤷ¤¿Êý¸þ°Ê³°¤Ø°Üư¤·¤Æ¤¤¤ë¤³¤È¤ò¼¨º¶¤·¤Æ¤¤¤Þ¤¹¡¥¤³¤Î¸íº¹¤Ï¡¤²óž¹ÔÎó¤ËÂФ¹¤ë¥ª¥¤¥é¡¼³Ñ¤ÎÈóÀþ·ÁÀ¤Ë¤è¤Ã¤ÆÀ¸¤¸¤Æ¤¤¤ë¤È¹Í¤¨¤é¤ì¤Þ¤¹¡¥°ìÊý¡¤Âпô¥¯¥©¡¼¥¿¥Ë¥ª¥ó¤â²óž¹ÔÎó¤È¤ÏÈóÀþ·Á¤Ê´Ø·¸¤Ë¤¢¤ë¤Î¤Ç¤¹¤¬¡¤¤³¤ì¤Ï¤Û¤È¤ó¤É̵»ë¤Ç¤¤ë¥ì¥Ù¥ë¤Ç¤¢¤ë¤¿¤á¡¤¾åµ¤Î¤è¤¦¤Ê·ë²Ì¤Ë¤Ê¤Ã¤¿¤Î¤À¤È»×¤ï¤ì¤Þ¤¹¡¥
¼¡¤Ë·×»»Â®ÅÙ¤òɾ²Á¤·¤Þ¤¹¡¥»ÑÀª¹¹¿·½èÍý1000²óʬ¤Î·×»»»þ´Ö¤ò¥ß¥êÉÃñ°Ì¤Ç·×¬¤·¡¤1²ó¤¢¤¿¤ê¤Î·×»»»þ´Ö¤ò»»½Ð¤·¤Þ¤·¤¿¡ÊAthlon64X2 5000+, Vista 64bit¡¤2GB-RAM¡¤32bit¥¢¥×¥ê¡Ë¡¥¥Æ¥¹¥È¥³¡¼¥É¤ò°Ê²¼¤Ë¼¨¤·¤Þ¤¹¡¥
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
|
-
-
|
|
!
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
!
| void CSceneView::OnTestView()
{
for (size_t i = 0;i < NUM_LINKS;++i) {
D3DXMatrixRotationYawPitchRoll(&m_pEulerPose[i], D3DX_PI * rand() / RAND_MAX, D3DX_PI * rand() / RAND_MAX, D3DX_PI * rand() / RAND_MAX);
m_pQuatPose[i] = m_pEulerPose[i];
}
D3DXVECTOR3 dest = -EffectorPos(m_pEulerPose);
timeBeginPeriod(1);
DWORD t0, t1;
t0 = timeGetTime();
for (int i = 0;i < 1000;++i)
UpdateQuatPose(dest, 0.001f);
t0 = timeGetTime() - t0;
t1 = timeGetTime();
for (int i = 0;i < 1000;++i)
UpdateEulerPose(dest, 0.001f);
t1 = timeGetTime() - t1;
timeEndPeriod(1);
CString str;
str.Format("%f %f", t0 / 1000.0f, t1 / 1000.0f);
MessageBox(str);
}
|
·ë²Ì¤ò²¼É½¤Ë¼¨¤·¤Þ¤¹¡¥
| »î¹Ô | ¥¯¥©¡¼¥¿¥Ë¥ª¥óIK [msec] | ¥ª¥¤¥é¡¼³ÑIK [msec] |
| A | 0.022 | 0.025 |
| B | 0.020 | 0.022 |
| C | 0.019 | 0.024 |
¤Û¤ÜƱÅù¤Î·ë²Ì¤Ç¤¹¤¬¡¤¥¯¥©¡¼¥¿¥Ë¥ª¥óIK¤Î¤Û¤¦¤¬¼ã´³¹â®¤Ç¤·¤¿¡¥¥³¡¼¥ÉŪ¤Ë¤â¥¢¥ë¥´¥ê¥º¥àŪ¤Ë¤â¥ª¥¤¥é¡¼³ÑIK¤Î¤Û¤¦¤¬¥·¥ó¥×¥ë¤Ê¤Î¤Ç¡¤¾¯¤·°Õ³°¤Ê·ë²Ì¤Ç¤¹¡¥¹Í¤¨¤é¤ì¤ë¸¶°ø¤È¤·¤Æ¤Ï¡¤¹ÔÎó¢Í¥ª¥¤¥é¡¼³Ñ¤Ø¤Îʬ²ò¤Î¤¿¤á¤Ë¡¤atan2¡¤asin ´Ø¿ôÅù¤ò»È¤Ã¤Æ¤¤¤ë¤¿¤á¤Ç¤·¤ç¤¦¤«¡¥¤â¤Á¤í¤ó¡¤ºÇŬ²½¤ä¼ÂÁõ¤ÎÊýË¡¤Ë¤è¤Ã¤Æ¤Ï·ë²Ì¤¬µÕž¤¹¤ë²ÄǽÀ¤â¤¢¤ê¤Þ¤¹¤Î¤Ç¡¤¤³¤Î®ÅÙÈæ³Ó¤Î·ë²Ì¤Ï¤¢¤¯¤Þ¤Ç¤â»²¹ÍÄøÅ٤Ȥ·¤Æ¤¯¤À¤µ¤¤¡¥ËܼÁŪ¤Ê·×»»Î̤κ¹¤È¤Ï¸À¤¤ÀÚ¤ì¤Ê¤¤¤È»×¤¤¤Þ¤¹¡¥
¤Þ¤È¤á †
¥¯¥©¡¼¥¿¥Ë¥ª¥ó¤òÍѤ¤¤¿¥¤¥ó¥Ð¡¼¥¹¥¥Í¥Þ¥Æ¥£¥¯¥¹Ë¡¤ò²òÀ⤷¤Þ¤·¤¿¡¥Âпô¥¯¥©¡¼¥¿¥Ë¥ª¥ó¤òƳÆþ¤¹¤ë¤³¤È¤Ç¡¤¥¨¥Õ¥§¥¯¥¿°ÌÃÖÄɽ¾À¤Ë¤Ä¤¤¤Æ¤Ï¥ª¥¤¥é¡¼³Ñ IK ¤è¤ê¤âÍ¥¤ì¤¿·ë²Ì¤¬ÆÀ¤é¤ì¤Þ¤·¤¿¡¥¤·¤¿¤¬¤Ã¤Æ¡¤»ØÄꤷ¤¿Â®Å٤ǥ¨¥Õ¥§¥¯¥¿¤òÀµ³Î¤Ëư¤«¤·¤¿¤¤¡¤¤È¤¤¤¦ÍÑÅӤˤϺÇŬ¤À¤È»×¤¤¤Þ¤¹¡¥¤Þ¤¿¡¤·×»»Î̤⥪¥¤¥é¡¼³ÑIK¤Ë½¿§¤Ê¤¯¡¤¼ÂÁõÊýË¡¤Ë¤è¤Ã¤Æ¤Ï¤è¤ê¸úΨŪ¤Ë·×»»¤Ç¤¤½¤¦¤Ç¤¹¡¥
¤¿¤À¤·¡¤ÆÃ°Û»ÑÀª¤ä¡Ö¼«Á³¤µ¡×¤ÎÌäÂê¤Ï²ò·è¤Ç¤¤Ê¤¤¤Þ¤Þ¤Þ¤Ç¤¹¡¥¤µ¤é¤Ë¡¤¥ª¥¤¥é¡¼³Ñɽ¸½¤ÈÈæ¤Ù¤ë¤ÈÂпô¥¯¥©¡¼¥¿¥Ë¥ª¥ó¤Ïľ´ÑÀ¤Ë·ç¤±¤ë¡Ê³Æ¥Ñ¥é¥á¡¼¥¿¤¬²¿¤ò°ÕÌ£¤¹¤ë¤Î¤«¤ï¤«¤ê¤º¤é¤¤¡Ë¤Î¤Ç¡¤´ØÀá²Äư°è¤ÎÀßÄê¤Ï¤µ¤é¤ËÆñ¤·¤¯¤Ê¤ê¤Þ¤¹¡¥¥ä¥³¥Ó¥¢¥ó¹ÔÎó¤Î²Ã½Åµ¼»÷µÕ¹ÔÎó¤ä¡¤¾éĹÊÑ¿ô¤Î·×»»¥Ñ¥é¥á¡¼¥¿ÀßÄê¤Ë¤Ä¤¤¤Æ¤âƱÍͤǤ¹¤Í¡¥¤³¤Î¤è¤¦¤ËÍÍ¡¹¤ÊÌäÂê¤â¤¢¤ê¤Þ¤¹¤¬¡¤¥ª¥¤¥é¡¼³ÑIK¤ÎÂåÂØ¤È¤·¤Æ½½Ê¬»È¤¨¤½¤¦¤Ç¤¹¡¥
º£²ó¾Ò²ð¤·¤¿µ»½Ñ¤Ï¡¤¥¯¥©¡¼¥¿¥Ë¥ª¥ó¤ò»È¤Ã¤¿IK¤Î°ì¤Ä¤Î¥¢¥ë¥´¥ê¥º¥à¤Ç¤¢¤ê¡¤¤â¤Ã¤È¥Ù¥¹¥È¤Ê²ò·èË¡¤¬¤¢¤ê¤½¤¦¤Ç¤¹¡¥¤É¤Ê¤¿¤«¥¢¥¤¥Ç¥¢¤¬¤¢¤ì¤Ð¡¤¤¼¤ÒÄ©À路¤Æ¤¯¤À¤µ¤¤¡¥