首先是结果,两个球碰撞,有重力
大概是这种感觉:
b1↓
b2↓
gggggggggggggggg
碰撞过后:
←b1 b2→
ggggggggggggg
直接用opengl画出来不是不可以
不过那样的话大量描画代码就把本身重点的东西给遮住了.
要导入glfw,gl,glu,几十行代码下来,就很难分清楚那些是ode的代码了.
因此数据才是硬道理
另外这个可以通过gnuplot写个循环来实现动画效果... 那样很好玩, 比如这样:
下面是数据
ball0 0.0000000.0000002.159022ball10.2000000.0000000.219847
ball0 0.0000000.0000002.034562ball10.2000000.0000000.227990
ball0 0.0000000.0000001.909122ball10.2000000.0000000.235153
ball0 0.0000000.0000001.782702ball10.2000000.0000000.241336
ball0 0.0000000.0000001.655303ball10.2000000.0000000.246540
ball0 0.0000000.0000001.526923ball10.2000000.0000000.250763
ball0 0.0000000.0000001.397563ball10.2000000.0000000.254006
ball0 0.0000000.0000001.267223ball10.2000000.0000000.256269
ball0 0.0000000.0000001.135903ball10.2000000.0000000.257553
ball0 0.0000000.0000001.003604ball10.2000000.0000000.257856
ball0 0.0000000.0000000.870324ball10.2000000.0000000.257179
ball0 0.0000000.0000000.736064ball10.2000000.0000000.255522
ball0 0.0000000.0000000.600824ball10.2000000.0000000.252886
ball0 0.0000000.0000000.464604ball10.2000000.0000000.249269
ball0 -0.0261940.0000000.383820ball10.2261940.0000000.188257
ball0 -0.0698740.0000000.346906ball10.2332210.0000000.190496
ball0 -0.1143260.0000000.307516ball10.2418150.0000000.193253
ball0 -0.1594500.0000000.265052ball10.2523560.0000000.197122
ball0 -0.2045740.0000000.221609ball10.2628980.0000000.200011
ball0 -0.2496980.0000000.177186ball10.2734400.0000000.201920
ball0 -0.3036170.0000000.181699ball10.2839820.0000000.202850
ball0 -0.3575380.0000000.185359ball10.2945240.0000000.202799
ball0 -0.4114590.0000000.188287ball10.3050660.0000000.201768
ball0 -0.4653800.0000000.190629ball10.3156070.0000000.199757
ball0 -0.5193010.0000000.192503ball10.3261490.0000000.199803
ball0 -0.5732220.0000000.194002ball10.3366910.0000000.199841
ball0 -0.6271430.0000000.195201ball10.3472330.0000000.199872
ball0 -0.6810640.0000000.196160ball10.3577750.0000000.199897
ball0 -0.7349850.0000000.196927ball10.3683170.0000000.199916
ball0 -0.7889060.0000000.197541ball10.3788590.0000000.199932
ball0 -0.8428270.0000000.198032ball10.3894000.0000000.199945
ball0 -0.8967480.0000000.198425ball10.3999420.0000000.199955
ball0 -0.9506690.0000000.198739ball10.4104840.0000000.199963
ball0 -1.0045900.0000000.198990ball10.4210260.0000000.199969
ball0 -1.0585110.0000000.199191ball10.4315680.0000000.199974
ball0 -1.1124320.0000000.199352ball10.4421100.0000000.199979
ball0 -1.1663530.0000000.199481ball10.4526520.0000000.199982
ball0 -1.2202740.0000000.199584ball10.4631930.0000000.199985
ball0 -1.2741950.0000000.199666ball10.4737350.0000000.199987
ball0 -1.3281160.0000000.199732ball10.4842770.0000000.199988
ball0 -1.3820370.0000000.199784ball10.4948190.0000000.199990
ball0 -1.4359580.0000000.199827ball10.5053610.0000000.199991
ball0 -1.4898790.0000000.199860ball10.5159030.0000000.199992
ball0 -1.5438000.0000000.199887ball10.5264450.0000000.199992
ball0 -1.5977210.0000000.199909ball10.5369860.0000000.199993
ball0 -1.6516420.0000000.199926ball10.5475280.0000000.199993
ball0 -1.7055630.0000000.199940ball10.5580700.0000000.199994
ball0 -1.7594840.0000000.199951ball10.5686120.0000000.199994
ball0 -1.8134050.0000000.199960ball10.5791540.0000000.199994
ball0 -1.8673260.0000000.199967ball10.5896960.0000000.199994
ball0 -1.9212470.0000000.199972ball10.6002380.0000000.199995
ball0 -1.9751680.0000000.199977ball10.6107790.0000000.199995
ball0 -2.0290890.0000000.199981ball10.6213210.0000000.199995
ball0 -2.0830100.0000000.199984ball10.6318630.0000000.199995
ball0 -2.1369310.0000000.199986ball10.6424050.0000000.199995
ball0 -2.1908520.0000000.199988ball10.6529470.0000000.199995
ball0 -2.2447730.0000000.199989ball10.6634890.0000000.199995
ball0 -2.2986940.0000000.199990ball10.6740310.0000000.199995
ball0 -2.3526150.0000000.199991ball10.6845720.0000000.199995
ball0 -2.4065360.0000000.199992ball10.6951140.0000000.199995
最后是代码:
Mac-mini:ode$ cat example2.d
import std.stdio;
import ode;
static dWorldID world;
static dSpaceID space;
static dGeomID ground;
static dJointGroupID contactgroup;
const dReal radius = 0.2;
const dReal mass = 1.;
struct obj{
dBodyID b;
dGeomID geom;
}
obj[] ball;
extern(System) void nearCallBack(void* date, dGeomID o1, dGeomID o2){
const int N = 10;
dContact[N] contact;
int n = dCollide(o1,o2,N,&contact[0].geom,dContact.sizeof);
for(int i=0;i<n;i++){
with (contact[i].surface){
mode = dContactBounce;
mu = dInfinity;
bounce = 0.;
bounce_vel = 0.;
}
dJointID c = dJointCreateContact(world, contactgroup, &contact[i]);
dJointAttach(c, dGeomGetBody(contact[i].geom.g1), dGeomGetBody(contact[i].geom.g2));
}
}
void simLoop(){
dSpaceCollide(space, null ,&nearCallBack);
dWorldStep(world, 0.01);
dJointGroupEmpty(contactgroup);
dReal* pos;
foreach(k,b;ball){
pos = dBodyGetPosition(b.b);
write("ball",k,"\t");
foreach(i;0..3) writef("%.6f\t",*(pos+i));
}
writeln();
}
void main(){
dInitODE();
world = dWorldCreate();
space = dHashSpaceCreate(null);
contactgroup = dJointGroupCreate(0);
dWorldSetGravity(world, 0, 0, -9.8);
ground = dCreatePlane(space, 0,0,1,0);
ball ~=
* new obj(dBodyCreate(world), dCreateSphere(space, radius));
dMass m1;
dMassSetZero(&m1);
dMassSetSphereTotal(&m1,mass,radius);
dBodySetMass(ball[$-1].b,&m1);
dBodySetPosition(ball[$-1].b, 0,0,10);
dGeomSetBody(ball[$-1].geom, ball[$-1].b);
ball ~=
* new obj(dBodyCreate(world), dCreateSphere(space, radius));
dMassSetZero(&m1);
dMassSetSphereTotal(&m1,mass,radius);
dBodySetMass(ball[$-1].b,&m1);
dBodySetPosition(ball[$-1].b, 0.2,0,7);
dGeomSetBody(ball[$-1].geom, ball[$-1].b);
foreach(i;0..300) simLoop();
dWorldDestroy(world);
dCloseODE();
}
当然,这个代码违反了不要拷贝的原则,不过我并不打算某部分整理成函数, 还是重新整理了一下,后面还会用到这里的代码
当然还是不够好,比如应该传入一个obj*来当做参数而不是position.
Mac-mini:ode$ cat example3.d
import std.stdio;
import ode;
static dWorldID world;
static dSpaceID space;
static dGeomID ground;
static dJointGroupID contactgroup;
const dReal radius = 0.2;
const dReal mass = 1.;
struct obj{
dBodyID b;
dGeomID geom;
dReal radius, length, mass;
}
obj[] ball;
extern(System) void nearCallBack(void* date, dGeomID o1, dGeomID o2){
const int N = 10;
dContact[N] contact;
int n = dCollide(o1,o2,N,&contact[0].geom,dContact.sizeof);
for(int i=0;i<n;i++){
with (contact[i].surface){
mode = dContactBounce;
mu = dInfinity;
bounce = 0.;
bounce_vel = 0.;
}
dJointID c = dJointCreateContact(world, contactgroup, &contact[i]);
dJointAttach(c, dGeomGetBody(contact[i].geom.g1), dGeomGetBody(contact[i].geom.g2));
}
}
void simLoop(){
dSpaceCollide(space, null ,&nearCallBack);
dWorldStep(world, 0.01);
dJointGroupEmpty(contactgroup);
dReal* pos;
foreach(k,b;ball){
pos = dBodyGetPosition(b.b);
write("ball",k,"\t");
foreach(i;0..3) writef("%.6f\t",*(pos+i));
}
writeln();
}
obj createsphere(float x, float y, float z){
dMass m1;
dMassSetZero(&m1);
dMassSetSphereTotal(&m1,mass,radius);
obj b = {b:dBodyCreate(world), geom: dCreateSphere(space,0.2), radius: 0.2, mass:1.};
dBodySetMass(b.b,&m1);
dBodySetPosition(b.b, x,y,z);
dGeomSetBody(b.geom, b.b);
return b;
}
void main(){
dInitODE();
world = dWorldCreate();
space = dHashSpaceCreate(null);
contactgroup = dJointGroupCreate(0);
dWorldSetGravity(world, 0, 0, -9.8);
ground = dCreatePlane(space, 0,0,1,0);
ball ~= createsphere(0,0,10);
ball ~= createsphere(0.1,0,6);
foreach(i;0..300) simLoop();
dWorldDestroy(world);
dCloseODE();
}