added the basic requiements for physics with box2d
This commit is contained in:
117
TSE_Core/src/BehaviourScripts/PhysicsObject.cpp
Normal file
117
TSE_Core/src/BehaviourScripts/PhysicsObject.cpp
Normal file
@@ -0,0 +1,117 @@
|
||||
#include "PhysicsObject.hpp"
|
||||
#include "MathF.hpp"
|
||||
#include "elements/Transformable.hpp"
|
||||
#include "elements/PhysicsEngine.hpp"
|
||||
|
||||
TSE::PhysicsObject::PhysicsObject(BodyType t, ColliderShape s, float d, float f, Vector3 cs)
|
||||
{
|
||||
type = t;
|
||||
shape = s;
|
||||
density = d;
|
||||
friction = f;
|
||||
collidersize = cs;
|
||||
}
|
||||
|
||||
TSE::PhysicsObject::~PhysicsObject()
|
||||
{
|
||||
PhysicsEngine::UnRegisterPhysicsObject(this);
|
||||
if(b2Body_IsValid(bodyId))
|
||||
b2DestroyBody(bodyId);
|
||||
}
|
||||
|
||||
void TSE::PhysicsObject::UpdatePosition()
|
||||
{
|
||||
b2Vec2 b2newPos = b2Body_GetPosition(bodyId);
|
||||
if(lastPos.x != b2newPos.x || lastPos.y != b2newPos.y)
|
||||
{
|
||||
Vector3 newPos(b2newPos.x, b2newPos.y, lastPos.z);
|
||||
lastPos = newPos;
|
||||
Vector3 delta = baseObject->GlobalToLocalPosition(newPos);
|
||||
baseObject->position = baseObject->position + delta;
|
||||
}
|
||||
float newRot = b2Rot_GetAngle(b2Body_GetRotation(bodyId));
|
||||
if(newRot != lastRot)
|
||||
{
|
||||
lastRot = newRot;
|
||||
Vector3 euler = baseObject->GetEuler();
|
||||
euler.z = Rad2Deg(newRot);
|
||||
}
|
||||
}
|
||||
|
||||
void TSE::PhysicsObject::OnUpdate()
|
||||
{
|
||||
Vector3 globalPos = baseObject->GetGlobalPosition();
|
||||
float rot = Deg2Rad(baseObject->GetEuler().z);
|
||||
if(globalPos != lastPos || rot != lastRot)
|
||||
{
|
||||
lastPos = globalPos;
|
||||
lastRot = rot;
|
||||
b2Vec2 pos;
|
||||
pos.x = globalPos.x;
|
||||
pos.y = globalPos.y;
|
||||
b2Body_SetTransform(bodyId, pos, b2MakeRot(rot));
|
||||
b2Body_SetAwake(bodyId, true);
|
||||
}
|
||||
}
|
||||
|
||||
void TSE::PhysicsObject::Start()
|
||||
{
|
||||
b2WorldId& wid = PhysicsEngine::GetWorldId();
|
||||
|
||||
b2BodyDef def = b2DefaultBodyDef();
|
||||
b2Vec2 pos;
|
||||
Vector3 globalPos = baseObject->GetGlobalPosition();
|
||||
pos.x = globalPos.x;
|
||||
pos.y = globalPos.y;
|
||||
def.position = pos;
|
||||
lastPos = globalPos;
|
||||
float rot = Deg2Rad(baseObject->GetEuler().z);
|
||||
def.rotation = b2MakeRot(rot);
|
||||
lastRot = rot;
|
||||
b2BodyType b2type;
|
||||
switch(type)
|
||||
{
|
||||
case BodyType::Dynamic:
|
||||
b2type = b2_dynamicBody;
|
||||
break;
|
||||
case BodyType::Static:
|
||||
b2type = b2_staticBody;
|
||||
break;
|
||||
}
|
||||
def.type = b2type;
|
||||
|
||||
bodyId = b2CreateBody(wid, &def);
|
||||
|
||||
b2ShapeDef shapeDef = b2DefaultShapeDef();
|
||||
shapeDef.density = density;
|
||||
shapeDef.material.friction = friction;
|
||||
|
||||
b2Polygon b2shape;
|
||||
b2Circle b2circle;
|
||||
b2Capsule b2capsule;
|
||||
|
||||
switch (shape)
|
||||
{
|
||||
case ColliderShape::Box:
|
||||
b2shape = b2MakeBox(collidersize.x * 0.5f, collidersize.y * 0.5f);
|
||||
b2CreatePolygonShape(bodyId, &shapeDef, &b2shape);
|
||||
break;
|
||||
case ColliderShape::RoundedBox:
|
||||
b2shape = b2MakeRoundedBox(collidersize.x * 0.5f, collidersize.y * 0.5f, collidersize.z);
|
||||
b2CreatePolygonShape(bodyId, &shapeDef, &b2shape);
|
||||
break;
|
||||
case ColliderShape::Circle:
|
||||
b2circle.radius = collidersize.x;
|
||||
b2CreateCircleShape(bodyId, &shapeDef, &b2circle);
|
||||
break;
|
||||
case ColliderShape::Capsule:
|
||||
b2capsule.radius = collidersize.x;
|
||||
b2capsule.center1 = {0, collidersize.y * 0.5f};
|
||||
b2capsule.center1 = {0, collidersize.y * -0.5f};
|
||||
b2CreateCapsuleShape(bodyId, &shapeDef, &b2capsule);
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
PhysicsEngine::RegisterPhysicsObject(this);
|
||||
}
|
||||
41
TSE_Core/src/BehaviourScripts/PhysicsObject.hpp
Normal file
41
TSE_Core/src/BehaviourScripts/PhysicsObject.hpp
Normal file
@@ -0,0 +1,41 @@
|
||||
#pragma once
|
||||
|
||||
#define PHYSICSOBJECT typeid(PhysicsObject).name()
|
||||
|
||||
#include "box2d/box2d.h"
|
||||
#include "enums/PhysicsEnums.hpp"
|
||||
#include "elements/BehaviourScript.hpp"
|
||||
#include "Vector3.hpp"
|
||||
|
||||
namespace TSE
|
||||
{
|
||||
class PhysicsObject: public BehaviourScript
|
||||
{
|
||||
private:
|
||||
BodyType type;
|
||||
ColliderShape shape;
|
||||
float density;
|
||||
float friction;
|
||||
|
||||
//in case of box: x = x, y = y, z = unused
|
||||
//in case of circle: x = radius, y = unused, z = unused
|
||||
//in case of capsule: x = radius, y = height, z = unused
|
||||
//in case of RoundedBox: x = x, y = y, z = radius
|
||||
Vector3 collidersize;
|
||||
|
||||
b2BodyId bodyId;
|
||||
Vector3 lastPos;
|
||||
float lastRot;
|
||||
public:
|
||||
PhysicsObject(BodyType type, ColliderShape shape, float density, float friction, Vector3 colliderSize);
|
||||
~PhysicsObject();
|
||||
|
||||
void UpdatePosition();
|
||||
void OnUpdate() override;
|
||||
void Start() override;
|
||||
inline const char* GetName() override
|
||||
{
|
||||
return "Physics Object";
|
||||
}
|
||||
};
|
||||
} // namespace TSE
|
||||
57
TSE_Core/src/elements/PhysicsEngine.cpp
Normal file
57
TSE_Core/src/elements/PhysicsEngine.cpp
Normal file
@@ -0,0 +1,57 @@
|
||||
#include "PhysicsEngine.hpp"
|
||||
#include "utils/Time.hpp"
|
||||
|
||||
void TSE::PhysicsEngine::InitPhysics(Vector2 gravity)
|
||||
{
|
||||
b2WorldDef def = b2DefaultWorldDef();
|
||||
def.enableSleep = true;
|
||||
b2Vec2 grav;
|
||||
grav.x = gravity.x;
|
||||
grav.y = gravity.y;
|
||||
def.gravity = grav;
|
||||
worldId = b2CreateWorld(&def);
|
||||
}
|
||||
|
||||
void TSE::PhysicsEngine::UpdatePhysics()
|
||||
{
|
||||
if(elapsedTime >= timestep)
|
||||
{
|
||||
elapsedTime = 0;
|
||||
b2World_Step(worldId, timestep, iterations);
|
||||
//update physics objects
|
||||
}
|
||||
elapsedTime += Time::deltaTime();
|
||||
|
||||
for(auto obj : registeredObjects)
|
||||
{
|
||||
obj->UpdatePosition();
|
||||
}
|
||||
}
|
||||
|
||||
void TSE::PhysicsEngine::DeletePhysics()
|
||||
{
|
||||
b2DestroyWorld(worldId);
|
||||
}
|
||||
|
||||
void TSE::PhysicsEngine::RegisterPhysicsObject(PhysicsObject *obj)
|
||||
{
|
||||
registeredObjects.push_back(obj);
|
||||
}
|
||||
|
||||
void TSE::PhysicsEngine::UnRegisterPhysicsObject(PhysicsObject *obj)
|
||||
{
|
||||
auto it = registeredObjects.begin();
|
||||
for (; it != registeredObjects.end(); it++)
|
||||
{
|
||||
if(*it == obj)
|
||||
{
|
||||
registeredObjects.erase(it);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
b2WorldId &TSE::PhysicsEngine::GetWorldId()
|
||||
{
|
||||
return worldId;
|
||||
}
|
||||
28
TSE_Core/src/elements/PhysicsEngine.hpp
Normal file
28
TSE_Core/src/elements/PhysicsEngine.hpp
Normal file
@@ -0,0 +1,28 @@
|
||||
#pragma once
|
||||
|
||||
#include "BehaviourScripts/PhysicsObject.hpp"
|
||||
#include "box2d/box2d.h"
|
||||
#include <vector>
|
||||
#include "Vector2.hpp"
|
||||
|
||||
namespace TSE
|
||||
{
|
||||
class PhysicsEngine
|
||||
{
|
||||
private:
|
||||
inline static std::vector<PhysicsObject*> registeredObjects = std::vector<PhysicsObject*>();
|
||||
inline static b2WorldId worldId = b2WorldId();
|
||||
inline static constexpr float timestep = 1.0f / 60.0f;
|
||||
inline static const int iterations = 4;
|
||||
inline static float elapsedTime = 0;
|
||||
|
||||
public:
|
||||
static void InitPhysics(Vector2 gravity);
|
||||
static void UpdatePhysics();
|
||||
static void DeletePhysics();
|
||||
static void RegisterPhysicsObject(PhysicsObject* obj);
|
||||
static void UnRegisterPhysicsObject(PhysicsObject* obj);
|
||||
|
||||
static b2WorldId& GetWorldId();
|
||||
};
|
||||
} // namespace TSE
|
||||
16
TSE_Core/src/enums/PhysicsEnums.hpp
Normal file
16
TSE_Core/src/enums/PhysicsEnums.hpp
Normal file
@@ -0,0 +1,16 @@
|
||||
#pragma once
|
||||
|
||||
namespace TSE
|
||||
{
|
||||
enum BodyType {
|
||||
Static,
|
||||
Dynamic,
|
||||
};
|
||||
enum ColliderShape {
|
||||
Box,
|
||||
RoundedBox,
|
||||
Circle,
|
||||
Capsule,
|
||||
};
|
||||
|
||||
} // namespace TSE
|
||||
Reference in New Issue
Block a user