This commit is contained in:
Antoine Pilote
2023-07-04 00:15:05 -04:00
16 changed files with 376 additions and 259 deletions

View File

@@ -17,30 +17,21 @@ public:
BeginComponentTable(CHARACTER CONTROLLER, Nuake::CharacterControllerComponent);
{
{
ImGui::Text("Height");
ImGui::Text("Friction");
ImGui::TableNextColumn();
ImGui::DragFloat("##Height", &component.Height, 0.01f, 0.1f, 100.0f);
ImGui::DragFloat("##Friction", &component.Friction, 0.01f, 0.1f, 100.0f);
ImGui::TableNextColumn();
ComponentTableReset(component.Height, 1.0f)
ComponentTableReset(component.Friction, 0.5f)
}
ImGui::TableNextColumn();
{
ImGui::Text("Radius");
ImGui::Text("Max Slope Angle");
ImGui::TableNextColumn();
ImGui::DragFloat("##Radius", &component.Radius, 0.01f, 0.1f, 10.0f);
ImGui::DragFloat("##MaxSlopeAngle", &component.MaxSlopeAngle, 0.01f, 0.1f, 90.0f);
ImGui::TableNextColumn();
ComponentTableReset(component.Radius, 0.25f)
}
ImGui::TableNextColumn();
{
ImGui::Text("Mass");
ImGui::TableNextColumn();
ImGui::DragFloat("##Mass", &component.Mass, 0.001f, 0.00001f, 10.0f);
ImGui::TableNextColumn();
ComponentTableReset(component.Mass, 0.001f)
ComponentTableReset(component.MaxSlopeAngle, 0.45f)
}
}
EndComponentTable()

View File

@@ -6,14 +6,21 @@ namespace Nuake
{
namespace Physics
{
CharacterController::CharacterController(float height, float radius, float mass, Vector3 position)
CharacterController::CharacterController(const Ref<PhysicShape>& shape, float friction, float maxSlopeAngle)
{
Shape = shape;
Friction = friction;
MaxSlopeAngle = maxSlopeAngle;
}
void CharacterController::SetEntity(Entity& ent)
{
Owner = ent;
}
Entity CharacterController::GetEntity() const
{
return Owner;
}
void CharacterController::MoveAndSlide(glm::vec3 velocity)

View File

@@ -1,6 +1,8 @@
#pragma once
#include "src/Core/Core.h"
#include "src/Core/Maths.h"
#include "src/Core/Physics/PhysicsShapes.h"
#include "src/Scene/Entities/Entity.h"
namespace Nuake
{
@@ -11,26 +13,30 @@ namespace Nuake
class CharacterController
{
public:
Vector3 Position = Vector3(0, 0, 0);
Entity Owner;
bool IsOnGround = false;
bool m_hittingWall;
float m_stepHeight = 0.35f;
float m_MaxSlopeAngle = 45.0f;
float m_stepHeight = 0.35f;
float MaxSlopeAngle = 45.0f;
float Friction = 0.5f;
Ref<PhysicShape> Shape;
//bool m_onJumpableGround; // A bit lower contact than just onGround
float m_bottomYOffset;
float m_bottomRoundedRegionYOffset;
glm::vec3 m_manualVelocity;
std::vector<glm::vec3> m_surfaceHitNormals;
float m_jumpRechargeTimer;
CharacterController(float height, float radius, float mass, Vector3 position);
CharacterController(const Ref<PhysicShape>& shape, float friction, float maxSlopeAngle);
void SetEntity(Entity& ent);
Entity GetEntity() const;
void MoveAndSlide(glm::vec3 velocity);
bool IsOnFloor()

View File

@@ -1,11 +1,11 @@
#include "DynamicWorld.h"
#include "Rigibody.h"
#include "../Core/Core.h"
#include <src/Vendors/glm/ext/quaternion_common.hpp>
#include <src/Core/Logger.h>
#include "src/Core/Core.h"
#include "src/Core/Logger.h"
#include <src/Core/Physics/PhysicsShapes.h>
#include <src/Vendors/glm/ext/quaternion_common.hpp>
#include "src/Vendors/glm/gtx/matrix_decompose.hpp"
#include <Jolt/Jolt.h>
@@ -241,103 +241,21 @@ namespace Nuake
void DynamicWorld::AddRigidbody(Ref<RigidBody> rb)
{
JPH::BodyInterface& bodyInterface = _JoltPhysicsSystem->GetBodyInterface();
JPH::ShapeSettings::ShapeResult shapeResult;
auto rbShape = rb->GetShape();
switch (rbShape->GetType())
{
case RigidbodyShapes::BOX:
{
Box* box = (Box*)rbShape.get();
const Vector3& boxSize = box->GetSize();
JPH::BoxShapeSettings shapeSettings(JPH::Vec3(boxSize.x, boxSize.y, boxSize.z));
shapeResult = shapeSettings.Create();
}
break;
case RigidbodyShapes::SPHERE:
{
Sphere* sphere = (Sphere*)rbShape.get();
const float sphereRadius = sphere->GetRadius();
JPH::SphereShapeSettings shapeSettings(sphereRadius);
shapeResult = shapeSettings.Create();
}
break;
case RigidbodyShapes::CAPSULE:
{
Capsule* capsule = (Capsule*)rbShape.get();
const float radius = capsule->GetRadius();
const float height = capsule->GetHeight();
JPH::CapsuleShapeSettings shapeSettings(height / 2.0f, radius);
shapeResult = shapeSettings.Create();
}
break;
case RigidbodyShapes::CYLINDER:
{
Cylinder* capsule = (Cylinder*)rbShape.get();
const float radius = capsule->GetRadius();
const float height = capsule->GetHeight();
JPH::CylinderShapeSettings shapeSettings(height / 2.0f, radius);
shapeResult = shapeSettings.Create();
}
break;
case RigidbodyShapes::MESH:
{
MeshShape* meshShape = (MeshShape*)rbShape.get();
const auto& mesh = meshShape->GetMesh();
const auto& vertices = mesh->GetVertices();
const auto& indices = mesh->GetIndices();
JPH::TriangleList triangles;
triangles.reserve(indices.size());
Matrix4 transform = rb->_transform;
transform[3] = Vector4(0, 0, 0, 1.0f);
for (int i = 0; i < indices.size() - 3; i += 3)
{
const Vector3& p1 = vertices[indices[i]].position;
const Vector3& p2 = vertices[indices[i + 1]].position;
const Vector3& p3 = vertices[indices[i + 2]].position;
const Vector4& tp1 = transform * Vector4(p1, 1.0f);
const Vector4& tp2 = transform * Vector4(p2, 1.0f);
const Vector4& tp3 = transform * Vector4(p3, 1.0f);
triangles.push_back(JPH::Triangle(JPH::Float3(tp1.x, tp1.y, tp1.z), JPH::Float3(tp2.x, tp2.y, tp2.z), JPH::Float3(tp3.x, tp3.y, tp3.z)));
}
JPH::MeshShapeSettings shapeSettings(std::move(triangles));
shapeResult = shapeSettings.Create();
}
break;
case CONVEX_HULL:
{
ConvexHullShape* shape = (ConvexHullShape*)rbShape.get();
const auto& hullPoints = shape->GetPoints();
JPH::Array<JPH::Vec3> points;
points.reserve(std::size(hullPoints));
for (const auto& p : hullPoints)
{
points.push_back(JPH::Vec3(p.x, p.y, p.z));
}
JPH::ConvexHullShapeSettings shapeSettings(points);
shapeResult = shapeSettings.Create();
}
break;
}
const float mass = rb->_mass;
JPH::EMotionType motionType = JPH::EMotionType::Static;
float mass = rb->_mass;
// According to jolt documentation, Mesh shapes should only be static.
if (mass > 0.0f && rb->GetShape()->GetType() != MESH)
const bool isMeshShape = rb->GetShape()->GetType() == MESH;
if (mass > 0.0f && !isMeshShape)
{
motionType = JPH::EMotionType::Dynamic;
}
const auto& startPos = rb->GetPosition();
const auto& joltPos = JPH::Vec3(startPos.x, startPos.y, startPos.z);
JPH::BodyCreationSettings bodySettings(shapeResult.Get(), joltPos, JPH::Quat::sIdentity(), motionType, Layers::MOVING);
auto joltShape = GetJoltShape(rb->GetShape());
JPH::BodyCreationSettings bodySettings(joltShape, joltPos, JPH::Quat::sIdentity(), motionType, Layers::MOVING);
if (mass > 0.0f)
{
@@ -358,12 +276,16 @@ namespace Nuake
void DynamicWorld::AddCharacterController(Ref<CharacterController> cc)
{
auto settings = new JPH::CharacterSettings();
JPH::Ref<JPH::CharacterSettings> settings = new JPH::CharacterSettings();
settings->mMaxSlopeAngle = JPH::DegreesToRadians(45.0f);
settings->mLayer = Layers::MOVING;
settings->mFriction = 0.5f;
settings->mShape = GetJoltShape(cc->Shape);
// Shape here
auto& joltPos = JPH::Vec3(cc->Position.x, cc->Position.y, cc->Position.z);
JPH::Character* character = new JPH::Character(settings, joltPos, JPH::Quat::sIdentity(), cc->GetEntity().GetID() , _JoltPhysicsSystem.get());
character->AddToPhysicsSystem(JPH::EActivation::Activate);
}
RaycastResult DynamicWorld::Raycast(glm::vec3 from, glm::vec3 to)
@@ -454,5 +376,94 @@ namespace Nuake
_JoltBodyInterface->RemoveBodies(reinterpret_cast<JPH::BodyID*>(_registeredBodies.data()), _registeredBodies.size());
_registeredBodies.clear();
}
JPH::Ref<JPH::Shape> DynamicWorld::GetJoltShape(const Ref<PhysicShape> shape)
{
JPH::ShapeSettings::ShapeResult result;
switch (shape->GetType())
{
case RigidbodyShapes::BOX:
{
Box* box = (Box*)shape.get();
const Vector3& boxSize = box->GetSize();
JPH::BoxShapeSettings shapeSettings(JPH::Vec3(boxSize.x, boxSize.y, boxSize.z));
result = shapeSettings.Create();
}
break;
case RigidbodyShapes::SPHERE:
{
Sphere* sphere = (Sphere*)shape.get();
const float sphereRadius = sphere->GetRadius();
JPH::SphereShapeSettings shapeSettings(sphereRadius);
result = shapeSettings.Create();
}
break;
case RigidbodyShapes::CAPSULE:
{
Capsule* capsule = (Capsule*)shape.get();
const float radius = capsule->GetRadius();
const float height = capsule->GetHeight();
JPH::CapsuleShapeSettings shapeSettings(height / 2.0f, radius);
result = shapeSettings.Create();
}
break;
case RigidbodyShapes::CYLINDER:
{
Cylinder* capsule = (Cylinder*)shape.get();
const float radius = capsule->GetRadius();
const float height = capsule->GetHeight();
JPH::CylinderShapeSettings shapeSettings(height / 2.0f, radius);
result = shapeSettings.Create();
}
break;
case RigidbodyShapes::MESH:
{
MeshShape* meshShape = (MeshShape*)shape.get();
const auto& mesh = meshShape->GetMesh();
const auto& vertices = mesh->GetVertices();
const auto& indices = mesh->GetIndices();
JPH::TriangleList triangles;
triangles.reserve(indices.size());
Matrix4 transform; //rb->_transform;
transform[3] = Vector4(0, 0, 0, 1.0f);
for (int i = 0; i < indices.size() - 3; i += 3)
{
const Vector3& p1 = vertices[indices[i]].position;
const Vector3& p2 = vertices[indices[i + 1]].position;
const Vector3& p3 = vertices[indices[i + 2]].position;
const Vector4& tp1 = transform * Vector4(p1, 1.0f);
const Vector4& tp2 = transform * Vector4(p2, 1.0f);
const Vector4& tp3 = transform * Vector4(p3, 1.0f);
triangles.push_back(JPH::Triangle(JPH::Float3(tp1.x, tp1.y, tp1.z), JPH::Float3(tp2.x, tp2.y, tp2.z), JPH::Float3(tp3.x, tp3.y, tp3.z)));
}
JPH::MeshShapeSettings shapeSettings(std::move(triangles));
result = shapeSettings.Create();
}
break;
case CONVEX_HULL:
{
auto* convexHullShape = (Physics::ConvexHullShape*)shape.get();
const auto& hullPoints = convexHullShape->GetPoints();
JPH::Array<JPH::Vec3> points;
points.reserve(std::size(hullPoints));
for (const auto& p : hullPoints)
{
points.push_back(JPH::Vec3(p.x, p.y, p.z));
}
JPH::ConvexHullShapeSettings shapeSettings(points);
result = shapeSettings.Create();
}
break;
}
return result.Get();
}
}
}

View File

@@ -10,6 +10,7 @@
#include "CharacterController.h"
#include <Jolt/Jolt.h>
#include "src/Core/Core.h"
namespace JPH
{
class PhysicsSystem;
@@ -17,8 +18,13 @@ namespace JPH
class ContactListener;
class BodyActivationListener;
class BodyInterface;
class Shape;
template<class T>
class Ref;
}
namespace Nuake
{
class BPLayerInterfaceImpl;
@@ -26,7 +32,8 @@ namespace Nuake
class MyBodyActivationListener;
namespace Physics {
class DynamicWorld {
class DynamicWorld
{
private:
uint32_t _stepCount;
@@ -38,6 +45,7 @@ namespace Nuake
BPLayerInterfaceImpl* _JoltBroadphaseLayerInterface;
std::vector<uint32_t> _registeredBodies;
std::vector<uint32_t> _registeredCharacters;
public:
DynamicWorld();
@@ -54,7 +62,7 @@ namespace Nuake
void Clear();
private:
JPH::Ref<JPH::Shape> GetJoltShape(const Ref<PhysicShape> shape);
};
}
}

View File

@@ -58,8 +58,6 @@ namespace Nuake
JPH::Factory::sInstance = new JPH::Factory();
JPH::RegisterTypes();
// This is the max amount of rigid bodies that you can add to the physics system. If you try to add more you'll get an error.
// Note: This value is low because this is a simple test. For a real project use something in the order of 65536.
m_World = new Physics::DynamicWorld();
m_World->SetGravity(glm::vec3(0, -3, 0));

View File

@@ -12,24 +12,27 @@ namespace Nuake
}
// Sphere
Box::Box(glm::vec3 size) {
Box::Box(glm::vec3 size)
{
Size = size;
m_Type = BOX;
}
Box::Box(float x, float y, float z) {
Box::Box(float x, float y, float z)
{
Size = glm::vec3(x, y, z);
m_Type = BOX;
}
// Sphere
Sphere::Sphere(float radius) {
Sphere::Sphere(float radius)
{
Radius = radius;
m_Type = SPHERE;
}
void Sphere::SetRadius(float radius) {
void Sphere::SetRadius(float radius)
{
Radius = radius;
}
}

View File

@@ -20,7 +20,7 @@ namespace Nuake
RigidBody();
RigidBody(glm::vec3 position, Entity handle);
RigidBody(float mass, glm::vec3 position, Matrix4 _transform, Ref<PhysicShape> shape, Entity entity, glm::vec3 initialVel = glm::vec3(0, 0, 0));
RigidBody(float mass, glm::vec3 position, Matrix4 transform, Ref<PhysicShape> shape, Entity entity, glm::vec3 initialVel = glm::vec3(0, 0, 0));
void UpdateTransform();

View File

@@ -39,7 +39,7 @@ namespace Nuake
void RigidBody::SetEntityID(Entity ent)
{
_entity = ent;
}
}
}

View File

@@ -29,25 +29,26 @@ namespace Nuake {
Meshes = std::vector<Ref<Mesh>>();
Materials = std::vector<Ref<Material>>();
Rigidbody = std::vector<Ref<Physics::RigidBody>>();
Hulls = std::vector<std::vector<Vector3>>();
}
json Serialize()
{
BEGIN_SERIALIZE();
//for (uint32_t i = 0; i < Hulls.size() - 1; i++)
//{
// json hullPointsJson;
for (uint32_t i = 0; i < Hulls.size(); i++)
{
json hullPointsJson;
// size_t hullSize = Hulls[i].size();
// for (uint32_t j = 0; j < hullSize; j++)
// {
// hullPointsJson[j]["x"] = Hulls[i][j].x;
// hullPointsJson[j]["y"] = Hulls[i][j].y;
// hullPointsJson[j]["z"] = Hulls[i][j].z;
// }
// j["Hulls"][i] = hullPointsJson;
//}
size_t hullSize = Hulls[i].size();
for (uint32_t j = 0; j < hullSize; j++)
{
hullPointsJson[j]["x"] = Hulls[i][j].x;
hullPointsJson[j]["y"] = Hulls[i][j].y;
hullPointsJson[j]["z"] = Hulls[i][j].z;
}
j["Hulls"][i] = hullPointsJson;
}
j["IsSolid"] = IsSolid;
END_SERIALIZE();

View File

@@ -7,28 +7,36 @@ namespace Nuake {
public:
Ref<Physics::CharacterController> CharacterController;
float Height = 1.0f;
float Radius = 0.2f;
float Mass = 25.0f;
float Friction = 0.5f;
float MaxSlopeAngle = 0.45f;
CharacterControllerComponent()
{
}
json Serialize() {
json Serialize()
{
BEGIN_SERIALIZE();
SERIALIZE_VAL(Height);
SERIALIZE_VAL(Radius);
SERIALIZE_VAL(Mass);
SERIALIZE_VAL(Friction);
SERIALIZE_VAL(MaxSlopeAngle);
END_SERIALIZE();
}
bool Deserialize(const std::string str) {
bool Deserialize(const std::string str)
{
BEGIN_DESERIALIZE();
Height = j["Height"];
Radius = j["Radius"];
Mass = j["Mass"];
if (j.contains("Friction"))
{
Friction = j["Friction"];
}
if (j.contains("MaxSlopeAngle"))
{
MaxSlopeAngle = j["MaxSlopeAngle"];
}
return true;
}
};

View File

@@ -8,6 +8,7 @@ namespace Nuake {
public:
int SubMesh = 0;
bool IsTrigger;
Ref<Physics::MeshShape> Shape;
json Serialize()
{

View File

@@ -14,7 +14,7 @@ namespace Nuake
float AtmosphereRadius = 6380e3f;
Vector3 RayleighScattering = Vector3(58e-7f, 135e-7f, 331e-7f);
Vector3 MieScattering = Vector3(2e-5f);
float SunIntensity = 10.0;
float SunIntensity = 2.0;
Vector3 CenterPoint = Vector3(0.f, -SurfaceRadius, 0.f);
Vector3 SunDirection = Vector3(0.20000f, 0.95917f, 0.20000f);

View File

@@ -84,7 +84,7 @@ namespace Nuake {
}
}
assert("Not found");
assert("Entity not found");
}
bool Scene::OnInit()

View File

@@ -22,113 +22,15 @@ namespace Nuake
bool PhysicsSystem::Init()
{
// Create physic world.
auto view = m_Scene->m_Registry.view<TransformComponent, RigidBodyComponent>();
for (auto e : view)
{
auto [transform, rigidBodyComponent] = view.get<TransformComponent, RigidBodyComponent>(e);
Entity ent = Entity({ e, m_Scene });
Ref<Physics::RigidBody> rigidBody;
if (ent.HasComponent<BoxColliderComponent>())
{
float mass = rigidBodyComponent.Mass;
// We need to initialize shapes first, then bodies...
InitializeShapes();
BoxColliderComponent& boxComponent = ent.GetComponent<BoxColliderComponent>();
Ref<Physics::Box> boxShape = CreateRef<Physics::Box>(boxComponent.Size);
rigidBody = CreateRef<Physics::RigidBody>(rigidBodyComponent.Mass, transform.GetGlobalPosition(), transform.GetGlobalTransform(), boxShape, ent);
PhysicsManager::Get().RegisterBody(rigidBody);
}
if (ent.HasComponent<CapsuleColliderComponent>())
{
auto& capsuleComponent = ent.GetComponent<CapsuleColliderComponent>();
float radius = capsuleComponent.Radius;
float height = capsuleComponent.Height;
auto capsuleShape = CreateRef<Physics::Capsule>(radius, height);
rigidBody = CreateRef<Physics::RigidBody>(rigidBodyComponent.Mass, transform.GetGlobalPosition(), transform.GetGlobalTransform(), capsuleShape, ent);
PhysicsManager::Get().RegisterBody(rigidBody);
}
if (ent.HasComponent<SphereColliderComponent>())
{
float mass = rigidBodyComponent.Mass;
const auto& component = ent.GetComponent<SphereColliderComponent>();
auto shape = CreateRef<Physics::Sphere>(component.Radius);
rigidBody = CreateRef<Physics::RigidBody>(rigidBodyComponent.Mass, transform.GetGlobalPosition(), transform.GetGlobalTransform(), shape, ent);
PhysicsManager::Get().RegisterBody(rigidBody);
}
if (ent.HasComponent<MeshColliderComponent>())
{
if (!ent.HasComponent<ModelComponent>())
{
Logger::Log("Cannot use mesh collider without model component", WARNING);
}
const auto& modelComponent = ent.GetComponent<ModelComponent>();
const auto& component = ent.GetComponent<MeshColliderComponent>();
if (modelComponent.ModelResource)
{
uint32_t subMeshId = component.SubMesh;
const std::vector<Ref<Mesh>>& submeshes = modelComponent.ModelResource->GetMeshes();
if (subMeshId >= submeshes.size())
{
Logger::Log("Cannot create mesh collider, invalid submesh ID", WARNING);
}
Ref<Mesh> mesh = submeshes[subMeshId];
auto shape = CreateRef<Physics::MeshShape>(mesh);
rigidBody = CreateRef<Physics::RigidBody>(rigidBodyComponent.Mass, transform.GetGlobalPosition(), transform.GetGlobalTransform(), shape, ent);
PhysicsManager::Get().RegisterBody(rigidBody);
}
}
}
//const auto characterControllerView = m_Scene->m_Registry.view<TransformComponent, CharacterControllerComponent>();
//for (auto e : characterControllerView)
//{
// Entity ent = Entity({ e, m_Scene });
// auto [transformComponent, ccc] = view.get<TransformComponent, CharacterControllerComponent>(e);
//auto& physicsObject = CreateRef<Physics::CharacterController>(ccc.);
//}
//// character controllers
//auto ccview = m_Scene->m_Registry.view<TransformComponent, CharacterControllerComponent>();
//for (auto e : ccview)
//{
// auto [transform, cc] = ccview.get<TransformComponent, CharacterControllerComponent>(e);
// cc.CharacterController = CreateRef<Physics::CharacterController>(cc.Height, cc.Radius, cc.Mass, transform.GetLocalPosition());
// Entity ent = Entity({ e, m_Scene });
// cc.CharacterController->SetEntity(ent);
// PhysicsManager::Get()->RegisterCharacterController(cc.CharacterController);
//}
auto bspView = m_Scene->m_Registry.view<TransformComponent, BSPBrushComponent, ModelComponent>();
for (auto e : bspView)
{
Entity ent = Entity({ e, m_Scene });
auto [transform, brush, model] = bspView.get<TransformComponent, BSPBrushComponent, ModelComponent>(e);
if (!brush.IsSolid)
continue;
for (const auto& h : brush.Hulls)
{
Ref<Physics::ConvexHullShape> meshShape = CreateRef<Physics::ConvexHullShape>(h);
Ref<Physics::RigidBody> btRigidbody = CreateRef<Physics::RigidBody>(0.0f, transform.GetGlobalPosition(), transform.GetGlobalTransform(), meshShape, ent);
btRigidbody->SetEntityID(Entity{ e, m_Scene });
brush.Rigidbody.push_back(btRigidbody);
PhysicsManager::Get().RegisterBody(btRigidbody);
}
}
InitializeRigidbodies();
InitializeCharacterControllers();
InitializeQuakeMap();
// TODO: Triggers
//auto bspTriggerView = m_Scene->m_Registry.view<TransformComponent, BSPBrushComponent, TriggerZone>();
//for (auto e : bspTriggerView)
//{
@@ -140,6 +42,7 @@ namespace Nuake
// PhysicsManager::Get()->RegisterGhostBody(ghostBody);
//}
return true;
}
@@ -219,4 +122,177 @@ namespace Nuake
{
PhysicsManager::Get().Reset();
}
void PhysicsSystem::InitializeQuakeMap()
{
auto quakeBrushesView = m_Scene->m_Registry.view<TransformComponent, BSPBrushComponent, ModelComponent>();
for (auto e : quakeBrushesView)
{
const auto [transformComponent, brushComponent, modelComponent] = quakeBrushesView.get<TransformComponent, BSPBrushComponent, ModelComponent>(e);
// Doesn't apply to non-solid brushes
if (!brushComponent.IsSolid)
{
continue;
}
for (const auto& hull : brushComponent.Hulls)
{
const auto entity = Entity({ e, m_Scene });
const Vector3 startPosition = transformComponent.GetGlobalPosition();
const Matrix4 startTransform = transformComponent.GetGlobalTransform();
const auto collisionShape = CreateRef<Physics::ConvexHullShape>(hull);
auto rigidBody = CreateRef<Physics::RigidBody>(0.0f, startPosition, startTransform, collisionShape, entity);
brushComponent.Rigidbody.push_back(rigidBody);
PhysicsManager::Get().RegisterBody(rigidBody);
}
}
}
void PhysicsSystem::InitializeShapes()
{
const auto boxView = m_Scene->m_Registry.view<BoxColliderComponent>();
for (auto entity : boxView)
{
auto& boxComponent = boxView.get<BoxColliderComponent>(entity);
boxComponent.Box = CreateRef<Physics::Box>(boxComponent.Size);
}
const auto capsuleView = m_Scene->m_Registry.view<CapsuleColliderComponent>();
for (auto entity : capsuleView)
{
auto& capsuleComponent = capsuleView.get<CapsuleColliderComponent>(entity);
float radius = capsuleComponent.Radius;
float height = capsuleComponent.Height;
capsuleComponent.Capsule = CreateRef<Physics::Capsule>(radius, height);
}
const auto sphereView = m_Scene->m_Registry.view<SphereColliderComponent>();
for (auto entity : sphereView)
{
auto& sphereComponent = sphereView.get<SphereColliderComponent>(entity);
sphereComponent.Sphere = CreateRef<Physics::Sphere>(sphereComponent.Radius);
}
const auto meshColliderView = m_Scene->m_Registry.view<MeshColliderComponent>();
for (auto e : meshColliderView)
{
Entity entity { e, m_Scene };
if (!entity.HasComponent<ModelComponent>())
{
Logger::Log("Cannot use mesh collider without model component", WARNING);
}
auto meshColliderComponent = meshColliderView.get<MeshColliderComponent>(e);
const auto& modelComponent = entity.GetComponent<ModelComponent>();
if (modelComponent.ModelResource)
{
uint32_t subMeshId = meshColliderComponent.SubMesh;
const std::vector<Ref<Mesh>>& submeshes = modelComponent.ModelResource->GetMeshes();
if (subMeshId >= submeshes.size())
{
Logger::Log("Cannot create mesh collider, invalid submesh ID", WARNING);
}
Ref<Mesh> mesh = submeshes[subMeshId];
meshColliderComponent.Shape = CreateRef<Physics::MeshShape>(mesh);
}
}
}
void PhysicsSystem::InitializeRigidbodies()
{
auto view = m_Scene->m_Registry.view<TransformComponent, RigidBodyComponent>();
for (auto e : view)
{
auto [transform, rigidBodyComponent] = view.get<TransformComponent, RigidBodyComponent>(e);
Entity ent = Entity({ e, m_Scene });
Ref<Physics::RigidBody> rigidBody;
if (ent.HasComponent<BoxColliderComponent>())
{
float mass = rigidBodyComponent.Mass;
BoxColliderComponent& boxComponent = ent.GetComponent<BoxColliderComponent>();
Ref<Physics::Box> boxShape = CreateRef<Physics::Box>(boxComponent.Size);
rigidBody = CreateRef<Physics::RigidBody>(rigidBodyComponent.Mass, transform.GetGlobalPosition(), transform.GetGlobalTransform(), boxShape, ent);
PhysicsManager::Get().RegisterBody(rigidBody);
}
if (ent.HasComponent<CapsuleColliderComponent>())
{
auto& capsuleComponent = ent.GetComponent<CapsuleColliderComponent>();
float radius = capsuleComponent.Radius;
float height = capsuleComponent.Height;
auto capsuleShape = CreateRef<Physics::Capsule>(radius, height);
rigidBody = CreateRef<Physics::RigidBody>(rigidBodyComponent.Mass, transform.GetGlobalPosition(), transform.GetGlobalTransform(), capsuleShape, ent);
PhysicsManager::Get().RegisterBody(rigidBody);
}
if (ent.HasComponent<SphereColliderComponent>())
{
float mass = rigidBodyComponent.Mass;
const auto& component = ent.GetComponent<SphereColliderComponent>();
auto shape = CreateRef<Physics::Sphere>(component.Radius);
rigidBody = CreateRef<Physics::RigidBody>(rigidBodyComponent.Mass, transform.GetGlobalPosition(), transform.GetGlobalTransform(), shape, ent);
PhysicsManager::Get().RegisterBody(rigidBody);
}
if (ent.HasComponent<MeshColliderComponent>())
{
if (!ent.HasComponent<ModelComponent>())
{
Logger::Log("Cannot use mesh collider without model component", WARNING);
}
const auto& modelComponent = ent.GetComponent<ModelComponent>();
const auto& component = ent.GetComponent<MeshColliderComponent>();
if (modelComponent.ModelResource)
{
uint32_t subMeshId = component.SubMesh;
const std::vector<Ref<Mesh>>& submeshes = modelComponent.ModelResource->GetMeshes();
if (subMeshId >= submeshes.size())
{
Logger::Log("Cannot create mesh collider, invalid submesh ID", WARNING);
}
Ref<Mesh> mesh = submeshes[subMeshId];
auto shape = CreateRef<Physics::MeshShape>(mesh);
rigidBody = CreateRef<Physics::RigidBody>(rigidBodyComponent.Mass, transform.GetGlobalPosition(), transform.GetGlobalTransform(), shape, ent);
PhysicsManager::Get().RegisterBody(rigidBody);
}
}
}
}
void PhysicsSystem::InitializeCharacterControllers()
{
auto characterControllerView = m_Scene->m_Registry.view<TransformComponent, CharacterControllerComponent>();
for (const auto& e : characterControllerView)
{
Entity entity = Entity({ e, m_Scene });
auto [transformComponent, characterControllerComponent] = characterControllerView.get<TransformComponent, CharacterControllerComponent>(e);
if (entity.HasComponent<CapsuleColliderComponent>())
{
const auto& capsuleColliderComponent = entity.GetComponent<CapsuleColliderComponent>();
auto& capsule = capsuleColliderComponent.Capsule;
float friction = characterControllerComponent.Friction;
float maxSlopeAngle = characterControllerComponent.MaxSlopeAngle;
auto characterController = CreateRef<Physics::CharacterController>(capsule, friction, maxSlopeAngle);
characterController->SetEntity(entity); // Used to link back to the entity
characterControllerComponent.CharacterController = characterController;
PhysicsManager::Get().RegisterCharacterController(characterControllerComponent.CharacterController);
}
// TODO: Other types of collider supported for character controller?
}
}
}

View File

@@ -12,5 +12,12 @@ namespace Nuake
void Draw() override {}
void FixedUpdate(Timestep ts) override;
void Exit() override;
private:
void InitializeShapes();
void InitializeQuakeMap();
void InitializeRigidbodies();
void InitializeCharacterControllers();
};
}