Physics system progress

Added CharacterController creation
Reworked and refactored shape and body system internally
Code cleanup
Brought back Hull serializing for Quake map brushes
Updated Editor panels accordingly
This commit is contained in:
Antoine Pilote
2023-07-03 19:16:02 -04:00
parent 7c95beefcc
commit fc183b4813
14 changed files with 370 additions and 258 deletions

View File

@@ -22,113 +22,12 @@ 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;
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 +39,7 @@ namespace Nuake
// PhysicsManager::Get()->RegisterGhostBody(ghostBody);
//}
return true;
}
@@ -219,4 +119,175 @@ 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);
characterControllerComponent.CharacterController = characterController;
PhysicsManager::Get().RegisterCharacterController(characterControllerComponent.CharacterController);
}
// TODO: Other types of collider supported for character controller?
}
}
}