mirror of
https://github.com/antopilo/Nuake.git
synced 2026-09-09 20:08:57 +03:00
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:
@@ -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()
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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;
|
||||
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()
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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));
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
|
||||
|
||||
@@ -39,7 +39,7 @@ namespace Nuake
|
||||
|
||||
void RigidBody::SetEntityID(Entity ent)
|
||||
{
|
||||
|
||||
_entity = ent;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -8,6 +8,7 @@ namespace Nuake {
|
||||
public:
|
||||
int SubMesh = 0;
|
||||
bool IsTrigger;
|
||||
Ref<Physics::MeshShape> Shape;
|
||||
|
||||
json Serialize()
|
||||
{
|
||||
|
||||
@@ -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?
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
};
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user