diff --git a/Editor/src/ComponentsPanel/CharacterControllerPanel.h b/Editor/src/ComponentsPanel/CharacterControllerPanel.h index 645611f3..acff5d59 100644 --- a/Editor/src/ComponentsPanel/CharacterControllerPanel.h +++ b/Editor/src/ComponentsPanel/CharacterControllerPanel.h @@ -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() diff --git a/Nuake/src/Core/Physics/CharacterController.cpp b/Nuake/src/Core/Physics/CharacterController.cpp index 0957aad3..3a1347eb 100644 --- a/Nuake/src/Core/Physics/CharacterController.cpp +++ b/Nuake/src/Core/Physics/CharacterController.cpp @@ -6,14 +6,21 @@ namespace Nuake { namespace Physics { - CharacterController::CharacterController(float height, float radius, float mass, Vector3 position) + CharacterController::CharacterController(const Ref& 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) diff --git a/Nuake/src/Core/Physics/CharacterController.h b/Nuake/src/Core/Physics/CharacterController.h index 45addd66..ba906174 100644 --- a/Nuake/src/Core/Physics/CharacterController.h +++ b/Nuake/src/Core/Physics/CharacterController.h @@ -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 Shape; //bool m_onJumpableGround; // A bit lower contact than just onGround float m_bottomYOffset; float m_bottomRoundedRegionYOffset; - glm::vec3 m_manualVelocity; std::vector m_surfaceHitNormals; - - float m_jumpRechargeTimer; - CharacterController(float height, float radius, float mass, Vector3 position); + CharacterController(const Ref& shape, float friction, float maxSlopeAngle); void SetEntity(Entity& ent); + Entity GetEntity() const; void MoveAndSlide(glm::vec3 velocity); bool IsOnFloor() diff --git a/Nuake/src/Core/Physics/DynamicWorld.cpp b/Nuake/src/Core/Physics/DynamicWorld.cpp index daa87c8a..49328988 100644 --- a/Nuake/src/Core/Physics/DynamicWorld.cpp +++ b/Nuake/src/Core/Physics/DynamicWorld.cpp @@ -1,11 +1,11 @@ #include "DynamicWorld.h" #include "Rigibody.h" -#include "../Core/Core.h" -#include -#include +#include "src/Core/Core.h" +#include "src/Core/Logger.h" #include +#include #include "src/Vendors/glm/gtx/matrix_decompose.hpp" #include @@ -241,103 +241,21 @@ namespace Nuake void DynamicWorld::AddRigidbody(Ref 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 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 cc) { - auto settings = new JPH::CharacterSettings(); + JPH::Ref 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(_registeredBodies.data()), _registeredBodies.size()); _registeredBodies.clear(); } + + JPH::Ref DynamicWorld::GetJoltShape(const Ref 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 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(); + } } } diff --git a/Nuake/src/Core/Physics/DynamicWorld.h b/Nuake/src/Core/Physics/DynamicWorld.h index 2e8d6a76..58f45846 100644 --- a/Nuake/src/Core/Physics/DynamicWorld.h +++ b/Nuake/src/Core/Physics/DynamicWorld.h @@ -10,6 +10,7 @@ #include "CharacterController.h" #include +#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 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 _registeredBodies; + std::vector _registeredCharacters; public: DynamicWorld(); @@ -54,7 +62,7 @@ namespace Nuake void Clear(); private: - + JPH::Ref GetJoltShape(const Ref shape); }; } } diff --git a/Nuake/src/Core/Physics/PhysicsManager.cpp b/Nuake/src/Core/Physics/PhysicsManager.cpp index 8f4261cd..96ad26e0 100644 --- a/Nuake/src/Core/Physics/PhysicsManager.cpp +++ b/Nuake/src/Core/Physics/PhysicsManager.cpp @@ -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)); diff --git a/Nuake/src/Core/Physics/PhysicsShapes.cpp b/Nuake/src/Core/Physics/PhysicsShapes.cpp index aa416fc0..5009e910 100644 --- a/Nuake/src/Core/Physics/PhysicsShapes.cpp +++ b/Nuake/src/Core/Physics/PhysicsShapes.cpp @@ -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; } } diff --git a/Nuake/src/Core/Physics/Rigibody.h b/Nuake/src/Core/Physics/Rigibody.h index ebe76d66..17030073 100644 --- a/Nuake/src/Core/Physics/Rigibody.h +++ b/Nuake/src/Core/Physics/Rigibody.h @@ -20,7 +20,7 @@ namespace Nuake RigidBody(); RigidBody(glm::vec3 position, Entity handle); - RigidBody(float mass, glm::vec3 position, Matrix4 _transform, Ref shape, Entity entity, glm::vec3 initialVel = glm::vec3(0, 0, 0)); + RigidBody(float mass, glm::vec3 position, Matrix4 transform, Ref shape, Entity entity, glm::vec3 initialVel = glm::vec3(0, 0, 0)); void UpdateTransform(); diff --git a/Nuake/src/Core/Physics/Rigidbody.cpp b/Nuake/src/Core/Physics/Rigidbody.cpp index 1135022c..73583412 100644 --- a/Nuake/src/Core/Physics/Rigidbody.cpp +++ b/Nuake/src/Core/Physics/Rigidbody.cpp @@ -39,7 +39,7 @@ namespace Nuake void RigidBody::SetEntityID(Entity ent) { - + _entity = ent; } } } diff --git a/Nuake/src/Scene/Components/BSPBrushComponent.h b/Nuake/src/Scene/Components/BSPBrushComponent.h index 3ab48472..e937accf 100644 --- a/Nuake/src/Scene/Components/BSPBrushComponent.h +++ b/Nuake/src/Scene/Components/BSPBrushComponent.h @@ -29,25 +29,26 @@ namespace Nuake { Meshes = std::vector>(); Materials = std::vector>(); Rigidbody = std::vector>(); + Hulls = std::vector>(); } 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(); diff --git a/Nuake/src/Scene/Components/CharacterControllerComponent.h b/Nuake/src/Scene/Components/CharacterControllerComponent.h index 95bbccf1..b7f3cfbd 100644 --- a/Nuake/src/Scene/Components/CharacterControllerComponent.h +++ b/Nuake/src/Scene/Components/CharacterControllerComponent.h @@ -7,28 +7,36 @@ namespace Nuake { public: Ref 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; } }; diff --git a/Nuake/src/Scene/Components/MeshCollider.h b/Nuake/src/Scene/Components/MeshCollider.h index 0d813853..c821d5b8 100644 --- a/Nuake/src/Scene/Components/MeshCollider.h +++ b/Nuake/src/Scene/Components/MeshCollider.h @@ -8,6 +8,7 @@ namespace Nuake { public: int SubMesh = 0; bool IsTrigger; + Ref Shape; json Serialize() { diff --git a/Nuake/src/Scene/Environment/ProceduralSky.h b/Nuake/src/Scene/Environment/ProceduralSky.h index 829f319d..9a1f4b73 100644 --- a/Nuake/src/Scene/Environment/ProceduralSky.h +++ b/Nuake/src/Scene/Environment/ProceduralSky.h @@ -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); diff --git a/Nuake/src/Scene/Scene.cpp b/Nuake/src/Scene/Scene.cpp index 835e4c9d..460db10f 100644 --- a/Nuake/src/Scene/Scene.cpp +++ b/Nuake/src/Scene/Scene.cpp @@ -84,7 +84,7 @@ namespace Nuake { } } - assert("Not found"); + assert("Entity not found"); } bool Scene::OnInit() diff --git a/Nuake/src/Scene/Systems/PhysicsSystem.cpp b/Nuake/src/Scene/Systems/PhysicsSystem.cpp index b00eac15..29d80313 100644 --- a/Nuake/src/Scene/Systems/PhysicsSystem.cpp +++ b/Nuake/src/Scene/Systems/PhysicsSystem.cpp @@ -22,113 +22,15 @@ namespace Nuake bool PhysicsSystem::Init() { - // Create physic world. - auto view = m_Scene->m_Registry.view(); - for (auto e : view) - { - auto [transform, rigidBodyComponent] = view.get(e); - Entity ent = Entity({ e, m_Scene }); - Ref rigidBody; - if (ent.HasComponent()) - { - float mass = rigidBodyComponent.Mass; + // We need to initialize shapes first, then bodies... + InitializeShapes(); - BoxColliderComponent& boxComponent = ent.GetComponent(); - Ref boxShape = CreateRef(boxComponent.Size); - - rigidBody = CreateRef(rigidBodyComponent.Mass, transform.GetGlobalPosition(), transform.GetGlobalTransform(), boxShape, ent); - PhysicsManager::Get().RegisterBody(rigidBody); - } - - if (ent.HasComponent()) - { - auto& capsuleComponent = ent.GetComponent(); - float radius = capsuleComponent.Radius; - float height = capsuleComponent.Height; - auto capsuleShape = CreateRef(radius, height); - - rigidBody = CreateRef(rigidBodyComponent.Mass, transform.GetGlobalPosition(), transform.GetGlobalTransform(), capsuleShape, ent); - PhysicsManager::Get().RegisterBody(rigidBody); - } - - if (ent.HasComponent()) - { - float mass = rigidBodyComponent.Mass; - - const auto& component = ent.GetComponent(); - auto shape = CreateRef(component.Radius); - - rigidBody = CreateRef(rigidBodyComponent.Mass, transform.GetGlobalPosition(), transform.GetGlobalTransform(), shape, ent); - PhysicsManager::Get().RegisterBody(rigidBody); - } - - if (ent.HasComponent()) - { - if (!ent.HasComponent()) - { - Logger::Log("Cannot use mesh collider without model component", WARNING); - } - const auto& modelComponent = ent.GetComponent(); - const auto& component = ent.GetComponent(); - - if (modelComponent.ModelResource) - { - uint32_t subMeshId = component.SubMesh; - const std::vector>& submeshes = modelComponent.ModelResource->GetMeshes(); - if (subMeshId >= submeshes.size()) - { - Logger::Log("Cannot create mesh collider, invalid submesh ID", WARNING); - } - Ref mesh = submeshes[subMeshId]; - auto shape = CreateRef(mesh); - rigidBody = CreateRef(rigidBodyComponent.Mass, transform.GetGlobalPosition(), transform.GetGlobalTransform(), shape, ent); - PhysicsManager::Get().RegisterBody(rigidBody); - } - } - } - - //const auto characterControllerView = m_Scene->m_Registry.view(); - //for (auto e : characterControllerView) - //{ - // Entity ent = Entity({ e, m_Scene }); - // auto [transformComponent, ccc] = view.get(e); - - //auto& physicsObject = CreateRef(ccc.); - //} - - //// character controllers - //auto ccview = m_Scene->m_Registry.view(); - //for (auto e : ccview) - //{ - // auto [transform, cc] = ccview.get(e); - - // cc.CharacterController = CreateRef(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(); - for (auto e : bspView) - { - Entity ent = Entity({ e, m_Scene }); - auto [transform, brush, model] = bspView.get(e); - - if (!brush.IsSolid) - continue; - - for (const auto& h : brush.Hulls) - { - Ref meshShape = CreateRef(h); - Ref btRigidbody = CreateRef(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(); //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(); + for (auto e : quakeBrushesView) + { + const auto [transformComponent, brushComponent, modelComponent] = quakeBrushesView.get(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(hull); + + auto rigidBody = CreateRef(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(); + for (auto entity : boxView) + { + auto& boxComponent = boxView.get(entity); + boxComponent.Box = CreateRef(boxComponent.Size); + } + + const auto capsuleView = m_Scene->m_Registry.view(); + for (auto entity : capsuleView) + { + auto& capsuleComponent = capsuleView.get(entity); + float radius = capsuleComponent.Radius; + float height = capsuleComponent.Height; + capsuleComponent.Capsule = CreateRef(radius, height); + } + + const auto sphereView = m_Scene->m_Registry.view(); + for (auto entity : sphereView) + { + auto& sphereComponent = sphereView.get(entity); + sphereComponent.Sphere = CreateRef(sphereComponent.Radius); + } + + const auto meshColliderView = m_Scene->m_Registry.view(); + for (auto e : meshColliderView) + { + Entity entity { e, m_Scene }; + if (!entity.HasComponent()) + { + Logger::Log("Cannot use mesh collider without model component", WARNING); + } + + auto meshColliderComponent = meshColliderView.get(e); + const auto& modelComponent = entity.GetComponent(); + + if (modelComponent.ModelResource) + { + uint32_t subMeshId = meshColliderComponent.SubMesh; + const std::vector>& submeshes = modelComponent.ModelResource->GetMeshes(); + if (subMeshId >= submeshes.size()) + { + Logger::Log("Cannot create mesh collider, invalid submesh ID", WARNING); + } + + Ref mesh = submeshes[subMeshId]; + meshColliderComponent.Shape = CreateRef(mesh); + } + } + } + + void PhysicsSystem::InitializeRigidbodies() + { + auto view = m_Scene->m_Registry.view(); + for (auto e : view) + { + auto [transform, rigidBodyComponent] = view.get(e); + Entity ent = Entity({ e, m_Scene }); + Ref rigidBody; + if (ent.HasComponent()) + { + float mass = rigidBodyComponent.Mass; + + BoxColliderComponent& boxComponent = ent.GetComponent(); + Ref boxShape = CreateRef(boxComponent.Size); + + rigidBody = CreateRef(rigidBodyComponent.Mass, transform.GetGlobalPosition(), transform.GetGlobalTransform(), boxShape, ent); + PhysicsManager::Get().RegisterBody(rigidBody); + } + + if (ent.HasComponent()) + { + auto& capsuleComponent = ent.GetComponent(); + float radius = capsuleComponent.Radius; + float height = capsuleComponent.Height; + auto capsuleShape = CreateRef(radius, height); + + rigidBody = CreateRef(rigidBodyComponent.Mass, transform.GetGlobalPosition(), transform.GetGlobalTransform(), capsuleShape, ent); + PhysicsManager::Get().RegisterBody(rigidBody); + } + + if (ent.HasComponent()) + { + float mass = rigidBodyComponent.Mass; + + const auto& component = ent.GetComponent(); + auto shape = CreateRef(component.Radius); + + rigidBody = CreateRef(rigidBodyComponent.Mass, transform.GetGlobalPosition(), transform.GetGlobalTransform(), shape, ent); + PhysicsManager::Get().RegisterBody(rigidBody); + } + + if (ent.HasComponent()) + { + if (!ent.HasComponent()) + { + Logger::Log("Cannot use mesh collider without model component", WARNING); + } + const auto& modelComponent = ent.GetComponent(); + const auto& component = ent.GetComponent(); + + if (modelComponent.ModelResource) + { + uint32_t subMeshId = component.SubMesh; + const std::vector>& submeshes = modelComponent.ModelResource->GetMeshes(); + if (subMeshId >= submeshes.size()) + { + Logger::Log("Cannot create mesh collider, invalid submesh ID", WARNING); + } + Ref mesh = submeshes[subMeshId]; + auto shape = CreateRef(mesh); + rigidBody = CreateRef(rigidBodyComponent.Mass, transform.GetGlobalPosition(), transform.GetGlobalTransform(), shape, ent); + PhysicsManager::Get().RegisterBody(rigidBody); + } + } + } + } + + void PhysicsSystem::InitializeCharacterControllers() + { + auto characterControllerView = m_Scene->m_Registry.view(); + for (const auto& e : characterControllerView) + { + Entity entity = Entity({ e, m_Scene }); + auto [transformComponent, characterControllerComponent] = characterControllerView.get(e); + + if (entity.HasComponent()) + { + const auto& capsuleColliderComponent = entity.GetComponent(); + auto& capsule = capsuleColliderComponent.Capsule; + + float friction = characterControllerComponent.Friction; + float maxSlopeAngle = characterControllerComponent.MaxSlopeAngle; + auto characterController = CreateRef(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? + } + } } diff --git a/Nuake/src/Scene/Systems/PhysicsSystem.h b/Nuake/src/Scene/Systems/PhysicsSystem.h index a8d4badf..5c14c303 100644 --- a/Nuake/src/Scene/Systems/PhysicsSystem.h +++ b/Nuake/src/Scene/Systems/PhysicsSystem.h @@ -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(); }; }