extern "C" { #include "screen.h" #include "event.h" #include "util.h" #include "block.h" } #include #define TYPE_STATIC 0x00 #define TYPE_MOVABLE 0x01 struct object { unsigned char type; dGeomID geom; dBodyID body; struct block block; }; struct screen screen; dWorldID world; dSpaceID space; dJointGroupID contactgroup; const char progname[] = "test1"; struct object objects[] = { { TYPE_STATIC, 0, 0, { "base1", 8.0, 1.0, 2.0, 10.0, 0, 0} }, { TYPE_MOVABLE, 0, 0, { "drop", 1.0, 1.0, 1.2, 1.0, 0, 0} }, }; void init_ode() { dMass dm; unsigned int ind; info("init_ode", "ode init"); world = dWorldCreate(); space = dHashSpaceCreate(0); contactgroup = dJointGroupCreate(0); dWorldSetGravity(world, 0, 9.81, 0); dWorldSetAutoDisableFlag(world, 1); dWorldSetContactMaxCorrectingVel(world, 0.1); for (ind = 0; ind < sizeof(objects) / sizeof(struct object); ++ind) { struct object *o = &objects[ind]; o->body = 0; o->geom = dCreateBox(space, o->block.w, o->block.h, 1.0); if (o->type == TYPE_MOVABLE) { o->body = dBodyCreate(world); dBodySetPosition(o->body, o->block.x, o->block.y, 0.0); dMassSetZero(&dm); dMassSetBoxTotal(&dm, 1.0, o->block.w, o->block.h, 1.0); dBodySetMass(o->body, &dm); } dGeomSetPosition(o->geom, o->block.x, o->block.y, 0.0); dGeomSetBody(o->geom, o->body); } } void close_ode() { info("close_ode", "ode close"); dJointGroupDestroy(contactgroup); dSpaceDestroy(space); dWorldDestroy(world); } void near_callback(void *data, dGeomID o1, dGeomID o2) { dContact contact[8]; unsigned int ind; unsigned int nc; dBodyID b1; dBodyID b2; b1 = dGeomGetBody(o1); b2 = dGeomGetBody(o2); /* do nothing if the two bodies are connected by a joint */ if (b1 && b2 && dAreConnectedExcluding(b1, b2, dJointTypeContact)) return; for (ind = 0; ind < 8; ++ind) { contact[ind].surface.mode = dContactBounce | dContactSoftCFM; contact[ind].surface.mu = 0; contact[ind].surface.mu2 = 0; contact[ind].surface.bounce = 0.1; contact[ind].surface.bounce_vel = 0.1; contact[ind].surface.soft_cfm = 0.01; } nc = dCollide(o1, o2, 8, &contact[0].geom, sizeof(dContact)); /* now what? */ if (nc) { const dReal *xyz; const dReal *rot; xyz = dGeomGetPosition(o1); rot = dGeomGetRotation(o1); printf("o1 %f %f %f %f %f %f\n", xyz[0], xyz[1], xyz[2], rot[0], rot[1], rot[2]); xyz = dGeomGetPosition(o2); rot = dGeomGetRotation(o2); printf("o2 %f %f %f %f %f %f\n", xyz[0], xyz[1], xyz[2], rot[0], rot[1], rot[2]); } for (ind = 0; ind < nc; ++ind) { dJointID cnt; cnt = dJointCreateContact(world, contactgroup, contact + ind); dJointAttach(cnt, b1, b2); } } void move() { const dReal *xyz; const dReal *rot; unsigned int ind; dSpaceCollide(space, 0, &near_callback); dWorldQuickStep(world, 0.01); dJointGroupEmpty(contactgroup); for (ind = 0; ind < sizeof(objects) / sizeof(struct object); ++ind) { struct object *o = &objects[ind]; xyz = dGeomGetPosition(o->geom); rot = dGeomGetRotation(o->geom); o->block.x = xyz[0]; o->block.y = xyz[1]; } } void draw() { unsigned int ind; glClearColor(1.0, 1.0, 1.0, 1.0); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glColor3f(0.0, 0.0, 0.0); glLoadIdentity(); for (ind = 0; ind < sizeof(objects) / sizeof(struct object); ++ind) block_draw(&objects[ind].block); SDL_GL_SwapBuffers(); } int main() { SDL_Event event; init_ode(); if (atexit(close_ode) == -1) die("atexit", 0); screen.rect.w = 640; screen.rect.h = 480; screen.bpp = 32; if (!screen_init(&screen)) die("screen_init", screen_error()); if (atexit(screen_end) == -1) die("atexit", 0); if (!event_init()) die("event_init", event_error()); if (atexit(event_end) == -1) die("atexit", 0); init_gl(); for (;;) { while (event_poll(&event)) { switch (event.type) { case SDL_KEYUP: switch (event.key.keysym.sym) { case SDLK_ESCAPE: quit(); break; default: break; } break; case SDL_QUIT: quit(); break; default: break; } } move(); draw(); SDL_Delay(10); } close_ode(); return 0; }