From fc8628fb4fc896a0407765035bdccb682ff19586 Mon Sep 17 00:00:00 2001 From: Antoine Pilote Date: Sun, 23 Jul 2023 16:19:14 -0400 Subject: [PATCH 1/4] Added raycast to physics world --- Nuake/src/Core/Physics/DynamicWorld.cpp | 43 ++++++++++++++++++------- Nuake/src/Core/Physics/DynamicWorld.h | 13 +++++--- Nuake/src/Core/Physics/RaycastResult.h | 15 ++++----- 3 files changed, 46 insertions(+), 25 deletions(-) diff --git a/Nuake/src/Core/Physics/DynamicWorld.cpp b/Nuake/src/Core/Physics/DynamicWorld.cpp index 0cc571e3..c7c2a1c2 100644 --- a/Nuake/src/Core/Physics/DynamicWorld.cpp +++ b/Nuake/src/Core/Physics/DynamicWorld.cpp @@ -28,6 +28,10 @@ #include #include #include +#include +#include + +#include namespace Nuake { @@ -211,6 +215,7 @@ namespace Nuake _JoltPhysicsSystem = CreateRef(); _JoltPhysicsSystem->Init(MaxBodies, NumBodyMutexes, MaxBodyPairs, MaxContactConstraints, JoltBroadphaseLayerInterface, MyBroadPhaseCanCollide, MyObjectCanCollide); + // A body activation listener gets notified when bodies activate and go to sleep // Note that this is called from a job so whatever you do here needs to be thread safe. // Registering one is entirely optional. @@ -322,20 +327,36 @@ namespace Nuake return false; } - RaycastResult DynamicWorld::Raycast(const Vector3& from, const Vector3& to) + std::vector DynamicWorld::Raycast(const Vector3& from, const Vector3& to) { - Vector3 localNorm = Vector3(0,0,0); + // Create jolt ray + const auto& fromJolt = JPH::Vec3(from.x, from.y, from.z); + const auto& toJolt = JPH::Vec3(to.x, to.y, to.z); + JPH::RayCast ray { fromJolt, toJolt - fromJolt }; + JPH::AllHitCollisionCollector collector; + _JoltPhysicsSystem->GetBroadPhaseQuery().CastRay(ray, collector); - //Logger::Log("normal: x:" + std::to_string(localNorm.x) + " y:" + std::to_string(localNorm.y )+ "z: " + std::to_string(localNorm.z)); - - // Map bullet result to dto. - RaycastResult result{ - Vector3(0,0,0), - Vector3(0,0,0), - localNorm - }; + // Fetch results + int num_hits = (int)collector.mHits.size(); + JPH::BroadPhaseCastResult* results = collector.mHits.data(); - return result; + // Format result + std::vector raycastResults; + for (int i = 0; i < num_hits; ++i) + { + const float hitFraction = results[i].mFraction; + const JPH::Vec3& hitPosition = ray.GetPointOnRay(results[i].mFraction); + + RaycastResult result + { + Vector3(hitPosition.GetX(), hitPosition.GetY(), hitPosition.GetZ()), + hitFraction + }; + + raycastResults.push_back(std::move(result)); + } + + return raycastResults; } void DynamicWorld::SyncEntitiesTranforms() diff --git a/Nuake/src/Core/Physics/DynamicWorld.h b/Nuake/src/Core/Physics/DynamicWorld.h index bbb5c05c..2336bdf5 100644 --- a/Nuake/src/Core/Physics/DynamicWorld.h +++ b/Nuake/src/Core/Physics/DynamicWorld.h @@ -1,8 +1,9 @@ #pragma once +#include "src/Core/Core.h" +#include "src/Core/Timestep.h" + #include #include "Rigibody.h" -#include "src/Core/Timestep.h" -#include "src/Core/Core.h" #include #include "RaycastResult.h" @@ -10,7 +11,7 @@ #include "CharacterController.h" #include -#include "src/Core/Core.h" + namespace JPH { class PhysicsSystem; @@ -32,7 +33,8 @@ namespace Nuake class MyContactListener; class MyBodyActivationListener; - namespace Physics { + namespace Physics + { class DynamicWorld { private: @@ -47,6 +49,7 @@ namespace Nuake std::vector _registeredBodies; std::map _registeredCharacters; + public: DynamicWorld(); @@ -62,7 +65,7 @@ namespace Nuake void MoveAndSlideCharacterController(const Entity& entity, const Vector3& velocity); void AddForceToRigidBody(const Entity& entity, const Vector3& force); - RaycastResult Raycast(const Vector3& from, const Vector3& to); + std::vector Raycast(const Vector3& from, const Vector3& to); void StepSimulation(Timestep ts); void Clear(); diff --git a/Nuake/src/Core/Physics/RaycastResult.h b/Nuake/src/Core/Physics/RaycastResult.h index be12f90c..6760ceaa 100644 --- a/Nuake/src/Core/Physics/RaycastResult.h +++ b/Nuake/src/Core/Physics/RaycastResult.h @@ -7,14 +7,11 @@ namespace Nuake { namespace Physics { - + // result object from raycast. + struct RaycastResult + { + Vector3 WorldPosition; + float Fraction; + }; } - - - // result object from raycast. - struct RaycastResult { - Vector3 WorldPoint; - Vector3 LocalPoint; - Vector3 Normal; - }; } From 5103101a0d09edb01872f03a11b3244d7ba214fc Mon Sep 17 00:00:00 2001 From: Antoine Pilote Date: Mon, 24 Jul 2023 00:56:27 -0400 Subject: [PATCH 2/4] Added wren binding to raycast function --- Editor/resources/Scripts/Scene.wren | 14 +++++ Editor/src/Windows/WelcomeWindow.cpp | 8 +-- Nuake/src/Core/Physics/PhysicsManager.cpp | 2 +- Nuake/src/Core/Physics/PhysicsManager.h | 2 +- Nuake/src/Core/Physics/RaycastResult.h | 13 ++-- Nuake/src/Scripting/Modules/PhysicsModule.h | 66 ++++++++++----------- Nuake/src/Scripting/Modules/SceneModule.h | 38 +++++++++++- 7 files changed, 92 insertions(+), 51 deletions(-) diff --git a/Editor/resources/Scripts/Scene.wren b/Editor/resources/Scripts/Scene.wren index 64aa3c93..3a4d0a3f 100644 --- a/Editor/resources/Scripts/Scene.wren +++ b/Editor/resources/Scripts/Scene.wren @@ -75,6 +75,20 @@ class Scene { // RigidBody foreign static AddForce_(e, x, y, z) + // Physics + static RayCast(from, to) { + var results = Scene.RayCast_(from.x, from.y, from.z, to.x, to.y, to.z) + + var points = [] + for(r in results.count / 3) { + points.add(Vector3.new(points[r], points[r + 1], points[r + 2])) + } + + return points + } + + foreign static RayCast_(fromX, fromY, fromZ, toX, toY, toZ) + foreign static TriggerGetOverlappingBodyCount_(e) foreign static TriggerGetOverlappingBodies_(e) diff --git a/Editor/src/Windows/WelcomeWindow.cpp b/Editor/src/Windows/WelcomeWindow.cpp index 19cd126d..927a4728 100644 --- a/Editor/src/Windows/WelcomeWindow.cpp +++ b/Editor/src/Windows/WelcomeWindow.cpp @@ -84,6 +84,7 @@ namespace Nuake void WelcomeWindow::LoadQueuedProject() { + FileSystem::SetRootDirectory(FileSystem::GetParentPath(queuedProjectPath)); auto project = Project::New(); auto projectFileData = FileSystem::ReadFile(queuedProjectPath, true); try @@ -274,14 +275,9 @@ namespace Nuake { assert(SelectedProject < std::size(_Projects)); - using namespace Nuake; - SaveRecentFile(); - std::string projectPath = _Projects[SelectedProject].Path; - FileSystem::SetRootDirectory(FileSystem::GetParentPath(projectPath)); - - queuedProjectPath = projectPath; + queuedProjectPath = _Projects[SelectedProject].Path;; } } } diff --git a/Nuake/src/Core/Physics/PhysicsManager.cpp b/Nuake/src/Core/Physics/PhysicsManager.cpp index ae3e9ce2..c7cc2ea4 100644 --- a/Nuake/src/Core/Physics/PhysicsManager.cpp +++ b/Nuake/src/Core/Physics/PhysicsManager.cpp @@ -37,7 +37,7 @@ namespace Nuake m_World->Clear(); } - RaycastResult PhysicsManager::Raycast(const Vector3& from, const Vector3& to) + std::vector PhysicsManager::Raycast(const Vector3& from, const Vector3& to) { return m_World->Raycast(from, to); } diff --git a/Nuake/src/Core/Physics/PhysicsManager.h b/Nuake/src/Core/Physics/PhysicsManager.h index 3934a07c..2946a036 100644 --- a/Nuake/src/Core/Physics/PhysicsManager.h +++ b/Nuake/src/Core/Physics/PhysicsManager.h @@ -45,7 +45,7 @@ namespace Nuake void Reset(); - RaycastResult Raycast(const Vector3& from, const Vector3& to); + std::vector Raycast(const Vector3& from, const Vector3& to); void RegisterBody(Ref rb); void RegisterGhostBody(Ref rb); diff --git a/Nuake/src/Core/Physics/RaycastResult.h b/Nuake/src/Core/Physics/RaycastResult.h index 6760ceaa..7a77e470 100644 --- a/Nuake/src/Core/Physics/RaycastResult.h +++ b/Nuake/src/Core/Physics/RaycastResult.h @@ -5,13 +5,10 @@ namespace Nuake { - namespace Physics + // result object from raycast. + struct RaycastResult { - // result object from raycast. - struct RaycastResult - { - Vector3 WorldPosition; - float Fraction; - }; - } + Vector3 WorldPosition; + float Fraction; + }; } diff --git a/Nuake/src/Scripting/Modules/PhysicsModule.h b/Nuake/src/Scripting/Modules/PhysicsModule.h index 621750bb..5fb11514 100644 --- a/Nuake/src/Scripting/Modules/PhysicsModule.h +++ b/Nuake/src/Scripting/Modules/PhysicsModule.h @@ -28,39 +28,39 @@ namespace Nuake static void Raycast(WrenVM* vm) { - Vector3 v1 = Vector3(wrenGetSlotDouble(vm, 1), - wrenGetSlotDouble(vm, 2), - wrenGetSlotDouble(vm, 3)); - Vector3 v2 = Vector3(wrenGetSlotDouble(vm, 4), - wrenGetSlotDouble(vm, 5), - wrenGetSlotDouble(vm, 6)); - - RaycastResult result = PhysicsManager::Get().Raycast(v1, v2); - wrenSetSlotNewList(vm, 0); - - // Returns a list with 3 vectors placed sequentially - // should be reconstructed in the wren side. - wrenSetSlotDouble(vm, 1, result.LocalPoint.x); - wrenSetSlotDouble(vm, 2, result.LocalPoint.y); - wrenSetSlotDouble(vm, 3, result.LocalPoint.z); - - wrenSetSlotDouble(vm, 4, result.WorldPoint.x); - wrenSetSlotDouble(vm, 5, result.WorldPoint.y); - wrenSetSlotDouble(vm, 6, result.WorldPoint.z); - - wrenSetSlotDouble(vm, 7, result.Normal.x); - wrenSetSlotDouble(vm, 8, result.Normal.y); - wrenSetSlotDouble(vm, 9, result.Normal.z); - - wrenInsertInList(vm, 0, -1, 1); - wrenInsertInList(vm, 0, -1, 2); - wrenInsertInList(vm, 0, -1, 3); - wrenInsertInList(vm, 0, -1, 4); - wrenInsertInList(vm, 0, -1, 5); - wrenInsertInList(vm, 0, -1, 6); - wrenInsertInList(vm, 0, -1, 7); - wrenInsertInList(vm, 0, -1, 8); - wrenInsertInList(vm, 0, -1, 9); + //Vector3 v1 = Vector3(wrenGetSlotDouble(vm, 1), + // wrenGetSlotDouble(vm, 2), + // wrenGetSlotDouble(vm, 3)); + //Vector3 v2 = Vector3(wrenGetSlotDouble(vm, 4), + // wrenGetSlotDouble(vm, 5), + // wrenGetSlotDouble(vm, 6)); + // + //RaycastResult result = PhysicsManager::Get().Raycast(v1, v2); + //wrenSetSlotNewList(vm, 0); + // + //// Returns a list with 3 vectors placed sequentially + //// should be reconstructed in the wren side. + //wrenSetSlotDouble(vm, 1, result.LocalPoint.x); + //wrenSetSlotDouble(vm, 2, result.LocalPoint.y); + //wrenSetSlotDouble(vm, 3, result.LocalPoint.z); + // + //wrenSetSlotDouble(vm, 4, result.WorldPoint.x); + //wrenSetSlotDouble(vm, 5, result.WorldPoint.y); + //wrenSetSlotDouble(vm, 6, result.WorldPoint.z); + // + //wrenSetSlotDouble(vm, 7, result.Normal.x); + //wrenSetSlotDouble(vm, 8, result.Normal.y); + //wrenSetSlotDouble(vm, 9, result.Normal.z); + // + //wrenInsertInList(vm, 0, -1, 1); + //wrenInsertInList(vm, 0, -1, 2); + //wrenInsertInList(vm, 0, -1, 3); + //wrenInsertInList(vm, 0, -1, 4); + //wrenInsertInList(vm, 0, -1, 5); + //wrenInsertInList(vm, 0, -1, 6); + //wrenInsertInList(vm, 0, -1, 7); + //wrenInsertInList(vm, 0, -1, 8); + //wrenInsertInList(vm, 0, -1, 9); } }; } diff --git a/Nuake/src/Scripting/Modules/SceneModule.h b/Nuake/src/Scripting/Modules/SceneModule.h index c15f109f..a3e17a8b 100644 --- a/Nuake/src/Scripting/Modules/SceneModule.h +++ b/Nuake/src/Scripting/Modules/SceneModule.h @@ -23,8 +23,10 @@ #include #include -namespace Nuake { - namespace ScriptAPI { +namespace Nuake +{ + namespace ScriptAPI + { class SceneModule : public ScriptModule { std::string GetModuleName() override @@ -56,6 +58,7 @@ namespace Nuake { RegisterMethod("MoveAndSlide_(_,_,_,_)", (void*)MoveAndSlide); RegisterMethod("IsCharacterControllerOnGround_(_)", (void*)IsCharacterControllerOnGround); + RegisterMethod("RayCast_(_,_,_,_,_,_)", (void*)Raycast); RegisterMethod("AddForce_(_,_,_,_)", (void*)AddForce); @@ -249,6 +252,37 @@ namespace Nuake { wrenSetSlotBool(vm, 0, result); } + static void Raycast(WrenVM* vm) + { + const double& fromX = wrenGetSlotDouble(vm, 1); + const double& fromY = wrenGetSlotDouble(vm, 2); + const double& fromZ = wrenGetSlotDouble(vm, 3); + const auto& from = Vector3(fromX, fromY, fromZ); + + const double& toX = wrenGetSlotDouble(vm, 4); + const double& toY = wrenGetSlotDouble(vm, 5); + const double& toZ = wrenGetSlotDouble(vm, 6); + const auto& to = Vector3(toX, toY, toZ); + + const auto& result = PhysicsManager::Get().GetWorld()->Raycast(from, to); + + // We multiply by 3 since we have 3 floats per hit result: vector3. + wrenEnsureSlots(vm, static_cast(result.size() * 3)); + wrenSetSlotNewList(vm, 0); + + uint32_t index = 1; + for (auto& r : result) + { + wrenSetSlotDouble(vm, index, r.WorldPosition.x); + wrenSetSlotDouble(vm, index + 1, r.WorldPosition.y); + wrenSetSlotDouble(vm, index + 2, r.WorldPosition.z); + wrenInsertInList(vm, 0, -1, index); + wrenInsertInList(vm, 0, -1, index + 1); + wrenInsertInList(vm, 0, -1, index + 2); + index += 3; + } + } + static void MoveAndSlide(WrenVM* vm) { double handle = wrenGetSlotDouble(vm, 1); From c637bd18ab955338fd3e488a126a72a0114dbb3b Mon Sep 17 00:00:00 2001 From: Antoine Pilote Date: Fri, 28 Jul 2023 13:11:24 -0400 Subject: [PATCH 3/4] Fixed wren api, packing into vec3 --- Editor/resources/Scripts/Scene.wren | 14 +++++++++++--- Nuake/src/Scripting/Modules/SceneModule.h | 1 + 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/Editor/resources/Scripts/Scene.wren b/Editor/resources/Scripts/Scene.wren index 3a4d0a3f..88db8711 100644 --- a/Editor/resources/Scripts/Scene.wren +++ b/Editor/resources/Scripts/Scene.wren @@ -77,11 +77,19 @@ class Scene { // Physics static RayCast(from, to) { + // Fetch results from physics manager, returns a list of floats + // that we need to unpack into vector3 var results = Scene.RayCast_(from.x, from.y, from.z, to.x, to.y, to.z) - var points = [] - for(r in results.count / 3) { - points.add(Vector3.new(points[r], points[r + 1], points[r + 2])) + var points = [] // Result array of vec3 + + var size = results.count / 3 + var i = 0 + while(i < size) { + // size is base 1 while array is base 0, offset by 1 + var listIndex = i - 1 + points.add(Vector3.new(results[listIndex], results[listIndex + 1], results[listIndex + 2])) + i = i + 1 } return points diff --git a/Nuake/src/Scripting/Modules/SceneModule.h b/Nuake/src/Scripting/Modules/SceneModule.h index a3e17a8b..4f8293b8 100644 --- a/Nuake/src/Scripting/Modules/SceneModule.h +++ b/Nuake/src/Scripting/Modules/SceneModule.h @@ -194,6 +194,7 @@ namespace Nuake double x = wrenGetSlotDouble(vm, 2); double y = wrenGetSlotDouble(vm, 3); double z = wrenGetSlotDouble(vm, 4); + Entity ent = Entity((entt::entity)handle, Engine::GetCurrentScene().get()); auto& cam = ent.GetComponent(); cam.CameraInstance->SetDirection(Vector3(x, y, z)); From f12ae4580c2ba6ef9db5ed8561bd09594f06d4ce Mon Sep 17 00:00:00 2001 From: Antoine Pilote Date: Fri, 28 Jul 2023 13:13:20 -0400 Subject: [PATCH 4/4] Removed old raycast --- Nuake/src/Scripting/Modules/PhysicsModule.h | 34 +-------------------- 1 file changed, 1 insertion(+), 33 deletions(-) diff --git a/Nuake/src/Scripting/Modules/PhysicsModule.h b/Nuake/src/Scripting/Modules/PhysicsModule.h index 5fb11514..5d3e4ad5 100644 --- a/Nuake/src/Scripting/Modules/PhysicsModule.h +++ b/Nuake/src/Scripting/Modules/PhysicsModule.h @@ -28,39 +28,7 @@ namespace Nuake static void Raycast(WrenVM* vm) { - //Vector3 v1 = Vector3(wrenGetSlotDouble(vm, 1), - // wrenGetSlotDouble(vm, 2), - // wrenGetSlotDouble(vm, 3)); - //Vector3 v2 = Vector3(wrenGetSlotDouble(vm, 4), - // wrenGetSlotDouble(vm, 5), - // wrenGetSlotDouble(vm, 6)); - // - //RaycastResult result = PhysicsManager::Get().Raycast(v1, v2); - //wrenSetSlotNewList(vm, 0); - // - //// Returns a list with 3 vectors placed sequentially - //// should be reconstructed in the wren side. - //wrenSetSlotDouble(vm, 1, result.LocalPoint.x); - //wrenSetSlotDouble(vm, 2, result.LocalPoint.y); - //wrenSetSlotDouble(vm, 3, result.LocalPoint.z); - // - //wrenSetSlotDouble(vm, 4, result.WorldPoint.x); - //wrenSetSlotDouble(vm, 5, result.WorldPoint.y); - //wrenSetSlotDouble(vm, 6, result.WorldPoint.z); - // - //wrenSetSlotDouble(vm, 7, result.Normal.x); - //wrenSetSlotDouble(vm, 8, result.Normal.y); - //wrenSetSlotDouble(vm, 9, result.Normal.z); - // - //wrenInsertInList(vm, 0, -1, 1); - //wrenInsertInList(vm, 0, -1, 2); - //wrenInsertInList(vm, 0, -1, 3); - //wrenInsertInList(vm, 0, -1, 4); - //wrenInsertInList(vm, 0, -1, 5); - //wrenInsertInList(vm, 0, -1, 6); - //wrenInsertInList(vm, 0, -1, 7); - //wrenInsertInList(vm, 0, -1, 8); - //wrenInsertInList(vm, 0, -1, 9); + } }; }