Sei sulla pagina 1di 80

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 54
Shape + Dynamic + Textures

8 Box2D + OpenGL + Edge Shape + Dynamic Body 61


9 Box2D + OpenGL + Drawing Static Walls + 66
Dynamic Body + velocity
10 Box2D + OpenGL + Contact Listener 71

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.

Setting up the library:


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

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).
Now, come back to the Visual Studio where we had our browsing window left.
10
Date:14/02/2017 v1Box2D With Opengl(GLFW) and SOIL

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)

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

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());
tmp=tmp->GetNext();
27
Date:14/02/2017 v1Box2D With Opengl(GLFW) and SOIL

}
}
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.

To make the simulation realistic we add one more function inside our game loop
30
Date:14/02/2017 v1Box2D With Opengl(GLFW) and SOIL

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];

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


mods);
31
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();
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();
}

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

}
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);
}
}

OUTPUT

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

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.

Use soil

34
Date:14/02/2017 v1Box2D With Opengl(GLFW) and 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.

Now go to drawSquare function

35
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{
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);
b2FixtureDef fixtureDef;
fixtureDef.shape=&shape;
42
Date:14/02/2017 v1Box2D With Opengl(GLFW) and SOIL

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()
{
glClear(GL_COLOR_BUFFER_BIT);
glLoadIdentity();
43
Date:14/02/2017 v1Box2D With Opengl(GLFW) and SOIL

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{
display();
world->Step(1.0/30.0,8,3);
glfwSwapBuffers(window);
44
Date:14/02/2017 v1Box2D With Opengl(GLFW) and SOIL

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);
47
Date:14/02/2017 v1Box2D With Opengl(GLFW) and SOIL

return textureID;
}

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++)
glVertex2f(points[i].x*M2P,points[i].y*M2P);
49
Date:14/02/2017 v1Box2D With Opengl(GLFW) and SOIL

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);
init();
50
Date:14/02/2017 v1Box2D With Opengl(GLFW) and SOIL

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


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

#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
glBindTexture(GL_TEXTURE_2D, 0);
53
Date:14/02/2017 v1Box2D With Opengl(GLFW) and SOIL

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;
fixtureDef.shape=&shape;
fixtureDef.density=1.0;
54
Date:14/02/2017 v1Box2D With Opengl(GLFW) and SOIL

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);
glRotatef(angle*180.0/M_PI,0,0,1);

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

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*M2
P);

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

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

glTexCoord2f(250/256,256/256);glVertex2f(points[3].x*M2P,points[3].y*M2
P);
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();

56
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);

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();
57
Date:14/02/2017 v1Box2D With Opengl(GLFW) and SOIL

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);
}
}

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


Dynamic + Textures

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

#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);
//free the image memory from GPL
59
Date:14/02/2017 v1Box2D With Opengl(GLFW) and SOIL

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);
b2FixtureDef fixtureDef;
fixtureDef.shape=&shape;
60
Date:14/02/2017 v1Box2D With Opengl(GLFW) and SOIL

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)


{
glColor3f(1,1,1);
glPushMatrix();
glTranslatef(center.x*M2P,center.y*M2P,0);
glRotatef(angle*180.0/M_PI,0,0,1);
61
Date:14/02/2017 v1Box2D With Opengl(GLFW) and SOIL

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){
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);

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

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();
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;
63
Date:14/02/2017 v1Box2D With Opengl(GLFW) and SOIL

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);
}
}

OUTPUT:

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

8) Box2D + OpenGL + Edge Shape + Dynamic Body


#include <Box2D/Box2D.h>
#include <glfw/glfw3.h>
#include <math.h>
#include <iostream>
using namespace std;
#define M_PI 3.14159265358979323846
GLFWwindow* window;
65
Date:14/02/2017 v1Box2D With Opengl(GLFW) and SOIL

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)


{
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);
66
Date:14/02/2017 v1Box2D With Opengl(GLFW) and SOIL

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);
//glVertex2f(-boxLen/2.0f,boxLen/2.0f);
//glEnd();
fixtureDef.shape=&es;
body->CreateFixture(&fixtureDef);
}
void display()
{
glClear(GL_COLOR_BUFFER_BIT);
glLoadIdentity();
67
Date:14/02/2017 v1Box2D With Opengl(GLFW) and SOIL

//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()
{
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)
{
68
Date:14/02/2017 v1Box2D With Opengl(GLFW) and SOIL

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);
}

OUTPUT:

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

9) Box2D + OpenGL + Drawing Static Walls + Dynamic


Body + velocity
#include <Box2D/Box2D.h>
#include <glfw/glfw3.h>
#include <math.h>
#include <iostream>
using namespace std;
#define M_PI 3.14159265358979323846
70
Date:14/02/2017 v1Box2D With Opengl(GLFW) and SOIL

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);

//add four walls to the static body


polygonShape.SetAsBox( 1, 20, b2Vec2(60, 40), 0);//right wall
staticBody->CreateFixture(&myFixtureDef);
71
Date:14/02/2017 v1Box2D With Opengl(GLFW) and SOIL

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;
}
drawSquare(points,tmp->GetWorldCenter(),tmp->GetAngle());

}
}else{
for(int i=0;i<4;i++)

72
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));
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){
if(key==GLFW_KEY_Q && action==GLFW_PRESS)
{
moveState = MS_LEFT;
}
else if(key==GLFW_KEY_W && action==GLFW_PRESS)
{
73
Date:14/02/2017 v1Box2D With Opengl(GLFW) and SOIL

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>
#include <GLFW/glfw3.h>
75
Date:14/02/2017 v1Box2D With Opengl(GLFW) and SOIL

#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;
b2Body* addRect(int x,int y,int w,int h,bool dyns=true)
{
b2BodyDef bodyDef;
76
Date:14/02/2017 v1Box2D With Opengl(GLFW) and SOIL

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++)
points[i]=((b2PolygonShape *)tmp->GetFixtureList()->GetShape())-
>GetVertex(i);
drawSquare(points,tmp->GetWorldCenter(),tmp->GetAngle());
tmp=tmp->GetNext();
}
77
Date:14/02/2017 v1Box2D With Opengl(GLFW) and SOIL

}
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);
addRect(x,y,50,50,false);
}
}

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

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

80

Potrebbero piacerti anche