You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
lunarium_OLD/src/run_modes/tester/scenes/physicsScene.cpp

185 lines
8.2 KiB
C++

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