À̹øÀå¿¡¼´Â ¹Ú½º¸¦ ƯÁ¤ ³ôÀÌ¿¡¼ ¶³¾î ¶ß·Á º¸ÀÚ. ½ºÆäÀ̽º Å°¸¦ ´©¸£¸é ¹Ú½º°¡ Áö»óÀ¸·Î ¶³¾îÁø´Ù.
< ºñÁê¾ó ½ºÆ©µð¿À Bullet ¼³Á¤ > : ºñÁê¾ó ½ºÆ©µð¿À 2008¿¡¼ Bullet ¹°¸® ¿£ÁøÀ» ºôµåÇϱâ À§ÇÑ È¯°æ ¼³Á¤µéÀÌ´Ù.
Ãß°¡ Æ÷ÇÔ µð·ºÅ丮 "c:\bullet-2.77\src" Ãß°¡ ¶óÀ̺귯¸® µð·ºÅ丮 "C:\bullet-2.77\msvc\2008\lib\Debug"
¶óÀ̺귯¸® Ãß°¡ BulletDynamics.lib BulletCollision.lib LinearMath.lib
Äڵ忡¼ Çì´õ Ãß°¡ #include <btBulletDynamicsCommon.h>
< ±¸Çö > Bullet ¹°¸® ¿£ÁøÀ» ó¸®Çϱâ À§ÇÑ ±¸ÇöÀº Å©°Ô ´ÙÀ½°ú °°´Ù.
1. InitBullet - ¹°¸® ¿£Áø ÃʱâÈ 2. UnInitBullet - ¹°¸® ¿£Áø¿¡ »ç¿ëµÈ ÀÚ¿øµéÀÇ ÇØÁ¦ 3. CreateGround - Á¤ÀûÀÎ Ãæµ¹ Plane ¸¸µé±â 4. CreateBox - µ¿ÀûÀÎ Ãæµ¹ ¹Ú½º ¸¸µé±â 5. SimulationBullet - ¹°¸® ½Ã¹Ä·¹À̼Ç
1. InitBullet ÇÔ¼ö : Bullet ÃʱâÈ
¨ç broadphase »ý¼º broadphase¸¦ »ý¼ºÇÏ´Â ÀÌÀ¯´Â aabb-overlapping ¿ÀºêÁ§Æ® ½ÖÀ» ã¾Æ³»¾î,¿ùµå ¾È¿¡¼ Ãæµ¹ÇÏÁö ¾ÊÀº ¿ÀºêÁ§Æ® ½ÖµéÀ» ¹Ì¸® Á¦°ÅÇÏ¿© Ãæµ¹ ó¸® ½Ã°£À» ÁÙÀδÙ.
btDbvtBroadphase ¾Ë°í¸®Áò: 2°³ÀÇ µ¿ÀûÀÎ AABB bounding volume hierarchies/tree¸¦ »ç¿ëÇÑ´Ù. Çϳª´Â Á¤ÀûÀÎ ¿ÀºêÁ§Æ®, ¶Ç ´Ù¸¥ Çϳª´Â µ¿ÀûÀÎ ¿ÀºêÁ§Æ®¸¦ À§ÇØ »ç¿ëÇÑ´Ù. ¿ÀºêÁ§Æ®µéÀº ÇϳªÀÇ Æ®¸®¿¡¼ ´Ù¸¥Æ®¸®·Î À̵¿ ÇÒ ¼ö ÀÖ´Ù. ¿ÀºêÁ§Æ®¸¦ Ãß°¡, Á¦°ÅÇÏ´Â µ¿ÀÛÀº sweep and prune( btAxisSweep3 ¿Í bt32BitAxisSweep3 )º¸´Ù ºü¸£´Ù.
¨è collision configuration »ý¼º
¨é collision dispatcher »ý¼º broadphase ¿¡ ÀÇÇØ °É·¯ÁöÁö ¾ÊÀº ¿ÀºêÁ§Æ®µéÀ» Ãæµ¹ ó¸®ÇÒ Äݹé ÇÔ¼ö¸¦ µî·ÏÇϱâ À§Çؼ collision dispatcher¸¦ »ç¿ëÇØ¾ß ÇÑ´Ù. À̶§ collision configurationÀ» »ç¿ëÇÏ¿© ¼¼ºÎ Ãæµ¹ °¨Áö ¾Ë°í¸®ÁòÀ» Æ©´×ÇÑ´Ù.
¨ê constraint solver »ý¼º ÀÌÁ¦ ¿ÀºêÁ§Æ®µé¿¡ Áß·Â, Èû, Ãæµ¹, °üÀý Á¦¾à µéÀ» Àû¿ëÇϱâ À§ÇÏ¿© solver°¡ ÇÊ¿äÇÏ´Ù. solver ´Â ¼º´É ½Ã¹Ä·¹À̼ÇÀÇ º´¸ñÀ» ÃÊ·¡ÇÏ´Â ±ØÇѱîÁö Àû¿ëÇÏÁö ¾Ê´Â´Ù¸é ²Ï ÁÁÀº ±â´ÉÀ» ÇÑ´Ù. ¶ÇÇÑ ¸î °¡Áö º´·Ä ¾²·¹µù ¸ðµ¨ (threading model)µµ Á¸ÀçÇÑ´Ù.
¨ë dynamics world »ý¼º btDiscreteDynamicsWorld Ŭ·¡½ºÀÇ »ý¼ºÀÚ ÇÁ·ÎŸÀÔÀº ´ÙÀ½°ú °°´Ù. btDiscreteDynamicsWorld::btDiscreteDynamicsWorld( btDispatcher* dispatcher, btBroadphaseInterface* pairCache, btConstraintSolver* constraintSolver, btCollisionConfiguration* collisionConfiguration)
Áß·Â ¹æÇâÀ» ¼³Á¤ÇÑ´Ù. Up ¹æÇâÀÌ ¾çÀÇ YÀ̹ǷΠÁß·ÂÀº -YÀÌ´Ù. g_world->setGravity( btVector3(0,-10,0) )
btBroadphaseInterface* g_broadphase = NULL;
btDefaultCollisionConfiguration* g_collisionConfiguration = NULL;
btCollisionDispatcher* g_dispatcher = NULL;
btConstraintSolver* g_solver = NULL;
btDynamicsWorld* g_world = NULL;
btAlignedObjectArray<btCollisionShape*> g_collisionShapes;
bool InitBullet()
{
//¨ç broadphase »ý¼º
btVector3 worldAabbMin(-10000,-10000,-10000);
btVector3 worldAabbMax(10000,10000,10000);
g_broadphase = new btAxisSweep3( worldAabbMin, worldAabbMax, 100);
//¨è collision configuration »ý¼º
g_collisionConfiguration = new btDefaultCollisionConfiguration();
//¨é collision dispatcher »ý¼º
g_dispatcher = new btCollisionDispatcher(g_collisionConfiguration);
//¨ê constraint solver »ý¼º
g_solver = new btSequentialImpulseConstraintSolver;
//¨ë dynamics world »ý¼º
g_world = new btDiscreteDynamicsWorld( g_dispatcher, g_broadphase, g_solver, g_collisionConfiguration);
g_world->setGravity( btVector3(0,-10,0) );
return true;
}
|
2. UnInitBullet ÇÔ¼ö InitBullet¿¡¼ »ý¼ºµÈ ÀÚ¿øµéÀ» ÇØÁ¦ÇÑ´Ù.
void UnInitBullet()
{
for (int i = g_world->getNumCollisionObjects()-1; i>=0 ;i--)
{
btCollisionObject* obj = g_world->getCollisionObjectArray()[i];
btRigidBody* body = btRigidBody::upcast(obj);
if (body && body->getMotionState())
{
delete body->getMotionState();
}
g_world->removeCollisionObject( obj );
delete obj;
}
//
for (int j=0;j<g_collisionShapes.size();j++)
{
btCollisionShape* shape = g_collisionShapes[j];
delete shape;
}
//
SAFE_DELETE( g_broadphase );
SAFE_DELETE( g_dispatcher );
SAFE_DELETE( g_solver );
SAFE_DELETE( g_world );
SAFE_DELETE( g_collisionConfiguration );
}
|
3. CreateGround ÇÔ¼ö
Ãæµ¹Àº Å©°Ô Áú·®, ¸¶Âû·Â, º¹¿ø·Â, °ü¼º¿¡ ÀÇÇØ ¿µÇâÀ» ¹Þ´Â´Ù. ÀÌµé ¿ë¾îÀ» Á¤¸®ÇØ º»´Ù.
Áú·®(Mass): µ¿¿ªÇÐ ¿ùµå¿¡¼ ¿òÁ÷ÀÌ´Â ¹°Ã¼ÀÇ Áú·®Àº ¾çÀÇ °ªÀÌ°í, Bullet ¿£Áø¿¡¼ ¿òÁ÷ÀÌÁö ¾Ê´Â Á¤ÀûÀÎ ¹°Ã¼´Â 0 ÀÌ´Ù. Bullet ¿£Áø¿¡¼ ´ÜÀ§´Â KgÀÌ´Ù.
¸¶Âû·Â(friction): ¸¶Âû·ÂÀº µÎ°³ÀÇ ¹°Ã¼°¡ ¼·Î ºÎµ÷Èú ¶§ ¹ß»ýµÇ´Â ¿¡³ÊÁö¸¦ ÃøÁ¤ÇÏ´Â °ÍÀ¸·Î ¾Æ·¡¿Í °°ÀÌ ¿©·¯ ´ÜÀ§·Î ±¸ºÐÇÑ´Ù. ¸¶Âû·ÂÀº ¹°Ã¼°¡ ¶Ç ´Ù¸¥ ¹°Ã¼¿Í ºÎµ÷Ä¥ ¶§ »ý°Ü³ª´Â ÈûÀ» ÃøÁ¤ÇÏ´Â ´ÜÀ§·Î ¸¶Âû°è¼ö(COEFFICIENT OF FRICTION)¶ó ÇÑ´Ù. ¸¶Âû°è¼ö´Â ¹°Ã¼ÀÇ ¹«°Ô¿¡ µû¶ó¼ ´Þ¶óÁö´Âµ¥, ÇϳªÀÇ ¹°Ã¼°¡ ´Ù¸¥ ¹°Ã¼ À§¸¦ ¹Ì²ô·¯Áú ¶§ ÇÊ¿äÇÑ ÈûÀ» ÃøÁ¤ÇÏ´Â ´ÜÀ§¸¦ ¸¶Âû°è¼ö¶ó ÇÑ´Ù.
º¹¿ø·Â(restitution): ÆòÇà À§Ä¡¿¡¼ ¹þ¾î³ ¹°Ã¼(º¼)°¡ ¿ø·¡ÀÇ À§Ä¡·Î º¹±ÍÇÏ·Á´Â ÈûÀ» ¸»Çϸç, µ¿Àû »óÅ¿¡¼ º¼ÀÌ ÇÉ°ú Ãßµ¹ÇÒ ¶§ °¨¼ÒÇÏ´Â º¼ÀÇ ¿¡³ÊÁö »óŸ¦ ȸº¹½ÃÅ°´Â °ÍÀ» º¹¿ø·ÂÀ̶ó ÇÑ´Ù. º¹¿ø°è¼ö Ç¥¸é ÀçÁú°ú µÎ²²¿¡ µû¶ó ¸¹Àº ¿µÇâÀ» ³¢Ä¡°Ô µÈ´Ù.
°ü¼º(inertia): ¹°Ã¼(º¼)°¡ ¿Ü·ÂÀÇ ÀÛ¿ëÀ» ¹ÞÁö ¾Ê´Â ÇÑ Á¤Áö ¶Ç´Â ¿îµ¿ »óŸ¦ Áö¼ÓÇÏ·Á´Â ¼ºÁú·Î ¿ÜºÎ·ÎºÎÅÍ ÈûÀÇ ÀÛ¿ëÀ» ¹ÞÁö ¾Ê´Â ¹°Ã¼(º¼)´Â óÀ½¿¡ ¾î¶² ¼Óµµ¸¦ °¡Áö¸é ±× ¼Óµµ¸¦ À¯ÁöÇÏ¿© µî¼Óµµ ¿îµ¿À» °è¼ÓÇÏ°Ô µÈ´Ù. ÀÌ°ÍÀ» °ü¼º ¹ýÄ¢À̶ó°í ÇÑ´Ù. ¹°Ã¼(º¼)¿¡ ÈûÀÌ ÀÛ¿ëÇÏ¸é ¼Óµµ°¡ º¯ÇÏ°í ¼Óµµ º¯ÈÀÇ ½Ã°£ ºñÀ²Àº °¡¼Óµµ·Î ³ªÅ¸³ª´Âµ¥, °°Àº ¹°Ã¼¿¡ ¿©·¯ °¡Áö ÈûÀ» °¡ÇßÀ» ¶§ »ý±â´Â °¡¼Óµµ´Â Èû¿¡ ºñ·ÊÇϸç, ¹æÇâµµ ÈûÀÇ ¹æÇâ°ú ÀÏÄ¡ÇÏ°Ô µÈ´Ù.
Ãæµ¹ ÇüÅÂ(shape)¸¦ »ý¼ºÇÏ´Â ´Ü°è´Â 5´Ü°è·Î ¿ä¾à ÇÒ ¼ö ÀÖ´Ù.
¨ç collision shape »ý¼º
»ý¼ºÀÚ btStaticPlaneShape( const btVector3& planeNormal, btScalar planeConstant ) ù¹ø° Àμö´Â Æò¸éÀÇ ³ë¸Ö°ªÀÌ°í, µÎ¹ø° Àμö´Â ¹«ÇÑ Æò¸éÀÇ À§Ä¡ °ªÀÌ´Ù.
btCollisionShape::calculateLocalInertia(btScalar mass,btVector3& inertia) ù ¹ø° ÀÎÀÚ¿¡ Áú·® 0, µÎ ¹ø° ÀÎÀÚ¿¡ °ü¼ºÀ» ³Ö´Â´Ù.
¨è MotionState »ý¼º btDefaultMotionState´Â ¹°¸®¿Í ±×·¡ÇÈ ¿ÀºêÁ§Æ® »çÀÌ¿¡¼ ¿ÀÇÁ¼ÂÀ» °¡Áö´Â ¿ùµå º¯È¯ÀÇ µ¿½Ã¼ºÀ» ¸ÂÃß´Â (synchronize) °øÅëÀûÀÎ ±¸ÇöÀ» Á¦°øÇÑ´Ù. °ÔÀÓ¿¡¼ ¸ÅÇÁ·¹ÀÓ ¾÷µ¥ÀÌÆ®½Ã, ¹°¸® °´Ã¼ BodyÀÇ À§Ä¡³ª ȸÀü°ªÀÌ ¹Ù²ï´Ù. ÀÌ ¶§ ¹°¸® °´Ã¼ÀÇ À§Ä¡, ȸÀü°ªÀ» ¾ò¾î ¿Ã·Á¸é MotionState°¡ ÇÊ¿äÇÏ´Ù.
¨é construction info »ý¼º
btRigidBody¿¡ Àü´ÞÇØÁÖ±â À§ÇÑ btRigidBody::btRigidBodyConstructionInfo ±¸Á¶Ã¼¸¦ ¸¸ŠÒ´Ï´Ù.
¨ê rigid body »ý¼º
btRigidBody¸¦ »ý¼º ÇÕ´Ï´Ù.
¨ë rigid body¸¦ world¿¡ Ãß°¡
btDynamicsWorld¿¡ btRidgidBody °´Ã¼¸¦ Ãß°¡ ÇÕ´Ï´Ù.
void CreateGround()
{
//¨ç collision shape »ý¼º
btCollisionShape* groundShape = new btStaticPlaneShape( btVector3(0,1,0), 0);
g_collisionShapes.push_back(groundShape);
btTransform groundTransform;
groundTransform.setIdentity();
groundTransform.setOrigin(btVector3(0,0,0));
btScalar mass(0);
//rigidbody is dynamic if and only if mass is non zero, otherwise static
bool isDynamic = (mass != 0.f);
btVector3 localInertia(0,0,0);
if (isDynamic)
groundShape->calculateLocalInertia( mass, localInertia);
//¨è MotionState »ý¼º
btDefaultMotionState* myMotionState = new btDefaultMotionState(groundTransform);
//¨é construction info »ý¼º
btRigidBody::btRigidBodyConstructionInfo rbInfo(mass,myMotionState,groundShape,localInertia);
//¨ê rigid body »ý¼º
btRigidBody* body = new btRigidBody(rbInfo);
//¨ë rigid body¸¦ world¿¡ Ãß°¡
g_world->addRigidBody(body);
}
|
4. CreateBox
void CreateBox(const D3DXVECTOR3& vec)
{
//¨ç collision shape »ý¼º
btVector3 v = btVector3( vec.x, vec.y, vec.z );
btCollisionShape* colShape = new btBoxShape(btVector3(1,1,1));
g_collisionShapes.push_back(colShape);
btTransform startTransform;
startTransform.setIdentity();
btScalar mass(10);
bool isDynamic = (mass != 0.f);
btVector3 localInertia(0,0,0);
if (isDynamic)
colShape->calculateLocalInertia(mass,localInertia);
startTransform.setOrigin(v);
//¨è MotionState »ý¼º
btDefaultMotionState* myMotionState = new btDefaultMotionState(startTransform);
//¨é construction info »ý¼º
btRigidBody::btRigidBodyConstructionInfo rbInfo(mass,myMotionState,colShape,localInertia);
//¨ê rigid body »ý¼º
btRigidBody* body = new btRigidBody(rbInfo);
//¨ë rigid body¸¦ world¿¡ Ãß°¡
g_world->addRigidBody(body);
}
|
5. SimulationBullet
int stepSimulation( btScalar timeStep,
int maxSubSteps=1,
btScalar fixedTimeStep=btScalar(1.)/btScalar(60.) )
|
timpStepÀº delta time Áï, ÀÌÀü ÇÁ·¹ÀÓ¿¡ ´ëÇÑ °æ°ú ½Ã°£ À¸·Î ÃÊ´ÜÀ§ÀÌ´Ù. fixedTimeStep¿¡ ÀÇÇØ subStepÀ¸·Î timeStepÀ» ³ª´«´Ù. subStepÀÇ ÃÖ°í ¹Ýº¹ Ƚ¼ö´Â maxSubSteps¿¡ ÀÇÇØ Á¦ÇÑ µÈ´Ù. fixedTimeStepÀº 60ÇÁ·¹ÀÓÀ¸·Î ³ª´« °ªÀÌ´Ù.
void SimulationBullet(float fElapsedTime)
{
if(g_world)
{
g_world->stepSimulation( fElapsedTime );
}
}
|
< MotionState·Î Transform ±¸Çϱâ >
GetCollisionOb jectSize()´Â ¹°¸® ¿ÀºêÁ§Æ®ÀÇ °¹¼ö¸¦ ¸®ÅÏÇÑ´Ù. GetCollisionObjectTransform()Àº ¹°¸® ¿ÀºêÁ§Æ®ÀÇ Çà·ÄÀ» ¸®ÅÏÇÑ´Ù. ¿©±â¼ 0¹ø À妽º´Â óÀ½À¸·Î Ãß°¡ÇÑ Á¤ÀûÀÎ ¹«ÇÑ Æò¸éÀÌ´Ù.
int GetCollisionObjectSize()
{
return g_world->getCollisionObjectArray().size();
}
D3DXMATRIX GetCollisionObjectTransform( int nIndex )
{
btTransform trans = g_world->getCollisionObjectArray()[nIndex]->getWorldTransform();
float mat[16];
D3DXMATRIX matObj;
trans.getOpenGLMatrix(mat);
memcpy( &matObj, mat, sizeof(float)*16);
return matObj;
}
|
getOpenGLMatrix·Î ±¸ÇÑ Çà·ÄÀº OpenGL Çà·ÄÀε¥ ÀüÄ¡ Çà·Ä·Î º¯È¯ÇÏÁö ¾Ê´Â ÀÌÀ¯´Â ´ÙÀ½°ú °°´Ù.
OpenGL ¿ ¿ì¼±(column major) Çà·Ä |
DirectX Çà ¿ì¼±(row major) Çà·Ä |
m0 |
m4 |
m8 |
m12 |
m1 |
m5 |
m9 |
m13 |
m2 |
m6 |
m10 |
m14 |
m3 |
m7 |
m11 |
m15 |
|
m0 |
m1 |
m2 |
m3 |
m4 |
m5 |
m6 |
m7 |
m8 |
m9 |
m10 |
m11 |
m12 |
m13 |
m14 |
m15 |
|
2Â÷¿ø ¹è¿À» »ç¿ëÇÏ´Â °æ¿ì OpenGLÀº ¿ ¿ì¼±À̹ǷΠm3¿¡ Á¢±Ù ÇÒ·Á¸é m[0][3], m12¿¡ Á¢±ÙÇÒ·Á¸é m[3][0]À» »ç¿ëÇÑ´Ù. ÀÏÂ÷¿ø ¹è¿ÀÇ ¼ø¼´Â m0, m1, m2, m3 ..... m13, m14, m15 ¼ø¼ÀÌ´Ù.
DirectX´Â Çà ¿ì¼±À̹ǷΠm3¿¡ Á¢±Ù ÇÒ·Á¸é m[0[3], m12¿¡ Á¢±Ù ÇÒ·Á¸é m[3][0]ÀÌ´Ù. ÀÏÂ÷¿ø ¹è¿ÀÇ ¼ø¼´Â m0, m1, m2, m3 ..... m13, m14, m15 ¼ø¼ÀÌ´Ù.
±×·¯¹Ç·Î OpenGLÀÇ 1Â÷¿ø Çà·ÄÀ» DirectX Çà·Ä·Î ¹Ù²Ü¶§ ÀüÄ¡ Çà·Ä·Î º¯È¯ ÇÒ ÇÊ¿ä°¡ ¾ø´Ù. 1Â÷¿ø ¹è¿ÀÇ °ªÀ» ±×´ë·Î ¿Å±â¸é µÈ´Ù.
btAlignedObjectArray: btAlignedObjectArrayÀº std::vector¿Í ºñ½ÁÇϸç Äü Á¤·Ä, Èü Á¤·ÄÀ» Áö¿øÇÑ´Ù. ºñÁê¾ó ½ºÆ©µð¿À µð¹ö°Å ¸ðµå¿¡¼ btAlignedObjectArray¿Í btVector3 ³»¿ëÀ» º¼·Á¸é, Bullet/msvc/autoexp_ext.txt¸¦ Âü°íÇÑ´Ù.
ÇÁ·ÎÁ§Æ®: BulletBox.zip
|