mirror of
https://github.com/antopilo/Nuake.git
synced 2026-09-04 11:35:06 +03:00
Character controller now moving! 🏃♂️
- Added character controller transform syncing Jolt -> Scene - Physic system code cleanup - Fixed crash with WrenScript loading - Fixed Normalize() returning NaN vector when lenght is 0
This commit is contained in:
@@ -108,10 +108,14 @@ class Vector3 {
|
||||
|
||||
Normalize() {
|
||||
var length = this.Length()
|
||||
var x = _x / length
|
||||
var y = _y / length
|
||||
var z = _z / length
|
||||
return Vector3.new(x, y, z)
|
||||
if(length > 0.0) {
|
||||
var x = _x / length
|
||||
var y = _y / length
|
||||
var z = _z / length
|
||||
return Vector3.new(x, y, z)
|
||||
}
|
||||
|
||||
return Vector3.new(0, 0, 0)
|
||||
}
|
||||
|
||||
Angle(vec) {
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
* Scripting API for editing UI maybe
|
||||
* Launch game standalone
|
||||
* Fix physics system
|
||||
* --play argument rendering in framebuffer
|
||||
*/
|
||||
|
||||
// Welcome to the Nuake source code.
|
||||
|
||||
@@ -2,6 +2,8 @@
|
||||
#include "src/Core/Physics/PhysicsManager.h"
|
||||
#include "src/Core/Physics/RaycastResult.h"
|
||||
|
||||
#include "src/Core/Physics/PhysicsManager.h"
|
||||
|
||||
namespace Nuake
|
||||
{
|
||||
namespace Physics
|
||||
@@ -23,12 +25,9 @@ namespace Nuake
|
||||
return Owner;
|
||||
}
|
||||
|
||||
void CharacterController::MoveAndSlide(glm::vec3 velocity)
|
||||
void CharacterController::MoveAndSlide(const Vector3& velocity)
|
||||
{
|
||||
IsOnGround = false;
|
||||
ParseGhostContacts();
|
||||
UpdatePosition();
|
||||
UpdateVelocity();
|
||||
PhysicsManager::Get().GetWorld()->MoveAndSlideCharacterController(Owner, velocity);
|
||||
}
|
||||
|
||||
void CharacterController::ParseGhostContacts()
|
||||
@@ -44,8 +43,6 @@ namespace Nuake
|
||||
|
||||
void CharacterController::UpdateVelocity()
|
||||
{
|
||||
|
||||
|
||||
// Decelerate
|
||||
//m_manualVelocity -= m_manualVelocity * m_deceleration * m_pPhysicsWorld->GetScene()->m_frameTimer.GetTimeMultiplier();
|
||||
|
||||
|
||||
@@ -37,7 +37,7 @@ namespace Nuake
|
||||
|
||||
void SetEntity(Entity& ent);
|
||||
Entity GetEntity() const;
|
||||
void MoveAndSlide(glm::vec3 velocity);
|
||||
void MoveAndSlide(const Vector3& velocity);
|
||||
|
||||
bool IsOnFloor()
|
||||
{
|
||||
|
||||
@@ -4,6 +4,8 @@
|
||||
#include "src/Core/Core.h"
|
||||
#include "src/Core/Logger.h"
|
||||
#include <src/Core/Physics/PhysicsShapes.h>
|
||||
#include "src/Scene/Components/TransformComponent.h"
|
||||
#include "src/Scene/Components/CharacterControllerComponent.h"
|
||||
|
||||
#include <src/Vendors/glm/ext/quaternion_common.hpp>
|
||||
#include "src/Vendors/glm/gtx/matrix_decompose.hpp"
|
||||
@@ -198,6 +200,9 @@ namespace Nuake
|
||||
{
|
||||
DynamicWorld::DynamicWorld() : _stepCount(0)
|
||||
{
|
||||
_registeredCharacters = std::map<uint32_t, JPH::Character*>();
|
||||
|
||||
// Initialize Jolt Physics
|
||||
const uint32_t MaxBodies = 1024;
|
||||
const uint32_t NumBodyMutexes = 0;
|
||||
const uint32_t MaxBodyPairs = 1024;
|
||||
@@ -265,8 +270,8 @@ namespace Nuake
|
||||
|
||||
bodySettings.mUserData = rb->GetEntity().GetID();
|
||||
// Create the actual rigid body
|
||||
JPH::BodyID floor = _JoltBodyInterface->CreateAndAddBody(bodySettings, JPH::EActivation::Activate); // Note that if we run out of bodies this can return nullptr
|
||||
_registeredBodies.push_back((uint32_t)floor.GetIndexAndSequenceNumber());
|
||||
JPH::BodyID body = _JoltBodyInterface->CreateAndAddBody(bodySettings, JPH::EActivation::Activate); // Note that if we run out of bodies this can return nullptr
|
||||
_registeredBodies.push_back((uint32_t)body.GetIndexAndSequenceNumber());
|
||||
}
|
||||
|
||||
void DynamicWorld::AddGhostbody(Ref<GhostObject> gb)
|
||||
@@ -286,6 +291,9 @@ namespace Nuake
|
||||
JPH::Character* character = new JPH::Character(settings, joltPos, JPH::Quat::sIdentity(), cc->GetEntity().GetID() , _JoltPhysicsSystem.get());
|
||||
|
||||
character->AddToPhysicsSystem(JPH::EActivation::Activate);
|
||||
|
||||
// To get the jolt character control from a scene entity.
|
||||
_registeredCharacters[cc->Owner.GetHandle()] = character;
|
||||
}
|
||||
|
||||
RaycastResult DynamicWorld::Raycast(glm::vec3 from, glm::vec3 to)
|
||||
@@ -304,12 +312,9 @@ namespace Nuake
|
||||
return result;
|
||||
}
|
||||
|
||||
void DynamicWorld::StepSimulation(Timestep ts)
|
||||
void DynamicWorld::SyncEntitiesTranforms()
|
||||
{
|
||||
// Next step
|
||||
++_stepCount;
|
||||
const auto& bodyInterface = _JoltPhysicsSystem->GetBodyInterface();
|
||||
|
||||
for (const auto& body : _registeredBodies)
|
||||
{
|
||||
auto bodyId = static_cast<JPH::BodyID>(body);
|
||||
@@ -339,14 +344,52 @@ namespace Nuake
|
||||
transformComponent.SetLocalRotation(Quat(bodyRotation.GetW(), bodyRotation.GetX(), bodyRotation.GetY(), bodyRotation.GetZ()));
|
||||
transformComponent.SetLocalTransform(transform);
|
||||
transformComponent.Dirty = false;
|
||||
|
||||
/* Logging
|
||||
const std::string& name = entity.GetComponent<NameComponent>().Name;
|
||||
const std::string& posStr = "(" + std::to_string(pos.x) + ", " + std::to_string(pos.y) + ", " + std::to_string(pos.z) + ")";
|
||||
const std::string& logMsg = "Physics pos: " + name + " at " + posStr;
|
||||
Logger::Log(logMsg);
|
||||
*/
|
||||
}
|
||||
}
|
||||
|
||||
void DynamicWorld::SyncCharactersTransforms()
|
||||
{
|
||||
// TODO(ANTO): Finish this to connect updated jolt transforms back to the entity.
|
||||
// The problem was that I dont know yet how to go from jolt body ptr to the entity
|
||||
// Combinations of find and iterators etc. I do not have the brain power rn zzz.
|
||||
// const auto& bodyInterface = _JoltPhysicsSystem->GetBodyInterface();
|
||||
|
||||
for (const auto& e : _registeredCharacters)
|
||||
{
|
||||
Entity entity { (entt::entity)e.first, Engine::GetCurrentScene().get()};
|
||||
|
||||
JPH::Character* characterController = e.second;
|
||||
JPH::Mat44 joltTransform = characterController->GetWorldTransform();
|
||||
const auto bodyRotation = characterController->GetRotation();
|
||||
|
||||
Matrix4 transform = glm::mat4(
|
||||
joltTransform(0, 0), joltTransform(1, 0), joltTransform(2, 0), joltTransform(3, 0),
|
||||
joltTransform(0, 1), joltTransform(1, 1), joltTransform(2, 1), joltTransform(3, 1),
|
||||
joltTransform(0, 2), joltTransform(1, 2), joltTransform(2, 2), joltTransform(3, 2),
|
||||
joltTransform(0, 3), joltTransform(1, 3), joltTransform(2, 3), joltTransform(3, 3)
|
||||
);
|
||||
|
||||
Vector3 scale = Vector3();
|
||||
Quat rotation = Quat();
|
||||
Vector3 pos = Vector3();
|
||||
Vector3 skew = Vector3();
|
||||
Vector4 pesp = Vector4();
|
||||
glm::decompose(transform, scale, rotation, pos, skew, pesp);
|
||||
|
||||
auto& transformComponent = entity.GetComponent<TransformComponent>();
|
||||
transformComponent.SetLocalPosition(pos);
|
||||
transformComponent.SetLocalRotation(Quat(bodyRotation.GetW(), bodyRotation.GetX(), bodyRotation.GetY(), bodyRotation.GetZ()));
|
||||
transformComponent.SetLocalTransform(transform);
|
||||
transformComponent.Dirty = false;
|
||||
}
|
||||
}
|
||||
|
||||
void DynamicWorld::StepSimulation(Timestep ts)
|
||||
{
|
||||
// Next step
|
||||
++_stepCount;
|
||||
SyncEntitiesTranforms();
|
||||
SyncCharactersTransforms();
|
||||
|
||||
// If you take larger steps than 1 / 60th of a second you need to do multiple collision steps in order to keep the simulation stable.
|
||||
// Do 1 collision step per 1 / 60th of a second (round up).
|
||||
@@ -364,6 +407,7 @@ namespace Nuake
|
||||
_JoltPhysicsSystem->Update(ts, collisionSteps, subSteps, new JPH::TempAllocatorMalloc(), _JoltJobSystem);
|
||||
}
|
||||
|
||||
|
||||
void DynamicWorld::Clear()
|
||||
{
|
||||
_stepCount = 0;
|
||||
@@ -377,6 +421,54 @@ namespace Nuake
|
||||
_registeredBodies.clear();
|
||||
}
|
||||
|
||||
void DynamicWorld::MoveAndSlideCharacterController(const Entity& entity, const Vector3 velocity)
|
||||
{
|
||||
const uint32_t entityHandle = entity.GetHandle();
|
||||
if (_registeredCharacters.find(entityHandle) != _registeredCharacters.end())
|
||||
{
|
||||
auto& characterController = _registeredCharacters[entityHandle];
|
||||
characterController->SetLinearVelocity(JPH::Vec3(velocity.x, velocity.y, velocity.z));
|
||||
}
|
||||
}
|
||||
|
||||
const Matrix4& DynamicWorld::GetCharacterControllerSimulatedTransform(const Entity& entity)
|
||||
{
|
||||
const uint32_t entityHandle = entity.GetHandle();
|
||||
if (_registeredCharacters.find(entityHandle) != _registeredCharacters.end())
|
||||
{
|
||||
auto& characterController = _registeredCharacters[entityHandle];
|
||||
|
||||
JPH::Mat44 joltTransform = characterController->GetWorldTransform();
|
||||
const auto bodyRotation = characterController->GetRotation();
|
||||
|
||||
Matrix4 transform = glm::mat4(
|
||||
joltTransform(0, 0), joltTransform(1, 0), joltTransform(2, 0), joltTransform(3, 0),
|
||||
joltTransform(0, 1), joltTransform(1, 1), joltTransform(2, 1), joltTransform(3, 1),
|
||||
joltTransform(0, 2), joltTransform(1, 2), joltTransform(2, 2), joltTransform(3, 2),
|
||||
joltTransform(0, 3), joltTransform(1, 3), joltTransform(2, 3), joltTransform(3, 3)
|
||||
);
|
||||
|
||||
|
||||
return transform;
|
||||
|
||||
//Vector3 scale = Vector3();
|
||||
//Quat rotation = Quat();
|
||||
//Vector3 pos = Vector3();
|
||||
//Vector3 skew = Vector3();
|
||||
//Vector4 pesp = Vector4();
|
||||
//glm::decompose(transform, scale, rotation, pos, skew, pesp);
|
||||
|
||||
//auto& transformComponent = entity.GetComponent<TransformComponent>();
|
||||
//transformComponent.SetLocalPosition(pos);
|
||||
//transformComponent.SetLocalRotation(Quat(bodyRotation.GetW(), bodyRotation.GetX(), bodyRotation.GetY(), bodyRotation.GetZ()));
|
||||
//transformComponent.SetLocalTransform(transform);
|
||||
//transformComponent.Dirty = false;
|
||||
}
|
||||
|
||||
assert("Shouldn't have reached here!");
|
||||
return Matrix4(1.0);
|
||||
}
|
||||
|
||||
JPH::Ref<JPH::Shape> DynamicWorld::GetJoltShape(const Ref<PhysicShape> shape)
|
||||
{
|
||||
JPH::ShapeSettings::ShapeResult result;
|
||||
@@ -426,8 +518,8 @@ namespace Nuake
|
||||
|
||||
JPH::TriangleList triangles;
|
||||
triangles.reserve(indices.size());
|
||||
Matrix4 transform; //rb->_transform;
|
||||
transform[3] = Vector4(0, 0, 0, 1.0f);
|
||||
auto transform = Matrix4(1.0f);
|
||||
transform[3] = Vector4(0.0f, 0.0f, 0.0f, 1.0f);
|
||||
for (int i = 0; i < indices.size() - 3; i += 3)
|
||||
{
|
||||
const Vector3& p1 = vertices[indices[i]].position;
|
||||
@@ -448,7 +540,6 @@ namespace Nuake
|
||||
case CONVEX_HULL:
|
||||
{
|
||||
auto* convexHullShape = (Physics::ConvexHullShape*)shape.get();
|
||||
|
||||
const auto& hullPoints = convexHullShape->GetPoints();
|
||||
JPH::Array<JPH::Vec3> points;
|
||||
points.reserve(std::size(hullPoints));
|
||||
|
||||
@@ -19,6 +19,7 @@ namespace JPH
|
||||
class BodyActivationListener;
|
||||
class BodyInterface;
|
||||
class Shape;
|
||||
class Character;
|
||||
|
||||
template<class T>
|
||||
class Ref;
|
||||
@@ -45,7 +46,7 @@ namespace Nuake
|
||||
BPLayerInterfaceImpl* _JoltBroadphaseLayerInterface;
|
||||
|
||||
std::vector<uint32_t> _registeredBodies;
|
||||
std::vector<uint32_t> _registeredCharacters;
|
||||
std::map<uint32_t, JPH::Character*> _registeredCharacters;
|
||||
public:
|
||||
DynamicWorld();
|
||||
|
||||
@@ -57,13 +58,18 @@ namespace Nuake
|
||||
void AddGhostbody(Ref<GhostObject> gb);
|
||||
void AddCharacterController(Ref<CharacterController> cc);
|
||||
|
||||
// This is going to be ugly. TODO: Find a better way that passing itself as a parameter
|
||||
void MoveAndSlideCharacterController(const Entity& entity, const Vector3 velocity);
|
||||
|
||||
const Matrix4& GetCharacterControllerSimulatedTransform(const Entity& entity);
|
||||
RaycastResult Raycast(glm::vec3 from, glm::vec3 to);
|
||||
void StepSimulation(Timestep ts);
|
||||
void Clear();
|
||||
|
||||
private:
|
||||
JPH::Ref<JPH::Shape> GetJoltShape(const Ref<PhysicShape> shape);
|
||||
void SyncEntitiesTranforms();
|
||||
void SyncCharactersTransforms();
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -20,7 +20,6 @@ namespace Nuake
|
||||
void PhysicsManager::RegisterGhostBody(Ref<GhostObject> rb)
|
||||
{
|
||||
m_World->AddGhostbody(rb);
|
||||
|
||||
}
|
||||
|
||||
void PhysicsManager::RegisterCharacterController(Ref<Physics::CharacterController> cc)
|
||||
|
||||
@@ -9,11 +9,12 @@ namespace Nuake {
|
||||
std::string Script;
|
||||
|
||||
unsigned int mModule = 0;
|
||||
Ref<WrenScript> mWrenScript;
|
||||
Ref<WrenScript> mWrenScript = nullptr;
|
||||
|
||||
void LoadScript(const std::string& path)
|
||||
{
|
||||
Ref<Nuake::File> nuakeFile = Nuake::FileSystem::GetFile(Script);
|
||||
Script = path;
|
||||
Ref<Nuake::File> nuakeFile = Nuake::FileSystem::GetFile(path);
|
||||
mWrenScript = CreateRef<Nuake::WrenScript>(nuakeFile, true);
|
||||
auto modules = mWrenScript->GetModules();
|
||||
if (modules.size() > 0)
|
||||
|
||||
@@ -17,7 +17,7 @@ namespace Nuake
|
||||
|
||||
void AddChild(Entity ent);
|
||||
|
||||
int GetHandle() { return (int)m_EntityHandle; }
|
||||
int GetHandle() const { return (int)m_EntityHandle; }
|
||||
int GetID() { return GetComponent<NameComponent>().ID; }
|
||||
|
||||
template<typename T>
|
||||
|
||||
@@ -108,7 +108,7 @@ namespace Nuake {
|
||||
wrenGetSlotDouble(vm, 3));
|
||||
|
||||
float length = glm::length(v1);
|
||||
wrenSetSlotDouble(vm, 0, glm::length(v1));
|
||||
wrenSetSlotDouble(vm, 0, length);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@@ -77,7 +77,6 @@ namespace Nuake {
|
||||
if (name == "Transform") result = ent.HasComponent<TransformComponent>();
|
||||
if (name == "Light") result = ent.HasComponent<LightComponent>();
|
||||
if (name == "QuakeMap") result = ent.HasComponent<QuakeMapComponent>();
|
||||
|
||||
if (name == "CharacterController")
|
||||
{
|
||||
result = ent.HasComponent<CharacterControllerComponent>();
|
||||
|
||||
Reference in New Issue
Block a user