diff options
author | Alon Zakai <alonzakai@gmail.com> | 2013-04-10 15:53:50 -0700 |
---|---|---|
committer | Alon Zakai <alonzakai@gmail.com> | 2013-04-10 15:53:50 -0700 |
commit | f84537c333524d0841923eaec66604584bf77326 (patch) | |
tree | 6a43fab885a397a80de2cd8117b6ebafdb00cdf5 /tests/box2d/Testbed/Framework/Main.cpp | |
parent | a4a20535e79f10c553b685b188fcfd6af12fac07 (diff) |
more work towards box2d benchmark
Diffstat (limited to 'tests/box2d/Testbed/Framework/Main.cpp')
-rwxr-xr-x | tests/box2d/Testbed/Framework/Main.cpp | 447 |
1 files changed, 447 insertions, 0 deletions
diff --git a/tests/box2d/Testbed/Framework/Main.cpp b/tests/box2d/Testbed/Framework/Main.cpp new file mode 100755 index 00000000..048ed886 --- /dev/null +++ b/tests/box2d/Testbed/Framework/Main.cpp @@ -0,0 +1,447 @@ +/*
+* Copyright (c) 2006-2007 Erin Catto http://www.box2d.org
+*
+* This software is provided 'as-is', without any express or implied
+* warranty. In no event will the authors be held liable for any damages
+* arising from the use of this software.
+* Permission is granted to anyone to use this software for any purpose,
+* including commercial applications, and to alter it and redistribute it
+* freely, subject to the following restrictions:
+* 1. The origin of this software must not be misrepresented; you must not
+* claim that you wrote the original software. If you use this software
+* in a product, an acknowledgment in the product documentation would be
+* appreciated but is not required.
+* 2. Altered source versions must be plainly marked as such, and must not be
+* misrepresented as being the original software.
+* 3. This notice may not be removed or altered from any source distribution.
+*/
+
+#include "Render.h"
+#include "Test.h"
+#include "glui/glui.h"
+
+#include <cstdio>
+using namespace std;
+
+namespace
+{
+ int32 testIndex = 0;
+ int32 testSelection = 0;
+ int32 testCount = 0;
+ TestEntry* entry;
+ Test* test;
+ Settings settings;
+ int32 width = 640;
+ int32 height = 480;
+ int32 framePeriod = 16;
+ int32 mainWindow;
+ float settingsHz = 60.0;
+ GLUI *glui;
+ float32 viewZoom = 1.0f;
+ int tx, ty, tw, th;
+ bool rMouseDown;
+ b2Vec2 lastp;
+}
+
+static void Resize(int32 w, int32 h)
+{
+ width = w;
+ height = h;
+
+ GLUI_Master.get_viewport_area(&tx, &ty, &tw, &th);
+ glViewport(tx, ty, tw, th);
+
+ glMatrixMode(GL_PROJECTION);
+ glLoadIdentity();
+ float32 ratio = float32(tw) / float32(th);
+
+ b2Vec2 extents(ratio * 25.0f, 25.0f);
+ extents *= viewZoom;
+
+ b2Vec2 lower = settings.viewCenter - extents;
+ b2Vec2 upper = settings.viewCenter + extents;
+
+ // L/R/B/T
+ gluOrtho2D(lower.x, upper.x, lower.y, upper.y);
+}
+
+static b2Vec2 ConvertScreenToWorld(int32 x, int32 y)
+{
+ float32 u = x / float32(tw);
+ float32 v = (th - y) / float32(th);
+
+ float32 ratio = float32(tw) / float32(th);
+ b2Vec2 extents(ratio * 25.0f, 25.0f);
+ extents *= viewZoom;
+
+ b2Vec2 lower = settings.viewCenter - extents;
+ b2Vec2 upper = settings.viewCenter + extents;
+
+ b2Vec2 p;
+ p.x = (1.0f - u) * lower.x + u * upper.x;
+ p.y = (1.0f - v) * lower.y + v * upper.y;
+ return p;
+}
+
+// This is used to control the frame rate (60Hz).
+static void Timer(int)
+{
+ glutSetWindow(mainWindow);
+ glutPostRedisplay();
+ glutTimerFunc(framePeriod, Timer, 0);
+}
+
+static void SimulationLoop()
+{
+ glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+
+ glMatrixMode(GL_MODELVIEW);
+ glLoadIdentity();
+
+ test->SetTextLine(30);
+ b2Vec2 oldCenter = settings.viewCenter;
+ settings.hz = settingsHz;
+ test->Step(&settings);
+ if (oldCenter.x != settings.viewCenter.x || oldCenter.y != settings.viewCenter.y)
+ {
+ Resize(width, height);
+ }
+
+ test->DrawTitle(5, 15, entry->name);
+
+ glutSwapBuffers();
+
+ if (testSelection != testIndex)
+ {
+ testIndex = testSelection;
+ delete test;
+ entry = g_testEntries + testIndex;
+ test = entry->createFcn();
+ viewZoom = 1.0f;
+ settings.viewCenter.Set(0.0f, 20.0f);
+ Resize(width, height);
+ }
+}
+
+static void Keyboard(unsigned char key, int x, int y)
+{
+ B2_NOT_USED(x);
+ B2_NOT_USED(y);
+
+ switch (key)
+ {
+ case 27:
+#ifndef __APPLE__
+ // freeglut specific function
+ glutLeaveMainLoop();
+#endif
+ exit(0);
+ break;
+
+ // Press 'z' to zoom out.
+ case 'z':
+ viewZoom = b2Min(1.1f * viewZoom, 20.0f);
+ Resize(width, height);
+ break;
+
+ // Press 'x' to zoom in.
+ case 'x':
+ viewZoom = b2Max(0.9f * viewZoom, 0.02f);
+ Resize(width, height);
+ break;
+
+ // Press 'r' to reset.
+ case 'r':
+ delete test;
+ test = entry->createFcn();
+ break;
+
+ // Press space to launch a bomb.
+ case ' ':
+ if (test)
+ {
+ test->LaunchBomb();
+ }
+ break;
+
+ case 'p':
+ settings.pause = !settings.pause;
+ break;
+
+ // Press [ to prev test.
+ case '[':
+ --testSelection;
+ if (testSelection < 0)
+ {
+ testSelection = testCount - 1;
+ }
+ glui->sync_live();
+ break;
+
+ // Press ] to next test.
+ case ']':
+ ++testSelection;
+ if (testSelection == testCount)
+ {
+ testSelection = 0;
+ }
+ glui->sync_live();
+ break;
+
+ default:
+ if (test)
+ {
+ test->Keyboard(key);
+ }
+ }
+}
+
+static void KeyboardSpecial(int key, int x, int y)
+{
+ B2_NOT_USED(x);
+ B2_NOT_USED(y);
+
+ switch (key)
+ {
+ case GLUT_ACTIVE_SHIFT:
+ // Press left to pan left.
+ case GLUT_KEY_LEFT:
+ settings.viewCenter.x -= 0.5f;
+ Resize(width, height);
+ break;
+
+ // Press right to pan right.
+ case GLUT_KEY_RIGHT:
+ settings.viewCenter.x += 0.5f;
+ Resize(width, height);
+ break;
+
+ // Press down to pan down.
+ case GLUT_KEY_DOWN:
+ settings.viewCenter.y -= 0.5f;
+ Resize(width, height);
+ break;
+
+ // Press up to pan up.
+ case GLUT_KEY_UP:
+ settings.viewCenter.y += 0.5f;
+ Resize(width, height);
+ break;
+
+ // Press home to reset the view.
+ case GLUT_KEY_HOME:
+ viewZoom = 1.0f;
+ settings.viewCenter.Set(0.0f, 20.0f);
+ Resize(width, height);
+ break;
+ }
+}
+
+static void KeyboardUp(unsigned char key, int x, int y)
+{
+ B2_NOT_USED(x);
+ B2_NOT_USED(y);
+
+ if (test)
+ {
+ test->KeyboardUp(key);
+ }
+}
+
+static void Mouse(int32 button, int32 state, int32 x, int32 y)
+{
+ // Use the mouse to move things around.
+ if (button == GLUT_LEFT_BUTTON)
+ {
+ int mod = glutGetModifiers();
+ b2Vec2 p = ConvertScreenToWorld(x, y);
+ if (state == GLUT_DOWN)
+ {
+ b2Vec2 p = ConvertScreenToWorld(x, y);
+ if (mod == GLUT_ACTIVE_SHIFT)
+ {
+ test->ShiftMouseDown(p);
+ }
+ else
+ {
+ test->MouseDown(p);
+ }
+ }
+
+ if (state == GLUT_UP)
+ {
+ test->MouseUp(p);
+ }
+ }
+ else if (button == GLUT_RIGHT_BUTTON)
+ {
+ if (state == GLUT_DOWN)
+ {
+ lastp = ConvertScreenToWorld(x, y);
+ rMouseDown = true;
+ }
+
+ if (state == GLUT_UP)
+ {
+ rMouseDown = false;
+ }
+ }
+}
+
+static void MouseMotion(int32 x, int32 y)
+{
+ b2Vec2 p = ConvertScreenToWorld(x, y);
+ test->MouseMove(p);
+
+ if (rMouseDown)
+ {
+ b2Vec2 diff = p - lastp;
+ settings.viewCenter.x -= diff.x;
+ settings.viewCenter.y -= diff.y;
+ Resize(width, height);
+ lastp = ConvertScreenToWorld(x, y);
+ }
+}
+
+static void MouseWheel(int wheel, int direction, int x, int y)
+{
+ B2_NOT_USED(wheel);
+ B2_NOT_USED(x);
+ B2_NOT_USED(y);
+ if (direction > 0)
+ {
+ viewZoom /= 1.1f;
+ }
+ else
+ {
+ viewZoom *= 1.1f;
+ }
+ Resize(width, height);
+}
+
+static void Restart(int)
+{
+ delete test;
+ entry = g_testEntries + testIndex;
+ test = entry->createFcn();
+ Resize(width, height);
+}
+
+static void Pause(int)
+{
+ settings.pause = !settings.pause;
+}
+
+static void Exit(int code)
+{
+ // TODO: freeglut is not building on OSX
+#ifdef FREEGLUT
+ glutLeaveMainLoop();
+#endif
+ exit(code);
+}
+
+static void SingleStep(int)
+{
+ settings.pause = 1;
+ settings.singleStep = 1;
+}
+
+int main(int argc, char** argv)
+{
+ testCount = 0;
+ while (g_testEntries[testCount].createFcn != NULL)
+ {
+ ++testCount;
+ }
+
+ testIndex = b2Clamp(testIndex, 0, testCount-1);
+ testSelection = testIndex;
+
+ entry = g_testEntries + testIndex;
+ test = entry->createFcn();
+
+ glutInit(&argc, argv);
+ glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE);
+ glutInitWindowSize(width, height);
+ char title[32];
+ sprintf(title, "Box2D Version %d.%d.%d", b2_version.major, b2_version.minor, b2_version.revision);
+ mainWindow = glutCreateWindow(title);
+ //glutSetOption (GLUT_ACTION_ON_WINDOW_CLOSE, GLUT_ACTION_GLUTMAINLOOP_RETURNS);
+
+ glutDisplayFunc(SimulationLoop);
+ GLUI_Master.set_glutReshapeFunc(Resize);
+ GLUI_Master.set_glutKeyboardFunc(Keyboard);
+ GLUI_Master.set_glutSpecialFunc(KeyboardSpecial);
+ GLUI_Master.set_glutMouseFunc(Mouse);
+#ifdef FREEGLUT
+ glutMouseWheelFunc(MouseWheel);
+#endif
+ glutMotionFunc(MouseMotion);
+
+ glutKeyboardUpFunc(KeyboardUp);
+
+ glui = GLUI_Master.create_glui_subwindow( mainWindow,
+ GLUI_SUBWINDOW_RIGHT );
+
+ glui->add_statictext("Tests");
+ GLUI_Listbox* testList =
+ glui->add_listbox("", &testSelection);
+
+ glui->add_separator();
+
+ GLUI_Spinner* velocityIterationSpinner =
+ glui->add_spinner("Vel Iters", GLUI_SPINNER_INT, &settings.velocityIterations);
+ velocityIterationSpinner->set_int_limits(1, 500);
+
+ GLUI_Spinner* positionIterationSpinner =
+ glui->add_spinner("Pos Iters", GLUI_SPINNER_INT, &settings.positionIterations);
+ positionIterationSpinner->set_int_limits(0, 100);
+
+ GLUI_Spinner* hertzSpinner =
+ glui->add_spinner("Hertz", GLUI_SPINNER_FLOAT, &settingsHz);
+
+ hertzSpinner->set_float_limits(5.0f, 200.0f);
+
+ glui->add_checkbox("Warm Starting", &settings.enableWarmStarting);
+ glui->add_checkbox("Time of Impact", &settings.enableContinuous);
+ glui->add_checkbox("Sub-Stepping", &settings.enableSubStepping);
+
+ //glui->add_separator();
+
+ GLUI_Panel* drawPanel = glui->add_panel("Draw");
+ glui->add_checkbox_to_panel(drawPanel, "Shapes", &settings.drawShapes);
+ glui->add_checkbox_to_panel(drawPanel, "Joints", &settings.drawJoints);
+ glui->add_checkbox_to_panel(drawPanel, "AABBs", &settings.drawAABBs);
+ glui->add_checkbox_to_panel(drawPanel, "Pairs", &settings.drawPairs);
+ glui->add_checkbox_to_panel(drawPanel, "Contact Points", &settings.drawContactPoints);
+ glui->add_checkbox_to_panel(drawPanel, "Contact Normals", &settings.drawContactNormals);
+ glui->add_checkbox_to_panel(drawPanel, "Contact Forces", &settings.drawContactForces);
+ glui->add_checkbox_to_panel(drawPanel, "Friction Forces", &settings.drawFrictionForces);
+ glui->add_checkbox_to_panel(drawPanel, "Center of Masses", &settings.drawCOMs);
+ glui->add_checkbox_to_panel(drawPanel, "Statistics", &settings.drawStats);
+ glui->add_checkbox_to_panel(drawPanel, "Profile", &settings.drawProfile);
+
+ int32 testCount = 0;
+ TestEntry* e = g_testEntries;
+ while (e->createFcn)
+ {
+ testList->add_item(testCount, e->name);
+ ++testCount;
+ ++e;
+ }
+
+ glui->add_button("Pause", 0, Pause);
+ glui->add_button("Single Step", 0, SingleStep);
+ glui->add_button("Restart", 0, Restart);
+
+ glui->add_button("Quit", 0,(GLUI_Update_CB)Exit);
+ glui->set_main_gfx_window( mainWindow );
+
+ // Use a timer to control the frame rate.
+ glutTimerFunc(framePeriod, Timer, 0);
+
+ glutMainLoop();
+
+ return 0;
+}
|