| 
 | 
 
本例子源于ode自带的例子:demo_chain2 
演示的是一个由小盒子构成的链子在受正弦力左右下的物理现象(当然还有重力因素). 
其代码如下: 
//! 2010.03.03 
///////////////////////////////////////////////////// 
/// 盖莫游戏引擎的物理引擎测试2 
/////////////////////////////////////////////////////   
#include <GEngine/Gaimo.hpp> 
//! 定义立方体个数  
#define NUM 9 
#define SIDE 2.0f 
#define MASS 1.0f  
core: hysicsEngine<dWorldID,dSpaceID,dJointGroupID,dGeomID> engine; 
core::PhysicsBody<dBodyID,dGeomID,1> object[NUM]; 
dJointID joint[NUM-1]; 
//! 盒子表面纹理 
int   cubeid; 
//! 检测碰撞回调函数 
static void nearCallback(void *data, dGeomID o1, dGeomID o2) 
{ 
   //! 获取几何体对于德物理对象     
   dBodyID b1 = dGeomGetBody(o1); 
   dBodyID b2 = dGeomGetBody(o2); 
   //! 如果物体是相连的则返回之  
   if(b1 && b2 && dAreConnected(b1,b2))  
      return; 
 
   dContact contact; 
   contact.surface.mode = 0; 
   contact.surface.mu = dInfinity; 
   //! 如果物体之间发生了碰撞则关联之  
   if(dCollide (o1,o2,1,&contact.geom,sizeof(dContactGeom)))  
   { 
      dJointID c = dJointCreateContact(engine.GetWorld(),engine.GetContactGroup(),&contact); 
      dJointAttach (c,b1,b2); 
   } 
}   
void ShowGrid(); 
void SimLoop(); 
int main(int argc, char **argv) 
{    
    //! 初始化引擎设备并得到设备指针 
    core: evice* device = core::InitDevice("盖莫引擎物理场景测试2"); 
    //! 得到引擎场景指针 
    core::RefPtr<core::SceneManager> scenemanager = device->GetSceneManager(); 
    //! 得到引擎资源指针 
    core::ResourceManager* resourcemanager = device->GetResourceManager(); 
 
    //! 获取盒子图形和纹理 
    core::RefPtr<core::Image>   cubeimage = resourcemanager->GetImage("cube","..\\image//tile.tga"); 
    core::RefPtr<core::Texture> cubetexture = resourcemanager->GetTexture("cube",cubeimage);      
    cubetexture->Bind();    
    cubeid = cubetexture->GetTextureId(); 
    //! 获取全局摄像机 
    core::RefPtr<core::Camera> camera = scenemanager->GetGlobalCamera(Vector3f(30,11,30), 
                                                                      Vector3f(0,0,0), 
                                                                      Vector3f(0,1,0)); 
    camera->SetViewport(0,0,640,480);   
    camera->SetPerspective(50.0f,640.0f/480.0f,0.1f,1000.0f);                                                                   
    glClearDepth(1.0f);                                             
    glDepthFunc(GL_LEQUAL);                                        
    glEnable(GL_DEPTH_TEST); 
    glEnable(GL_CULL_FACE);    
    glShadeModel(GL_SMOOTH);                                     
    glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);    
    //! 设置空间重力加速度 
    engine.SetGravity(0,-0.8,0); 
    //! 设置空间平面 
    engine.SetPlane(0,1,0,0); 
    //! 加载碰撞检测回调函数 
    engine.SetCollideCallBack(&nearCallback); 
 
    for(int i=0; i<NUM; i++)  
    { 
        dMass m;     
        object.body = dBodyCreate(engine.GetWorld()); 
        dReal k = i*SIDE; 
        dBodySetPosition(object.body,k,k+0.8,k); 
        dMassSetBox(&m,1,SIDE,SIDE,SIDE); 
        dMassAdjust(&m,MASS); 
        dBodySetMass(object.body,&m); 
        dBodySetData(object.body,(void*)i); 
        object.geom[0] = dCreateBox(engine.GetSpace(),SIDE,SIDE,SIDE); 
        dGeomSetBody(object.geom[0],object.body); 
    } 
    for(int i=0; i< NUM-1; i++)  
    { 
        //! 必须确保生成关节的空间指针为空      
        joint = dJointCreateBall(engine.GetWorld(),NULL); 
        dJointAttach(joint,object.body,object[i+1].body); 
        dReal k = (i+0.5)*SIDE; 
        dJointSetBallAnchor(joint,k,k+0.8,k); 
    }    
    
    BEGIN_LOOP(device) 
       glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);             
       glLoadIdentity(); 
       camera->SetPerspective(45.0f,640.0f/480.0f,0.1f,1000.0f); 
       camera->Render();    
       //! 绘制网格  
       ShowGrid(); 
       SimLoop();       
    END_LOOP(device) 
    
    device->Close(); 
    device->Drop(); 
    return 0; 
} 
void SimLoop() 
{ 
    static double angle = 0; 
    angle += 0.05; 
    dBodyAddForce(object[NUM-1].body,0,3*(sin(angle)+1.0),0); 
     
    engine.Simulation();  
   
    for (int i=0; i<NUM; i++) 
    {    
        dReal sides[3]; 
        const dReal *pos; 
        const dReal *mat; 
        dGeomBoxGetLengths(object.geom[0], sides); 
        float dsides[] = {sides[0],sides[1],sides[2]}; 
        pos = dGeomGetPosition(object.geom[0]); 
        float dpos[] = {pos[0],pos[1],pos[2]}; 
        mat = dGeomGetRotation(object.geom[0]); 
        float dmat[] = {mat[0],mat[1],mat[2], mat[3], 
                        mat[4],mat[5],mat[6], mat[7], 
                        mat[8],mat[9],mat[10],mat[11]}; 
        core::Render::RenderCube(cubeid,dpos,dmat,dsides); 
    } 
} 
//! 显示地面网格 
void ShowGrid() 
{    
    glPushAttrib(GL_CURRENT_BIT);  
    glPushMatrix();                  
    glColor3f(0,0,1); 
    glBegin(GL_QUADS); 
            glTexCoord2f(0.0f,0.0f); 
         glVertex3i(-50,0,-50);   
         glTexCoord2f(1.0f, 0.0f); 
         glVertex3i(50,0,-50);    
         glTexCoord2f(1.0f, 1.0f); 
         glVertex3i(50,0,50);  
         glTexCoord2f(0.0f, 1.0f); 
         glVertex3i(-50,0,50);  
    glEnd();  
for(float i = -50; i <= 50; i += 1) 
{ 
  glBegin(GL_LINES); 
   glVertex3f(-50, 0, i); 
   glVertex3f(50, 0, i); 
   glVertex3f(i, 0, -50); 
   glVertex3f(i, 0, 50); 
  glEnd(); 
} 
glPopMatrix();  
    glPopAttrib(); 
} 
 
显示图片如下:  
 
 
  
  
需要说明的就是函数: 
dJointCreateBall(world,space 
在一般情况下第二个参数也就是space必须是空值 
再看其回调函数: 
//! 检测碰撞回调函数 
static void nearCallback(void *data, dGeomID o1, dGeomID o2) 
{ 
   //! 获取几何体对于德物理对象     
   dBodyID b1 = dGeomGetBody(o1); 
   dBodyID b2 = dGeomGetBody(o2); 
   //! 如果物体是相连的则返回之  
   if(b1 && b2 && dAreConnected(b1,b2))  
      return; 
 
   dContact contact; 
   contact.surface.mode = 0; 
   contact.surface.mu = dInfinity; 
   //! 如果物体之间发生了碰撞则关联之  
   if(dCollide (o1,o2,1,&contact.geom,sizeof(dContactGeom)))  
   { 
      dJointID c = dJointCreateContact(engine.GetWorld(),engine.GetContactGroup(),&contact); 
      dJointAttach (c,b1,b2); 
   } 
} 其一般描述就是先有几何体获取其body句柄 
如果为空则返回 
再者说明如果body是连接在一起的应该如何处理 
接下来局势如何发生碰撞应该如何处理 
最后看看其关节生成和链接: 
 
        joint = dJointCreateBall(engine.GetWorld(),NULL); 
        dJointAttach(joint,object.body,object[i+1].body); 
        dReal k = (i+0.5)*SIDE; 
        dJointSetBallAnchor(joint,k,k+0.8,k); 
首先是关节生成 
其次是关节连接 
其次是设置关节位置 
ok  
 |   
 
 
 
 |