CB的global compiler settings -> compiler settings -> Other options 填-fexceptions
#defines填FREEGLUT_STATIC
link libraries加入libFreeGLUT.a libGLUI.a GlU32(GlU32.Lib) Gdi32(Gdi32.Lib) OpenGL32(OpenGL32.Lib) User32(User32.Lib) WinMM(WinMM.Lib)
多加一個libBox2D.a
main.cpp
#include "gluiDraw.h"
#include "glui/GL/glui.h"
#include "myBox2D.h"
MyBox2D mybox2d;
GluiDraw draw;
GLint mainWindow;
GLint winWidth = 640;
GLint winHeight = 640;
int tx, ty, tw, th;
float viewCenterX=0,viewCenterY=0;
GLUI *glui;
int framePeriod = 16;
float viewZoom = 1.0f;
NeoVec2 mp,pre_mp;
bool isMouseRightPressed = false;
bool isMouseLeftPressed = false;
void Resize(int32 newWidth, int32 newHeight)
{
winWidth = newWidth;
winHeight = newHeight;
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(viewCenterX-extents.x,viewCenterY-extents.y);
b2Vec2 upper(viewCenterX+extents.x,viewCenterY+extents.y);
// L/R/B/T
gluOrtho2D(lower.x, upper.x, lower.y, upper.y);
}
void Mouse(int button, int state, int x, int y)
{
// Use the mouse to move things around.
if (button == GLUT_LEFT_BUTTON)
{
int specialKey = glutGetModifiers();
if (state == GLUT_DOWN)
{
if (specialKey == GLUT_ACTIVE_SHIFT)
{
// cout << "GLUT_LEFT_BUTTON click with SHIFT" << endl;
}
else
{
// cout << "GLUT_LEFT_BUTTON click" << endl;
}
}
if (state == GLUT_UP)
{
// cout << "GLUT_LEFT_BUTTON release" << endl;
}
}
else if (button == GLUT_RIGHT_BUTTON)
{
if (state == GLUT_DOWN)
{
isMouseRightPressed = true;
// cout << "GLUT_RIGHT_BUTTON click" << endl;
}
if (state == GLUT_UP)
{
isMouseRightPressed = false;
// cout << "GLUT_RIGHT_BUTTON release" << endl;
}
}
}
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(viewCenterX-extents.x,viewCenterY-extents.y);
b2Vec2 upper(viewCenterX+extents.x,viewCenterY+extents.y);
b2Vec2 p;
p.x = (1.0f - u) * lower.x + u * upper.x;
p.y = (1.0f - v) * lower.y + v * upper.y;
return p;
}
void MouseMotion(int x, int y)
{
b2Vec2 p = ConvertScreenToWorld(x, y);
if(isMouseRightPressed)
{
float distanceX = p.x - pre_mp.x;
float distanceY = p.y - pre_mp.y;
viewCenterX -= distanceX;
viewCenterY -= distanceY;
Resize(winWidth, winHeight);
p = ConvertScreenToWorld(x, y);
pre_mp.x = p.x;
pre_mp.y = p.y;
glutPostRedisplay(); //要求重畫視窗
}
//cout << "Mouse clicked and x=" << mp.x << ",y=" << mp.y << endl;
}
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(winWidth, winHeight);
}
void Keyboard(unsigned char key, int x, int y)
{
switch (key)
{
case 27:
exit(0);
break;
case 'a':
mybox2d.m_bodies[2]->ApplyForce(b2Vec2(-400,0), mybox2d.m_bodies[2]->GetWorldPoint(b2Vec2(1,1)));
break;
case 'd':
mybox2d.m_bodies[2]->ApplyForce(b2Vec2(400,0), mybox2d.m_bodies[2]->GetWorldPoint(b2Vec2(-1,1)));
break;
default:
break;
}
}
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:
viewCenterX -= 0.5f;
Resize(winWidth, winHeight);
break;
// Press right to pan right.
case GLUT_KEY_RIGHT:
viewCenterX += 0.5f;
Resize(winWidth, winHeight);
break;
// Press down to pan down.
case GLUT_KEY_DOWN:
viewCenterY -= 0.5f;
Resize(winWidth, winHeight);
break;
// Press up to pan up.
case GLUT_KEY_UP:
viewCenterY += 0.5f;
Resize(winWidth, winHeight);
break;
}
}
void drawWholeBody(b2World* world,b2Body* m_bodies[])
{
int32 bodyCount = world->GetBodyCount();
for(int number = 0; number < bodyCount; number++) //扣掉地面一個body
{
const b2Transform& xf = m_bodies[number]->GetTransform();
for (b2Fixture* fixture = m_bodies[number]->GetFixtureList();fixture; fixture = fixture->GetNext())
{
switch (fixture->GetType())
{
case b2Shape::e_circle:
{
b2CircleShape* circle = (b2CircleShape*)fixture->GetShape();
b2Vec2 center = b2Mul(xf, circle->m_p);
float32 radius = circle->m_radius;
b2Vec2 axis = b2Mul(xf.q, b2Vec2(1.0f, 0.0f)); //還沒用到
draw.DrawSolidCircle(NeoVec2(center.x,center.y),radius,NeoVec2(axis.x,axis.y),NeoColor(1,1,1));
}
break;
case b2Shape::e_edge:
{
b2EdgeShape* edge = (b2EdgeShape*)fixture->GetShape();
b2Vec2 v1 = b2Mul(xf, edge->m_vertex1);
b2Vec2 v2 = b2Mul(xf, edge->m_vertex2);
draw.DrawLine(NeoVec2(v1.x,v1.y),NeoVec2(v2.x,v2.y),NeoColor(0,1,0));
}
break;
case b2Shape::e_chain:
{
b2ChainShape* chain = (b2ChainShape*)fixture->GetShape();
int32 count = chain->GetVertexCount();
const b2Vec2* vertices = chain->GetVertices();
b2Vec2 v1 = b2Mul(xf, vertices[0]);
for (int32 i = 1; i < count; ++i)
{
b2Vec2 v2 = b2Mul(xf, vertices[i]);
draw.DrawLine(NeoVec2(v1.x,v1.y),NeoVec2(v2.x,v2.y),NeoColor(1,1,1));
draw.DrawCircle(NeoVec2(v1.x,v1.y),0.01,NeoColor(1,1,1));
v1 = v2;
}
}
break;
case b2Shape::e_polygon:
{
b2PolygonShape* poly = (b2PolygonShape*)fixture->GetShape();
int32 vertexCount = poly->m_vertexCount;
b2Assert(vertexCount <= b2_maxPolygonVertices);
b2Vec2 vertices[b2_maxPolygonVertices];
NeoVec2 v[b2_maxPolygonVertices];
for (int32 i = 0; i < vertexCount; ++i)
{
vertices[i] = b2Mul(xf, poly->m_vertices[i]);
v[i] = NeoVec2(vertices[i].x,vertices[i].y);
}
draw.DrawSolidPolygon(v,vertexCount,NeoColor(1,1,1));
}
break;
default:
break;
}
}
}
}
void display()
{
//glEnable(GL_DEPTH_TEST);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glPushMatrix();
int32 bodyCount = mybox2d.m_world->GetBodyCount();
float32 timeStep = 1.0f / 60.0f;
int32 velocityIterations = 6;
int32 positionIterations = 2;
mybox2d.m_world->Step(timeStep, velocityIterations, positionIterations);
drawWholeBody(mybox2d.m_world, mybox2d.m_bodies);
glPopMatrix();
glutSwapBuffers();
glFlush();
}
void Timer(int)
{
glutSetWindow(mainWindow);
glutPostRedisplay(); //要求重畫視窗
glutTimerFunc(framePeriod, Timer, 0); //Do Repeat
}
int main(int argc, char* argv[])
{
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE);
glutInitWindowSize(winWidth, winHeight);
mainWindow = glutCreateWindow("Neo Box2D");
glutDisplayFunc(display);
GLUI_Master.set_glutReshapeFunc(Resize);
GLUI_Master.set_glutSpecialFunc(KeyboardSpecial);
GLUI_Master.set_glutKeyboardFunc(Keyboard);
GLUI_Master.set_glutMouseFunc(Mouse);
glutMouseWheelFunc(MouseWheel);
glutMotionFunc(MouseMotion);
glutTimerFunc(framePeriod, Timer, 0);
//glui->set_main_gfx_window( mainWindow );
glutMainLoop();
return 0;
}
myBox2d.h
#ifndef MYBOX2D_H
#define MYBOX2D_H
#include <Box2D/Box2D.h>
class MyBox2D : public b2ContactListener
{
public:
b2World* m_world;
b2Body* m_groundBody;
b2Body* m_bodies[4];
b2Joint* m_joints[8];
MyBox2D()
{
b2Vec2 gravity(0.0f, -10.0f);
bool doSleep = true;
m_world = new b2World(gravity, doSleep);
//宣告static物體定義
b2BodyDef staticBodyDef;
staticBodyDef.type = b2_staticBody;
//宣告dynamic物體定義
b2BodyDef dynamicBodyDef;
dynamicBodyDef.type = b2_dynamicBody;
//註冊地面(先新增shape,再利用BodyDef給出location)
//shape
b2EdgeShape groundShape;
groundShape.Set(b2Vec2(-50,0), b2Vec2(50,0));
//材質
b2FixtureDef groundFixtureDef;
groundFixtureDef.shape = &groundShape;
groundFixtureDef.density = 1.0f;
groundFixtureDef.friction = 1.0f;
//location
staticBodyDef.position.Set(0, -20);
m_groundBody = m_world->CreateBody(&staticBodyDef);
m_groundBody->CreateFixture(&groundFixtureDef);
m_bodies[0] = m_groundBody;
//球shape
b2CircleShape dynamicCircle;
dynamicCircle.m_p.Set(0.0f, 0.0f);
dynamicCircle.m_radius = 3.0f;
//location
dynamicBodyDef.position.Set(2, 20);
m_bodies[1] = m_world->CreateBody(&dynamicBodyDef);
m_bodies[1]->CreateFixture(&dynamicCircle,1.0f);
b2PolygonShape dynamicBox;
dynamicBox.SetAsBox(2, 2);
dynamicBodyDef.position.Set(0.0f, 10.0f);
m_bodies[2] = m_world->CreateBody(&dynamicBodyDef);
m_bodies[2]->CreateFixture(&dynamicBox, 1.0f);
/*
b2Vec2 vs[4];
vs[0].Set(0.7f, 0.0f);
vs[1].Set(1.0f, 0.02);
vs[2].Set(0.0f, 0.0f);
vs[3].Set(-0.7f, 0.4f);
b2ChainShape chain;
chain.CreateChain(vs, 4);
bodyDef.position.Set(0.0f, 0.0f);
m_bodies[4] = m_world->CreateBody(&bodyDef);
m_bodies[4]->CreateFixture(&chain, 0.01f);
*/
}
virtual ~MyBox2D()
{
delete m_world;
m_world = NULL;
}
};
#endif
gluiDraw.h
#ifndef GLUIDRAW_H
#define GLUIDRAW_H
#include <math.h>
#include <glui/GL/glui.h>
#define PI 3.141592653
const float deg2Rad = PI / 180.;
const float rad2Deg = 180. / PI;
struct NeoColor
{
float r, g, b;
NeoColor(){}
NeoColor(float r_,float g_,float b_) : r(r_), g(g_), b(b_){}
void Set(float r_,float g_,float b_) {r = r_; g = g_; b = b_;}
};
struct NeoVec2
{
float x, y;
NeoVec2(){}
NeoVec2(float x_,float y_) : x(x_), y(y_){}
void Set(float x_,float y_) {x = x_; y = y_;}
};
inline NeoVec2 operator + (const NeoVec2 &v1, const NeoVec2 &v2)
{
return NeoVec2(v1.x + v2.x, v1.y + v2.y);
}
inline NeoVec2 operator * (float a, const NeoVec2 &v)
{
return NeoVec2(v.x * a, v.y * a);
}
class GluiDraw
{
public:
GluiDraw(){}
~GluiDraw(){}
void DrawLine(const NeoVec2 &v1,const NeoVec2 &v2,const NeoColor &color)
{
glBegin(GL_LINES);
glColor3f(color.r,color.g,color.b);
glVertex2f(v1.x,v1.y);
glVertex2f(v2.x,v2.y);
glEnd();
}
void DrawCircle(const NeoVec2 ¢er, const float radius, const NeoColor &color)
{
const float segments = 16.;
const float inc = 2 * PI / 16.;
float theta = 0;
glBegin(GL_LINE_LOOP);
glColor3f(color.r,color.g,color.b);
for (int i=0;i < segments;++i)
{
NeoVec2 real_v = center + radius * NeoVec2(cosf(theta),sinf(theta));
glVertex2f(real_v.x,real_v.y);
theta += inc;
}
glEnd();
}
void DrawSolidCircle(const NeoVec2 ¢er, const float radius,const NeoVec2 &axis, const NeoColor &color)
{
const float segments = 16.;
const float inc = 2 * PI / 16.;
float theta = 0;
glBegin(GL_LINE_LOOP);
glColor3f(color.r,color.g,color.b);
for (int i=0;i < segments;++i)
{
NeoVec2 real_v = center + radius * NeoVec2(cosf(theta),sinf(theta));
glVertex2f(real_v.x,real_v.y);
theta += inc;
}
glEnd();
DrawLine(center,center + (radius * axis),color);
}
void DrawPolygon(const NeoVec2* vertices, int vertexCount, const NeoColor& color)
{
glColor3f(color.r, color.g, color.b);
glBegin(GL_LINE_LOOP);
for (int i = 0; i < vertexCount; ++i)
{
glVertex2f(vertices[i].x, vertices[i].y);
}
glEnd();
}
void DrawSolidPolygon(const NeoVec2* vertices, int vertexCount, const NeoColor& color)
{
glEnable(GL_BLEND);
glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glColor4f(0.5f * color.r, 0.5f * color.g, 0.5f * color.b, 0.5f);
glBegin(GL_TRIANGLE_FAN);
for (int i = 0; i < vertexCount; ++i)
{
glVertex2f(vertices[i].x, vertices[i].y);
}
glEnd();
glDisable(GL_BLEND);
glColor4f(color.r, color.g, color.b, 1.0f);
glBegin(GL_LINE_LOOP);
for (int i = 0; i < vertexCount; ++i)
{
glVertex2f(vertices[i].x, vertices[i].y);
}
glEnd();
}
void DrawBox(const NeoVec2 ¢er,const float half_width,const float half_height, const NeoColor& color)
{
NeoVec2 list[4] = {
NeoVec2(center.x-(half_width),center.y-(half_height)),
NeoVec2(center.x+(half_width),center.y-(half_height)),
NeoVec2(center.x+(half_width),center.y+(half_height)),
NeoVec2(center.x-(half_width),center.y+(half_height))
};
DrawSolidPolygon(list, 4, color);
}
};
#endif