glutで自由落下
glutで実装してみた。
drawstuffが無いとなんとも味気ない画面に。
あれは、他にもマウス操作とかテクスチャ貼ったりと意外と機能あるしな。
z-upを止めてy-upに変更。
状態更新は、タイマーで定期的に呼ぶようにしてみた(ちゃんとFPSを維持するようにはしていない)。
// g++ -DdDOUBLE -lode -lglut main.cpp #include <ode/ode.h> #include <GL/glut.h> const int INTERVAL=1000/30; const dReal STEP=1.0/INTERVAL; const dReal GRAVITY=4.9; dWorldID g_world; class Ball { dBodyID id; dReal radius; dReal mass; dReal pos[3]; dReal rot[4]; public: Ball(dReal _radius, dReal _mass) : radius(_radius), mass(_mass) { pos[0]=0.0; pos[1]=0.0; pos[2]=0.0; rot[0]=0.0; rot[1]=0.0; rot[2]=0.0; rot[3]=0.0; } void create(dBodyID _id, dReal x, dReal y, dReal z) { id=_id; pos[0]=x; pos[1]=y; pos[2]=z; // mass dMass _mass; dMassSetZero(&_mass); dMassSetSphereTotal(&_mass, mass, radius); dBodySetMass(id, &_mass); // position dBodySetPosition(id, x, y, z); } void update(){ setPos(dBodyGetPosition(id)); setRot(dBodyGetRotation(id)); } void draw() { glPushMatrix(); glTranslatef(pos[0], pos[1], pos[2]); glRotatef(rot[0], rot[1], rot[2], rot[3]); glutSolidSphere(radius, 16, 16); glPopMatrix(); } void print(){ printf("%f %f %f\n", pos[0], pos[1], pos[2]); } void setPos(const dReal *_pos){ pos[0]=_pos[0]; pos[1]=_pos[1]; pos[2]=_pos[2]; } void setRot(const dReal *_rot){ rot[0]=_rot[0]; rot[1]=_rot[1]; rot[2]=_rot[2]; rot[3]=_rot[3]; } }; Ball g_ball(0.2, 1.0); // camera float g_xyz[]={0.0, 1.0, 6.0}; float g_hpr[]={180.0, 0.0, 0.0}; //////////////////////////////////////////////////////////////////////////////// // ODE //////////////////////////////////////////////////////////////////////////////// // create ball void setupScene() { g_ball.create(dBodyCreate(g_world), 0.0, 2.0, 0.0); } // update void onFrame(dReal step) { dWorldStep(g_world, step); g_ball.update(); } //////////////////////////////////////////////////////////////////////////////// // OpenGL //////////////////////////////////////////////////////////////////////////////// // OpenGL Context生成後に一度だけ呼ぶ void init(void) { glClearColor(0.4, 0.4, 1.0, 1.0); glEnable(GL_DEPTH_TEST); glEnable(GL_LIGHTING); glEnable(GL_LIGHT0); } void drawPlane() { glBegin(GL_QUADS); glVertex3f(-10.0, 0.0, -10.0); glNormal3f(0.0, 10.0, 0.0); glVertex3f(-10.0, 0.0, 10.0); glNormal3f(0.0, 10.0, 0.0); glVertex3f( 10.0, 0.0, 10.0); glNormal3f(0.0, 10.0, 0.0); glVertex3f( 10.0, 0.0, -10.0); glNormal3f(0.0, 10.0, 0.0); glEnd(); } //////////////////////////////////////////////////////////////////////////////// // glut callback functions //////////////////////////////////////////////////////////////////////////////// void display() { glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // setup view glMatrixMode(GL_MODELVIEW); glLoadIdentity(); glTranslatef(-g_xyz[0], -g_xyz[1], -g_xyz[2]); glRotatef(g_hpr[2], 0.0, 0.0, 1.0); glRotatef(g_hpr[1], 1.0, 0.0, 0.0); glRotatef(g_hpr[0], 0.0, 1.0, 0.0); // draw drawPlane(); g_ball.draw(); glutSwapBuffers(); } void resize(int w, int h) { glViewport(0, 0, w, h); glMatrixMode(GL_PROJECTION); glLoadIdentity(); gluPerspective(30.0, (double)w / (double)h, 0.1, 1000.0); } void timer(int value) { onFrame(STEP); glutTimerFunc(INTERVAL, &timer, 0); // debug g_ball.print(); glutPostRedisplay(); } //////////////////////////////////////////////////////////////////////////////// // entry point //////////////////////////////////////////////////////////////////////////////// int main(int argc, char **argv) { // setup ODE dInitODE(); g_world=dWorldCreate(); dWorldSetGravity(g_world, 0, -GRAVITY, 0); // setup scene setupScene(); // glut glutInit(&argc, argv); glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE | GLUT_DEPTH); glutCreateWindow(argv[0]); // initialize OpenGL init(); // setup callback glutReshapeFunc(resize); glutDisplayFunc(display); glutTimerFunc(INTERVAL, &timer, 0); glutMainLoop(); // cleanup ODE dWorldDestroy(g_world); dCloseODE(); return 0; }