Box2Dである程度遊んだらまたODEいじってみようかなあ、と思っている。
というのは参考書を買ってあったのを思い出したから。
せっかく本があるんだし遊ばないとな。
で、Box2Dの話。
Box2Dにはふたつサンプルプログラムが付属している。
一つは昨年末に画像を上げた、箱が噴水のように湧き出てくるプログラム。
もうひとつはHelloWorldという名前のプログラム。
グラフィック描画されず、実行すると何やら数値が出力される。
今日はこれを読み解いて可視化することが出来た。
Box2Dには可視化の機能がついていない。
可視化のための抽象クラスb2Drawが実装されているため、これを継承して自分で可視化のためのクラスを実装する必要がある。
幸い、もうひとつのサンプルプログラムにglutを使って実装したものがあるのでそれをそのまま流用すればよい(Render.h,Render.cpp)。
glutを使うので、main関数内にglutの初期化処理を加える。
世界クラス(b2World)のSetDebugDrawメソッドを使って定義した描画用クラスを渡す。
世界、オブジェクトの定義はmain関数で行い、描画ループでステップを進める。
world->DrawDebugData();で世界について描画を行うようだ。これをステップごとにやればよいということだ。
以下にコードを示す。
#include <Box2D/Box2D.h>#include <freeglut¥freeglut.h>#include "Render.h"#include <cstdio>using namespace std;b2World *world;static void SimulationLoop(){ glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); glOrtho(-10 , 10 , -100 , 100 ,-4 ,4); float32 timeStep = 1.0f / 600.0f; int32 velocityIterations = 6; int32 positionIterations = 2; for (int32 i = 0; i < 60; ++i) { world->Step(timeStep, velocityIterations, positionIterations); world->DrawDebugData(); } glutSwapBuffers(); }void idle(void){ glutPostRedisplay();}int main(int argc, char** argv){ //glutの初期化、ウィンドウ生成 glutInit(&argc, argv); glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA); glutCreateWindow("test"); glutDisplayFunc(SimulationLoop); glutIdleFunc(idle); B2_NOT_USED(argc); B2_NOT_USED(argv); // Define the gravity vector. b2Vec2 gravity(0.0f, -0.1f); // Construct a world object, which will hold and simulate the rigid bodies. DebugDraw debugdraw; debugdraw.SetFlags(0x00FF); world = new b2World(gravity); world->SetDebugDraw(&debugdraw); // Define the ground body. b2BodyDef groundBodyDef; groundBodyDef.position.Set(0.0f, -30.0f); // Call the body factory which allocates memory for the ground body // from a pool and creates the ground box shape (also from a pool). // The body is also added to the world. b2Body* groundBody = world->CreateBody(&groundBodyDef); // Define the ground box shape. b2PolygonShape groundBox; // The extents are the half-widths of the box. groundBox.SetAsBox(50.0f, 10.0f); // Add the ground fixture to the ground body. groundBody->CreateFixture(&groundBox, 0.0f); // Define the dynamic body. We set its position and call the body factory. b2BodyDef bodyDef; bodyDef.type = b2_dynamicBody; bodyDef.position.Set(0.0f, 4.0f); b2Body* body = world->CreateBody(&bodyDef); // Define another box shape for our dynamic body. b2PolygonShape dynamicBox; dynamicBox.SetAsBox(1.0f, 1.0f); // Define the dynamic body fixture. b2FixtureDef fixtureDef; fixtureDef.shape = &dynamicBox; // Set the box density to be non-zero, so it will be dynamic. fixtureDef.density = 1.0f; // Override the default friction. fixtureDef.friction = 0.3f; // Add the shape to the body. body->CreateFixture(&fixtureDef); glutMainLoop(); delete world; return 0;}