|
本例子源于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
|
|