Beruflich Dokumente
Kultur Dokumente
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
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:
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.
click the Configure button once again (and red selection will turn white):
5
Date:14/02/2017 v1Box2D With Opengl(GLFW) and SOIL
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
choose your version of Visual Studio for C++ (I use Visual C++ Express 2010), and click OK
button.
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
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
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:
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
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.
16
Date:14/02/2017 v1Box2D With Opengl(GLFW) and SOIL
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 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.
20
Date:14/02/2017 v1Box2D With Opengl(GLFW) and SOIL
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
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.
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)
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
#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];
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
29
Date:14/02/2017 v1Box2D With Opengl(GLFW) and SOIL
if(dyns){
bodyDef.type=b2_staticBody;
}
else{
bodyDef.type=b2_dynamicBody;
}
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
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
#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
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;
}
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
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
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
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
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.
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
#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;
38
Date:14/02/2017 v1Box2D With Opengl(GLFW) and SOIL
//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;
}
OUTPUT:
40
Date:14/02/2017 v1Box2D With Opengl(GLFW) and SOIL
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
}
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;
}
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;
}
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();
}
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);
}
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;
}
OUTPUT:
45
Date:14/02/2017 v1Box2D With Opengl(GLFW) and SOIL
46
Date:14/02/2017 v1Box2D With Opengl(GLFW) and SOIL
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;
GLuint textureID;
47
Date:14/02/2017 v1Box2D With Opengl(GLFW) and SOIL
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;
}
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;
}
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)
{
glTexCoord2f(tx, ty);
glVertex2f(x, y);
}
glEnd();
glPopMatrix();
}
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);
}
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;
}
51
Date:14/02/2017 v1Box2D With Opengl(GLFW) and SOIL
OUTPUT:
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;
GLuint textureID[2];
53
Date:14/02/2017 v1Box2D With Opengl(GLFW) and SOIL
glBindTexture(GL_TEXTURE_2D, 0);
return textureID[2];
}
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;
}
glTexCoord2f(tx, ty);
glVertex2f(x, y);
}
glEnd();
glPopMatrix();
}
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);
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;
}
58
Date:14/02/2017 v1Box2D With Opengl(GLFW) and SOIL
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;
GLuint textureID[2];
59
Date:14/02/2017 v1Box2D With Opengl(GLFW) and SOIL
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;
}
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);
}
63
Date:14/02/2017 v1Box2D With Opengl(GLFW) and SOIL
return 0;
}
}
}
64
Date:14/02/2017 v1Box2D With Opengl(GLFW) and SOIL
OUTPUT:
#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;
}
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();
}
//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;
}
69
Date:14/02/2017 v1Box2D With Opengl(GLFW) and SOIL
OUTPUT:
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;
71
Date:14/02/2017 v1Box2D With Opengl(GLFW) and SOIL
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;
}
73
Date:14/02/2017 v1Box2D With Opengl(GLFW) and SOIL
OUTPUT:
74
Date:14/02/2017 v1Box2D With Opengl(GLFW) and SOIL
#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
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;
}
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:
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
#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
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);
}
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;
}
double x;
double y;
glfwGetCursorPos(window,&x,&y);
addRect(x,y,50,50,false);
}
}
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.
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>
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;
};
class Perspective_View
{
private:
P_3D_Vector View_Direction;
P_3D_Vector Right_Vector;
P_3D_Vector Up_Vector;
P_3D_Vector Position;
public:
Perspective_View();
void Render_View(void);
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"
Temporary.x = x;
Temporary.y = y;
Temporary.z = z;
return Temporary;
}
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;
}
86
Date:14/02/2017 v1Box2D With Opengl(GLFW) and SOIL
P_3D_Vector Resultant;
return Resultant;
}
return Resultant;
}
Resultant.x = V.x * R;
Resultant.y = V.y * R;
Resultant.z = V.z * R;
return Resultant;
}
return Resultant_Vector;
}
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
88
Date:14/02/2017 v1Box2D With Opengl(GLFW) and SOIL
Physics.cpp
#include "Physics.h"
89
Date:14/02/2017 v1Box2D With Opengl(GLFW) and SOIL
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
{
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();
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(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;
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);
94
Date:14/02/2017 v1Box2D With Opengl(GLFW) and SOIL
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
//angular velocity
m_body->ApplyAngularImpulse( 0.1f * m_body->GetInertia() * -m_body-
>GetAngularVelocity(),true );
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
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);
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_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_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