|
|
|
|
/******************************************************************************
|
|
|
|
|
* File - physicsScene.h
|
|
|
|
|
* Author - Joey Pollack
|
|
|
|
|
* Date - 2021/10/27 (y/m/d)
|
|
|
|
|
* Mod Date - 2021/10/27 (y/m/d)
|
|
|
|
|
* Description - Displays a scene that tests the Box2D physics system
|
|
|
|
|
******************************************************************************/
|
|
|
|
|
|
|
|
|
|
#include "physicsScene.h"
|
|
|
|
|
#include <box2d/box2d.h>
|
|
|
|
|
#include <core/core.h>
|
|
|
|
|
#include <graphics/igraphics.h>
|
|
|
|
|
#include <utils/logger.h>
|
|
|
|
|
|
|
|
|
|
namespace lunarium
|
|
|
|
|
{
|
|
|
|
|
PhysicsScene::PhysicsScene(uint32_t logCat)
|
|
|
|
|
: BaseScene(logCat), mb2World(nullptr)
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
PhysicsScene::~PhysicsScene()
|
|
|
|
|
{
|
|
|
|
|
delete mb2World;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void PhysicsScene::OnLoad()
|
|
|
|
|
{
|
|
|
|
|
Logger::Log(mLogCat, LogLevel::INFO, "Running Simple Render Test Scene");
|
|
|
|
|
|
|
|
|
|
// Comments from the docs: https://box2d.org/documentation/md__d_1__git_hub_box2d_docs_hello.html
|
|
|
|
|
|
|
|
|
|
// Every Box2D program begins with the creation of a b2World object.
|
|
|
|
|
// b2World is the physics hub that manages memory, objects, and simulation.
|
|
|
|
|
// You can allocate the physics world on the stack, heap, or data section.
|
|
|
|
|
|
|
|
|
|
// It is easy to create a Box2D world. First, we define the gravity vector.
|
|
|
|
|
b2Vec2 gravity(0.0f, 10.0f);
|
|
|
|
|
mb2World = new b2World(gravity);
|
|
|
|
|
|
|
|
|
|
/* CREATING THE GOUND BOX
|
|
|
|
|
Bodies are built using the following steps:
|
|
|
|
|
|
|
|
|
|
1) Define a body with position, damping, etc.
|
|
|
|
|
2) Use the world object to create the body.
|
|
|
|
|
3) Define fixtures with a shape, friction, density, etc.
|
|
|
|
|
4) Create fixtures on the body.
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
// For step 1 we create the ground body. For this we need a body definition.
|
|
|
|
|
// With the body definition we specify the initial position of the ground body.
|
|
|
|
|
b2BodyDef groundBodyDef;
|
|
|
|
|
groundBodyDef.position.Set(60.0f, 50.0f);
|
|
|
|
|
|
|
|
|
|
// For step 2 the body definition is passed to the world object to create the ground body.
|
|
|
|
|
// The world object does not keep a reference to the body definition. Bodies are static by default.
|
|
|
|
|
// Static bodies don't collide with other static bodies and are immovable.
|
|
|
|
|
mpGroundBody = mb2World->CreateBody(&groundBodyDef);
|
|
|
|
|
|
|
|
|
|
// For step 3 we create a ground polygon. We use the SetAsBox shortcut to form the ground polygon
|
|
|
|
|
// into a box shape, with the box centered on the origin of the parent body.
|
|
|
|
|
// MORE INFO ABOUT SetAsBox() On the web page (see above)
|
|
|
|
|
mpGroundBox = new b2PolygonShape;
|
|
|
|
|
mpGroundBox->SetAsBox(20.0f, 5.0f);
|
|
|
|
|
|
|
|
|
|
// We finish the ground body in step 4 by creating the shape fixture. For this step we have a shortcut.
|
|
|
|
|
// We do not have a need to alter the default fixture material properties, so we can pass the shape directly
|
|
|
|
|
// to the body without creating a fixture definition.
|
|
|
|
|
mpGroundBody->CreateFixture(mpGroundBox, 0.0f);
|
|
|
|
|
|
|
|
|
|
// Create a second ground body
|
|
|
|
|
groundBodyDef.position.Set(20.0f, 70.0f);
|
|
|
|
|
mpGroundBody2 = mb2World->CreateBody(&groundBodyDef);
|
|
|
|
|
mpGroundBox2 = new b2PolygonShape;
|
|
|
|
|
mpGroundBox2->SetAsBox(30.0f, 5.0f);
|
|
|
|
|
mpGroundBody2->CreateFixture(mpGroundBox2, 0.0f);
|
|
|
|
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
// So now we have a ground body. We can use the same technique to create a dynamic body.
|
|
|
|
|
// The main difference, besides dimensions, is that we must establish the dynamic body's mass properties.
|
|
|
|
|
|
|
|
|
|
// First we create the body using CreateBody. By default bodies are static, so we should set the b2BodyType
|
|
|
|
|
// at construction time to make the body dynamic.
|
|
|
|
|
b2BodyDef bodyDef;
|
|
|
|
|
bodyDef.type = b2_dynamicBody; // Caution: You must set the body type to b2_dynamicBody if you want the body to move in response to forces.
|
|
|
|
|
bodyDef.position.Set(39.0f, 4.0f);
|
|
|
|
|
mpDynamicBody = mb2World->CreateBody(&bodyDef);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Next we create and attach a polygon shape using a fixture definition. First we create a box shape:
|
|
|
|
|
mpDynamicBox = new b2PolygonShape;
|
|
|
|
|
mpDynamicBox->SetAsBox(1.0f, 1.0f);
|
|
|
|
|
|
|
|
|
|
// Next we create a fixture definition using the box. Notice that we set density to 1.
|
|
|
|
|
// The default density is zero. Also, the friction on the shape is set to 0.3.
|
|
|
|
|
// Caution: A dynamic body should have at least one fixture with a non-zero density. Otherwise you will get strange behavior.
|
|
|
|
|
b2FixtureDef fixtureDef;
|
|
|
|
|
fixtureDef.shape = mpDynamicBox;
|
|
|
|
|
fixtureDef.density = 1.0f;
|
|
|
|
|
fixtureDef.friction = 0.3f;
|
|
|
|
|
|
|
|
|
|
// Using the fixture definition we can now create the fixture. This automatically updates the mass of the body.
|
|
|
|
|
// You can add as many fixtures as you like to a body. Each one contributes to the total mass.
|
|
|
|
|
mpDynamicBody->CreateFixture(&fixtureDef);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void PhysicsScene::OnTick(double delta)
|
|
|
|
|
{
|
|
|
|
|
// TODO: Implement the "hello world" Box2D example and
|
|
|
|
|
// use a scaling factor of 10 to render it
|
|
|
|
|
float timeStep = 1.0f / 60.0f;
|
|
|
|
|
int32 velocityIterations = 6;
|
|
|
|
|
int32 positionIterations = 2;
|
|
|
|
|
|
|
|
|
|
mb2World->Step(timeStep, velocityIterations, positionIterations);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void PhysicsScene::OnRender(IGraphics* g)
|
|
|
|
|
{
|
|
|
|
|
// This scaling is a little backwards.
|
|
|
|
|
// Info about scaling factor:
|
|
|
|
|
// https://box2d.org/documentation/md__d_1__git_hub_box2d_docs__f_a_q.html#autotoc_md139
|
|
|
|
|
float scaleFactor = 10.0f;
|
|
|
|
|
|
|
|
|
|
b2AABB groundbox;
|
|
|
|
|
mpGroundBox->ComputeAABB(&groundbox, mpGroundBody->GetTransform(), 0);
|
|
|
|
|
|
|
|
|
|
Rectangle groundRect(groundbox);
|
|
|
|
|
g->DrawFilledBox(groundRect.LeftTop() * scaleFactor,
|
|
|
|
|
groundRect.RightBottom() * scaleFactor,
|
|
|
|
|
Color(0.0f, 1.0f, 0.0f, 1.0f));
|
|
|
|
|
|
|
|
|
|
b2AABB groundbox2;
|
|
|
|
|
mpGroundBox2->ComputeAABB(&groundbox2, mpGroundBody2->GetTransform(), 0);
|
|
|
|
|
|
|
|
|
|
Rectangle groundRect2(groundbox2);
|
|
|
|
|
g->DrawFilledBox(groundRect2.LeftTop() * scaleFactor,
|
|
|
|
|
groundRect2.RightBottom() * scaleFactor,
|
|
|
|
|
Color(0.0f, 1.0f, 0.0f, 1.0f));
|
|
|
|
|
|
|
|
|
|
b2AABB dynbox;
|
|
|
|
|
b2Transform transform;
|
|
|
|
|
transform.p = mpDynamicBody->GetTransform().p;
|
|
|
|
|
transform.q = b2Rot(0.0f);
|
|
|
|
|
mpDynamicBox->ComputeAABB(&dynbox, transform, 0);
|
|
|
|
|
Rectangle dynRect(dynbox);
|
|
|
|
|
float angle = mpDynamicBody->GetAngle();
|
|
|
|
|
g->DrawFilledBox(dynRect.LeftTop() * scaleFactor,
|
|
|
|
|
dynRect.RightBottom() * scaleFactor,
|
|
|
|
|
Color(0.0f, 0.0f, 1.0f, 1.0f), angle);
|
|
|
|
|
|
|
|
|
|
// Debug info
|
|
|
|
|
char str[256] = { 0 };
|
|
|
|
|
sprintf(str, "GroundBox: (%f, %f) (%f, %f)",
|
|
|
|
|
groundRect.LeftTop().x * scaleFactor, groundRect.LeftTop().y * scaleFactor,
|
|
|
|
|
groundRect.RightBottom().x * scaleFactor, groundRect.RightBottom().y * scaleFactor);
|
|
|
|
|
g->DrawString(str, Rectangle(10.0f, 10.0f, 800.0f, 30.0f), Color(0.75f, 0.85f, 0.5f, 1.0f), 0.4f);
|
|
|
|
|
|
|
|
|
|
sprintf(str, "GroundBox Half Size: (%f, %f)", groundRect.Width, groundRect.Height);
|
|
|
|
|
g->DrawString(str, Rectangle(10.0f, 35.0f, 800.0f, 30.0f), Color(0.75f, 0.85f, 0.5f, 1.0f), 0.4f);
|
|
|
|
|
|
|
|
|
|
sprintf(str, "DynBox: (%f, %f) (%f, %f), Angle: %f",
|
|
|
|
|
dynRect.LeftTop().x * scaleFactor, dynRect.LeftTop().y * scaleFactor,
|
|
|
|
|
dynRect.RightBottom().x * scaleFactor, dynRect.RightBottom().y * scaleFactor, angle);
|
|
|
|
|
g->DrawString(str, Rectangle(10.0f, 60.0f, 1000.0f, 100.0f), Color(0.75f, 0.85f, 0.5f, 1.0f), 0.4);
|
|
|
|
|
|
|
|
|
|
int ww, wh;
|
|
|
|
|
Core::MainWindow().GetFramebufferSize(&ww, &wh);
|
|
|
|
|
for (int i = 0; i < wh; i += 10)
|
|
|
|
|
{
|
|
|
|
|
sprintf(str, "%d", i);
|
|
|
|
|
g->DrawString(str, Rectangle(ww - 35.0f, i, 4.0f, 5.0f), Color(1.0f, 0.0f, 0.0f, 1.0f), 0.25f);
|
|
|
|
|
g->DrawBox(Rectangle(ww - 10.0f, i, 10.0f, 2.0f), Color(1.0f, 0.0f, 0.0f, 1.0f), 1.0f);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for (int i = 0; i < ww; i += 25)
|
|
|
|
|
{
|
|
|
|
|
sprintf(str, "%d", i);
|
|
|
|
|
g->DrawString(str, Rectangle(i, wh - 20.0f, 4.0f, 5.0f), Color(1.0f, 0.0f, 0.0f, 1.0f), 0.25f);
|
|
|
|
|
g->DrawBox(Rectangle(i, wh - 5.0f, 2.0f, 5.0f), Color(1.0f, 0.0f, 0.0f, 1.0f), 1.0f);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|