From f857d8e79190df20a53c4565868b4b7de0112c73 Mon Sep 17 00:00:00 2001 From: Atdunbg Date: Sat, 10 Jan 2026 14:48:17 +0800 Subject: [PATCH] move imgui property code and Pysics Actor code to a single file --- ExampleApp/Src/FPSPlayer.cs | 122 ++++++++++++------ Prism-ScriptCore/Prism-ScriptCore.csproj | 10 ++ Prism-ScriptCore/Prism-ScriptCore.sln | 9 ++ Prism-ScriptCore/Src/Prism/Math/Vec2.cs | 23 ++++ Prism-ScriptCore/Src/Prism/Math/Vec3.cs | 5 + Prism/src/Prism/Core/ImGui/ImGui.h | 36 ++++++ Prism/src/Prism/Editor/SceneHierachyPanel.cpp | 35 +++-- Prism/src/Prism/Physics/Physics3D.cpp | 83 +++--------- Prism/src/Prism/Physics/PhysicsActor.cpp | 121 +++++++++++++++++ Prism/src/Prism/Physics/PhysicsActor.h | 49 +++++++ Prism/src/Prism/Physics/PhysicsWrappers.cpp | 107 +++++---------- Prism/src/Prism/Physics/PhysicsWrappers.h | 23 +++- Prism/src/Prism/Renderer/SceneRenderer.cpp | 8 +- Prism/src/Prism/Scene/Components.h | 3 + Prism/src/Prism/Scene/Scene.cpp | 17 ++- Prism/src/Prism/Script/ScriptWrappers.cpp | 1 + 16 files changed, 442 insertions(+), 210 deletions(-) create mode 100644 Prism/src/Prism/Physics/PhysicsActor.cpp create mode 100644 Prism/src/Prism/Physics/PhysicsActor.h diff --git a/ExampleApp/Src/FPSPlayer.cs b/ExampleApp/Src/FPSPlayer.cs index 28c5b81..00621e8 100644 --- a/ExampleApp/Src/FPSPlayer.cs +++ b/ExampleApp/Src/FPSPlayer.cs @@ -7,9 +7,14 @@ namespace FPSExample public float WalkingSpeed = 10.0f; public float RunSpeed = 20.0f; public float JumpForce = 50.0f; + + + [NonSerialized] public float MouseSensitivity = 10.0f; - public float Distance = 5.0f; + public float CameraForwardOffset = 0.5f; + public float CameraYOffset = 0.5f; + private bool m_Colliding = false; private float m_CurrentSpeed; @@ -21,7 +26,10 @@ namespace FPSExample private Vec2 m_LastMousePosition; private float m_CurrentYMovement = 0.0f; - + + private Vec2 m_MovementDirection = new Vec2(0.0f); + private bool m_ShouldJump = false; + void OnCreate() { m_Transform = GetComponent(); @@ -40,7 +48,6 @@ namespace FPSExample Input.SetCursorMode(Input.CursorMode.Locked); } - Collider[] colliders = new Collider[10]; void OnUpdate(float ts) { if (Input.IsKeyPressed(KeyCode.Escape) && Input.GetCursorMode() == Input.CursorMode.Locked) @@ -51,32 +58,10 @@ namespace FPSExample m_CurrentSpeed = Input.IsKeyPressed(KeyCode.LeftControl) ? RunSpeed : WalkingSpeed; - RaycastHit hitInfo; - if (Input.IsKeyPressed(KeyCode.H) && - Physics.Raycast(m_CameraTransform.Position + (m_CameraTransform.Transform.Forward), - m_CameraTransform.Transform.Forward, 20.0f, out hitInfo)) - { - FindEntityByID(hitInfo.EntityID).GetComponent().Mesh.GetMaterial(0).Set("u_AlbedoColor", new Vec3(1.0f ,0.0f, 0.0f)); - } - - if (Input.IsKeyPressed(KeyCode.I)) - { - // NOTE: The NonAlloc version of Overlap functions should be used when possible since it doesn't allocate a new array - // whenever you call it. The normal versions allocates a brand new array every time. - - int numColliders = Physics.OverlapBoxNonAlloc(m_Transform.Position, new Vec3(1.0f), colliders); - - Console.WriteLine("Colliders: {0}", numColliders); - // When using NonAlloc it's not safe to use a foreach loop since some of the colliders may not exist - for (int i = 0; i < numColliders; i++) - { - Console.WriteLine(colliders[i]); - } - } - + UpdateRayCasting(); + UpdateMovementInput(); UpdateRotation(ts); - UpdateMovement(); UpdateCameraTransform(); } @@ -99,29 +84,82 @@ namespace FPSExample m_LastMousePosition = currentMousePosition; } + private void UpdateMovementInput() + { + if (Input.IsKeyPressed(KeyCode.W)) + m_MovementDirection.Y += 1.0f; + else if (Input.IsKeyPressed(KeyCode.S)) + m_MovementDirection.Y -= 1.0f; + else + m_MovementDirection.Y = 0.0f; + + if(Input.IsKeyPressed(KeyCode.A)) + m_MovementDirection.X -= 1.0f; + else if (Input.IsKeyPressed(KeyCode.D)) + m_MovementDirection.X += 1.0f; + else + m_MovementDirection.X = 0.0f; + m_ShouldJump = Input.IsKeyPressed(KeyCode.Space) && !m_ShouldJump; + } + + Collider[] colliders = new Collider[10]; + + private void UpdateRayCasting() + { + RaycastHit hitInfo; + if (Input.IsKeyPressed(KeyCode.H) && + Physics.Raycast(m_CameraTransform.Position + (m_CameraTransform.Transform.Forward), + m_CameraTransform.Transform.Forward, 20.0f, out hitInfo)) + { + FindEntityByID(hitInfo.EntityID).GetComponent().Mesh.GetMaterial(0).Set("u_AlbedoColor", new Vec3(1.0f ,0.0f, 0.0f)); + } + + if (Input.IsKeyPressed(KeyCode.I)) + { + // NOTE: The NonAlloc version of Overlap functions should be used when possible since it doesn't allocate a new array + // whenever you call it. The normal versions allocates a brand new array every time. + + int numColliders = Physics.OverlapBoxNonAlloc(m_Transform.Position, new Vec3(1.0f), colliders); + + Console.WriteLine("Colliders: {0}", numColliders); + // When using NonAlloc it's not safe to use a foreach loop since some of the colliders may not exist + for (int i = 0; i < numColliders; i++) + { + Console.WriteLine(colliders[i]); + } + } + + } + + void OnPhysicsUpdate(float fixedTimeStep) + { + UpdateMovement(); + } + private void UpdateMovement() { m_RigidBody.Rotate(new Vec3(0.0f, m_CurrentYMovement, 0.0f)); - if (Input.IsKeyPressed(KeyCode.W)) - m_RigidBody.AddForce(m_Transform.Transform.Forward * m_CurrentSpeed); - else if (Input.IsKeyPressed(KeyCode.S)) - m_RigidBody.AddForce(m_Transform.Transform.Forward * -m_CurrentSpeed); - - if (Input.IsKeyPressed(KeyCode.A)) - m_RigidBody.AddForce(m_Transform.Transform.Right * -m_CurrentSpeed); - else if (Input.IsKeyPressed(KeyCode.D)) - m_RigidBody.AddForce(m_Transform.Transform.Right * m_CurrentSpeed); - - if (Input.IsKeyPressed(KeyCode.Space) && m_Colliding) - m_RigidBody.AddForce(Vec3.Up * JumpForce); - + Vec3 movement = m_CameraTransform.Transform.Right * m_MovementDirection.X + m_CameraTransform.Transform.Forward * m_MovementDirection.Y; + if (m_MovementDirection.LengthSquared() != 0.0f) + { + movement.Normalize(); + Vec3 velocity = movement * m_CurrentSpeed; + velocity.Y = m_RigidBody.GetLinearVelocity().Y; + m_RigidBody.SetLinearVelocity(velocity); + } + + if (m_ShouldJump && m_Colliding) + { + m_RigidBody.AddForce(Vec3.Up * JumpForce, RigidBodyComponent.ForceMode.Impulse); + m_ShouldJump = false; + } } private void UpdateCameraTransform(){ - Vec3 position = m_Transform.Position; - position.Y += m_Transform.Position.Y + 1.5f; + Vec3 position = m_Transform.Position + m_CameraTransform.Transform.Forward * CameraForwardOffset; + position.Y += m_Transform.Position.Y + CameraYOffset; m_CameraTransform.Position = position; } } diff --git a/Prism-ScriptCore/Prism-ScriptCore.csproj b/Prism-ScriptCore/Prism-ScriptCore.csproj index 4d66758..4cebc04 100644 --- a/Prism-ScriptCore/Prism-ScriptCore.csproj +++ b/Prism-ScriptCore/Prism-ScriptCore.csproj @@ -7,4 +7,14 @@ enable + + + + + + + + + + diff --git a/Prism-ScriptCore/Prism-ScriptCore.sln b/Prism-ScriptCore/Prism-ScriptCore.sln index 0c874f6..f5b3eac 100644 --- a/Prism-ScriptCore/Prism-ScriptCore.sln +++ b/Prism-ScriptCore/Prism-ScriptCore.sln @@ -1,5 +1,8 @@  Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 18 +VisualStudioVersion = 18.1.11312.151 d18.0 +MinimumVisualStudioVersion = 10.0.40219.1 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Prism-ScriptCore", "Prism-ScriptCore.csproj", "{B94EF710-0487-4388-97E3-B650761A849C}" EndProject Global @@ -13,4 +16,10 @@ Global {B94EF710-0487-4388-97E3-B650761A849C}.Release|Any CPU.ActiveCfg = Release|Any CPU {B94EF710-0487-4388-97E3-B650761A849C}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {BA69725C-3CFE-4882-9EDF-2A8E92423E8F} + EndGlobalSection EndGlobal diff --git a/Prism-ScriptCore/Src/Prism/Math/Vec2.cs b/Prism-ScriptCore/Src/Prism/Math/Vec2.cs index 4696906..c50f399 100644 --- a/Prism-ScriptCore/Src/Prism/Math/Vec2.cs +++ b/Prism-ScriptCore/Src/Prism/Math/Vec2.cs @@ -29,6 +29,29 @@ namespace Prism Y = Mathf.Clamp(Y, min.Y, max.Y); } + public float LengthSquared() + { + return X * X + Y * Y; + } + + public float Length() + { + return (float)Math.Sqrt(X * X + Y * Y); + } + + public Vec2 Normalized() + { + float length = Length(); + return new Vec2(X / length, Y / length); + } + + public void Normalize() + { + float length = Length(); + X = X / length; + Y = Y / length; + } + public static Vec2 operator -(Vec2 l, Vec2 r) { return new Vec2(l.X - r.X, l.Y - r.Y); diff --git a/Prism-ScriptCore/Src/Prism/Math/Vec3.cs b/Prism-ScriptCore/Src/Prism/Math/Vec3.cs index 0102fcc..71d3798 100644 --- a/Prism-ScriptCore/Src/Prism/Math/Vec3.cs +++ b/Prism-ScriptCore/Src/Prism/Math/Vec3.cs @@ -60,6 +60,11 @@ namespace Prism Z = Mathf.Clamp(Z, min.Z, max.Z); } + public float LengthSquared() + { + return X * X + Y * Y + Z * Z; + } + public float Length() { return (float)Math.Sqrt(X * X + Y * Y + Z * Z); diff --git a/Prism/src/Prism/Core/ImGui/ImGui.h b/Prism/src/Prism/Core/ImGui/ImGui.h index efaf543..7a08667 100644 --- a/Prism/src/Prism/Core/ImGui/ImGui.h +++ b/Prism/src/Prism/Core/ImGui/ImGui.h @@ -268,6 +268,42 @@ namespace Prism::UI { ImGui::TreePop(); } + static int s_CheckboxCount = 0; + + static void BeginCheckboxGroup(const char* label) + { + ImGui::Text(label); + ImGui::NextColumn(); + ImGui::PushItemWidth(-1); + } + + static bool PropertyCheckboxGroup(const char* label, bool& value) + { + bool modified = false; + + if (++s_CheckboxCount > 1) + ImGui::SameLine(); + + ImGui::Text(label); + ImGui::SameLine(); + + s_IDBuffer[0] = '#'; + s_IDBuffer[1] = '#'; + memset(s_IDBuffer + 2, 0, 14); + snprintf(s_IDBuffer + 2, 14, "%x", s_Counter++); + if (ImGui::Checkbox(s_IDBuffer, &value)) + modified = true; + + return modified; + } + + static void EndCheckboxGroup() + { + ImGui::PopItemWidth(); + ImGui::NextColumn(); + s_CheckboxCount = 0; + } + } #endif //IMGUI_H diff --git a/Prism/src/Prism/Editor/SceneHierachyPanel.cpp b/Prism/src/Prism/Editor/SceneHierachyPanel.cpp index 8e61666..35f50e6 100644 --- a/Prism/src/Prism/Editor/SceneHierachyPanel.cpp +++ b/Prism/src/Prism/Editor/SceneHierachyPanel.cpp @@ -367,15 +367,16 @@ namespace Prism const bool open = ImGui::TreeNodeEx((void*)typeid(T).hash_code(), treeNodeFlags, name.c_str()); ImGui::PopStyleVar(); + // TODO: should use address instead ImGui::SameLine(contentRegionAvailable.x - lineHeight * 0.5f); - if (ImGui::Button("+", ImVec2{ lineHeight, lineHeight })) + if (ImGui::Button(("+##" + name).c_str(), ImVec2{ lineHeight, lineHeight })) { - ImGui::OpenPopup("ComponentSettings"); + ImGui::OpenPopup(("ComponentSettings" + name).c_str()); } bool removeComponent = false; - if (ImGui::BeginPopup("ComponentSettings")) + if (ImGui::BeginPopup(("ComponentSettings" + name).c_str())) { if (ImGui::MenuItem("Remove component")) removeComponent = true; @@ -799,23 +800,31 @@ namespace Prism { UI::BeginPropertyGrid(); UI::Property("Mass", rbc.Mass); + UI::Property("Linear Drag", rbc.LinearDrag); + UI::Property("Angular Drag", rbc.AngularDrag); + UI::Property("Disable Gravity", rbc.DisableGravity); UI::Property("Is Kinematic", rbc.IsKinematic); UI::EndPropertyGrid(); - if (ImGui::TreeNode("RigidBodyConstraints", "Constraints")) + if (UI::BeginTreeNode("Constraints", false)) { UI::BeginPropertyGrid(); - UI::Property("Position: X", rbc.LockPositionX); - UI::Property("Position: Y", rbc.LockPositionY); - UI::Property("Position: Z", rbc.LockPositionZ); - UI::Property("Rotation: X", rbc.LockRotationX); - UI::Property("Rotation: Y", rbc.LockRotationY); - UI::Property("Rotation: Z", rbc.LockRotationZ); + + UI::BeginCheckboxGroup("Freeze Position"); + UI::PropertyCheckboxGroup("X", rbc.LockPositionX); + UI::PropertyCheckboxGroup("Y", rbc.LockPositionY); + UI::PropertyCheckboxGroup("Z", rbc.LockPositionZ); + UI::EndCheckboxGroup(); + + UI::BeginCheckboxGroup("Freeze Rotation"); + UI::PropertyCheckboxGroup("X", rbc.LockRotationX); + UI::PropertyCheckboxGroup("Y", rbc.LockRotationY); + UI::PropertyCheckboxGroup("Z", rbc.LockRotationZ); + UI::EndCheckboxGroup(); + UI::EndPropertyGrid(); - - ImGui::TreePop(); + UI::EndTreeNode(); } - } }); diff --git a/Prism/src/Prism/Physics/Physics3D.cpp b/Prism/src/Prism/Physics/Physics3D.cpp index 265f1ee..6a89590 100644 --- a/Prism/src/Prism/Physics/Physics3D.cpp +++ b/Prism/src/Prism/Physics/Physics3D.cpp @@ -17,7 +17,8 @@ namespace Prism { static physx::PxScene* s_Scene; - static std::vector s_SimulatedEntities; + static std::vector> s_SimulatedActors; + static std::vector> s_StaticActors; static Entity* s_EntityStorageBuffer; static uint32_t s_EntityBufferCount; static int s_EntityStorageBufferPosition; @@ -87,52 +88,18 @@ namespace Prism const auto transform = e.Transform(); - physx::PxRigidActor* actor = PhysicsWrappers::CreateActor(rigidbody, transform); - if (rigidbody.BodyType == RigidBodyComponent::Type::Dynamic) - s_SimulatedEntities.push_back(e); + Ref actor = Ref::Create(e); + + if (actor->IsDynamic()) + s_SimulatedActors.push_back(actor); + else + s_StaticActors.push_back(actor); Entity* entityStorage = &s_EntityStorageBuffer[s_EntityStorageBufferPosition]; *entityStorage = e; - actor->userData = (void*)entityStorage; - rigidbody.RuntimeActor = actor; - rigidbody.EntityBufferIndex = s_EntityStorageBufferPosition; + + actor->SetRuntimeDataInternal((void *)entityStorage, s_EntityStorageBufferPosition); s_EntityStorageBufferPosition++; - - const physx::PxMaterial* material = PhysicsWrappers::CreateMaterial(e.GetComponent()); - - - - // Add all colliders - if (e.HasComponent()) - { - const BoxColliderComponent& collider = e.GetComponent(); - PhysicsWrappers::AddBoxCollider(*actor, *material, collider, transform.Scale); - } - - if (e.HasComponent()) - { - const SphereColliderComponent& collider = e.GetComponent(); - PhysicsWrappers::AddSphereCollider(*actor, *material, collider, transform.Scale); - } - - if (e.HasComponent()) - { - const CapsuleColliderComponent& collider = e.GetComponent(); - PhysicsWrappers::AddCapsuleCollider(*actor, *material, collider, transform.Scale); - } - - if (e.HasComponent()) - { - auto& collider = e.GetComponent(); - PhysicsWrappers::AddMeshCollider(*actor, *material, collider, transform.Scale); - } - - if (!PhysicsLayerManager::IsLayerValid(rigidbody.Layer)) - rigidbody.Layer = 0; - - PhysicsWrappers::SetCollisionFilters(*actor, rigidbody.Layer); - - s_Scene->addActor(*actor); } void Physics3D::Simulate(TimeStep ts) @@ -146,25 +113,14 @@ namespace Prism s_SimulationTime -= s_Settings.FixedTimestep; - for (const Entity& e : s_SimulatedEntities) - { - if (ScriptEngine::IsEntityModuleValid(e)) - ScriptEngine::OnPhysicsUpdateEntity(e, s_Settings.FixedTimestep); - } + for (auto& actor : s_SimulatedActors) + actor->Update(s_Settings.FixedTimestep); s_Scene->simulate(s_Settings.FixedTimestep); s_Scene->fetchResults(true); - for (Entity& e : s_SimulatedEntities) - { - auto& transform = e.Transform(); - const auto& rb = e.GetComponent(); - const auto actor = static_cast(rb.RuntimeActor); - - physx::PxTransform actorPose = actor->getGlobalPose(); - transform.Translation = FromPhysXVector(actorPose.p); - transform.Rotation = glm::degrees(glm::eulerAngles(FromPhysXQuat(actorPose.q))); - } + for (auto& actor : s_SimulatedActors) + actor->SynchronizeTransform(); } void Physics3D::DestroyScene() @@ -175,7 +131,8 @@ namespace Prism s_EntityStorageBuffer = nullptr; s_EntityStorageBufferPosition = 0; - s_SimulatedEntities.clear(); + s_SimulatedActors.clear(); + s_StaticActors.clear(); s_Scene->release(); s_Scene = nullptr; } @@ -188,12 +145,12 @@ namespace Prism bool Physics3D::ConnectPVD() { PM_CORE_INFO("Trying to connect PVD"); - const bool isconnect = PhysicsWrappers::ConnectPVD(); - if (isconnect) + const bool isConnect = PhysicsWrappers::ConnectPVD(); + if (isConnect) PM_CORE_INFO("PVD Connected"); else - PM_CORE_WARN("canot connect PVD!"); - return isconnect; + PM_CORE_WARN("cannot connect PVD!"); + return isConnect; } bool Physics3D::IsPVDConnected() {return PhysicsWrappers::IsPVDConnected();} diff --git a/Prism/src/Prism/Physics/PhysicsActor.cpp b/Prism/src/Prism/Physics/PhysicsActor.cpp new file mode 100644 index 0000000..3934481 --- /dev/null +++ b/Prism/src/Prism/Physics/PhysicsActor.cpp @@ -0,0 +1,121 @@ +// +// Created by Atdunbg on 2026/1/10. +// + +#include "PhysicsActor.h" + +#include "Physics3D.h" +#include "PhysicsLayer.h" +#include "PhysicsWrappers.h" +#include "PxRigidActor.h" +#include "Prism/Script/ScriptEngine.h" + +namespace Prism +{ + PhysicsActor::PhysicsActor(Entity entity) + : m_Entity(entity), m_RigidBody(entity.GetComponent()) + { + m_Material = entity.GetComponent(); + + Create(); + } + + PhysicsActor::~PhysicsActor() + { + m_ActorInternal->release(); + m_ActorInternal = nullptr; + } + + void PhysicsActor::Create() + { + physx::PxPhysics& physics = PhysicsWrappers::GetPhysics(); + + if (m_RigidBody.BodyType == RigidBodyComponent::Type::Static) + { + m_ActorInternal = physics.createRigidStatic(ToPhysXTransform(m_Entity.Transform())); + } + else + { + const PhysicsSettings& settings = Physics3D::GetSettings(); + + physx::PxRigidDynamic* actor = physics.createRigidDynamic(ToPhysXTransform(m_Entity.Transform())); + actor->setLinearDamping(m_RigidBody.LinearDrag); + actor->setAngularDamping(m_RigidBody.AngularDrag); + actor->setRigidBodyFlag(physx::PxRigidBodyFlag::eKINEMATIC, m_RigidBody.IsKinematic); + actor->setRigidDynamicLockFlag(physx::PxRigidDynamicLockFlag::eLOCK_LINEAR_X, m_RigidBody.LockPositionX); + actor->setRigidDynamicLockFlag(physx::PxRigidDynamicLockFlag::eLOCK_LINEAR_Y, m_RigidBody.LockPositionY); + actor->setRigidDynamicLockFlag(physx::PxRigidDynamicLockFlag::eLOCK_LINEAR_Z, m_RigidBody.LockPositionZ); + actor->setRigidDynamicLockFlag(physx::PxRigidDynamicLockFlag::eLOCK_ANGULAR_X, m_RigidBody.LockRotationX); + actor->setRigidDynamicLockFlag(physx::PxRigidDynamicLockFlag::eLOCK_ANGULAR_Y, m_RigidBody.LockRotationY); + actor->setRigidDynamicLockFlag(physx::PxRigidDynamicLockFlag::eLOCK_ANGULAR_Z, m_RigidBody.LockRotationZ); + actor->setActorFlag(physx::PxActorFlag::eDISABLE_GRAVITY, m_RigidBody.DisableGravity); + actor->setSolverIterationCounts(settings.SolverIterations, settings.SolverVelocityIterations); + + physx::PxRigidBodyExt::updateMassAndInertia(*actor, m_RigidBody.Mass); + m_ActorInternal = actor; + } + + physx::PxMaterial* physicsMat = physics.createMaterial(m_Material.StaticFriction, m_Material.DynamicFriction, m_Material.Bounciness); + if (m_Entity.HasComponent()) PhysicsWrappers::AddBoxCollider(*this, *physicsMat); + if (m_Entity.HasComponent()) PhysicsWrappers::AddSphereCollider(*this, *physicsMat); + if (m_Entity.HasComponent()) PhysicsWrappers::AddCapsuleCollider(*this, *physicsMat); + if (m_Entity.HasComponent()) PhysicsWrappers::AddMeshCollider(*this, *physicsMat); + + if (!PhysicsLayerManager::IsLayerValid(m_RigidBody.Layer)) + m_RigidBody.Layer = 0; + + SetLayer(m_RigidBody.Layer); + + static_cast(Physics3D::GetPhysicsScene())->addActor(*m_ActorInternal); + } + + void PhysicsActor::SetRuntimeDataInternal(void* entityStorage, int storageBufferPosition) + { + m_ActorInternal->userData = entityStorage; + m_RigidBody.RuntimeActor = m_ActorInternal; + m_RigidBody.EntityBufferIndex = storageBufferPosition; + } + + void PhysicsActor::Update(float fixedTimestep) + { + if (!ScriptEngine::IsEntityModuleValid(m_Entity)) + return; + + ScriptEngine::OnPhysicsUpdateEntity(m_Entity, fixedTimestep); + } + + void PhysicsActor::SynchronizeTransform() + { + TransformComponent& transform = m_Entity.Transform(); + physx::PxRigidActor* actor = static_cast(m_RigidBody.RuntimeActor); + physx::PxTransform actorPose = actor->getGlobalPose(); + transform.Translation = FromPhysXVector(actorPose.p); + transform.Rotation = glm::eulerAngles(FromPhysXQuat(actorPose.q)); + } + + void PhysicsActor::SetLayer(uint32_t layer) + { + physx::PxAllocatorCallback& allocator = PhysicsWrappers::GetAllocator(); + + const PhysicsLayer& layerInfo = PhysicsLayerManager::GetLayer(layer); + + if (layerInfo.CollidesWith == 0) + return; + + physx::PxFilterData filterData; + filterData.word0 = layerInfo.BitValue; + filterData.word1 = layerInfo.CollidesWith; + + const physx::PxU32 numShapes = m_ActorInternal->getNbShapes(); + + physx::PxShape** shapes = (physx::PxShape**)allocator.allocate(sizeof(physx::PxShape*) * numShapes, "", "", 0); + m_ActorInternal->getShapes(shapes, numShapes); + + for (physx::PxU32 i = 0; i < numShapes; i++) + shapes[i]->setSimulationFilterData(filterData); + + allocator.deallocate(shapes); + + } + +} diff --git a/Prism/src/Prism/Physics/PhysicsActor.h b/Prism/src/Prism/Physics/PhysicsActor.h new file mode 100644 index 0000000..ce4a70e --- /dev/null +++ b/Prism/src/Prism/Physics/PhysicsActor.h @@ -0,0 +1,49 @@ +// +// Created by Atdunbg on 2026/1/10. +// + +#ifndef PRISM_PHYSICSACTOR_H +#define PRISM_PHYSICSACTOR_H +#include "Prism/Core/Ref.h" +#include "Prism/Scene/Entity.h" + +namespace physx +{ + class PxRigidActor; +} + +namespace Prism +{ + class PhysicsActor : public RefCounted + { + public: + PhysicsActor(Entity entity); + ~PhysicsActor(); + + void Update(float fixedTimestep); + void SynchronizeTransform(); + + void SetLayer(uint32_t layer); + + bool IsDynamic() const { return m_RigidBody.BodyType == RigidBodyComponent::Type::Dynamic; } + + Entity& GetEntity() { return m_Entity; } + + private: + void Create(); + + void SetRuntimeDataInternal(void* entityStorage, int storageBufferPosition); + + private: + Entity m_Entity; + RigidBodyComponent& m_RigidBody; + PhysicsMaterialComponent m_Material; + + physx::PxRigidActor* m_ActorInternal; + + friend class Physics3D; + friend class PhysicsWrappers; + }; +} + +#endif //PRISM_PHYSICSACTOR_H diff --git a/Prism/src/Prism/Physics/PhysicsWrappers.cpp b/Prism/src/Prism/Physics/PhysicsWrappers.cpp index 9975b5c..fce4116 100644 --- a/Prism/src/Prism/Physics/PhysicsWrappers.cpp +++ b/Prism/src/Prism/Physics/PhysicsWrappers.cpp @@ -177,70 +177,10 @@ namespace Prism return s_Physics->createScene(sceneDesc); } - physx::PxRigidActor* PhysicsWrappers::CreateActor(const RigidBodyComponent& rigidbody, const TransformComponent& transformComponent) - { - physx::PxRigidActor* actor = nullptr; - const auto transform = ToPhysXTransform(transformComponent.GetTransform()); - const PhysicsSettings& settings = Physics3D::GetSettings(); - - if (rigidbody.BodyType == RigidBodyComponent::Type::Static) - { - actor = s_Physics->createRigidStatic(transform); - } - else if (rigidbody.BodyType == RigidBodyComponent::Type::Dynamic) - { - physx::PxRigidDynamic* dynamicActor = s_Physics->createRigidDynamic(transform); - - dynamicActor->setRigidBodyFlag(physx::PxRigidBodyFlag::eKINEMATIC, rigidbody.IsKinematic); - - dynamicActor->setRigidDynamicLockFlag(physx::PxRigidDynamicLockFlag::eLOCK_LINEAR_X, rigidbody.LockPositionX); - dynamicActor->setRigidDynamicLockFlag(physx::PxRigidDynamicLockFlag::eLOCK_LINEAR_Y, rigidbody.LockPositionY); - dynamicActor->setRigidDynamicLockFlag(physx::PxRigidDynamicLockFlag::eLOCK_LINEAR_Z, rigidbody.LockPositionZ); - dynamicActor->setRigidDynamicLockFlag(physx::PxRigidDynamicLockFlag::eLOCK_ANGULAR_X, rigidbody.LockRotationX); - dynamicActor->setRigidDynamicLockFlag(physx::PxRigidDynamicLockFlag::eLOCK_ANGULAR_Y, rigidbody.LockRotationY); - dynamicActor->setRigidDynamicLockFlag(physx::PxRigidDynamicLockFlag::eLOCK_ANGULAR_Z, rigidbody.LockRotationZ); - - dynamicActor->setSleepThreshold(0.1f); - dynamicActor->setAngularVelocity({1,1,1}); - dynamicActor->setActorFlag(physx::PxActorFlag::eDISABLE_SIMULATION, false); - - dynamicActor->setSolverIterationCounts(settings.SolverIterations, settings.SolverVelocityIterations); - - // using OnWake and OnSleep callback should enable eSEND_SLEEP_NOTIFIES - // https://nvidia-omniverse.github.io/PhysX/physx/5.6.1/_api_build/classPxSimulationEventCallback.html#_CPPv4N25PxSimulationEventCallback6onWakeEPP7PxActor5PxU32 - dynamicActor->setActorFlag(physx::PxActorFlag::eSEND_SLEEP_NOTIFIES, true); - - physx::PxRigidBodyExt::updateMassAndInertia(*dynamicActor, rigidbody.Mass); - actor = dynamicActor; - } - - return actor; - } - - void PhysicsWrappers::SetCollisionFilters(const physx::PxRigidActor& actor, uint32_t physicsLayer) - { - const PhysicsLayer& layerInfo = PhysicsLayerManager::GetLayer(physicsLayer); - - if (layerInfo.CollidesWith == 0) - return; - - physx::PxFilterData filterData; - filterData.word0 = layerInfo.BitValue; - filterData.word1 = layerInfo.CollidesWith; - - const physx::PxU32 numShapes = actor.getNbShapes(); - - const auto shapes = static_cast(s_Allocator.allocate(sizeof(physx::PxShape*) * numShapes, "", "", 0)); - actor.getShapes(shapes, numShapes); - - for (physx::PxU32 i = 0; i < numShapes; i++) - shapes[i]->setSimulationFilterData(filterData); - - s_Allocator.deallocate(shapes); - } - - void PhysicsWrappers::AddBoxCollider(physx::PxRigidActor& actor, const physx::PxMaterial& material, const BoxColliderComponent& collider, const glm::vec3& scale) + void PhysicsWrappers::AddBoxCollider(PhysicsActor& actor, const physx::PxMaterial& material) { + const auto& collider = actor.m_Entity.GetComponent(); + const glm::vec3 scale = actor.m_Entity.Transform().Scale; glm::vec3 colliderSize = collider.Size; if (scale.x != 0.0f) colliderSize.x *= scale.x; @@ -249,28 +189,34 @@ namespace Prism const auto boxGeometry = physx::PxBoxGeometry(colliderSize.x / 2.0f, colliderSize.y / 2.0f, colliderSize.z / 2.0f); - physx::PxShape* shape = physx::PxRigidActorExt::createExclusiveShape(actor, boxGeometry, material); + physx::PxShape* shape = physx::PxRigidActorExt::createExclusiveShape(*actor.m_ActorInternal, boxGeometry, material); + // physx::PxShape* shape = physx::PxRigidActorExt::createExclusiveShape(actor, boxGeometry, material); shape->setFlag(physx::PxShapeFlag::eSIMULATION_SHAPE, !collider.IsTrigger); shape->setFlag(physx::PxShapeFlag::eTRIGGER_SHAPE, collider.IsTrigger); shape->setLocalPose(ToPhysXTransform(glm::translate(glm::mat4(1.0F), collider.Offset))); } - void PhysicsWrappers::AddSphereCollider(physx::PxRigidActor& actor, const physx::PxMaterial& material, const SphereColliderComponent& collider, const glm::vec3& scale) + void PhysicsWrappers::AddSphereCollider(PhysicsActor& actor, const physx::PxMaterial& material) { + const auto& collider = actor.m_Entity.GetComponent(); + const glm::vec3 scale = actor.m_Entity.Transform().Scale; float colliderRadius = collider.Radius; if (scale.x != 0.0f) colliderRadius *= scale.x; const auto sphereGeometry = physx::PxSphereGeometry(colliderRadius); - physx::PxShape* shape = physx::PxRigidActorExt::createExclusiveShape(actor, sphereGeometry, material); + physx::PxShape* shape = physx::PxRigidActorExt::createExclusiveShape(*actor.m_ActorInternal, sphereGeometry, material); + // physx::PxShape* shape = physx::PxRigidActorExt::createExclusiveShape(actor, sphereGeometry, material); shape->setFlag(physx::PxShapeFlag::eSIMULATION_SHAPE, !collider.IsTrigger); shape->setFlag(physx::PxShapeFlag::eTRIGGER_SHAPE, collider.IsTrigger); } - void PhysicsWrappers::AddCapsuleCollider(physx::PxRigidActor& actor, const physx::PxMaterial& material,const CapsuleColliderComponent& collider, const glm::vec3& scale) + void PhysicsWrappers::AddCapsuleCollider(PhysicsActor& actor, const physx::PxMaterial& material) { + const auto& collider = actor.m_Entity.GetComponent(); + const glm::vec3 scale = actor.m_Entity.Transform().Scale; float colliderRadius = collider.Radius; float colliderHeight = collider.Height; @@ -280,16 +226,18 @@ namespace Prism const auto capsuleGeometry = physx::PxCapsuleGeometry(colliderRadius, colliderHeight * 0.5f); - physx::PxShape* shape = physx::PxRigidActorExt::createExclusiveShape(actor, capsuleGeometry, material); + physx::PxShape* shape = physx::PxRigidActorExt::createExclusiveShape(*actor.m_ActorInternal, capsuleGeometry, material); shape->setFlag(physx::PxShapeFlag::eSIMULATION_SHAPE, !collider.IsTrigger); shape->setFlag(physx::PxShapeFlag::eTRIGGER_SHAPE, collider.IsTrigger); // shape->setLocalPose(physx::PxTransform(physx::PxQuat(physx::PxHalfPi, physx::PxVec3(0, 0, 1)))); } - - void PhysicsWrappers::AddMeshCollider(physx::PxRigidActor& actor, const physx::PxMaterial& material,MeshColliderComponent& collider, const glm::vec3& scale) + void PhysicsWrappers::AddMeshCollider(PhysicsActor& actor, const physx::PxMaterial& material) { + auto& collider = actor.m_Entity.GetComponent(); + glm::vec3 scale = actor.m_Entity.Transform().Scale; + if (collider.IsConvex) { std::vector meshes = CreateConvexMesh(collider, true); @@ -298,7 +246,7 @@ namespace Prism { physx::PxConvexMeshGeometry convexGeometry = physx::PxConvexMeshGeometry(mesh, physx::PxMeshScale(ToPhysXVector(scale))); convexGeometry.meshFlags = physx::PxConvexMeshGeometryFlag::eTIGHT_BOUNDS; - physx::PxShape* shape = physx::PxRigidActorExt::createExclusiveShape(actor, convexGeometry, material); + physx::PxShape* shape = physx::PxRigidActorExt::createExclusiveShape(*actor.m_ActorInternal, convexGeometry, material); shape->setFlag(physx::PxShapeFlag::eSIMULATION_SHAPE, !collider.IsTrigger); shape->setFlag(physx::PxShapeFlag::eTRIGGER_SHAPE, collider.IsTrigger); } @@ -310,7 +258,7 @@ namespace Prism for (const auto mesh : meshes) { physx::PxTriangleMeshGeometry convexGeometry = physx::PxTriangleMeshGeometry(mesh, physx::PxMeshScale(ToPhysXVector(scale))); - physx::PxShape* shape = physx::PxRigidActorExt::createExclusiveShape(actor, convexGeometry, material); + physx::PxShape* shape = physx::PxRigidActorExt::createExclusiveShape(*actor.m_ActorInternal, convexGeometry, material); shape->setFlag(physx::PxShapeFlag::eSIMULATION_SHAPE, !collider.IsTrigger); shape->setFlag(physx::PxShapeFlag::eTRIGGER_SHAPE, collider.IsTrigger); } @@ -633,11 +581,6 @@ namespace Prism #endif } - physx::PxMaterial* PhysicsWrappers::CreateMaterial(const PhysicsMaterialComponent& material) - { - return s_Physics->createMaterial(material.StaticFriction, material.DynamicFriction, material.Bounciness); - } - bool PhysicsWrappers::Raycast(const glm::vec3& origin, const glm::vec3& direction, float maxDistance, RaycastHit* hit) { const auto* scene = static_cast(Physics3D::GetPhysicsScene()); @@ -746,6 +689,16 @@ namespace Prism s_Foundation->release(); } + physx::PxPhysics& PhysicsWrappers::GetPhysics() + { + return *s_Physics; + } + + physx::PxAllocatorCallback& PhysicsWrappers::GetAllocator() + { + return s_Allocator; + } + bool PhysicsWrappers::ConnectPVD() { bool isConnect = false; diff --git a/Prism/src/Prism/Physics/PhysicsWrappers.h b/Prism/src/Prism/Physics/PhysicsWrappers.h index 0fec25e..ed55d06 100644 --- a/Prism/src/Prism/Physics/PhysicsWrappers.h +++ b/Prism/src/Prism/Physics/PhysicsWrappers.h @@ -5,6 +5,7 @@ #ifndef PHYSICSWRAPPERS_H #define PHYSICSWRAPPERS_H +#include "PhysicsActor.h" #include "PhysicsUtils.h" #define OVERLAP_MAX_COLLIDERS 10 @@ -36,20 +37,25 @@ namespace Prism { public: static physx::PxScene* CreateScene(); - static physx::PxRigidActor* CreateActor(const RigidBodyComponent& rigidbody, const TransformComponent& transformComponent); - static void SetCollisionFilters(const physx::PxRigidActor& actor, uint32_t physicsLayer); + // static physx::PxRigidActor* CreateActor(const RigidBodyComponent& rigidbody, const TransformComponent& transformComponent); + // static void SetCollisionFilters(const physx::PxRigidActor& actor, uint32_t physicsLayer); - static void AddBoxCollider(physx::PxRigidActor& actor, const physx::PxMaterial& material, const BoxColliderComponent& collider, const glm::vec3& scale = glm::vec3(0.0f)); - static void AddSphereCollider(physx::PxRigidActor& actor, const physx::PxMaterial& material, const SphereColliderComponent& collider, const glm::vec3& scale = glm::vec3(0.0f)); - static void AddCapsuleCollider(physx::PxRigidActor& actor, const physx::PxMaterial& material, const CapsuleColliderComponent& collider, const glm::vec3& scale = glm::vec3(0.0f)); - static void AddMeshCollider(::physx::PxRigidActor& actor, const ::physx::PxMaterial& material, ::Prism::MeshColliderComponent& collider, const glm::vec3& scale = glm::vec3(0.0f)); + static void AddBoxCollider(PhysicsActor& actor, const physx::PxMaterial& material); + static void AddSphereCollider(PhysicsActor& actor, const physx::PxMaterial& material); + static void AddCapsuleCollider(PhysicsActor& actor, const physx::PxMaterial& material); + static void AddMeshCollider(PhysicsActor& actor, const physx::PxMaterial& material); + + // static void AddBoxCollider(physx::PxRigidActor& actor, const physx::PxMaterial& material, const BoxColliderComponent& collider, const glm::vec3& scale = glm::vec3(0.0f)); + // static void AddSphereCollider(physx::PxRigidActor& actor, const physx::PxMaterial& material, const SphereColliderComponent& collider, const glm::vec3& scale = glm::vec3(0.0f)); + // static void AddCapsuleCollider(physx::PxRigidActor& actor, const physx::PxMaterial& material, const CapsuleColliderComponent& collider, const glm::vec3& scale = glm::vec3(0.0f)); + // static void AddMeshCollider(::physx::PxRigidActor& actor, const ::physx::PxMaterial& material, ::Prism::MeshColliderComponent& collider, const glm::vec3& scale = glm::vec3(0.0f)); static std::vector CreateTriangleMesh(MeshColliderComponent& collider, bool invalidateOld = false); static std::vector CreateConvexMesh(MeshColliderComponent& collider, bool invalidateOld = false); - static physx::PxMaterial* CreateMaterial(const PhysicsMaterialComponent& material); + // static physx::PxMaterial* CreateMaterial(const PhysicsMaterialComponent& material); static bool Raycast(const glm::vec3& origin, const glm::vec3& direction, float maxDistance, RaycastHit* hit); /* static bool OverlapBox(const glm::vec3& origin, const glm::vec3& halfSize, std::vector& buffer); @@ -63,6 +69,8 @@ namespace Prism static void Initialize(); static void Shutdown(); + static physx::PxPhysics& GetPhysics(); + static physx::PxAllocatorCallback& GetAllocator(); static bool ConnectPVD(); static bool IsPVDConnected(); @@ -70,6 +78,7 @@ namespace Prism private: friend class Physics3D; + friend class PhysicsActor; }; } diff --git a/Prism/src/Prism/Renderer/SceneRenderer.cpp b/Prism/src/Prism/Renderer/SceneRenderer.cpp index 75ec1d4..ac269cc 100644 --- a/Prism/src/Prism/Renderer/SceneRenderer.cpp +++ b/Prism/src/Prism/Renderer/SceneRenderer.cpp @@ -405,8 +405,8 @@ namespace Prism void SceneRenderer::GeometryPass() { - const bool outline = s_Data.SelectedMeshDrawList.size() > 0; - const bool collider = s_Data.ColliderDrawList.size() > 0; + const bool outline = !s_Data.SelectedMeshDrawList.empty(); + const bool collider = !s_Data.ColliderDrawList.empty(); if (outline || collider) { @@ -923,6 +923,10 @@ namespace Prism if (UI::BeginTreeNode("Shadows")) { + UI::Property("Composite Pass time: %.2fs", s_Stats.CompositePass); + UI::Property("Geometry Pass time: %.2fs", s_Stats.GeometryPass); + UI::Property("Shadow Pass time: %.2fs", s_Stats.ShadowPass); + UI::BeginPropertyGrid(); UI::Property("Soft Shadows", s_Data.SoftShadows); UI::Property("Light Size", s_Data.LightSize, 0.01f); diff --git a/Prism/src/Prism/Scene/Components.h b/Prism/src/Prism/Scene/Components.h index 960bc65..eeed723 100644 --- a/Prism/src/Prism/Scene/Components.h +++ b/Prism/src/Prism/Scene/Components.h @@ -168,6 +168,9 @@ namespace Prism enum class Type { Static, Dynamic}; Type BodyType; float Mass = 1.0f; + float LinearDrag = 0.0F; + float AngularDrag = 0.05F; + bool DisableGravity = false; bool IsKinematic = false; uint32_t Layer = 0; diff --git a/Prism/src/Prism/Scene/Scene.cpp b/Prism/src/Prism/Scene/Scene.cpp index 4ae9af6..3c78dfa 100644 --- a/Prism/src/Prism/Scene/Scene.cpp +++ b/Prism/src/Prism/Scene/Scene.cpp @@ -330,7 +330,7 @@ namespace Prism auto group = m_Registry.group(entt::get); // SceneRenderer::BeginScene(this, { static_cast(editorCamera), editorCamera.GetViewMatrix() }); SceneRenderer::BeginScene(this, { static_cast(editorCamera), editorCamera.GetViewMatrix(), 0.1f, 1000.0f, 45.0f }); // TODO: real values - for (auto entity : group) + for (const auto entity : group) { const auto& [transformComponent, meshComponent] = group.get(entity); if (meshComponent.Mesh) @@ -339,12 +339,17 @@ namespace Prism // TODO: Should we render (logically) SceneRenderer::SubmitMesh(meshComponent, transformComponent.GetTransform()); + + if (m_SelectedEntity == entity) + { + SceneRenderer::SubmitSelectedMesh(meshComponent, transformComponent.GetTransform()); + } } } { - auto view = m_Registry.view(); - for (auto entity : view) + const auto view = m_Registry.view(); + for (const auto entity : view) { Entity e = { entity, this }; auto& collider = e.GetComponent(); @@ -356,7 +361,7 @@ namespace Prism { const auto view = m_Registry.view(); - for (auto entity : view) + for (const auto entity : view) { Entity e = { entity, this }; auto& collider = e.GetComponent(); @@ -368,7 +373,7 @@ namespace Prism { const auto view = m_Registry.view(); - for (auto entity : view) + for (const auto entity : view) { Entity e = { entity, this }; auto& collider = e.GetComponent(); @@ -380,7 +385,7 @@ namespace Prism { const auto view = m_Registry.view(); - for (auto entity : view) + for (const auto entity : view) { Entity e = { entity, this }; auto& collider = e.GetComponent(); diff --git a/Prism/src/Prism/Script/ScriptWrappers.cpp b/Prism/src/Prism/Script/ScriptWrappers.cpp index 27ccf66..75d0a04 100644 --- a/Prism/src/Prism/Script/ScriptWrappers.cpp +++ b/Prism/src/Prism/Script/ScriptWrappers.cpp @@ -584,6 +584,7 @@ namespace Prism { namespace Script { PM_CORE_ASSERT(dynamicActor); PM_CORE_ASSERT(velocity); + PM_CORE_INFO("Hazel_RigidBodyComponent_SetLinearVelocity - {0}, {1}, {2}", velocity->x, velocity->y, velocity->z); dynamicActor->setLinearVelocity({ velocity->x, velocity->y, velocity->z }); }