本例子源于ode自带的例子:demo_chain2
演示的是一个由小盒子构成的链子在受正弦力左右下的物理现象(当然还有重力因素).
其代码如下:
1 //! 2010.03.03
2 /////////////////////////////////////////////////////
3 /// 盖莫游戏引擎的物理引擎测试2
4 /////////////////////////////////////////////////////
5 #include <GEngine/Gaimo.hpp>
6
7 //! 定义立方体个数
8 #define NUM 9
9
10 #define SIDE 2.0f
11 #define MASS 1.0f
12
13 core::PhysicsEngine<dWorldID,dSpaceID,dJointGroupID,dGeomID> engine;
14 core::PhysicsBody<dBodyID,dGeomID,1> object[NUM];
15 dJointID joint[NUM-1];
16
17 //! 盒子表面纹理
18 int cubeid;
19
20 //! 检测碰撞回调函数
21 static void nearCallback(void *data, dGeomID o1, dGeomID o2)
22 {
23 //! 获取几何体对于德物理对象
24 dBodyID b1 = dGeomGetBody(o1);
25 dBodyID b2 = dGeomGetBody(o2);
26 //! 如果物体是相连的则返回之
27 if(b1 && b2 && dAreConnected(b1,b2))
28 return;
29
30 dContact contact;
31 contact.surface.mode = 0;
32 contact.surface.mu = dInfinity;
33 //! 如果物体之间发生了碰撞则关联之
34 if(dCollide (o1,o2,1,&contact.geom,sizeof(dContactGeom)))
35 {
36 dJointID c = dJointCreateContact(engine.GetWorld(),engine.GetContactGroup(),&contact);
37 dJointAttach (c,b1,b2);
38 }
39 }
40
41 void ShowGrid();
42 void SimLoop();
43
44 int main(int argc, char **argv)
45 {
46 //! 初始化引擎设备并得到设备指针
47 core::Device* device = core::InitDevice("盖莫引擎物理场景测试2");
48 //! 得到引擎场景指针
49 core::RefPtr<core::SceneManager> scenemanager = device->GetSceneManager();
50 //! 得到引擎资源指针
51 core::ResourceManager* resourcemanager = device->GetResourceManager();
52
53 //! 获取盒子图形和纹理
54 core::RefPtr<core::Image> cubeimage = resourcemanager->GetImage("cube","..\\image//tile.tga");
55 core::RefPtr<core::Texture> cubetexture = resourcemanager->GetTexture("cube",cubeimage);
56 cubetexture->Bind();
57 cubeid = cubetexture->GetTextureId();
58
59 //! 获取全局摄像机
60 core::RefPtr<core::Camera> camera = scenemanager->GetGlobalCamera(Vector3f(30,11,30),
61 Vector3f(0,0,0),
62 Vector3f(0,1,0));
63 camera->SetViewport(0,0,640,480);
64 camera->SetPerspective(50.0f,640.0f/480.0f,0.1f,1000.0f);
65 glClearDepth(1.0f);
66 glDepthFunc(GL_LEQUAL);
67 glEnable(GL_DEPTH_TEST);
68 glEnable(GL_CULL_FACE);
69 glShadeModel(GL_SMOOTH);
70 glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
71
72 //! 设置空间重力加速度
73 engine.SetGravity(0,-0.8,0);
74 //! 设置空间平面
75 engine.SetPlane(0,1,0,0);
76 //! 加载碰撞检测回调函数
77 engine.SetCollideCallBack(&nearCallback);
78
79 for(int i=0; i<NUM; i++)
80 {
81 dMass m;
82 object[i].body = dBodyCreate(engine.GetWorld());
83 dReal k = i*SIDE;
84 dBodySetPosition(object[i].body,k,k+0.8,k);
85 dMassSetBox(&m,1,SIDE,SIDE,SIDE);
86 dMassAdjust(&m,MASS);
87 dBodySetMass(object[i].body,&m);
88 dBodySetData(object[i].body,(void*)i);
89 object[i].geom[0] = dCreateBox(engine.GetSpace(),SIDE,SIDE,SIDE);
90 dGeomSetBody(object[i].geom[0],object[i].body);
91 }
92 for(int i=0; i< NUM-1; i++)
93 {
94 //! 必须确保生成关节的空间指针为空
95 joint[i] = dJointCreateBall(engine.GetWorld(),NULL);
96 dJointAttach(joint[i],object[i].body,object[i+1].body);
97 dReal k = (i+0.5)*SIDE;
98 dJointSetBallAnchor(joint[i],k,k+0.8,k);
99 }
100
101 BEGIN_LOOP(device)
102 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
103 glLoadIdentity();
104 camera->SetPerspective(45.0f,640.0f/480.0f,0.1f,1000.0f);
105 camera->Render();
106 //! 绘制网格
107 ShowGrid();
108 SimLoop();
109 END_LOOP(device)
110
111 device->Close();
112 device->Drop();
113
114 return 0;
115 }
116
117 void SimLoop()
118 {
119 static double angle = 0;
120 angle += 0.05;
121 dBodyAddForce(object[NUM-1].body,0,3*(sin(angle)+1.0),0);
122
123 engine.Simulation();
124
125 for (int i=0; i<NUM; i++)
126 {
127 dReal sides[3];
128 const dReal *pos;
129 const dReal *mat;
130 dGeomBoxGetLengths(object[i].geom[0], sides);
131 float dsides[] = {sides[0],sides[1],sides[2]};
132 pos = dGeomGetPosition(object[i].geom[0]);
133 float dpos[] = {pos[0],pos[1],pos[2]};
134 mat = dGeomGetRotation(object[i].geom[0]);
135 float dmat[] = {mat[0],mat[1],mat[2], mat[3],
136 mat[4],mat[5],mat[6], mat[7],
137 mat[8],mat[9],mat[10],mat[11]};
138 core::Render::RenderCube(cubeid,dpos,dmat,dsides);
139 }
140 }
141
142 //! 显示地面网格
143 void ShowGrid()
144 {
145 glPushAttrib(GL_CURRENT_BIT);
146 glPushMatrix();
147 glColor3f(0,0,1);
148 glBegin(GL_QUADS);
149 glTexCoord2f(0.0f,0.0f);
150 glVertex3i(-50,0,-50);
151 glTexCoord2f(1.0f, 0.0f);
152 glVertex3i(50,0,-50);
153 glTexCoord2f(1.0f, 1.0f);
154 glVertex3i(50,0,50);
155 glTexCoord2f(0.0f, 1.0f);
156 glVertex3i(-50,0,50);
157 glEnd();
158
159 for(float i = -50; i <= 50; i += 1)
160 {
161 glBegin(GL_LINES);
162 glVertex3f(-50, 0, i);
163 glVertex3f(50, 0, i);
164 glVertex3f(i, 0, -50);
165 glVertex3f(i, 0, 50);
166 glEnd();
167 }
168 glPopMatrix();
169 glPopAttrib();
170 }
171
显示图片如下:
2.
需要说明的就是函数:
dJointCreateBall(world,space)
在一般情况下第二个参数也就是space必须是空值
再看其回调函数:
1 //! 检测碰撞回调函数
2 static void nearCallback(void *data, dGeomID o1, dGeomID o2)
3 {
4 //! 获取几何体对于德物理对象
5 dBodyID b1 = dGeomGetBody(o1);
6 dBodyID b2 = dGeomGetBody(o2);
7 //! 如果物体是相连的则返回之
8 if(b1 && b2 && dAreConnected(b1,b2))
9 return;
10
11 dContact contact;
12 contact.surface.mode = 0;
13 contact.surface.mu = dInfinity;
14 //! 如果物体之间发生了碰撞则关联之
15 if(dCollide (o1,o2,1,&contact.geom,sizeof(dContactGeom)))
16 {
17 dJointID c = dJointCreateContact(engine.GetWorld(),engine.GetContactGroup(),&contact);
18 dJointAttach (c,b1,b2);
19 }
20 }
其一般描述就是先有几何体获取其body句柄
如果为空则返回
再者说明如果body是连接在一起的应该如何处理
接下来局势如何发生碰撞应该如何处理
最后看看其关节生成和链接:
1
2 joint[i] = dJointCreateBall(engine.GetWorld(),NULL);
3 dJointAttach(joint[i],object[i].body,object[i+1].body);
4 dReal k = (i+0.5)*SIDE;
5 dJointSetBallAnchor(joint[i],k,k+0.8,k);
首先是关节生成
其次是关节连接
其次是设置关节位置
ok