You are on page 1of 99

Date:14/02/2017 v1Box2D With Opengl(GLFW) and SOIL

S.NO Table of Contents Page No


1 BOX2D + OpenGL + Static Body(Ground Creation) 23
2 Box2D+ OpenGL + DynamicBody + Static 30
Body(Ground)
3 Box2D + Static Body + Dynamic Body + Textures 33
4 Box2D + Opengl + Circle Shape + Static Ground 37
5 Box2D + Opengl + Circle Shape + Textures 42
6 Box2D + Opengl + Circle + Polygon + Textures 48
7 Box2D + OpenGL + Circle Shape + Polygon Shape + Dynamic + 54
Textures

8 Box2D + OpenGL + Edge Shape + Dynamic Body 61


9 Box2D + OpenGL + Drawing Static Walls + Dynamic Body + 66
velocity
10 Box2D + OpenGL + Contact Listener 71
11 Box2D + OpenGL + Joints 82
12 Box2D + OpenGL + Camera using Debug Draw 86
13 Box2D + OpenGL + Car simulation 95

By,
A,ArunKumar,
Lecturer,Game Design & Development
ICAT Design & Media College,Hyderabad

1
Date:14/02/2017 v1Box2D With Opengl(GLFW) and SOIL

1. INTRODUCTION

Box2D is a Physics engine; Physics engine does not mean it is a game engine.
Box2D is good at simulating physics but it is not intended to draw nice graphics, so we have
to choose the Graphics for us. Here in this manual OpenGL is chosen as the choice but can
be extended to any others as desired.

Box2D is a 2D rigid body simulation library for games. Programmers can use in
their games for moving objects in a more realistic way and make the game world more
interactive. In Box2D all the types start with prefix b2 which makes programmer avoid
name clashing. The most famous application that has used this open-source engine is Angry
Birds. Box2D has ports to many other languages such as Java, Python, Ruby, C #,
JavaScript, Flash and many more. So what you learn for one language is sufficient to move
to the other language. Box2D calculates all the positions and rotations of the bodies that you
created

1.1 About Configuring

The four steps that you need to go through to use Box2D in your game are
1. Download Box2D(http://box2d.org/)
2. Install the Box2D header files
3. Change the visual studio code generation settings.
4. Build and install the Box2D library file Box2D.lib
In detail
1.Download Box2D. Go to the Box2D website(http://box2d.org/), go to GitHub
Download Box2D. This will download a zip folder to your computer.
2.Install the Box2D header files.
(a) You will find a folder called Box2D once you extract the zip file, grap the manual
once you are there.
(b) If the build not available in the folder then use CMAKE to build the solution
folder for you.
3. Now go to http://www.cmake.org/ download the cmake

2
Date:14/02/2017 v1Box2D With Opengl(GLFW) and SOIL

Download the zip-file of the latest version of cmake and Extract the zip-file to somewhere in
your computer

Now open the cmake extracted folder, goto bin, and run cmake-gui.exe (highlighted in the
image above). You should see the program as shown in the image below:

Building the library:


3
Date:14/02/2017 v1Box2D With Opengl(GLFW) and SOIL

You need to set the Box2D directory from the Browse Source button, and Box2D/Build
directory from the Browse Build. In my case, the extracted directory Box2D_v2.1.2 was on
the desktop, so the directories set were as follows:

If there is no Build folder available you create a new folder and rename it to build inside the
extracted zip folder of Box2D and add the path of that build directory to where to build the
binaries.
After setting the directories, click Configure button. You will see the dialog as follows:

Here configure chooses Visual Studio 10 depending on the version you have
installed it will display so for example if you have installed Visual Studio 2012 it

4
Date:14/02/2017 v1Box2D With Opengl(GLFW) and SOIL

will show Visual Studio 12 so make the settings as same as given as default now
click Finish button at the bottom. once you click Finish the below figure appears.

After configuration is done, you will see selection in red:

click the Configure button once again (and red selection will turn white):

5
Date:14/02/2017 v1Box2D With Opengl(GLFW) and SOIL

Now, click Generate button,

After generating is done, goto extracted box2D build folder (example C:/Users/Desktop/
Box2D_v2.1.2/Box2D/Build/):

6
Date:14/02/2017 v1Box2D With Opengl(GLFW) and SOIL

open Box2D.sln from there (shown in above figure).


A dialog box will come up:

choose your version of Visual Studio for C++ (I use Visual C++ Express 2010), and click OK
button.

Visual studio will open the Box2D solution.

7
Date:14/02/2017 v1Box2D With Opengl(GLFW) and SOIL

Now, from the explorer, right-click the Box2D project and click Build (shown in above image).
This will start building the Box2D project library.

8
Date:14/02/2017 v1Box2D With Opengl(GLFW) and SOIL

After the building is complete (shown in above image), close current solution.

Create a new Folder called lib inside the Box2D you have extracted and goto the folder
C:/Users/Desktop/ Box2D_v2.1.2/Box2D/ and create a lib folder and copy the library file
you have generated from the C:/Users/Desktop/ Box2D_v2.1.2/Box2D/build/Box2D/Debug
in my case this is the folder in which the library file is generated here in this folder you will see
the Box2D library copy it and paste it into the lib folder you have created.

9
Date:14/02/2017 v1Box2D With Opengl(GLFW) and SOIL

Setting up the library:

Create a new folder there, and name it lib where we will be putting Box2d library files.
This library shown is for visual studio 2010

Now copy the library files from the build folder (in my case, the files are located at
Box2D_v2.1.2/Box2D/Build/ on the desktop).
10
Date:14/02/2017 v1Box2D With Opengl(GLFW) and SOIL

Now, come back to the Visual Studio where we had our browsing window left.

and paste the library files in the lib folder (shown in above image).

11
Date:14/02/2017 v1Box2D With Opengl(GLFW) and SOIL

Now, go to the Box2D folder (in my case, it is located at Box2D_v2.1.2/Box2D/ on the


desktop),

and copy the Box2D folder in there.


Now, go back to the Visual Studio where we left,

and paste the copied Box2D folder in the directory where lib is saved.

12
Date:14/02/2017 v1Box2D With Opengl(GLFW) and SOIL

Now, we will use pre-made, HelloWorld program which is located at the HelloWorld folder in
Box2D_v2.1.2/Box2D directory.

Copy the HelloWorld.cpp file and paste it in the folder where we have our project files:

Creating a new project


13
Date:14/02/2017 v1Box2D With Opengl(GLFW) and SOIL

Open Visual studio File->New->Project the figure below will appear

Once you click New Project will display as shown below

Select Empty Project and at the bottom you can see a Name field type the name of the project
here I have typed as Box2D_Helloworld and you can change the location where u want to
store the project you created here I am saving in location E:\students project Directx\ Now
click OK button at the bottom right hand corner.

14
Date:14/02/2017 v1Box2D With Opengl(GLFW) and SOIL

Now your screen appears as above in the right hand corner you have got the solution explorer go
to the Source Files Right click with your mouse you will get ADD now hover over there and
go to New Item. You will get a screen as shown below

Now click ADDat the bottom right hand corner your source file is ready.

15
Date:14/02/2017 v1Box2D With Opengl(GLFW) and SOIL

PRECONFIGARATION SETTINGS TO RUN THE PROJECT

Now right click the Project in the solution explorer here we have given the name at the first step
as Box2D_Helloworld you will get a hover window go to Properties at the bottom click on
it.

Now you will get the window as shown below

16
Date:14/02/2017 v1Box2D With Opengl(GLFW) and SOIL

Here click on the C/C++ expand it go to General settings

17
Date:14/02/2017 v1Box2D With Opengl(GLFW) and SOIL

Now go to Additional Include Directories click it and click Edit you will get another
window opened with the title Additional Include Directories

Now click on the folder icon there are four buttons available at the top folder icon, delete button,
hover down, hover up click only the folder icon you will have an elipses() seen click on the
three dots shown at the end this will open up a window now go to the Box2D folder which you
have extracted.

18
Date:14/02/2017 v1Box2D With Opengl(GLFW) and SOIL

Now hover the window and go to the folder where you have copied the Box2D folder go to the
folder where Box2D.h is available it may not be visible if you follow this step so make sure
Box2D.h is available in that folder where you are clicking and going from here select till Box2D
and inside this also another Box2D will be available where the three modules required for
Box2D will be available collision, Common & Dynamics along with Box2D.h. So we have
found the path now click ok button you will see the next screen shown below.

19
Date:14/02/2017 v1Box2D With Opengl(GLFW) and SOIL

Now click ok you should see the path available next to the Additional Include Directories
thats it done for include files

Now, go to Configuration Properties > Linker > General

Now Goto Additional Library Directories click the drop down list click edit and go to the
folder where we have the Box2D.lib these files we have copied and pasted into a folder lib
so select the path of lib folder and click ok. Again as in previous step this will show the full path
to the library folder in the Additional Library Directories.

Now Goto Linker->Input as shown in the below figure

20
Date:14/02/2017 v1Box2D With Opengl(GLFW) and SOIL

Now click Additional Dependencies->Edit


You will get a window opened in that type Box2D.lib click ok done
thats it

Now click on Apply at the bottom right hand corner now our settings are over for Box2D now
you can right click the Box2D_helloworld and click Build and click the Run button a console
window will open showing the where abouts of our body in the window.

This setting has to be done each time you create a new project
21
Date:14/02/2017 v1Box2D With Opengl(GLFW) and SOIL

If you are using OpenGL then the same steps as above has to be done for OpenGL for example

Goto C/C++->General->Additional Include Directories->Edit->


Click on the folder icon and go to the folder where glfw3.h is available give one folder ahead
of this for example if it is available in GLFW/glfw3.h then select only the folder till the
GLFW folder and click ok.

Now for adding library Goto Linker->General->Additional Library Directories-> choose the
path till the folder which contains the glfw3.lib and also here we need to control the version
for example here I used Visual studio 2012 so select the version for which the library was
generated if it is available then build the binaries by yourself

After doing these steps goto Linker->Input->Additional Dependencies then click Edit and type
Opengl32.lib
glfw3.lib
Box2D.lib

So these steps are same for any API which you are going to work with Visual studio if the
binaries are available build by yourself use Cmake if required.

1) BOX2D + OpenGL + Static Body(Ground Creation)

22
Date:14/02/2017 v1Box2D With Opengl(GLFW) and SOIL

Introduction:

Firstly, Box2D has an object called b2World. b2World is the boss of everything; Its where you
create bodies and joints, and it also automatically manages all the memories its responsible for.
To create a b2World in Box2D, you simply define the gravity (which uses b2Vec2, a 2D vector)
and declare a b2World with the gravity as the parameter

world=new b2World(b2Vec2(0.0,9.8));

You can see this in the init() function in this program where the gravity is specified along the
Y-axis and for x-axis the gravity is specified as 0.0. Not all game requires gravity. If it does not
require gravity then u can set the value to 0.0 and here in this 9.8 is the value which we give to
our world so thats the value specified here.

Lets now create a function to spawn the ground where the bodies are going to fall.
void drawSquare(b2Vec2 points[],b2Vec2 center,float angle)

This function renders square once the vertices are given.

In order to create bodies in Box2D, we need to define what Box2D calls a Body Definition
(b2BodyDef). BodyDef defines the initial position of the body and the type of the body (static,
dynamic or kinematic).
Static basically means that the body may never move.
Dynamic means that the body can interact with other bodies.
Kinematic means the body can move but it will not be affected by other bodies (for example, an
elevator perhaps).

So here, were going to declare a static body because we want the ground to stay still.
b2BodyDef bodyDef;
bodyDef.position.Set(x*P2M,y*P2M);
bodyDef.type=b2_staticBody;//here the type of body is static
body=world->CreateBody(&bodyDef);//function returns a value body

You can see this inside the addRect(int x,int y,int w,int h) function. Here the argument passed
are (x,y) to set the position of the body and (w,h) are the width and height of the body here we
are using polygonshape and you can also see that the position of the body
bodyDef.position.Set(x*P2M,y*P2M); is multiplied by P2M(Pixels to Meters) this is done to
integrate with Box2D. Box2D works on MKS(Meters-Kilograms-Seconds) units but opengl
works with pixels so when we pass pixels as arguments to Box2D we have to convert into Meters
and vice-versa for example you can see inside the
drawSquare(b2Vec2 points[],b2Vec2 center,float angle) function where we declared
glVertex2f(points[i].x*M2P,points[i].y*M2P);
where we convert back into pixels by a scaling factor set initially points[i].x*M2P we multiply it
by Meters-to-Pixels so the declaration of this will be seen as a global variable
const float M2P=60;
const float P2M=1/M2P;
23
Date:14/02/2017 v1Box2D With Opengl(GLFW) and SOIL

here we set the scaling ratio of 60. The values for M2P and P2M can be changed depending on
the requirement.
After we defined the body, well want to define the shape and the properties of the body. We
define the shape using b2Shape and the properties using what Box2D calls b2FixtureDef.
Then we define PolygonShape. In Box2D a shape can be a circle or a polygon.
Polygon shapes are solid convex polygons
b2PolygonShape shape;
shape.SetAsBox(w/2*P2M,h/2*P2M);

Collision can occur between bodies only if there is a volume for example we have got edge in
Box2D edge-edge collision cannot occur but polygon with edge and circle with edge can collide
polygon-circle can collide since these have volumes.
Fixtures are used to describe the size, shape, and material properties of an object in the physics
scene. One body can have multiple fixtures attached to it, and the center of mass of the body will
be affected by the arrangement of its fixtures. When two bodies collide, their fixtures are used to
decide how they will react. The main properties of fixtures are:
shape - a polygon or circle
restitution - how bouncy the fixture is
friction - how slippery it is
density - how heavy it is in relation to its area
Fixtures uses these shapes it is here with the help of fixtures we attach the shape to the body
b2FixtureDef fixtureDef;
fixtureDef.shape=&shape;
fixtureDef.density=1.0f;
body->CreateFixture(&fixtureDef);
Now this part is over.
In our game loop
do{
display();
world->Step(1.0/30.0,8,3);
glfwPollEvents();
glfwSwapBuffers(window);
}while(!glfwWindowShouldClose(window));

We have declared a function world->Step(1.0/30.0,8,3) This is required to simulate our world the
three arguments that we pass are (time step, position iterations, velocity iterations) the first
argument is how many times we update the screen, the position and velocity iterations values
can be changed the more iteration you give the more accurate simulation becomes but affects
performance.
Then we go to our opengl for window we use glfw we specify the height and width of the
window globally
const int WIDTH=640;
const int HEIGHT=480;
GLFWwindow* window;//object for handling window
Then we intialize glfw window using the function glfwInit() and create the window by calling
the glfwCreateWindow() where we pass the width and height set globally and give the window
24
Date:14/02/2017 v1Box2D With Opengl(GLFW) and SOIL

title name you can give names that needs to appear as the title of the window and the last two
parameters are set to NULL u can change this value and set the screen to full screen mode, then
we need to set the context of the window and set the viewport to full size of the window
glfwInit();
window=glfwCreateWindow(WIDTH,HEIGHT,"Box2D Example",NULL,NULL);
glfwMakeContextCurrent(window);
glViewport(0,0,WIDTH,HEIGHT);
Now we need to render a Rectangle so we declare a function
void drawSquare(b2Vec2 points[],b2Vec2 center,float angle){
glColor3f(1,1,1);
glPushMatrix();
glTranslatef(center.x*M2P,center.y*M2P,0);
glRotatef(angle*180.0/M_PI,0,0,1);
glBegin(GL_QUADS);
for(int i=0;i<4;i++)
glVertex2f(points[i].x*M2P,points[i].y*M2P);
glEnd();
glPopMatrix();
}
Here in this function we pass three arguments first is the vertices of the rectangle this argument
gets its vertices from Box2D PolygonShape vertices and we get the bodies world center and give
it as second argument(tmp->GetWorldCenter()) used for translation and we get the bodies angle
for rotation. the second and the third argument are required for translation and rotation in the
window which is what makes our display realistic requirement for the Physics engine.

Next You can see the function display() which is our render called inside our game loop
do{}while(!glfwWindowShouldClose(window));
Inside the display() function we get the vertices of the PolygonShape and pass it as arguments to
the drawSquare function.

void display()
{
glClear(GL_COLOR_BUFFER_BIT);
glLoadIdentity();
b2Body* tmp=world->GetBodyList();
while(tmp)
{
for(int i=0;i<4;i++){
points[i]=((b2PolygonShape*)tmp->GetFixtureList()->GetShape())-
>GetVertex(i);
}
drawSquare(points,tmp->GetWorldCenter(),tmp->GetAngle());
tmp=tmp->GetNext();
}
}

25
Date:14/02/2017 v1Box2D With Opengl(GLFW) and SOIL

Here in this function we get the BodyList first,


b2Body* tmp=world->GetBodyList();
This will return the list of the bodies that are added. Here in this program we have created only
one body static body so this will return only one value then we iterate over the bodies and get all
bodies this is a linear data structure where we iterate with the help of while loop and
tmp=tmp->GetNext();
Then we get the vertices of the PolygonShape using
points[i]=((b2PolygonShape*)tmp->GetFixtureList()->GetShape())->GetVertex(i);
we get the body then its fixture list since a body can have many number of fixtures then we get
its shape after this we have to type cast the return value to PolygonShape which we do using
b2PolygonShape and then get the vertices and store it in b2Vec2 points[4] which we declared
globally then we pass these vertices and bodies location and bodies angle to the drawSquare()
function and get our static body rendered.
glfw
See the below coding for implementation

#include <GLFW/glfw3.h>
#include <Box2D/Box2D.h>
#define M_PI 3.141592653
GLFWwindow* window;
b2World* world;
b2Body* body;

26
Date:14/02/2017 v1Box2D With Opengl(GLFW) and SOIL

b2Vec2 points[4];

const float M2P=60;


const float P2M=1/M2P;

const int WIDTH=640;


const int HEIGHT=480;
b2Body* addRect(int x,int y,int w,int h)
{
b2BodyDef bodyDef;
bodyDef.position.Set(x*P2M,y*P2M);
bodyDef.type=b2_staticBody;
body=world->CreateBody(&bodyDef);
b2PolygonShape shape;
shape.SetAsBox(w/2*P2M,h/2*P2M);
b2FixtureDef fixtureDef;
fixtureDef.shape=&shape;
fixtureDef.density=1.0f;
body->CreateFixture(&fixtureDef);
return body;
}
void drawSquare(b2Vec2 points[],b2Vec2 center,float angle){
glColor3f(1,1,1);
glPushMatrix();
glTranslatef(center.x*M2P,center.y*M2P,0);
glRotatef(angle*180.0/M_PI,0,0,1);
glBegin(GL_QUADS);
for(int i=0;i<4;i++)
glVertex2f(points[i].x*M2P,points[i].y*M2P);
glEnd();
glPopMatrix();
}
void display()
{
glClear(GL_COLOR_BUFFER_BIT);
glLoadIdentity();
b2Body* tmp=world->GetBodyList();
while(tmp)
{
for(int i=0;i<4;i++){
points[i]=((b2PolygonShape*)tmp->GetFixtureList()->GetShape())-
>GetVertex(i);
}
drawSquare(points,tmp->GetWorldCenter(),tmp->GetAngle());

27
Date:14/02/2017 v1Box2D With Opengl(GLFW) and SOIL

tmp=tmp->GetNext();
}
}
void init()
{
glMatrixMode(GL_PROJECTION);
glOrtho(0,WIDTH,HEIGHT,0,-1,1);
glMatrixMode(GL_MODELVIEW);
glClearColor(0,0,0,1);
world=new b2World(b2Vec2(0.0,9.8));
addRect(WIDTH/2,HEIGHT-50,WIDTH,30);
}

int main()
{
glfwInit();
window=glfwCreateWindow(WIDTH,HEIGHT,"Box2D Example with
opengl",NULL,NULL);
glfwMakeContextCurrent(window);
glViewport(0,0,WIDTH,HEIGHT);
init();
do{
display();
world->Step(1.0/30.0,8,3);
glfwPollEvents();
glfwSwapBuffers(window);
}while(!glfwWindowShouldClose(window));
glfwTerminate();
return 0;
}

OUTPUT

You can see a static ground body created at the bottom of the window.

28
Date:14/02/2017 v1Box2D With Opengl(GLFW) and SOIL

2)Box2D+ OpenGL + DynamicBody + Static Body(Ground)


Here in this example the extension of above program here we create a dynamic body where ever
we click the mouse button

The steps to be updated in the above program to get this is

Add a function prototype

29
Date:14/02/2017 v1Box2D With Opengl(GLFW) and SOIL

static void mouse_callback(GLFWwindow* window,int button,int


action,int mods);

at the top of the program i.e., globally

then declare a Boolean variable inside the addRect function

b2Body* addRect(int x,int y,int w,int h,bool dyns=true)


if this variable dyns is true then it will be static body else it will be dynamic body

if(dyns){
bodyDef.type=b2_staticBody;
}
else{
bodyDef.type=b2_dynamicBody;
}

Thats it done for dynamicBody

Now for mouse event function use the callback function

glfwSetMouseButtonCallback(window,mouse_callback);
inside the main function outside our game loop u should register which window the event is
generated and write the call-back function in our case this is mouse_callback which we have
declared globally as function prototype.

Now define the mouse callback function u can see it at the bottom

static void mouse_callback(GLFWwindow* window,int button,int


action,int mods)
{
if(button==GLFW_MOUSE_BUTTON_RIGHT && action==GLFW_PRESS)
{

double x;
double y;
glfwGetCursorPos(window,&x,&y);
addRect(x,y,50,50,false);
}
}

Here we register the mouse right button click event we declare two variables x and y and get
the current position of the mouse cursor using the function
glfwGetCursorPos(window,&x,&y); and give this values of the variable x & y as
arguments to the addRect() function to draw rectangle where ever we rightclick the mouse.

30
Date:14/02/2017 v1Box2D With Opengl(GLFW) and SOIL

To make the simulation realistic we add one more function inside our game loop

glfwSwapInterval(5); you can experiment by removing this function.

#include <Box2D/Box2D.h>
#include <glfw/glfw3.h>
#define M_PI 3.141592653
GLFWwindow* window;
const int WIDTH=640;
const int HEIGHT=480;
const float M2P=60;
const float P2M=1/M2P;
b2World* world;
b2Body* body;
b2Vec2 points[4];

31
Date:14/02/2017 v1Box2D With Opengl(GLFW) and SOIL

static void mouse_callback(GLFWwindow* window,int button,int


action,int mods);
b2Body* addRect(int x,int y,int w,int h,bool dyns=true)
{
b2BodyDef bodyDef;
bodyDef.position.Set(x*P2M,y*P2M);
if(dyns){
bodyDef.type=b2_staticBody;
}
else{
bodyDef.type=b2_dynamicBody;
}
body=world->CreateBody(&bodyDef);
b2PolygonShape shape;
shape.SetAsBox(w/2*P2M,h/2*P2M);
b2FixtureDef fixtureDef;
fixtureDef.shape=&shape;
fixtureDef.density=1.0;
body->CreateFixture(&fixtureDef);
return body;
}
void drawSquare(b2Vec2 points[],b2Vec2 center,float angle)
{
glColor3f(1,1,1);
glPushMatrix();
glTranslatef(center.x*M2P,center.y*M2P,0);
glRotatef(angle*180.0/M_PI,0,0,1);

glBegin(GL_QUADS);
for(int i=0;i<4;i++)
glVertex2f(points[i].x*M2P,points[i].y*M2P);
glEnd();

glPopMatrix();
}
void display()
{
glClear(GL_COLOR_BUFFER_BIT);
glLoadIdentity();
b2Body* tmp=world->GetBodyList();
while(tmp){
for(int i=0;i<4;i++)
points[i]=((b2PolygonShape *)tmp->GetFixtureList()->GetShape())-
>GetVertex(i);
drawSquare(points,tmp->GetWorldCenter(),tmp->GetAngle());

32
Date:14/02/2017 v1Box2D With Opengl(GLFW) and SOIL

tmp=tmp->GetNext();
}

}
void init()
{
glMatrixMode(GL_PROJECTION);
glOrtho(0,WIDTH,HEIGHT,0,-1,1);
glMatrixMode(GL_MODELVIEW);
glClearColor(0,0,0,1);
world=new b2World(b2Vec2(0.0,9.8));
addRect(WIDTH/2,HEIGHT-50,WIDTH,30,true);
}
int main()
{
glfwInit();
window=glfwCreateWindow(WIDTH,HEIGHT,"Hello world",NULL,NULL);
glfwMakeContextCurrent(window);
glViewport(0,0,WIDTH,HEIGHT);
glfwSetMouseButtonCallback(window,mouse_callback);
init();
do{
display();
world->Step(1.0/30.0,8,3);
glfwSwapBuffers(window);
glfwPollEvents();
glfwSwapInterval(5);
}while(!glfwWindowShouldClose(window));
glfwTerminate();
return 0;
}

static void mouse_callback(GLFWwindow* window,int button,int


action,int mods)
{
if(button==GLFW_MOUSE_BUTTON_RIGHT && action==GLFW_PRESS)
{

double x;
double y;
glfwGetCursorPos(window,&x,&y);
addRect(x,y,50,50,false);
}
}

33
Date:14/02/2017 v1Box2D With Opengl(GLFW) and SOIL

OUTPUT

Here in this example you can see a dynamic body created at the place
we right click the mouse

3)Box2D + Static Body + Dynamic Body + Textures


Now in this example we are going to add Textures to our bodies for this we use SOIL (Simple
OpenGL Image Loader) is a public-domain cross-platform image loader that's extremely small. It
can read a small variety of useful formats (BMP, JPEG, PNG, various DDS files, etc).
It does have functions to load images into OpenGL textures. Indeed, it only allows this (which is
why it is "simple").
Texture coordinates specify which pixels (or texels) in the texture should be used. The values are
normalized such that (0,0) corresponds to the bottom-left of your image and (1,1) corresponds to
the top-right of your image. Whether your object is at (0,0) or at (42,35) in your world does not
change which pixels in the texture you want to use.

If you want to map the entirety of a texture to a quad, then you should pass (0,0), (0,1), (1,1) and
(1,0) as the texture coordinates for each of your four vertices. You might have to play with the
order of the coordinates if the texture appears rotated.
34
Date:14/02/2017 v1Box2D With Opengl(GLFW) and SOIL

Use soil

1) Goto properties of the Project right click the project and go to Properties

2) In Configuration settings expand the C/C++->General->Additional Include


directories add the include file of soil.h to your project in my case it is E:\Opengl
ebooks\softwares\opengl-wrappers\soil\Simple OpenGL Image Library\src

3) Then add the library files expand Linker and goto Linker->General->Additional
Library Directories add the library file to your project search for SOIL.lib and add
that location here in my case it is E:\Opengl ebooks\softwares\opengl-
wrappers\soil\Simple OpenGL Image Library\lib

4) Then goto Linker->Input->Additional Dependencies add SOIL.lib to the already


added library files for example you would have set the project settings like
opengl32.lib;glfw3.lib to that add SOIL.lib

After that add a global variable

GLuint textureID;

Then add GLuint loadTextures(const char* filename) function this takes as arguments filename
thats the path to the image file and returns an GLuint object.

Inside this function the first thing we are going to do is the addition of glGenTextures(1,
&textureID);text

Tells opengl we want to generate one texture name(increase the number if you load more than
one texture). If you need to store more than one texture for example if you need to store two
textures then at the starting add GLuint texture[2].Where our first texture would be stored at
&texture[0] and second at texture[1].

The second line glBindTexture(GL_TEXTURE_2D, textureID); tells opengl to bind the named
texture textureID to a texture target. glBindTexture is to assign a texture name to texture data.

Next we create actual texture. Following line tells openGL the texture will be a 2D
texture(GL_TEXTURE_2D).we are wrapping the texture along the S and T axis.

Next two lines tell openGL what type of filtering to use when the image is
larger(GL_TEXTURE_MAG_FILTER)or stretched on the screen than the original texture,or
when its smaller(GL_TEXTURE_MIN_FILTER) on the screen than the actual texture.Usually
GL_LINEAR is used for both.If your system is slower then you need to use GL_NEAREST
since it requires a lot of work from the processor.

Then convert the image into char array and store it in a variable image which we first declared.
Then attach it to the target and free the memory and return the GLuint textureID object thats it
done for textures this code will remain same for adding textures using soil.

35
Date:14/02/2017 v1Box2D With Opengl(GLFW) and SOIL

Now go to drawSquare function

void drawSquare(b2Vec2 points[],b2Vec2 center,float angle)


{
glColor3f(1,1,1);
glPushMatrix();
glTranslatef(center.x*M2P,center.y*M2P,0);
glRotatef(angle*180.0/M_PI,0,0,1);
if(dyn){
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D,textureID);
glBegin(GL_QUADS);
glTexCoord2f(250/256,250/256);glVertex2f(points[0].x*M2P,points[0].y*M2P);
glTexCoord2f(256/256,250/256);glVertex2f(points[1].x*M2P,points[1].y*M2P);
glTexCoord2f(256/256,256/256);glVertex2f(points[2].x*M2P,points[2].y*M2P);
glTexCoord2f(250/256,256/256);glVertex2f(points[3].x*M2P,points[3].y*M2P);
glEnd();
glDisable(GL_TEXTURE_2D);
}else{
glBegin(GL_QUADS);
for(int i=0;i<4;i++)
glVertex2f(points[i].x*M2P,points[i].y*M2P);
glEnd();
//dyn=true;
}
glPopMatrix();
}
To properly map a texture onto a quad you have to make sure the top right of the texture is
mapped to the top right of the quad. The top left of the texture is mapped to the top left of the
quad same for all corners. If the corners of the texture do not match the same corners of the quad,
the image may appear upside down, sideways or not at all.

The first value of glTexCoord2f is the x coordinat. 0.0fis the left side of the texture 0.5f is the
middle of the texture and 1.0 is the right of the texture. The second value of glTexCoord2f is the
y coordinate 0.0f is the bottom of the texture, 0.5f is the middle of the texture and 1.0f is the top
of the texture.

Thats it done for textures

Now inside the main function call the loadTextures() function

textureID=loadTextures("./images/1.jpg");

Here right click the source.cpp at the window this is the name of the file I gave and
goto Open containing folder and create a folder named images and add the image into
this folder and call that using the method shown above

36
Date:14/02/2017 v1Box2D With Opengl(GLFW) and SOIL

Inside the drawSquare(b2Vec2 points[],b2Vec2 center,float angle){} function add the


below lines before rendering the quad.
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D,textureID);
At the end you can disable the texture glDisable(GL_TEXTURE_2D);
Thats it done you have to see texture inside the body.

#include <Box2D/Box2D.h>
#include <glfw/glfw3.h>
#include <SOIL.h>
#define M_PI 3.141592653

GLFWwindow* window;
const int WIDTH=640;
const int HEIGHT=480;
const float M2P=60;
const float P2M=1/M2P;
b2World* world;
b2Body* body;
b2Vec2 points[4];
bool dyn=true;

GLuint textureID;

GLuint loadTextures(const char* filename) {


unsigned char* image;
int width, height;
37
Date:14/02/2017 v1Box2D With Opengl(GLFW) and SOIL

//generating texture object and attaching to the target


glGenTextures(1, &textureID);
glBindTexture(GL_TEXTURE_2D, textureID);
//wrapping along the s and t axis of texture
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
//filtering so thet the resolution fits to the object
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
//load the img data
image = SOIL_load_image(filename, &width, &height, 0,
SOIL_LOAD_RGBA);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0,
GL_RGBA, GL_UNSIGNED_BYTE, image);
//free the image memory from GPL
SOIL_free_image_data(image);
//unbind the texture
glBindTexture(GL_TEXTURE_2D, 0);
return textureID;
}

static void mouse_callback(GLFWwindow* window,int button,int


action,int mods);
b2Body* addRect(int x,int y,int w,int h,bool dyns=true)
{
b2BodyDef bodyDef;
bodyDef.position.Set(x*P2M,y*P2M);
if(dyns){
dyn=false;
bodyDef.type=b2_staticBody;
textureID=NULL;
}
else{
dyn=true;
bodyDef.type=b2_dynamicBody;
}
body=world->CreateBody(&bodyDef);
b2PolygonShape shape;
shape.SetAsBox(w/2*P2M,h/2*P2M);
b2FixtureDef fixtureDef;
fixtureDef.shape=&shape;
fixtureDef.density=1.0;
body->CreateFixture(&fixtureDef);
return body;
}

38
Date:14/02/2017 v1Box2D With Opengl(GLFW) and SOIL

void drawSquare(b2Vec2 points[],b2Vec2 center,float angle)


{
glColor3f(1,1,1);
glPushMatrix();
glTranslatef(center.x*M2P,center.y*M2P,0);
glRotatef(angle*180.0/M_PI,0,0,1);
if(dyn){
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D,textureID);
glBegin(GL_QUADS);
glTexCoord2f(250/256,250/256);glVertex2f(points[0].x*M2P,points[0].y*M2P);
glTexCoord2f(256/256,250/256);glVertex2f(points[1].x*M2P,points[1].y*M2P);
glTexCoord2f(256/256,256/256);glVertex2f(points[2].x*M2P,points[2].y*M2P);
glTexCoord2f(250/256,256/256);glVertex2f(points[3].x*M2P,points[3].y*M2P);
glEnd();
glDisable(GL_TEXTURE_2D);
}else{
//textureID=NULL;
glBegin(GL_QUADS);
for(int i=0;i<4;i++)
glVertex2f(points[i].x*M2P,points[i].y*M2P);
glEnd();
//dyn=true;
}
glPopMatrix();
}
void display()
{
glClear(GL_COLOR_BUFFER_BIT);
glLoadIdentity();
b2Body* tmp=world->GetBodyList();

//glEnable(GL_TEXTURE_2D);
//glBindTexture(GL_TEXTURE_2D,textureID);

while(tmp){
for(int i=0;i<4;i++)
points[i]=((b2PolygonShape *)tmp->GetFixtureList()->GetShape())->GetVertex(i);
drawSquare(points,tmp->GetWorldCenter(),tmp->GetAngle());
if(body->GetType()==0)dyn=false;else dyn=true;
tmp=tmp->GetNext();
}

}
void init()
{
39
Date:14/02/2017 v1Box2D With Opengl(GLFW) and SOIL

glMatrixMode(GL_PROJECTION);
glOrtho(0,WIDTH,HEIGHT,0,-1,1);
glMatrixMode(GL_MODELVIEW);
glClearColor(0,0,0,1);
world=new b2World(b2Vec2(0.0,9.8));
addRect(WIDTH/2,HEIGHT-50,WIDTH,30,true);
}
int main()
{
glfwInit();
window=glfwCreateWindow(WIDTH,HEIGHT,"Hello world",NULL,NULL);
glfwMakeContextCurrent(window);
glViewport(0,0,WIDTH,HEIGHT);
glfwSetMouseButtonCallback(window,mouse_callback);
init();
textureID=loadTextures("./images/1.jpg");
do{
display();
world->Step(1.0/30.0,8,3);
glfwSwapBuffers(window);
glfwPollEvents();
glfwSwapInterval(5);
}while(!glfwWindowShouldClose(window));
glfwTerminate();
return 0;
}

static void mouse_callback(GLFWwindow* window,int button,int


action,int mods)
{
if(button==GLFW_MOUSE_BUTTON_RIGHT && action==GLFW_PRESS)
{
double x;
double y;
glfwGetCursorPos(window,&x,&y);
dyn=true;
addRect(x,y,50,50,false);
}
}

OUTPUT:

40
Date:14/02/2017 v1Box2D With Opengl(GLFW) and SOIL

4)Box2D + Opengl + Circle Shape + Static Ground


#include <Windows.h>
#include <iostream>
#include <Box2D/Box2D.h>
#include <GLFW/glfw3.h>
#define M_PI 3.14159265358979323846
using namespace std;

GLFWwindow* window;
GLfloat start;
const int WIDTH=640;
const int HEIGHT=480;
b2World* world;
b2Body* body;
b2Vec2 points[4];
const float M2P=60;
const float P2M=1/M2P;
41
Date:14/02/2017 v1Box2D With Opengl(GLFW) and SOIL

static void mouse_callback(GLFWwindow* window,int button,int


action,int mods);

b2Body* addRect(int x,int y,int w,int h,bool dyns=true)


{
b2BodyDef bodyDef;
bodyDef.position.Set(x*P2M,y*P2M);
if(dyns){
bodyDef.type=b2_staticBody;
}else{
bodyDef.type=b2_dynamicBody;

}
body=world->CreateBody(&bodyDef);
b2PolygonShape shape;
shape.SetAsBox(P2M*w/2,P2M*h/2);
b2FixtureDef fixtureDef;
fixtureDef.shape=&shape;
fixtureDef.density=1.0;
fixtureDef.friction=0.0;//step-1 try giving 0.9 dont fly usually this
is given
fixtureDef.restitution=0.8;//now it is like a ball it can bounce
body->CreateFixture(&fixtureDef);
return body;
}

b2Body* addCircle(int x,int y,int r,bool byns=true)


{
b2BodyDef bodyDef;
bodyDef.position.Set(x*P2M,y*P2M);
if(byns){
bodyDef.type=b2_staticBody;
}else{
bodyDef.type=b2_dynamicBody;

body=world->CreateBody(&bodyDef);
b2CircleShape shape;
shape.m_radius=r*P2M;
shape.m_p.Set(0,0);

42
Date:14/02/2017 v1Box2D With Opengl(GLFW) and SOIL

b2FixtureDef fixtureDef;
fixtureDef.shape=&shape;
fixtureDef.density=1.0;
fixtureDef.friction=0.0;
fixtureDef.restitution=0.8;
body->CreateFixture(&fixtureDef);
return body;
}

void drawCircle(b2Vec2 center,float r,float angle)


{
const int PRECISION=60;
glColor3f(1,1,1);
glPushMatrix();
glTranslatef(center.x*M2P,center.y*M2P,0);
glRotatef(angle*180.0/M_PI,0,0,1);

glBegin(GL_TRIANGLE_FAN);
glVertex2f(0,0);
for(float i=0.0;i<=360.0;i+=360.0/PRECISION)
glVertex2f((cos(i*M_PI/180.0)*r)*M2P,(sin(i*M_PI/180.0)*r)*M2P);
glEnd();

glPopMatrix();
}

void drawSquare(b2Vec2 points[],b2Vec2 center,float angle)


{
glColor3f(1,1,1);
glPushMatrix();
glTranslatef(center.x*M2P,center.y*M2P,0);
glRotatef(angle*180.0/M_PI,0,0,1);

glBegin(GL_QUADS);
for(int i=0;i<4;i++)
glVertex2f(points[i].x*M2P,points[i].y*M2P);
glEnd();
glPopMatrix();
}

void display()

43
Date:14/02/2017 v1Box2D With Opengl(GLFW) and SOIL

{
glClear(GL_COLOR_BUFFER_BIT);
glLoadIdentity();
b2Body* tmp=world->GetBodyList();
while(tmp){
if((tmp->GetFixtureList()->GetShape()->GetType())==0){
b2CircleShape* c= (b2CircleShape*)tmp->GetFixtureList()-
>GetShape();

drawCircle(tmp->GetWorldCenter(),0.4,tmp->GetAngle());
}else{
for(int i=0;i<4;i++)
points[i]=((b2PolygonShape*)tmp->GetFixtureList()->GetShape())-
>GetVertex(i);

drawSquare(points,tmp->GetWorldCenter(),tmp->GetAngle());

}
tmp=tmp->GetNext();
}
}

void init()
{
glMatrixMode(GL_PROJECTION);
glOrtho(0,WIDTH,HEIGHT,0,-1,1);
glMatrixMode(GL_MODELVIEW);
glClearColor(0,0,0,1);
world=new b2World(b2Vec2(0.0,9.8));
addRect(WIDTH/2,HEIGHT-50,WIDTH,20,true);
}

int main(int argc,char **argv)


{
glfwInit();
window=glfwCreateWindow(WIDTH,HEIGHT,"HELLO WORLD",NULL,NULL);
glfwMakeContextCurrent(window);
glViewport(0,0,WIDTH,HEIGHT);
glfwSetMouseButtonCallback(window,mouse_callback);

init();

do{

44
Date:14/02/2017 v1Box2D With Opengl(GLFW) and SOIL

display();
world->Step(1.0/30.0,8,3);
glfwSwapBuffers(window);
glfwPollEvents();
glfwSwapInterval(3);
}while(!glfwWindowShouldClose(window));
glfwTerminate();
return 0;
}

static void mouse_callback(GLFWwindow* window,int button,int


action,int mods)
{

if(button==GLFW_MOUSE_BUTTON_RIGHT && action==GLFW_PRESS)


{
double x;
double y;
glfwGetCursorPos(window,&x,&y);
addCircle(x,y,15,false);
}
}

OUTPUT:

45
Date:14/02/2017 v1Box2D With Opengl(GLFW) and SOIL

46
Date:14/02/2017 v1Box2D With Opengl(GLFW) and SOIL

5) Box2D + Opengl + Circle Shape + Textures


#include <iostream>
#include <Box2D/Box2D.h>
#include <GLFW/glfw3.h>
#include <SOIL.h>
#define M_PI 3.14159265358979323846
using namespace std;

GLFWwindow* window;
const int WIDTH=640;
const int HEIGHT=480;
b2World* world;
b2Body* body;
b2Vec2 points[4];
const float M2P=60;
const float P2M=1/M2P;

static void mouse_callback(GLFWwindow* window,int button,int


action,int mods);

GLuint textureID;

GLuint loadTextures(const char* filename) {


unsigned char* image;
int width, height;
//generating texture object and attaching to the target
glGenTextures(1, &textureID);
glBindTexture(GL_TEXTURE_2D, textureID);
//wrapping along the s and t axis of texture
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
//filtering so thet the resolution fits to the object
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
//load the img data
image = SOIL_load_image(filename, &width, &height, 0,
SOIL_LOAD_RGBA);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0,
GL_RGBA, GL_UNSIGNED_BYTE, image);
//free the image memory from GPL
SOIL_free_image_data(image);
//unbind the texture
glBindTexture(GL_TEXTURE_2D, 0);
return textureID;

47
Date:14/02/2017 v1Box2D With Opengl(GLFW) and SOIL

b2Body* addRect(int x,int y,int w,int h,bool dyns=true)


{
b2BodyDef bodyDef;
bodyDef.position.Set(x*P2M,y*P2M);
if(dyns){

bodyDef.type=b2_staticBody;
}else{

bodyDef.type=b2_dynamicBody;
}
body=world->CreateBody(&bodyDef);
b2PolygonShape shape;
shape.SetAsBox(P2M*w/2,P2M*h/2);
b2FixtureDef fixtureDef;
fixtureDef.shape=&shape;
fixtureDef.density=1.0;
fixtureDef.friction=0.0;//step-1 try giving 0.9 they dont fly
usually this is given
fixtureDef.restitution=0.8;//now it is like a ball it can bounce
body->CreateFixture(&fixtureDef);
return body;
}

b2Body* addCircle(int x,int y,int r,bool byns=true)


{
b2BodyDef bodyDef;
bodyDef.position.Set(x*P2M,y*P2M);
if(byns){
bodyDef.type=b2_staticBody;
}else{
bodyDef.type=b2_dynamicBody;
}

body=world->CreateBody(&bodyDef);
b2CircleShape shape;
shape.m_radius=r*P2M;
shape.m_p.Set(0,0);
b2FixtureDef fixtureDef;
fixtureDef.shape=&shape;
fixtureDef.density=1.0;
fixtureDef.friction=0.0;

48
Date:14/02/2017 v1Box2D With Opengl(GLFW) and SOIL

fixtureDef.restitution=0.8;
body->CreateFixture(&fixtureDef);
return body;
}

void drawCircle(b2Vec2 center,float r,float angle)


{
const int PRECISION=60;
glColor3f(1,1,1);
glPushMatrix();
glTranslatef(center.x*M2P,center.y*M2P,0);
glRotatef(angle*180.0/M_PI,0,0,1);

glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, textureID);
glBegin(GL_TRIANGLE_FAN);
glVertex2f(0,0);
for (float i=0.0; i<360.0; i+=360.0/PRECISION)
{

float radian = i * (M_PI/180.0f);

float xcos = (float)cos(radian);


float ysin = (float)sin(radian);
float x = (xcos * r)*M2P;
float y = (ysin * r)*M2P;
float tx = xcos * 0.5 + 0.5;
float ty = ysin * 0.5 + 0.5;

glTexCoord2f(tx, ty);
glVertex2f(x, y);
}
glEnd();
glPopMatrix();
}

void drawSquare(b2Vec2 points[],b2Vec2 center,float angle)


{
glColor3f(1,1,1);
glPushMatrix();
glTranslatef(center.x*M2P,center.y*M2P,0);
glRotatef(angle*180.0/M_PI,0,0,1);
glBegin(GL_QUADS);
for(int i=0;i<4;i++)

49
Date:14/02/2017 v1Box2D With Opengl(GLFW) and SOIL

glVertex2f(points[i].x*M2P,points[i].y*M2P);
glEnd();
glPopMatrix();
}

void display()
{
glClear(GL_COLOR_BUFFER_BIT);
glLoadIdentity();
b2Body* tmp=world->GetBodyList();
while(tmp){
if((tmp->GetFixtureList()->GetShape()->GetType())==0){
b2CircleShape* c= (b2CircleShape*)tmp-
>GetFixtureList()->GetShape();
drawCircle(tmp->GetWorldCenter(),0.4,tmp-
>GetAngle());
}else{
for(int i=0;i<4;i++)
points[i]=((b2PolygonShape*)tmp->GetFixtureList()-
>GetShape())->GetVertex(i);
drawSquare(points,tmp->GetWorldCenter(),tmp-
>GetAngle());
}
tmp=tmp->GetNext();
}
}

void init()
{
glMatrixMode(GL_PROJECTION);
glOrtho(0,WIDTH,HEIGHT,0,-1,1);
glMatrixMode(GL_MODELVIEW);
glClearColor(0,0,0,1);
world=new b2World(b2Vec2(0.0,9.8));
textureID=loadTextures("./images/11.jpg");
addRect(WIDTH/2,HEIGHT-50,WIDTH,20,true);
}

int main(int argc,char **argv)


{
glfwInit();
window=glfwCreateWindow(WIDTH,HEIGHT,"HELLO WORLD",NULL,NULL);
glfwMakeContextCurrent(window);
glViewport(0,0,WIDTH,HEIGHT);
glfwSetMouseButtonCallback(window,mouse_callback);

50
Date:14/02/2017 v1Box2D With Opengl(GLFW) and SOIL

init();
do{
display();
world->Step(1.0/30.0,8,3);
glfwSwapBuffers(window);
glfwPollEvents();
glfwSwapInterval(5);
}while(!glfwWindowShouldClose(window));
glfwTerminate();
return 0;
}

static void mouse_callback(GLFWwindow* window,int button,int


action,int mods)
{

if(button==GLFW_MOUSE_BUTTON_RIGHT && action==GLFW_PRESS)


{
double x;
double y;
glfwGetCursorPos(window,&x,&y);
addCircle(x,y,15,false);
}
}

51
Date:14/02/2017 v1Box2D With Opengl(GLFW) and SOIL

OUTPUT:

6) Box2D + Opengl + Circle + Polygon + Textures

52
Date:14/02/2017 v1Box2D With Opengl(GLFW) and SOIL

#include <iostream>
#include <Box2D/Box2D.h>
#include <GLFW/glfw3.h>
#include <SOIL.h>
#define M_PI 3.14159265358979323846
using namespace std;

bool dyn=true;
GLFWwindow* window;
GLfloat start;
const int WIDTH=640;
const int HEIGHT=480;
b2World* world;
b2Body* body;
b2Vec2 points[4];
const float M2P=60;
const float P2M=1/M2P;

static void mouse_callback(GLFWwindow* window,int button,int


action,int mods);
void key_callback(GLFWwindow* window, int key, int scancode, int
action, int mods);

GLuint textureID[2];

GLuint loadTextures(const char* filename) {


unsigned char* image;
int width, height;
//generating texture object and attaching to the target
glGenTextures(1, &textureID[2]);
glBindTexture(GL_TEXTURE_2D, textureID[2]);
//wrapping along the s and t axis of texture
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
//filtering so thet the resolution fits to the object
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
//load the img data
image = SOIL_load_image(filename, &width, &height, 0,
SOIL_LOAD_RGBA);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0,
GL_RGBA, GL_UNSIGNED_BYTE, image);
//free the image memory from GPL
SOIL_free_image_data(image);
//unbind the texture

53
Date:14/02/2017 v1Box2D With Opengl(GLFW) and SOIL

glBindTexture(GL_TEXTURE_2D, 0);
return textureID[2];
}

b2Body* addRect(int x,int y,int w,int h,bool dyns=true)


{
b2BodyDef bodyDef;
bodyDef.position.Set(x*P2M,y*P2M);
if(dyns){
dyn=false;
bodyDef.type=b2_staticBody;
}else{
dyn=true;
bodyDef.type=b2_dynamicBody;
}
body=world->CreateBody(&bodyDef);
b2PolygonShape shape;
shape.SetAsBox(P2M*w/2,P2M*h/2);
b2FixtureDef fixtureDef;
fixtureDef.shape=&shape;
fixtureDef.density=1.0;
fixtureDef.friction=0.0;//step-1 try giving 0.9 they dont fly
usually this is given
fixtureDef.restitution=0.8;//now it is like a ball it can bounce
body->CreateFixture(&fixtureDef);
return body;
}

b2Body* addCircle(int x,int y,int r,bool byns=true)


{
b2BodyDef bodyDef;
bodyDef.position.Set(x*P2M,y*P2M);
if(byns){
bodyDef.type=b2_staticBody;
}else{
bodyDef.type=b2_dynamicBody;

body=world->CreateBody(&bodyDef);
b2CircleShape shape;
shape.m_radius=r*P2M;
shape.m_p.Set(0,0);
b2FixtureDef fixtureDef;

54
Date:14/02/2017 v1Box2D With Opengl(GLFW) and SOIL

fixtureDef.shape=&shape;
fixtureDef.density=1.0;
fixtureDef.friction=0.0;
fixtureDef.restitution=0.8;
body->CreateFixture(&fixtureDef);
return body;
}

void drawCircle(b2Vec2 center,float r,float angle,GLuint textureID1)


{
const int PRECISION=60;
glColor3f(1,1,1);
glPushMatrix();
glTranslatef(center.x*M2P,center.y*M2P,0);
glRotatef(angle*180.0/M_PI,0,0,1);
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, textureID1);
glBegin(GL_TRIANGLE_FAN);
glVertex2f(0,0);
for (float i=0.0; i<360.0; i+=360.0/PRECISION)
{

float radian = i * (M_PI/180.0f);

float xcos = (float)cos(radian);


float ysin = (float)sin(radian);
float x = (xcos * r)*M2P;
float y = (ysin * r)*M2P;
float tx = xcos * 0.5 + 0.5;
float ty = ysin * 0.5 + 0.5;

glTexCoord2f(tx, ty);
glVertex2f(x, y);
}
glEnd();
glPopMatrix();
}

void drawSquare(b2Vec2 points[],b2Vec2 center,float angle,GLuint


textureID)
{
glColor3f(1,1,1);
glPushMatrix();
glTranslatef(center.x*M2P,center.y*M2P,0);

55
Date:14/02/2017 v1Box2D With Opengl(GLFW) and SOIL

glRotatef(angle*180.0/M_PI,0,0,1);

if(dyn){
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D,textureID);
glBegin(GL_QUADS);
//for(int i=0;i<4;i++)

glTexCoord2f(250/256,250/256);glVertex2f(points[0].x*M2P,points[0].y
*M2P);

glTexCoord2f(256/256,250/256);glVertex2f(points[1].x*M2P,points[1].y
*M2P);

glTexCoord2f(256/256,256/256);glVertex2f(points[2].x*M2P,points[2].y
*M2P);

glTexCoord2f(250/256,256/256);glVertex2f(points[3].x*M2P,points[3].y
*M2P);
glEnd();
//glDisable(GL_TEXTURE_2D);
}else{
glBegin(GL_QUADS);
for(int i=0;i<4;i++)
glVertex2f(points[i].x*M2P,points[i].y*M2P);
glEnd();
}

glPopMatrix();
}

b2Body* myRect;

void display()
{
glClear(GL_COLOR_BUFFER_BIT);
glLoadIdentity();
b2Body* tmp=world->GetBodyList();

while(tmp){
56
Date:14/02/2017 v1Box2D With Opengl(GLFW) and SOIL

if((tmp->GetFixtureList()->GetShape()->GetType())==0){
b2CircleShape* c= (b2CircleShape*)tmp-
>GetFixtureList()->GetShape();

//drawCircle(tmp->GetWorldCenter(),c-
>m_radius,tmp->GetAngle(),textureID[1]);
drawCircle(tmp->GetWorldCenter(),0.4,tmp-
>GetAngle(),textureID[1]);
}else{
for(int i=0;i<4;i++)
points[i]=((b2PolygonShape*)tmp->GetFixtureList()-
>GetShape())->GetVertex(i);

drawSquare(points,tmp->GetWorldCenter(),tmp-
>GetAngle(),textureID[0]);

}
tmp=tmp->GetNext();
}
}

void init()
{
glMatrixMode(GL_PROJECTION);
glOrtho(0,WIDTH,HEIGHT,0,-1,1);
glMatrixMode(GL_MODELVIEW);
glClearColor(0,0,0,1);
world=new b2World(b2Vec2(0.0,9.8));
textureID[0]=loadTextures("./images/1.jpg");
textureID[1]=loadTextures("./images/11.jpg");
addRect(WIDTH/2,HEIGHT-50,WIDTH,20,true);

int main(int argc,char **argv)


{
glfwInit();
window=glfwCreateWindow(WIDTH,HEIGHT,"HELLO WORLD",NULL,NULL);
glfwMakeContextCurrent(window);
glViewport(0,0,WIDTH,HEIGHT);
glfwSetMouseButtonCallback(window,mouse_callback);
glfwSetKeyCallback(window,key_callback);
init();

57
Date:14/02/2017 v1Box2D With Opengl(GLFW) and SOIL

do{
display();
world->Step(1.0/30.0,8,3);
glfwSwapBuffers(window);
glfwPollEvents();
glfwSwapInterval(3);
}while(!glfwWindowShouldClose(window));
glfwTerminate();
return 0;
}

void key_callback(GLFWwindow* window, int key, int scancode, int


action, int mods){
if(key== GLFW_KEY_SPACE && action == GLFW_PRESS){
double x;
double y;
glfwGetCursorPos(window,&x,&y);
addCircle(x,y,15,false);
b2Vec2 vel = myRect->GetLinearVelocity();
vel.y = 10;//upwards - don't change x velocity
myRect->SetLinearVelocity( vel );
//myRect->ApplyLinearImpulse(b2Vec2(10,0),myRect-
>GetWorldPoint(points[1]),false);
}
}

static void mouse_callback(GLFWwindow* window,int button,int


action,int mods)
{

if(button==GLFW_MOUSE_BUTTON_RIGHT && action==GLFW_PRESS)


{
double x;
double y;
glfwGetCursorPos(window,&x,&y);
addRect(x,y,40,40,false);
}
}

58
Date:14/02/2017 v1Box2D With Opengl(GLFW) and SOIL

7) Box2D + OpenGL + Circle Shape + Polygon Shape + Dynamic + Textures


#include <Windows.h>
#include <iostream>
#include <Box2D/Box2D.h>
#include <GLFW/glfw3.h>
#include <SOIL.h>
#define M_PI 3.14159265358979323846
using namespace std;

bool dyn=true;
GLFWwindow* window;
GLfloat start;
const int WIDTH=640;
const int HEIGHT=480;
b2World* world;
b2Body* body;
b2Vec2 points[4];
const float M2P=60;
const float P2M=1/M2P;

static void mouse_callback(GLFWwindow* window,int button,int


action,int mods);
static void key_callback(GLFWwindow* window, int key, int scancode,
int action, int mods);

GLuint textureID[2];

GLuint loadTextures(const char* filename) {


unsigned char* image;
int width, height;
//generating texture object and attaching to the target
glGenTextures(1, &textureID[2]);
glBindTexture(GL_TEXTURE_2D, textureID[2]);
//wrapping along the s and t axis of texture
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
//filtering so thet the resolution fits to the object
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
//load the img data
image = SOIL_load_image(filename, &width, &height, 0,
SOIL_LOAD_RGBA);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0,
GL_RGBA, GL_UNSIGNED_BYTE, image);

59
Date:14/02/2017 v1Box2D With Opengl(GLFW) and SOIL

//free the image memory from GPL


SOIL_free_image_data(image);
//unbind the texture
glBindTexture(GL_TEXTURE_2D, 0);
return textureID[2];
}

b2Body* addRect(int x,int y,int w,int h,bool dyns=true)


{
b2BodyDef bodyDef;
bodyDef.position.Set(x*P2M,y*P2M);
if(dyns){
dyn=false;
bodyDef.type=b2_staticBody;
}else{
dyn=true;
bodyDef.type=b2_dynamicBody;
}
body=world->CreateBody(&bodyDef);
b2PolygonShape shape;
shape.SetAsBox(P2M*w/2,P2M*h/2);
b2FixtureDef fixtureDef;
fixtureDef.shape=&shape;
fixtureDef.density=1.0;
fixtureDef.friction=0.0;//step-1 try giving 0.9 they dont fly
usually this is given
fixtureDef.restitution=0.8;//now it is like a ball it can bounce
body->CreateFixture(&fixtureDef);
return body;
}

b2Body* addCircle(int x,int y,int r,bool byns=true)


{
b2BodyDef bodyDef;
bodyDef.position.Set(x*P2M,y*P2M);
if(byns){
bodyDef.type=b2_staticBody;
}else{
bodyDef.type=b2_dynamicBody;
}
body=world->CreateBody(&bodyDef);
b2CircleShape shape;
shape.m_radius=r*P2M;
shape.m_p.Set(0,0);

60
Date:14/02/2017 v1Box2D With Opengl(GLFW) and SOIL

b2FixtureDef fixtureDef;
fixtureDef.shape=&shape;
fixtureDef.density=1.0;
fixtureDef.friction=0.0;
fixtureDef.restitution=0.8;
body->CreateFixture(&fixtureDef);
return body;
}

void drawCircle(b2Vec2 center,float r,float angle,GLuint textureID1)


{
const int PRECISION=60;
glColor3f(1,1,1);
glPushMatrix();
glTranslatef(center.x*M2P,center.y*M2P,0);
glRotatef(angle*180.0/M_PI,0,0,1);
/*glBegin(GL_TRIANGLE_FAN);
glVertex2f(0,0);
for(float i=0.0;i<=360.0;i+=360.0/PRECISION)
glVertex2f((cos(i*M_PI/180.0)*r)*M2P,(sin(i*M_PI/180.0)*r)*M2P);
glEnd();*/
//glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, textureID1);
glBegin(GL_TRIANGLE_FAN);
glVertex2f(0,0);
for (float i=0.0; i<360.0; i+=360.0/PRECISION)
{
float radian = i * (M_PI/180.0f);
float xcos = (float)cos(radian);
float ysin = (float)sin(radian);
float x = (xcos * r)*M2P;
float y = (ysin * r)*M2P;
float tx = xcos * 0.5 + 0.5;
float ty = ysin * 0.5 + 0.5;
glTexCoord2f(tx, ty);
glVertex2f(x, y);
}
glEnd();
//glDisable(GL_TEXTURE_2D);
glPopMatrix();
}

void drawSquare(b2Vec2 points[],b2Vec2 center,float angle,GLuint


textureID)
{

61
Date:14/02/2017 v1Box2D With Opengl(GLFW) and SOIL

glColor3f(1,1,1);
glPushMatrix();
glTranslatef(center.x*M2P,center.y*M2P,0);
glRotatef(angle*180.0/M_PI,0,0,1);
if(dyn){
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D,textureID);
glBegin(GL_QUADS);
//for(int i=0;i<4;i++)

glTexCoord2f(250/256,250/256);glVertex2f(points[0].x*M2P,points[0].y*M
2P);

glTexCoord2f(256/256,250/256);glVertex2f(points[1].x*M2P,points[1].y*M
2P);

glTexCoord2f(256/256,256/256);glVertex2f(points[2].x*M2P,points[2].y*M
2P);

glTexCoord2f(250/256,256/256);glVertex2f(points[3].x*M2P,points[3].y*M
2P);
glEnd();
//glDisable(GL_TEXTURE_2D);
}else{
glBegin(GL_QUADS);
for(int i=0;i<4;i++)
glVertex2f(points[i].x*M2P,points[i].y*M2P);
glEnd();
}

glPopMatrix();
}
b2Body* myRect;
void display()
{
glClear(GL_COLOR_BUFFER_BIT);
glLoadIdentity();
b2Body* tmp=world->GetBodyList();
while(tmp){
if((tmp->GetFixtureList()->GetShape()->GetType())==0){
b2CircleShape* c= (b2CircleShape*)tmp-
>GetFixtureList()->GetShape();
62
Date:14/02/2017 v1Box2D With Opengl(GLFW) and SOIL

//drawCircle(tmp->GetWorldCenter(),c-
>m_radius,tmp->GetAngle(),textureID[1]);
drawCircle(tmp->GetWorldCenter(),0.4,tmp-
>GetAngle(),textureID[1]);
}else{
for(int i=0;i<4;i++)
points[i]=((b2PolygonShape*)tmp->GetFixtureList()-
>GetShape())->GetVertex(i);
drawSquare(points,tmp->GetWorldCenter(),tmp-
>GetAngle(),textureID[0]);
}
tmp=tmp->GetNext();
}
}

void init()
{
glMatrixMode(GL_PROJECTION);
glOrtho(0,WIDTH,HEIGHT,0,-1,1);
glMatrixMode(GL_MODELVIEW);
glClearColor(0,0,0,1);
world=new b2World(b2Vec2(0.0,9.8));
textureID[0]=loadTextures("./images/1.jpg");
textureID[1]=loadTextures("./images/11.jpg");
addRect(WIDTH/2,HEIGHT-50,WIDTH,20,true);
myRect=addRect(150,300,50,50,false);
}

int main(int argc,char **argv)


{
glfwInit();
window=glfwCreateWindow(WIDTH,HEIGHT,"HELLO WORLD",NULL,NULL);
glfwMakeContextCurrent(window);
glViewport(0,0,WIDTH,HEIGHT);
glfwSetMouseButtonCallback(window,mouse_callback);
glfwSetKeyCallback(window,key_callback);
init();
do{
display();
world->Step(1.0/30.0,8,3);
glfwSwapBuffers(window);
glfwPollEvents();
glfwSwapInterval(3);
}while(!glfwWindowShouldClose(window));
glfwTerminate();

63
Date:14/02/2017 v1Box2D With Opengl(GLFW) and SOIL

return 0;
}

void key_callback(GLFWwindow* window, int key, int scancode, int


action, int mods){
if(key== GLFW_KEY_SPACE && action == GLFW_PRESS){
double x;
double y;
glfwGetCursorPos(window,&x,&y);
addCircle(x,y,15,false);

}
}

static void mouse_callback(GLFWwindow* window,int button,int


action,int mods)
{

if(button==GLFW_MOUSE_BUTTON_RIGHT && action==GLFW_PRESS)


{
double x;
double y;
glfwGetCursorPos(window,&x,&y);
addRect(x,y,40,40,false);
}
}

64
Date:14/02/2017 v1Box2D With Opengl(GLFW) and SOIL

OUTPUT:

8) Box2D + OpenGL + Edge Shape + Dynamic Body


#include <Box2D/Box2D.h>
65
Date:14/02/2017 v1Box2D With Opengl(GLFW) and SOIL

#include <glfw/glfw3.h>
#include <math.h>
#include <iostream>
using namespace std;
#define M_PI 3.14159265358979323846
GLFWwindow* window;
const int WIDTH=840;
const int HEIGHT=680;
const float WORLD_TO_BOX=0.01f;
const float BOX_TO_WORLD=100.0f;
b2World* world;
b2Body* body;
b2Vec2 points[4];
static void mouse_callback(GLFWwindow* window,int button,int
action,int mods);
static float ConvertToBox(float x){
return x*WORLD_TO_BOX;
}
static float ConvertToWorld(float x){
return x*BOX_TO_WORLD;
}
void MakeEdgeShape(b2Body* body,float len,b2BodyType bodyType,float
density,float restitution,float friction);
b2Body* addRect(int x,int y,int w,int h,bool dyns=true)
{
b2BodyDef bodyDef;
bodyDef.position.Set(ConvertToBox(x),ConvertToBox(y));
if(dyns)
bodyDef.type=b2_dynamicBody;
body=world->CreateBody(&bodyDef);
b2PolygonShape shape;
shape.SetAsBox(ConvertToBox(w/2),ConvertToBox(h/2));
b2FixtureDef fixtureDef;
fixtureDef.shape=&shape;
fixtureDef.density=1.0;
fixtureDef.friction=0.0;//step-1 try giving 0.9 they dont fly
usually this is given
fixtureDef.restitution=0.0;//now it is like a ball it can bounce
body->CreateFixture(&fixtureDef);
return body;
}

void drawSquare(b2Vec2 points[],b2Vec2 center,float angle)


{

66
Date:14/02/2017 v1Box2D With Opengl(GLFW) and SOIL

glColor3f(1,1,1);
glPushMatrix();

glTranslatef(ConvertToWorld(center.x),ConvertToWorld(center.y),0);
glRotatef(angle*180.0/M_PI,0,0,1);

glBegin(GL_QUADS);
for(int i=0;i<4;i++)

glVertex2f(ConvertToWorld(points[i].x),ConvertToWorld(points[i].y));
glEnd();

glPopMatrix();
}

b2Body* CreateEdgeBody(b2BodyType bodyType,float v1x,float v1y,float


v2x,float v2y)
{
b2BodyDef bodyDef;
bodyDef.type=bodyType;
float posX=(v1x + v2x)/2.0f;
float posY=(v1y + v2y)/2.0f;
float len=(float)sqrt((v1x-v2x)*(v1x-v2x)+(v1y-v2y)*(v1y-v2y));
float bx=ConvertToBox(posX);
float by=ConvertToBox(posY);
bodyDef.position.Set(bx,by);
bodyDef.angle=0;
body=world->CreateBody(&bodyDef);
MakeEdgeShape(body,len,bodyType,1,0,1);
body->SetTransform(b2Vec2(bx,by),atan2(v2y-v1y,v2x-v1x));
return body;
}
void MakeEdgeShape(b2Body* body,float len,b2BodyType bodyType,float
density,float restitution,float friction){
b2FixtureDef fixtureDef;
fixtureDef.density=density;
fixtureDef.restitution=restitution;
fixtureDef.friction=friction;
b2EdgeShape es;
float boxLen=ConvertToBox(len);
es.Set(b2Vec2(-boxLen/2.0f,0),b2Vec2(boxLen/2.0f,0));
//glBegin(GL_LINE);
67
Date:14/02/2017 v1Box2D With Opengl(GLFW) and SOIL

//glVertex2f(-boxLen/2.0f,boxLen/2.0f);
//glEnd();
fixtureDef.shape=&es;
body->CreateFixture(&fixtureDef);
}
void display()
{
glClear(GL_COLOR_BUFFER_BIT);
glLoadIdentity();
//edge = CreateEdgeBody(b2_staticBody,100,290,260,280);

b2Body* tmp=world->GetBodyList();

while(tmp){
if((tmp->GetFixtureList()->GetShape()->GetType())==1){
glBegin(GL_LINES);
glVertex3f(100.0f, 290.0f, 0.0f); // origin of the FIRST line
glVertex3f(260.0f, 280.0f, 0.0f); // ending point of the FIRST
line
glVertex3f(65.0,255.0,0.0);
glVertex3f(260.0,215.0,0.0);
glEnd( );
}
else{
for(int i=0;i<4;i++)
points[i]=((b2PolygonShape*)tmp->GetFixtureList()-
>GetShape())->GetVertex(i);

drawSquare(points,tmp->GetWorldCenter(),tmp->GetAngle());

}
tmp=tmp->GetNext();
}
//edge = CreateEdgeBody(b2_staticBody,330,280,180,250);
//edge = CreateEdgeBody(b2_staticBody,65,255,260,215);
//edge = CreateEdgeBody(b2_staticBody,400,240,170,170);
//edge = CreateEdgeBody(b2_staticBody,5,190,290,95);
//edge = CreateEdgeBody(b2_staticBody,290,95,290,70);
//edge = CreateEdgeBody(b2_staticBody,315,95,315,70);
//edge = CreateEdgeBody(b2_staticBody,290,70,315,70);
}
void init()
{

68
Date:14/02/2017 v1Box2D With Opengl(GLFW) and SOIL

b2Body* edge;
glMatrixMode(GL_PROJECTION);
glOrtho(0,WIDTH,HEIGHT,0,-1,1);
glMatrixMode(GL_MODELVIEW);
glClearColor(1,0,0,1);
world=new b2World(b2Vec2(0.0,9.8));
edge = CreateEdgeBody(b2_staticBody,100,290,260,280);
edge = CreateEdgeBody(b2_staticBody,65,255,260,215);
}
int main(int argc,char **argv)
{
glfwInit();
window=glfwCreateWindow(WIDTH,HEIGHT,"HELLO WORLD",NULL,NULL);
glfwMakeContextCurrent(window);
glViewport(0,0,WIDTH,HEIGHT);
glfwSetMouseButtonCallback(window,mouse_callback);
init();
do{
display();
world->Step(1.0/30.0,8,3);
glfwSwapBuffers(window);
glfwPollEvents();
glfwSwapInterval(5);
}while(!glfwWindowShouldClose(window));
glfwTerminate();
return 0;
}

static void mouse_callback(GLFWwindow* window,int button,int


action,int mods)
{
if(button==GLFW_MOUSE_BUTTON_RIGHT && action==GLFW_PRESS)
{
double x;
double y;
glfwGetCursorPos(window,&x,&y);
addRect(x,y,20,20,true);
}

69
Date:14/02/2017 v1Box2D With Opengl(GLFW) and SOIL

OUTPUT:

9) Box2D + OpenGL + Drawing Static Walls + Dynamic Body + velocity


#include <Box2D/Box2D.h>
#include <glfw/glfw3.h>
#include <math.h>

70
Date:14/02/2017 v1Box2D With Opengl(GLFW) and SOIL

#include <iostream>
using namespace std;
#define M_PI 3.14159265358979323846
GLFWwindow* window;
const int WIDTH=840;
const int HEIGHT=680;
const float WORLD_TO_BOX=0.01f;
const float BOX_TO_WORLD=100.0f;
const int M2P=10;
const int P2M=1/M2P;
b2World* world;
b2Body* body;
b2Vec2 points[4];
enum _moveState {
MS_STOP,
MS_LEFT,
MS_RIGHT,
};
_moveState moveState;
void key_callback(GLFWwindow* window, int key, int scancode, int
action, int mods);
void addRect()
{

b2BodyDef myBodyDef;
myBodyDef.type = b2_dynamicBody;

//shape definition
b2PolygonShape polygonShape;
polygonShape.SetAsBox(1, 1); //a 2x2 rectangle

//fixture definition
b2FixtureDef myFixtureDef;
myFixtureDef.shape = &polygonShape;
myFixtureDef.density = 1;

//create dynamic body


myBodyDef.position.Set(40, 25);
body = world->CreateBody(&myBodyDef);
body->CreateFixture(&myFixtureDef);

//a static body


myBodyDef.type = b2_staticBody;
myBodyDef.position.Set(0, 0);
b2Body* staticBody = world->CreateBody(&myBodyDef);

71
Date:14/02/2017 v1Box2D With Opengl(GLFW) and SOIL

//add four walls to the static body


polygonShape.SetAsBox( 1, 20, b2Vec2(60, 40), 0);//right wall
staticBody->CreateFixture(&myFixtureDef);
polygonShape.SetAsBox( 20, 1, b2Vec2(40, 20), 0);//ceiling
staticBody->CreateFixture(&myFixtureDef);
polygonShape.SetAsBox( 20, 1, b2Vec2(40, 60), 0);//grond wall
staticBody->CreateFixture(&myFixtureDef);
polygonShape.SetAsBox( 1, 20, b2Vec2(20, 40), 0);//left wall
staticBody->CreateFixture(&myFixtureDef);
moveState = MS_STOP;
}
void drawSquare(b2Vec2 points[],b2Vec2 center,float angle)
{
glColor3f(1,1,1);
glPushMatrix();
glTranslatef(center.x*M2P,center.y*M2P,0);
glRotatef(angle*180.0/M_PI,0,0,1);

glBegin(GL_QUADS);
for(int i=0;i<4;i++)
glVertex2f(points[i].x*M2P,points[i].y*M2P);
glEnd();

glPopMatrix();
}
void display()
{
glClear(GL_COLOR_BUFFER_BIT);
glLoadIdentity();
b2Body* tmp=world->GetBodyList();

while(tmp){
if(tmp->GetType()==0)
{
for (b2Fixture *f = tmp->GetFixtureList(); f; f=f->GetNext()){
for(int i=0;i<4;i++){
points[i]=((b2PolygonShape *)f->GetShape())-
>GetVertex(i);
cout<<"points of"<<" "<<i<<"polygon"<<"
"<<points[i].x<<" "<<points[i].y<<endl;
}

72
Date:14/02/2017 v1Box2D With Opengl(GLFW) and SOIL

drawSquare(points,tmp->GetWorldCenter(),tmp->GetAngle());

}
}else{
for(int i=0;i<4;i++)
points[i]=((b2PolygonShape *)tmp->GetFixtureList()-
>GetShape())->GetVertex(i);
drawSquare(points,tmp->GetWorldCenter(),tmp-
>GetAngle());
}
tmp=tmp->GetNext();
}

}
void init()
{
glMatrixMode(GL_PROJECTION);
glOrtho(0,WIDTH,HEIGHT,0,-1,1);
glMatrixMode(GL_MODELVIEW);
glClearColor(0,0,0,1);
world=new b2World(b2Vec2(0.0,9.8));
addRect();
}
int main()
{
glfwInit();
window=glfwCreateWindow(WIDTH,HEIGHT,"Hello world",NULL,NULL);
glfwMakeContextCurrent(window);
glViewport(0,0,WIDTH,HEIGHT);
glfwSetKeyCallback(window,key_callback);
init();

do{
display();
world->Step(1.0/30.0,8,3);
glfwSwapBuffers(window);
glfwPollEvents();
glfwSwapInterval(5);
}while(!glfwWindowShouldClose(window));
glfwTerminate();
return 0;
}

void key_callback(GLFWwindow* window, int key, int scancode, int


action, int mods){

73
Date:14/02/2017 v1Box2D With Opengl(GLFW) and SOIL

if(key==GLFW_KEY_Q && action==GLFW_PRESS)


{
moveState = MS_LEFT;
}
else if(key==GLFW_KEY_W && action==GLFW_PRESS)
{
moveState = MS_STOP;
}
else if(key==GLFW_KEY_E && action==GLFW_PRESS)
{
moveState = MS_RIGHT;
}

b2Vec2 vel = body->GetLinearVelocity();


float force = 0;
switch ( moveState )
{
case MS_LEFT: if ( vel.x > -5 ) force = -50; break;
case MS_STOP: force = vel.x * -10; break;
case MS_RIGHT: if ( vel.x < 5 ) force = 50; break;
}
body->ApplyForce( b2Vec2(force,0), body->GetWorldCenter(),true );
}

OUTPUT:

74
Date:14/02/2017 v1Box2D With Opengl(GLFW) and SOIL

10)Box2D + OpenGL + Contact Listener

#include <iostream>

75
Date:14/02/2017 v1Box2D With Opengl(GLFW) and SOIL

#include <GLFW/glfw3.h>
#include <Box2D/Box2D.h>
#define M_PI 3.14159265358979323846
using namespace std;
GLFWwindow* window;
const int WIDTH=640;
const int HEIGHT=480;
b2World* world;
b2Body* body;
b2Vec2 points[4];
const float M2P=60;
const float P2M=1/M2P;
bool destroy=false;
static void mouse_callback(GLFWwindow* window,int button,int
action,int mods);
class myListener:public b2ContactListener
{
void BeginContact(b2Contact* contact);
void EndContact(b2Contact* contact);
void PostSolve(b2Contact* contact,const b2ContactImpulse*
impulse);
void PreSolve(b2Contact* contact,const b2Manifold* oldmanifold);
};
void myListener::BeginContact(b2Contact* contact)
{
b2Body* one=contact->GetFixtureA()->GetBody();
b2Body* two=contact->GetFixtureB()->GetBody();
destroy=true;
cout<<"Begin Contact"<<endl;
}
void myListener::EndContact(b2Contact* contact)
{
cout<<"End Contact"<<endl;
}
void myListener::PostSolve(b2Contact* contact,const b2ContactImpulse*
impulse)
{
cout<<"Post solve"<<endl;
}
void myListener::PreSolve(b2Contact* contact,const b2Manifold*
oldmanifold)
{
cout<<"Pre solve"<<endl;
}
myListener listener;

76
Date:14/02/2017 v1Box2D With Opengl(GLFW) and SOIL

b2Body* addRect(int x,int y,int w,int h,bool dyns=true)


{
b2BodyDef bodyDef;
bodyDef.position.Set(x*P2M,y*P2M);
if(dyns){
bodyDef.type=b2_staticBody;
}
else{
bodyDef.type=b2_dynamicBody;
}
body=world->CreateBody(&bodyDef);
b2PolygonShape shape;
shape.SetAsBox(w/2*P2M,h/2*P2M);
b2FixtureDef fixtureDef;
fixtureDef.shape=&shape;
fixtureDef.density=1.0;
body->CreateFixture(&fixtureDef);
return body;
}
void drawSquare(b2Vec2 points[],b2Vec2 center,float angle)
{
glColor3f(1,1,1);
glPushMatrix();
glTranslatef(center.x*M2P,center.y*M2P,0);
glRotatef(angle*180.0/M_PI,0,0,1);

glBegin(GL_QUADS);
for(int i=0;i<4;i++)
glVertex2f(points[i].x*M2P,points[i].y*M2P);
glEnd();

glPopMatrix();
}
void display()
{
glClear(GL_COLOR_BUFFER_BIT);
glLoadIdentity();
if(destroy){
world->DestroyBody(body);
destroy=false;
}
b2Body* tmp=world->GetBodyList();
while(tmp){
for(int i=0;i<4;i++)

77
Date:14/02/2017 v1Box2D With Opengl(GLFW) and SOIL

points[i]=((b2PolygonShape *)tmp->GetFixtureList()->GetShape())-
>GetVertex(i);
drawSquare(points,tmp->GetWorldCenter(),tmp->GetAngle());
tmp=tmp->GetNext();
}

}
void init()
{
glMatrixMode(GL_PROJECTION);
glOrtho(0,WIDTH,HEIGHT,0,-1,1);
glMatrixMode(GL_MODELVIEW);
glClearColor(0,0,0,1);
world=new b2World(b2Vec2(0.0,9.8));
world->SetContactListener(&listener);
addRect(WIDTH/2,HEIGHT-50,WIDTH,30,true);
}
int main()
{
glfwInit();
window=glfwCreateWindow(WIDTH,HEIGHT,"Hello world",NULL,NULL);
glfwMakeContextCurrent(window);
glViewport(0,0,WIDTH,HEIGHT);
glfwSetMouseButtonCallback(window,mouse_callback);
init();
do{
display();
world->Step(1.0/30.0,8,3);
glfwSwapBuffers(window);
glfwPollEvents();
glfwSwapInterval(5);
}while(!glfwWindowShouldClose(window));
glfwTerminate();
return 0;
}

static void mouse_callback(GLFWwindow* window,int button,int


action,int mods)
{
if(button==GLFW_MOUSE_BUTTON_RIGHT && action==GLFW_PRESS)
{

double x;
double y;
glfwGetCursorPos(window,&x,&y);

78
Date:14/02/2017 v1Box2D With Opengl(GLFW) and SOIL

addRect(x,y,50,50,false);
}
}

OUTPUT:

Before Collision the console windows Displays nothing

After Collision of the Dynamic body with the Static Body check the console window its pops
up some message typed using the cout and also the dynamic body disappears what happens
because we have destroyed the body see in display() function where we have destroyed the
body world->DestroyBody(Body) and also coding in Begin Contact
79
Date:14/02/2017 v1Box2D With Opengl(GLFW) and SOIL

Box2D + OpenGL + Revolute Joints

#include <Box2D/Box2D.h>
#include <glfw/glfw3.h>
#define M_PI 3.141592653
GLFWwindow* window;
const int WIDTH=640;
80
Date:14/02/2017 v1Box2D With Opengl(GLFW) and SOIL

const int HEIGHT=480;


const float M2P=60;
const float P2M=1/M2P;
b2World* world;
b2Body *body,*sta1,*sta2;
b2Vec2 points[4];

static void mouse_callback(GLFWwindow* window,int button,int action,int mods);


b2Body* addRect(int x,int y,int w,int h,bool dyns=true)
{
b2BodyDef bodyDef;
bodyDef.position.Set(x*P2M,y*P2M);
if(dyns){
bodyDef.type=b2_staticBody;
}
else{
bodyDef.type=b2_dynamicBody;
}
body=world->CreateBody(&bodyDef);
b2PolygonShape shape;
shape.SetAsBox(w/2*P2M,h/2*P2M);
b2FixtureDef fixtureDef;
fixtureDef.shape=&shape;
fixtureDef.density=1.0;
body->CreateFixture(&fixtureDef);
return body;
}
void CreateBridge(b2Body* sta1,b2Body* sta2,int w,int h)
{
b2Vec2 pos1=M2P*(sta1->GetWorldCenter()+(((b2PolygonShape*)sta1->GetFixtureList()-
>GetShape())->GetVertex(1)));
b2Vec2 pos2=M2P*(sta2->GetWorldCenter()+(((b2PolygonShape*)sta2->GetFixtureList()-
>GetShape())->GetVertex(0)));
int num=(pos2.x-pos1.x)/w;
b2RevoluteJointDef jointDef;
//b2Joint* joint;
jointDef.bodyA=sta1;
//jointDef.bodyB=sta2;
//jointDef.collideConnected=true;
b2Body *prev,*cur;
prev=addRect(pos1.x+(w/2),pos1.y,w,h,false);
jointDef.bodyB=prev;
jointDef.localAnchorA.Set(((b2PolygonShape*)sta1->GetFixtureList()->GetShape())-
>GetVertex(1).x,0);
jointDef.localAnchorB.Set(-w/2*P2M,0);
world->CreateJoint(&jointDef);
//return world;
for(int i=0;i<num-2;i++)
{
cur=addRect(pos1.x+i*w,pos1.y,w,h,false);
jointDef.bodyA=prev;
jointDef.bodyB=cur;
jointDef.localAnchorA.Set(w/2*P2M,0);
jointDef.localAnchorB.Set(-w/2*P2M,0);
world->CreateJoint(&jointDef);
prev=cur;
}

81
Date:14/02/2017 v1Box2D With Opengl(GLFW) and SOIL

jointDef.bodyA=prev;
jointDef.bodyB=sta2;
jointDef.localAnchorA.Set(w/2*P2M,0);
jointDef.localAnchorB.Set(((b2PolygonShape*)sta2->GetFixtureList()->GetShape())-
>GetVertex(0).x,0);
world->CreateJoint(&jointDef);
}

void drawSquare(b2Vec2 points[],b2Vec2 center,float angle)


{
glColor3f(1,1,1);
glPushMatrix();
glTranslatef(center.x*M2P,center.y*M2P,0);
glRotatef(angle*180.0/M_PI,0,0,1);

glBegin(GL_QUADS);
for(int i=0;i<4;i++)
glVertex2f(points[i].x*M2P,points[i].y*M2P);
glEnd();

glPopMatrix();
}
void display()
{
glClear(GL_COLOR_BUFFER_BIT);
glLoadIdentity();
b2Body* tmp=world->GetBodyList();
while(tmp){
for(int i=0;i<4;i++)
points[i]=((b2PolygonShape *)tmp->GetFixtureList()->GetShape())->GetVertex(i);
drawSquare(points,tmp->GetWorldCenter(),tmp->GetAngle());
tmp=tmp->GetNext();
}

}
void init()
{
glMatrixMode(GL_PROJECTION);
glOrtho(0,WIDTH,HEIGHT,0,-1,1);
glMatrixMode(GL_MODELVIEW);
glClearColor(0,0,0,1);
world=new b2World(b2Vec2(0.0f,9.8f));
addRect(WIDTH/2,HEIGHT-50,WIDTH,30,true);
sta1=addRect(100,300,50,10,true);
sta2=addRect(600,300,50,10,true);
CreateBridge(sta1,sta2,30,10);

int main()
{
glfwInit();
window=glfwCreateWindow(WIDTH,HEIGHT,"Hello world",NULL,NULL);
glfwMakeContextCurrent(window);
glViewport(0,0,WIDTH,HEIGHT);
glfwSetMouseButtonCallback(window,mouse_callback);
init();

82
Date:14/02/2017 v1Box2D With Opengl(GLFW) and SOIL

do{
display();
world->Step(1.0f/30.0f,8,3);
glfwSwapBuffers(window);
glfwPollEvents();
glfwSwapInterval(5);
}while(!glfwWindowShouldClose(window));
glfwTerminate();
return 0;
}

static void mouse_callback(GLFWwindow* window,int button,int action,int mods)


{
if(button==GLFW_MOUSE_BUTTON_RIGHT && action==GLFW_PRESS)
{

double x;
double y;
glfwGetCursorPos(window,&x,&y);
addRect(x,y,50,50,false);
}
}

In principle, all physics engines are simply a direct application of Newton's


second law of motion:

acceleration = force / mass

83
Date:14/02/2017 v1Box2D With Opengl(GLFW) and SOIL

By integrating acceleration over time, you get velocity. By integrating velocity, you
get the positions of the object in space. The integrals are performed numerically,
using something like Runge-Kutta.

The main complications arise from:

Handling rotational motion


Handling impulse events, such as collisions and explosions
Detecting collisions at the extreme ends of velocity. At high speeds, objects
can end up penetrating or even passing through each other before the
collision is detected. At low speeds, it is a challenge to robustly handle one
object resting on another without jittering or sliding around
Kinematic linkages, where objects are partially constrained to each other
(like a hinge or slider)
Calculating the forces and torques for complex objects such as cars or
aircraft
Doing all this efficiently in real time for hundreds or thousands of objects
A good place to start is to simulate a single particle bouncing around in a 2-
dimensional box under the influence of gravity. Then, give the particle a radius,
add more of them, and calculate collisions between them. At that point, you have
a basic physics engine that's enough to use for simple games.

Box2D + OpenGL + Camera using Debug Draw

Include.h

#include <GL/glew.h>
#include <GLFW/glfw3.h>
#include <Box2D/Box2D.h>
#include <iostream>
84
Date:14/02/2017 v1Box2D With Opengl(GLFW) and SOIL

#include <GL/glut.h>

using namespace std;

PerspectiveView.h
#include "Include.h"
#define PI 3.14
#define PIdiv180 (PI/180)

struct P_3D_Vector
{
GLfloat x, y, z;
};

struct P_2D_Vector
{
GLfloat x, y;
};

P_3D_Vector View_3D_Vector(GLfloat x, GLfloat y, GLfloat z);

class Perspective_View
{
private:
P_3D_Vector View_Direction;
P_3D_Vector Right_Vector;
P_3D_Vector Up_Vector;
P_3D_Vector Position;

GLfloat Rotated_X, Rotated_Y, Rotated_Z;

public:
Perspective_View();
void Render_View(void);

void Look(P_3D_Vector Direction);


void Rotate_X(GLfloat Angle); // To rotate the camera along the X-axis
void Rotate_Y(GLfloat Angle); // To rotate the camera along the Y-axis
void Rotate_Z(GLfloat Angle); // To rotate the camera along the Z-axis

void Look_Z(GLfloat Distance); // To translate the camera along the X-axis


void Look_Y(GLfloat Distance); // To translate the camera along the Y-axis
void Look_X(GLfloat Distance); // To translate the camera along the Z-axis
};

Physics.h

#ifndef PHYSICS
#define PHYSICS

#include "Include.h"

class DebugDraw : public b2Draw { // b2Draw has all the virtual functions that we need to
override here
public:

85
Date:14/02/2017 v1Box2D With Opengl(GLFW) and SOIL

// We won't be implementing all of these, but if we don't declare them here we'll get
an override error
void DrawSolidPolygon(const b2Vec2* vertices, int32 vertexCount, const b2Color&
color);
void DrawPolygon(const b2Vec2* vertices, int32 vertexCount, const b2Color& color);
void DrawCircle(const b2Vec2& center, float32 radius, const b2Color& color);
void DrawSolidCircle(const b2Vec2& center, float32 radius, const b2Vec2& axis, const
b2Color& color);
void DrawSegment(const b2Vec2& p1, const b2Vec2& p2, const b2Color& color);
void DrawTransform(const b2Transform& xf);
void DrawPoint(const b2Vec2 &p,float32 size,const b2Color &c){}
};

#endif

PerspectiveView.cpp

#include "Include.h"
#include "PerspectiveView.h"

#define SQR(P) (P*P)

#define NULL_VECTOR View_3D_Vector(0.0f, 0.0f, 0.0f)

P_3D_Vector View_3D_Vector(GLfloat x, GLfloat y, GLfloat z)


{
P_3D_Vector Temporary;

Temporary.x = x;
Temporary.y = y;
Temporary.z = z;

return Temporary;
}

GLfloat Get_View_3D_Vector_Length(P_3D_Vector *V)


{
return (GLfloat)(sqrt(SQR(V->x) + SQR(V->y) + SQR(V->z)));
}

P_3D_Vector Normalize_3D_Vector(P_3D_Vector V)
{
P_3D_Vector Resultant;
float l = Get_View_3D_Vector_Length(&V);

if(l == 0.0f)
return NULL_VECTOR;

Resultant.x = V.x / l;
Resultant.y = V.y / l;
Resultant.z = V.z / l;

return Resultant;
}

P_3D_Vector operator+ (P_3D_Vector V, P_3D_Vector U)


{

86
Date:14/02/2017 v1Box2D With Opengl(GLFW) and SOIL

P_3D_Vector Resultant;

Resultant.x = V.x + U.x;


Resultant.y = V.y + U.y;
Resultant.z = V.z + U.z;

return Resultant;
}

P_3D_Vector operator- (P_3D_Vector V, P_3D_Vector U)


{
P_3D_Vector Resultant;

Resultant.x = V.x - U.x;


Resultant.y = V.y - U.y;
Resultant.z = V.z - U.z;

return Resultant;
}

P_3D_Vector operator* (P_3D_Vector V, float R)


{
P_3D_Vector Resultant;

Resultant.x = V.x * R;
Resultant.y = V.y * R;
Resultant.z = V.z * R;

return Resultant;
}

P_3D_Vector Cross_Product (P_3D_Vector *U, P_3D_Vector *V)


{
P_3D_Vector Resultant_Vector;

Resultant_Vector.x = U->y * V->z - U->z * V->y;


Resultant_Vector.y = U->z * V->x - U->x * V->z;
Resultant_Vector.z = U->x * V->y - U->y * V->x;

return Resultant_Vector;
}

float operator* (P_3D_Vector V, P_3D_Vector U)


{
return V.x * U.x + V.y * U.y + V.z * U.z;
}

Perspective_View::Perspective_View()
{
Position = View_3D_Vector(0.0f, 0.0f, 0.0f); // Initializing the position of camera
View_Direction = View_3D_Vector(0.0f, 0.0f, -1.0f); // Initializing which direction
to look at
Right_Vector = View_3D_Vector(1.0f, 0.0f, 0.0); // Initializing the rightward
direction vector
Up_Vector = View_3D_Vector(0.0f, 1.0f, 0.0f); // Initializing the upward direction
vector

87
Date:14/02/2017 v1Box2D With Opengl(GLFW) and SOIL

Rotated_X = Rotated_Y = Rotated_Z = 0.0f; // Initial Angle


}

void Perspective_View::Look(P_3D_Vector Direction) // Translating the camera in all


dimensions
{
Position = Position + Direction; // Incrementing position of camera when translated
}

void Perspective_View::Rotate_X(GLfloat Angle) // Rotating along the X-axis


{
Rotated_X += Angle; // Incrementing change in X-axis angle

View_Direction = Normalize_3D_Vector(View_Direction * (GLfloat)cos(Angle * PIdiv180)


+ Up_Vector * (GLfloat)sin(Angle * PIdiv180)); // Updating viewing direction

Up_Vector = Cross_Product(&View_Direction, &Right_Vector) * -1; // Updating upward


direction vector
}

void Perspective_View::Rotate_Y(GLfloat Angle) // Rotating along the Y-axis


{
Rotated_Y += Angle; // Incrementing change in Y-axis angle

View_Direction = Normalize_3D_Vector(View_Direction * (GLfloat)cos(Angle * PIdiv180)


+ Right_Vector * (GLfloat)sin(Angle * PIdiv180)); // Updating viewing direction

Right_Vector = Cross_Product(&View_Direction, &Up_Vector); // Updating rightward


direction vector
}

void Perspective_View::Rotate_Z(GLfloat Angle) // Rotating along the Z-axis


{
Rotated_Z += Angle; // Incrementing change in Z-axis angle

Right_Vector = Normalize_3D_Vector(Right_Vector * (GLfloat)cos(Angle * PIdiv180) +


Up_Vector * (GLfloat)sin(Angle * PIdiv180)); // Updating rightward direction vector

Up_Vector = Cross_Product(&View_Direction, &Right_Vector) * -1; // Updating upward


direction vector
}

void Perspective_View::Render_View(void) // Rendering the camera view


{
P_3D_Vector View_Point = Position + View_Direction; // Incrementing center with
change in movement
//cout<<"Inside perspective"<<endl;
gluLookAt(Position.x, Position.y, Position.z, View_Point.x, View_Point.y,
View_Point.z, Up_Vector.x, Up_Vector.y, Up_Vector.z); // gluLookAt() used here to see the
game space
}

void Perspective_View::Look_Z(GLfloat Distance) // Translating the camera along Z-axis


{
Position = (View_Direction * -Distance); // Updating position
}

88
Date:14/02/2017 v1Box2D With Opengl(GLFW) and SOIL

void Perspective_View::Look_X(GLfloat Distance) // Translating the camera along Z-axis


{
Position = (Right_Vector * Distance); // Updating position

void Perspective_View::Look_Y(GLfloat Distance) // Translating the camera along Z-axis


{
Position = (Up_Vector * Distance); // Updating position
cout<<Position.x<<" "<<Position.y<<" "<<Position.z<<endl;
}

Physics.cpp

#include "Physics.h"

void DebugDraw::DrawPolygon(const b2Vec2* vertices,int32 vertexCount,const b2Color&


color)
{
glColor3f(color.r,color.g,color.b);
glBegin(GL_LINE_LOOP);
for(int32 i=0;i<vertexCount;++i)
{
glVertex2f(vertices[i].x,vertices[i].y);
}
glEnd();
}
void DebugDraw::DrawSolidPolygon(const b2Vec2* vertices, int32 vertexCount, const
b2Color& color) {
// Standard OpenGL rendering stuff
glColor4f(color.r, color.g, color.b, color.a);
glBegin(GL_POLYGON);
for (int i = 0; i < vertexCount; i++) {
glVertex2f(vertices[i].x, vertices[i].y);
}
glEnd();
}

/*void DebugDraw::DrawSolidCircle(const b2Vec2& center, float32 radius, const b2Vec2&


axis, const b2Color& color) {
const float32 k_segments = 16.0f;
const int vertexCount = 16;
const float32 k_increment = 2.0f * b2_pi / k_segments;
float32 theta = 0.0f;

glColor4f(color.r, color.g, color.b, 0.5f);


glBegin(GL_TRIANGLE_FAN);
GLfloat glVertices[vertexCount * 2];
for (int32 i = 0; i < k_segments; ++i) {
b2Vec2 v = center + radius * b2Vec2(cos(theta), sin(theta));
glVertex2f(v.x, v.y);
theta += k_increment;
}
glEnd();

89
Date:14/02/2017 v1Box2D With Opengl(GLFW) and SOIL

DrawSegment(center, center + radius*axis, color);


}*/
void DebugDraw::DrawSolidCircle(const b2Vec2& center,float32 radius,const b2Vec2&
axis,const b2Color& color)
{
const float32 k_segments=16.0f;
const float32 k_increment=2.0f*b2_pi/k_segments;
float32 theta=0.0f;
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(int32 i=0;i<k_segments;i++)
{
b2Vec2 v=center+radius*b2Vec2(cosf(theta),sinf(theta));
glVertex2f(v.x,v.y);
theta+=k_increment;
}
glEnd();
glDisable(GL_BLEND);
theta=0.0f;
glColor4f(color.r,color.g,color.b,1.0f);
glBegin(GL_LINE_LOOP);
for(int32 i=0;i<k_segments;++i)
{
b2Vec2 v=center+radius*b2Vec2(cosf(theta),sinf(theta));
glVertex2f(v.x,v.y);
theta+=k_increment;
}
glEnd();
b2Vec2 p = center + radius*axis;
glBegin(GL_LINES);
glVertex2f(p.x,p.y);
glEnd();
}
void DebugDraw::DrawCircle(const b2Vec2& center,float32 radius,const b2Color& color){
const float32 k_segments=16.0f;
const float32 k_increment=2.0f*b2_pi/k_segments;
float32 theta=0.0f;
glColor3f(color.r,color.g,color.b);
glBegin(GL_LINE_LOOP);
for(int32 i=0;i<k_segments;i++)
{
b2Vec2 v=center+radius*b2Vec2(cosf(theta),sinf(theta));
glVertex2f(v.x,v.y);
theta+=k_increment;
}
glEnd();
}
void DebugDraw::DrawSegment(const b2Vec2& p1, const b2Vec2& p2, const b2Color& color) {
glColor4f(color.r, color.g, color.b, 1);
glBegin(GL_LINES);
glVertex2f(p1.x, p1.y);
glVertex2f(p2.x, p2.y);
glEnd();
}

90
Date:14/02/2017 v1Box2D With Opengl(GLFW) and SOIL

// We just need to have these to prevent override errors, they don't actually do anything
right now
//void DebugDraw::DrawPolygon(const b2Vec2* vertices, int32 vertexCount, const b2Color&
color) {}
//void DebugDraw::DrawCircle(const b2Vec2& center, float32 radius, const b2Color& color)
{}
//void DebugDraw::DrawSolidCircle(const b2Vec2& center, float32 radius, const b2Vec2&
axis, const b2Color& color) {}
//void DebugDraw::DrawSegment(const b2Vec2& p1, const b2Vec2& p2, const b2Color& color)
{}
void DebugDraw::DrawTransform(const b2Transform& xf) {
b2Vec2 p1=xf.p,p2;
const float32 k_axisscale=0.4f;
p2=p1+k_axisscale * xf.q.GetXAxis();
DrawSegment(p1,p2,b2Color(1,0,0));
p2=p1+k_axisscale*xf.q.GetYAxis();
DrawSegment(p1,p2,b2Color(0,1,0));
}

MainWindow.cpp

#include "Include.h"
#include "PerspectiveView.h"
#include "Physics.h"
GLFWwindow* window;
const int WIDTH=840;
const int HEIGHT=680;
bool No_Key_Pressed = true;
bool Facing_Right = true;
Perspective_View Current_View;
static float x=0.0,y=0.0;
void key_callback(GLFWwindow* window,int key,int scancode,int action,int mods);
int main()
{
glfwInit();
window=glfwCreateWindow(WIDTH,HEIGHT,"HELLO WORLD",NULL,NULL);
glfwMakeContextCurrent(window);
glViewport(0,0,WIDTH,HEIGHT);
glfwSetKeyCallback(window,key_callback);
// Declaring an object for the Perspective_View class

b2Vec2 World_Gravity(0.0f, 9.8f); // Defining gravity


b2World *Game_World = new b2World(World_Gravity); // Creating the Box2D world
DebugDraw debugDraw;
Game_World->SetDebugDraw(&debugDraw); // YOU NEED THIS SO BOX2D KNOWS WHERE TO
LOOK FOR DRAWING CALLBACKS
debugDraw.SetFlags(b2Draw::e_shapeBit);

{
b2BodyDef gbDef;
gbDef.type =b2_kinematicBody;
gbDef.position.Set(0.0f, 0.0f);
b2Body* groundBody = Game_World->CreateBody(&gbDef);

91
Date:14/02/2017 v1Box2D With Opengl(GLFW) and SOIL

b2PolygonShape gbShape;
gbShape.SetAsBox(0.2f, 0.2f);

groundBody->CreateFixture(&gbShape, 0.0f);
}

while(!glfwWindowShouldClose(window))
{
glClear(GL_COLOR_BUFFER_BIT);
Game_World->Step(1/60, 8, 3); // Iterating the game world in Box2D
Game_World->DrawDebugData();

//glClearColor(0.0f, 0.0f, 0.0f, 1.0f);

Current_View.Render_View();
// Here, we are calling the render function containing the gluLookAt()
glfwSwapBuffers(window);
glfwPollEvents();
glfwSwapInterval(5);
}

glfwTerminate();
return EXIT_SUCCESS;
}
void key_callback(GLFWwindow* window,int key,int scancode,int action,int mods)
{

if(key==GLFW_KEY_E && action==GLFW_PRESS)


{
No_Key_Pressed = false;
Facing_Right = true;
cout<<"E PRessed"<<endl;
}

if(key==GLFW_KEY_W && action==GLFW_PRESS)


{
No_Key_Pressed = false;
Facing_Right = false;
cout<<"W Pressed"<<endl;
}

if(No_Key_Pressed)
{
Current_View.Look_X(0.0); // Don't move
}

else
{
if(Facing_Right)
{
Current_View.Look_X(y+0.2); // Move Right
Current_View.Rotate_X(0.30);
Current_View.Rotate_Y(0.30);
}

92
Date:14/02/2017 v1Box2D With Opengl(GLFW) and SOIL

else
{
Current_View.Look_X(y-0.2); // Move Left
Current_View.Rotate_X(-0.30);
}

}
No_Key_Pressed = true;

Box2D + OpenGL + car simulation


#include <Windows.h>
#include <iostream>
#include <Box2D/Box2D.h>
#include <GLFW/glfw3.h>
#include <vector>
#define DEGTORAD 0.0174532925199432957f
#define RADTODEG 57.295779513082320876f
#define M_PI 3.14159265358979323846
using namespace std;
b2Body* wheel[4];
bool dyn=true;
float inputRotation=10.0f;
GLFWwindow* window;
GLfloat start;
const int WIDTH=640;
const int HEIGHT=480;

93
Date:14/02/2017 v1Box2D With Opengl(GLFW) and SOIL

b2World* world;
b2Body* body;
b2Vec2 points[4];
const float M2P=60;
const float P2M=1/M2P;
b2RevoluteJointDef jointDef;
b2Joint *fljoint,*frjoint;
float m_maxForwardSpeed=100; // 100;
float m_maxBackwardSpeed=-20; // -20;
float m_maxDriveForce=150; // 150;
vector<b2Body*> vec;
b2Body *myRect,*right_wheel,*left_wheel,*left_rear_wheel,*right_rear_wheel;
enum {
TDC_LEFT = 0x1,
TDC_RIGHT = 0x2,
TDC_UP = 0x4,
TDC_DOWN = 0x8
};
int m_controlState=0;
char key='\0';

static void key_callback(GLFWwindow* window, int key, int scancode, int action, int
mods);
void updateFriction(b2Body* m_body);
void updateDrive(int controlState,b2Body* m_body);
void updateTurn(int controlState,b2Body* m_body);
void update(int controlState);

b2Body* addRect(int x,int y,int w,int h,bool dyns=true)


{
b2BodyDef bodyDef;
bodyDef.position.Set(x*P2M,y*P2M);
if(dyns){
//dyn=false;
bodyDef.type=b2_staticBody;
}else{
//dyn=true;
bodyDef.type=b2_dynamicBody;
bodyDef.linearDamping = 1.0;
bodyDef.angularDamping = 1.0;
}
body=world->CreateBody(&bodyDef);
b2PolygonShape shape;
shape.SetAsBox(P2M*w/2,P2M*h/2);
b2FixtureDef fixtureDef;
fixtureDef.shape=&shape;
fixtureDef.density=1.0;
//fixtureDef.friction=0.8;//step-1 try giving 0.9 they dont fly usually this is
given
//fixtureDef.restitution=0.0;//now it is like a ball it can bounce
body->CreateFixture(&fixtureDef);
return body;
}

94
Date:14/02/2017 v1Box2D With Opengl(GLFW) and SOIL

void drawSquare(b2Vec2 points[],b2Vec2 center,float angle)


{
glColor3f(1,0,0);
glPushMatrix();
//the translate and rotate are used so that the movement will be realistic these
matrices must pushed onto stack and popped properly
glTranslatef(center.x*M2P,center.y*M2P,0);
glRotatef(angle*180.0/M_PI,0,0,1);

glBegin(GL_QUADS);
for(int i=0;i<4;i++)
glVertex2f(points[i].x*M2P,points[i].y*M2P);
//while going from box2d to opengl convert meters to pixel box2d works in
MKS(meters-kilograms-seconds) units
glEnd();

glPopMatrix();
}
void CreateBridge(b2Body* main,vector<b2Body*> vec)
{

jointDef.bodyA=main;

jointDef.enableLimit = true;
jointDef.lowerAngle = 0;
jointDef.upperAngle = 0;
jointDef.enableMotor = true;//default property is false
jointDef.maxMotorTorque = 100;
//if your are sure about the position of the objects then dont need
to set "localAnchor" position directly
//call "Initialize" method and send the arguments
//"frjoints" and "fljoints" are used for the left wheel and
backwheel whose "lowerAngle" and "upperAngle"
//will be set later using "setLimits"
jointDef.bodyB=vec[0];
jointDef.Initialize(main,vec[0],vec[0]->GetWorldCenter());

frjoint = (b2RevoluteJoint*)world->CreateJoint(&jointDef);

jointDef.bodyB=wheel[1];
jointDef.Initialize(main,vec[1],vec[1]->GetWorldCenter());

fljoint = (b2RevoluteJoint*)world->CreateJoint(&jointDef);

jointDef.bodyB=wheel[2];
jointDef.Initialize(main,vec[2],vec[2]->GetWorldCenter());

frjoint = (b2RevoluteJoint*)world->CreateJoint(&jointDef);

jointDef.bodyB=vec[3];
jointDef.Initialize(main,vec[3],vec[3]->GetWorldCenter());

fljoint = (b2RevoluteJoint*)world->CreateJoint(&jointDef);

95
Date:14/02/2017 v1Box2D With Opengl(GLFW) and SOIL

void display()
{
glClear(GL_COLOR_BUFFER_BIT);
glLoadIdentity();
b2Body* tmp=world->GetBodyList();
while(tmp){

for(int i=0;i<4;i++)
points[i]=((b2PolygonShape*)tmp->GetFixtureList()->GetShape())-
>GetVertex(i);
drawSquare(points,tmp->GetWorldCenter(),tmp->GetAngle());
tmp=tmp->GetNext();
}
for(int i=0;i<vec.size();i++){
updateFriction(vec[i]);
updateDrive(m_controlState,vec[i]);
updateTurn(m_controlState,vec[i]);
}
update(m_controlState);
}
void update(int controlState) {
for (int i = 0; i < vec.size(); i++)
updateFriction(vec[i]);
for (int i = 0; i < vec.size(); i++)
updateDrive(controlState,vec[i]);
float lockAngle = 35 * DEGTORAD;
float turnSpeedPerSec = 160 * DEGTORAD;//from lock to lock in 0.5 sec
float turnPerTimeStep = turnSpeedPerSec / 60.0f;
float desiredAngle = 0;
switch ( controlState & (TDC_LEFT|TDC_RIGHT) ) {
case TDC_LEFT: desiredAngle = lockAngle; break;
case TDC_RIGHT: desiredAngle = -lockAngle; break;
default: ;//nothing
}
float angleNow = ((b2RevoluteJoint*)fljoint)->GetJointAngle();//this line
is used to get the current joint angle
//if referenceAngle of joint = 0 then GetjointAngle returns 45 degrees
//if referenceAngle of joint = 123 then GetjointAngle returns 168 degrees
float angleToTurn = desiredAngle - angleNow;
angleToTurn = b2Clamp( angleToTurn, -turnPerTimeStep, turnPerTimeStep );
float newAngle = angleNow + angleToTurn;
((b2RevoluteJoint*)fljoint)->SetLimits(newAngle,newAngle);//setLimits sets
the lowerAngle and upperAngle of the joints this one for left wheel
((b2RevoluteJoint*)frjoint)->SetLimits(newAngle,newAngle);//this one for
right wheel
}
b2Vec2 getLateralVelocity(b2Body* m_body) {
b2Vec2 currentRightNormal = m_body->GetWorldVector( b2Vec2(1,0) );//b2Vec2(1,0)
gives the current direction thats to the right
return b2Dot( currentRightNormal, m_body->GetLinearVelocity() ) *
currentRightNormal;//canceling the lateral velocity
}
b2Vec2 getForwardVelocity(b2Body* m_body) {
b2Vec2 currentRightNormal = m_body->GetWorldVector( b2Vec2(0,1) );

96
Date:14/02/2017 v1Box2D With Opengl(GLFW) and SOIL

return b2Dot( currentRightNormal, m_body->GetLinearVelocity() ) *


currentRightNormal;
}
void updateFriction(b2Body* m_body) {
//lateral linear velocity
float maxLateralImpulse = 2.5f;
b2Vec2 impulse = left_wheel->GetMass() * -getLateralVelocity(m_body);
if ( impulse.Length() > maxLateralImpulse )
impulse *= maxLateralImpulse / impulse.Length();
m_body->ApplyLinearImpulse( impulse, m_body->GetWorldCenter(),true );

//angular velocity
m_body->ApplyAngularImpulse( 0.1f * m_body->GetInertia() * -m_body-
>GetAngularVelocity(),true );

//forward linear velocity


b2Vec2 currentForwardNormal = getForwardVelocity(m_body);
float currentForwardSpeed = currentForwardNormal.Normalize();
float dragForceMagnitude = -2 * currentForwardSpeed;
m_body->ApplyForce( dragForceMagnitude * currentForwardNormal, m_body-
>GetWorldCenter(),true );
}
void updateTurn(int controlState,b2Body* m_body) {
float desiredTorque = 0;
switch ( controlState & (TDC_LEFT|TDC_RIGHT) ) {
case TDC_LEFT: desiredTorque = 15; break;
case TDC_RIGHT: desiredTorque = -15; break;
default: ;//nothing
}
m_body->ApplyTorque( desiredTorque,true );
}
void updateDrive(int controlState,b2Body* m_body) {
//find desired speed
float desiredSpeed = 0;
switch ( controlState & (TDC_UP|TDC_DOWN) ) {
case TDC_UP: desiredSpeed = m_maxForwardSpeed; break;
case TDC_DOWN: desiredSpeed = m_maxBackwardSpeed; break;
default: return;//do nothing
}
cout<<controlState<<endl;
//find current speed in forward direction
b2Vec2 currentForwardNormal = m_body->GetWorldVector( b2Vec2(0,1) );
float currentSpeed = b2Dot( getForwardVelocity(m_body), currentForwardNormal );

//apply necessary force


float force = 0;
if ( desiredSpeed > currentSpeed )
force = m_maxDriveForce;
else if ( desiredSpeed < currentSpeed )
force = -m_maxDriveForce;
else
return;
m_body->ApplyForce( force * currentForwardNormal, m_body->GetWorldCenter(),true );
}
void init()
{
glMatrixMode(GL_PROJECTION);

97
Date:14/02/2017 v1Box2D With Opengl(GLFW) and SOIL

glOrtho(0,WIDTH,HEIGHT,0,-1,1);
glMatrixMode(GL_MODELVIEW);
glClearColor(0,0,0,1);
world=new b2World(b2Vec2(0.0,0.0));
addRect(WIDTH/2,HEIGHT-50,WIDTH,20,true);//ground creation

myRect=addRect(190,300,50,90,false);// drawing a rectangle at location 190,330


with width=50 and height=90 body type dynamic
right_wheel=addRect(220,330,8,18,false);//draw right wheel at 190+w/2=215 so x=220
and y=330 so that it will not be at the end some what above the edge since it is tire
left_wheel=addRect(160,330,8,18,false);// same applies to here also
//----------------|------------------------------|---------------//
//----------------|------------------------------|---------------//
//------(160,270)-|------------------------------|-(220,270)-----//
//----------------|------------------------------|---------------//
//----------------|------------------------------|---------------//
//----------------|------------------------------|---------------//
//----------------|------------------------------|---------------//
//----------------|------------------------------|---------------//
//----------------|------------------------------|---------------//
//----------------|------------------------------|---------------//
//------(160,330)-|------------------------------|-(220,330)-----//
//----------------|------------------------------|---------------//
//----------------|------------------------------|---------------//
wheel[0]=right_wheel;
vec.push_back(wheel[0]);

wheel[1]=left_wheel;
vec.push_back(wheel[1]);

right_rear_wheel=addRect(220,270,8,18,false);
left_rear_wheel=addRect(160,270,8,18,false);
wheel[2]=right_rear_wheel;
vec.push_back(wheel[2]);

wheel[3]=left_rear_wheel;
vec.push_back(wheel[3]);

CreateBridge(myRect,vec);

int main(int argc,char **argv)


{
glfwInit();
window=glfwCreateWindow(WIDTH,HEIGHT,"HELLO WORLD",NULL,NULL);
glfwMakeContextCurrent(window);
glViewport(0,0,WIDTH,HEIGHT);
glfwSetKeyCallback(window,key_callback);
init();
do{
glfwPollEvents();
display();
world->Step(1.0/80.0,8,3);
glfwSwapBuffers(window);
glfwSwapInterval(5);
}while(!glfwWindowShouldClose(window));

98
Date:14/02/2017 v1Box2D With Opengl(GLFW) and SOIL

glfwTerminate();
return 0;
}

void key_callback(GLFWwindow* window, int key, int scancode, int action, int mods){
if(key== GLFW_KEY_RIGHT && action == GLFW_PRESS){
key='a';
}

if(key==GLFW_KEY_LEFT && action == GLFW_PRESS){


key='d';

}
if(key==GLFW_KEY_DOWN && action == GLFW_PRESS){
key='w';

}
if(key==GLFW_KEY_UP && action == GLFW_PRESS){
key='s';

}
if(key== GLFW_KEY_RIGHT && action == GLFW_RELEASE){
key='t';
}

if(key==GLFW_KEY_LEFT && action == GLFW_RELEASE){


key='f';

}
if(key==GLFW_KEY_DOWN && action == GLFW_RELEASE){
key='g';

}
if(key==GLFW_KEY_UP && action == GLFW_RELEASE){
key='h';

}
switch (key) {
case 'a' : m_controlState |= TDC_LEFT; break;
case 'd' : m_controlState |= TDC_RIGHT; break;
case 'w' : m_controlState |= TDC_UP; break;
case 's' : m_controlState |= TDC_DOWN; break;

}
switch (key) {
case 't' : m_controlState &= ~TDC_LEFT; break;
case 'f' : m_controlState &= ~TDC_RIGHT; break;
case 'g' : m_controlState &= ~TDC_UP; break;
case 'h' : m_controlState &= ~TDC_DOWN; break;
}

99