diff --git a/Editor/Editor/EditorLayer.cpp b/Editor/Editor/EditorLayer.cpp index 0dd6a2d..480a987 100644 --- a/Editor/Editor/EditorLayer.cpp +++ b/Editor/Editor/EditorLayer.cpp @@ -9,6 +9,7 @@ #include "glm/gtx/matrix_decompose.hpp" #include "Prism/Core/Input.h" +#include "Prism/Editor/PhysicsSettingsWindow.h" #include "Prism/Physics/Physics3D.h" #include "Prism/Renderer/Renderer2D.h" #include "Prism/Script/ScriptEngine.h" @@ -192,7 +193,7 @@ namespace Prism { case SceneState::Edit: { - // if (m_ViewportPanelFocused) + if (m_ViewportPanelHovered || m_ViewportPanelFocused) m_EditorCamera.OnUpdate(deltaTime); m_EditorScene->OnRenderEditor(deltaTime, m_EditorCamera); @@ -361,6 +362,13 @@ namespace Prism ImGui::EndMenu(); } + if (ImGui::BeginMenu("Edit")) + { + ImGui::MenuItem("Physics Settings", nullptr, &m_ShowPhysicsSettings); + + ImGui::EndMenu(); + } + if (ImGui::BeginMenu("Tools")) { // PhysX Debugger @@ -380,6 +388,7 @@ namespace Prism } m_SceneHierarchyPanel->OnImGuiRender(); + PhysicsSettingsWindow::OnImGuiRender(&m_ShowPhysicsSettings); ImGui::Begin("Materials"); @@ -682,9 +691,13 @@ namespace Prism { if (ImGui::TreeNode(shader->GetName().c_str())) { - std::string buttonName = "Reload##" + shader->GetName(); - if (ImGui::Button(buttonName.c_str())) + + const std::string buttonName = shader->GetName(); + if (ImGui::Button(("Reload##" + buttonName).c_str())) + { + PM_CLIENT_INFO("Reloading Shader: {0}", buttonName); shader->Reload(); + } ImGui::TreePop(); } } @@ -735,7 +748,7 @@ namespace Prism ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(0, 0)); ImGui::Begin("Viewport"); - m_ViewportPanelMouseOver = ImGui::IsWindowHovered(); + m_ViewportPanelHovered = ImGui::IsWindowHovered(); m_ViewportPanelFocused = ImGui::IsWindowFocused(); auto viewportOffset = ImGui::GetCursorPos(); // includes tab bar @@ -809,7 +822,7 @@ namespace Prism { if (m_SceneState == SceneState::Edit) { - if (m_ViewportPanelMouseOver) + if (m_ViewportPanelHovered) m_EditorCamera.OnEvent(e); m_EditorScene->OnEvent(e); @@ -857,42 +870,49 @@ namespace Prism if (Input::IsKeyPressed(KeyCode::LEFT_CONTROL)) { - switch (e.GetKeyCode()) + const bool IsShiftPressed = Input::IsKeyPressed(KeyCode::LEFT_SHIFT); + if (!IsShiftPressed) { - case KeyCode::O: - OpenScene(); - break; - case KeyCode::S: - SaveScene(); - break; - - case KeyCode::B: - // Toggle bounding boxes - m_UIShowBoundingBoxes = !m_UIShowBoundingBoxes; - ShowBoundingBoxes(m_UIShowBoundingBoxes, m_UIShowBoundingBoxesOnTop); - break; - case KeyCode::D: - if (m_SelectionContext.size()) + switch (e.GetKeyCode()) { - Entity selectedEntity = m_SelectionContext[0].Entity; - m_EditorScene->DuplicateEntity(selectedEntity); + case KeyCode::O: + OpenScene(); + break; + case KeyCode::S: + SaveScene(); + break; + + case KeyCode::B: + // Toggle bounding boxes + m_UIShowBoundingBoxes = !m_UIShowBoundingBoxes; + ShowBoundingBoxes(m_UIShowBoundingBoxes, m_UIShowBoundingBoxesOnTop); + break; + case KeyCode::D: + if (m_SelectionContext.size()) + { + const Entity selectedEntity = m_SelectionContext[0].Entity; + m_EditorScene->DuplicateEntity(selectedEntity); + } + break; + case KeyCode::G: + // Toggle grid + SceneRenderer::GetOptions().ShowGrid = !SceneRenderer::GetOptions().ShowGrid; + break; } - break; - case KeyCode::G: - // Toggle grid - SceneRenderer::GetOptions().ShowGrid = !SceneRenderer::GetOptions().ShowGrid; - break; } - if (Input::IsKeyPressed(PM_KEY_LEFT_SHIFT)) - { + if (IsShiftPressed) { switch (e.GetKeyCode()) { case KeyCode::S: SaveSceneAs(); break; + default: + break; } } + + // TODO: ALT TAB } return false; @@ -902,7 +922,7 @@ namespace Prism { auto [mx, my] = Input::GetMousePosition(); - if (e.GetMouseButton() == PM_MOUSE_BUTTON_LEFT && !Input::IsKeyPressed(KeyCode::LEFT_ALT) && !ImGuizmo::IsOver() && m_SceneState != SceneState::Play) + if (m_ViewportPanelHovered && e.GetMouseButton() == PM_MOUSE_BUTTON_LEFT && !Input::IsKeyPressed(KeyCode::LEFT_ALT) && !ImGuizmo::IsOver() && m_SceneState != SceneState::Play) { auto [mouseX, mouseY] = GetMouseViewportSpace(); if (mouseX > -1.0f && mouseX < 1.0f && mouseY > -1.0f && mouseY < 1.0f) @@ -912,9 +932,9 @@ namespace Prism m_SelectionContext.clear(); m_EditorScene->SetSelectedEntity({}); const auto meshEntities = m_EditorScene->GetAllEntitiesWith(); - for (auto e : meshEntities) + for (const auto aEntity : meshEntities) { - Entity entity = { e, m_EditorScene.Raw() }; + Entity entity = { aEntity, m_EditorScene.Raw() }; auto mesh = entity.GetComponent().Mesh; if (!mesh) @@ -970,9 +990,7 @@ namespace Prism SelectedSubmesh selection; if (entity.HasComponent()) { - auto& meshComp = entity.GetComponent(); - - if (meshComp.Mesh) + if (auto& meshComp = entity.GetComponent(); meshComp.Mesh) { selection.Mesh = &meshComp.Mesh->GetSubmeshes()[0]; } @@ -1066,6 +1084,7 @@ namespace Prism void EditorLayer::SaveScene() { + PM_CLIENT_INFO("Saving scene to: {0}", m_SceneFilePath); SceneSerializer serializer(m_EditorScene); serializer.Serialize(m_SceneFilePath); } @@ -1076,6 +1095,7 @@ namespace Prism std::string filepath = app.SaveFile("Prism Scene (*.hsc)\0*.hsc\0"); if (!filepath.empty()) { + PM_CLIENT_INFO("Saving scene to: {0}", m_SceneFilePath); SceneSerializer serializer(m_EditorScene); serializer.Serialize(filepath); @@ -1112,6 +1132,8 @@ namespace Prism m_SelectionContext.clear(); ScriptEngine::SetSceneContext(m_EditorScene); m_SceneHierarchyPanel->SetContext(m_EditorScene); + + Input::SetCursorMode(CursorMode::Normal); } float EditorLayer::GetSnapValue() diff --git a/Editor/Editor/EditorLayer.h b/Editor/Editor/EditorLayer.h index 8e0717c..cb90fdc 100644 --- a/Editor/Editor/EditorLayer.h +++ b/Editor/Editor/EditorLayer.h @@ -143,8 +143,9 @@ namespace Prism }; SceneType m_SceneType; - bool m_ViewportPanelMouseOver = false; + bool m_ViewportPanelHovered = false; bool m_ViewportPanelFocused = false; + bool m_ShowPhysicsSettings = false; enum class SceneState { diff --git a/Editor/assets/scenes/FPSDemo.scene b/Editor/assets/scenes/FPSDemo.scene index 41c07aa..0790ad7 100644 --- a/Editor/assets/scenes/FPSDemo.scene +++ b/Editor/assets/scenes/FPSDemo.scene @@ -2,15 +2,15 @@ Scene: Scene Name Environment: AssetPath: assets/env/pink_sunrise_4k.hdr Light: - Direction: [-0.787, -0.73299998, 1] + Direction: [-0.787, -0.733, 1] Radiance: [1, 1, 1] - Multiplier: 0.514999986 + Multiplier: 0.515 Entities: - Entity: 3247025703490125974 TagComponent: Tag: Player TransformComponent: - Position: [2.80803752, 1.5, 0] + Position: [2.8080375, 1.5, 0] Rotation: [1, 0, 0, 0] Scale: [2, 2, 2] ScriptComponent: @@ -25,23 +25,30 @@ Entities: - Name: JumpForce Type: 1 Data: 50 + - Name: MouseSensitivity + Type: 1 + Data: 10 + - Name: Distance + Type: 1 + Data: 0 MeshComponent: AssetPath: assets/meshes/Capsule.fbx RigidBodyComponent: BodyType: 1 Mass: 1 IsKinematic: false + Layer: 1 Constraints: LockPositionX: false LockPositionY: false LockPositionZ: false LockRotationX: true - LockRotationY: false + LockRotationY: true LockRotationZ: true PhysicsMaterialComponent: - StaticFriction: 0.100000001 - DynamicFriction: 0.100000001 - Bounciness: 0.100000001 + StaticFriction: 0.1 + DynamicFriction: 0.1 + Bounciness: 0.1 MeshColliderComponent: AssetPath: assets/meshes/Capsule.fbx IsTrigger: false @@ -49,15 +56,16 @@ Entities: TagComponent: Tag: Mesh Collider TransformComponent: - Position: [-2.60455179, 1, -0.00171399117] + Position: [-2.6045518, 1, -0.0017139912] Rotation: [1, 0, 0, 0] Scale: [1, 1, 1] MeshComponent: AssetPath: assets/meshes/Sphere1m.fbx RigidBodyComponent: BodyType: 1 - Mass: 0.100000001 + Mass: 0.1 IsKinematic: false + Layer: 1 Constraints: LockPositionX: false LockPositionY: false @@ -68,7 +76,7 @@ Entities: PhysicsMaterialComponent: StaticFriction: 1 DynamicFriction: 1 - Bounciness: 0.100000001 + Bounciness: 0.1 MeshColliderComponent: AssetPath: assets/meshes/Sphere1m.fbx IsTrigger: false @@ -85,6 +93,7 @@ Entities: BodyType: 1 Mass: 0.5 IsKinematic: false + Layer: 0 Constraints: LockPositionX: false LockPositionY: false @@ -104,7 +113,7 @@ Entities: TagComponent: Tag: Sphere TransformComponent: - Position: [-3.98769951, 1, -1.96695328e-06] + Position: [-3.9876995, 1, -1.9669533e-06] Rotation: [1, 0, 0, 0] Scale: [1, 1, 1] MeshComponent: @@ -113,17 +122,18 @@ Entities: BodyType: 1 Mass: 1 IsKinematic: false + Layer: 1 Constraints: LockPositionX: false LockPositionY: false LockPositionZ: false - LockRotationX: true - LockRotationY: true - LockRotationZ: true + LockRotationX: false + LockRotationY: false + LockRotationZ: false PhysicsMaterialComponent: - StaticFriction: 0.100000001 - DynamicFriction: 0.100000001 - Bounciness: 0.100000001 + StaticFriction: 0.1 + DynamicFriction: 0.1 + Bounciness: 0.1 SphereColliderComponent: Radius: 0.5 IsTrigger: false @@ -131,7 +141,7 @@ Entities: TagComponent: Tag: Camera TransformComponent: - Position: [2.80800009, 2.25, 0] + Position: [2.808, 2.25, 0] Rotation: [1, 0, 0, 0] Scale: [1, 1, 1] CameraComponent: @@ -150,6 +160,7 @@ Entities: BodyType: 0 Mass: 1 IsKinematic: false + Layer: 0 Constraints: LockPositionX: false LockPositionY: false @@ -165,3 +176,7 @@ Entities: Offset: [0, 0, 0] Size: [1, 1, 1] IsTrigger: false +PhysicsLayers: + - Name: Default + CollidesWith: + [] \ No newline at end of file diff --git a/ExampleApp/Src/FPSPlayer.cs b/ExampleApp/Src/FPSPlayer.cs index 998b0b7..5c533c8 100644 --- a/ExampleApp/Src/FPSPlayer.cs +++ b/ExampleApp/Src/FPSPlayer.cs @@ -1,4 +1,3 @@ -using System; using Prism; namespace FPSExample @@ -9,7 +8,7 @@ namespace FPSExample public float RunSpeed = 20.0F; public float JumpForce = 50.0F; public float MouseSensitivity = 10.0F; - public Vec3 Forward = new Vec3(0.0f, 0.0f, 1.0f); + public float Distance = 5.0F; private bool m_Colliding = false; private float m_CurrentSpeed; @@ -44,12 +43,11 @@ namespace FPSExample void OnUpdate(float ts) { - Forward = m_Transform.Forward; - if (Input.IsKeyPressed(KeyCode.Escape) && Input.GetCursorMode() == Input.CursorMode.Locked) - { Input.SetCursorMode(Input.CursorMode.Normal); - } + + if(Input.IsMouseButtonPressed(Input.MouseButton.Left) && Input.GetCursorMode() == Input.CursorMode.Normal) + Input.SetCursorMode(Input.CursorMode.Locked); m_CurrentSpeed = Input.IsKeyPressed(KeyCode.LeftControl) ? RunSpeed : WalkingSpeed; @@ -78,9 +76,33 @@ namespace FPSExample m_LastMousePosition = currentMousePosition; } + Collider[] colliders = new Collider[10]; + private void UpdateMovement() { + RaycastHit hitInfo; + if (Input.IsKeyPressed(KeyCode.H) && + Physics.Raycast(m_CameraTransform.Transform.Translation + (m_CameraTransform.Forward * 5.0f), + m_CameraTransform.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.Transform.Translation, 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]); + } + } + if (Input.IsKeyPressed(KeyCode.W)) m_RigidBody.AddForce(m_Transform.Forward * m_CurrentSpeed); else if (Input.IsKeyPressed(KeyCode.S)) @@ -105,7 +127,7 @@ namespace FPSExample Vec3 translation = m_Transform.Transform.Translation; cameraTranslation.XZ = translation.XZ; cameraTranslation.Y = translation.Y + 1.5F; - cameraTransform.Translation = cameraTranslation; + cameraTransform.Translation = cameraTranslation + m_CameraTransform.Forward * -Mathf.Clamp(Distance, 0, 10); m_CameraTransform.Transform = cameraTransform; m_CameraTransform.Rotation = new Vec3(m_CameraRotationX, m_RotationY, 0.0f); diff --git a/Prism-ScriptCore/Src/Prism/Entity.cs b/Prism-ScriptCore/Src/Prism/Entity.cs index fd34361..ff6af10 100644 --- a/Prism-ScriptCore/Src/Prism/Entity.cs +++ b/Prism-ScriptCore/Src/Prism/Entity.cs @@ -55,6 +55,12 @@ namespace Prism return new Entity(entityID); } + public Entity FindEntityByID(ulong entityID) + { + // TODO: to verify it + return new Entity(entityID); + } + public Mat4 GetTransform() { Mat4 mat4Instance; diff --git a/Prism-ScriptCore/Src/Prism/Input.cs b/Prism-ScriptCore/Src/Prism/Input.cs index 443bb9d..65aceb8 100644 --- a/Prism-ScriptCore/Src/Prism/Input.cs +++ b/Prism-ScriptCore/Src/Prism/Input.cs @@ -10,12 +10,31 @@ namespace Prism Hidden = 1, Locked = 2, } + + public enum MouseButton + { + Button0 = 0, + Button1 = 1, + Button2 = 2, + Button3 = 3, + Button4 = 4, + Button5 = 5, + Left = Button0, + Right = Button1, + Middle = Button2 + } + public static bool IsKeyPressed(KeyCode keycode) { return IsKeyPressed_Native(keycode); } + public static bool IsMouseButtonPressed(MouseButton button) + { + return IsMouseButtonPressed_Native(button); + } + public static Vec2 GetMousePosition() { GetMousePosition_Native(out Vec2 position); @@ -30,6 +49,9 @@ namespace Prism [MethodImpl(MethodImplOptions.InternalCall)] private static extern bool IsKeyPressed_Native(KeyCode keycode); + [MethodImpl(MethodImplOptions.InternalCall)] + private static extern bool IsMouseButtonPressed_Native(MouseButton button); + [MethodImpl(MethodImplOptions.InternalCall)] private static extern void GetMousePosition_Native(out Vec2 position); diff --git a/Prism-ScriptCore/Src/Prism/Math/Vec3.cs b/Prism-ScriptCore/Src/Prism/Math/Vec3.cs index 313ad1d..e1100f1 100644 --- a/Prism-ScriptCore/Src/Prism/Math/Vec3.cs +++ b/Prism-ScriptCore/Src/Prism/Math/Vec3.cs @@ -46,6 +46,25 @@ namespace Prism Z = Mathf.Clamp(Z, min.Z, max.Z); } + public float Length() + { + return (float)Math.Sqrt(X * X + Y * Y + Z * Z); + } + + public Vec3 Normalized() + { + float length = Length(); + return new Vec3(X / length, Y / length, Z / length); + } + + public void Normalize() + { + float length = Length(); + X = X / length; + Y = Y / length; + Z = Z / length; + } + public Vec2 XY { get { return new Vec2(X, Y); } @@ -79,6 +98,11 @@ namespace Prism return new Vec3(left.X + right.X, left.Y + right.Y, left.Z + right.Z); } + public static Vec3 operator +(Vec3 left, float right) + { + return new Vec3(left.X + right, left.Y + right, left.Z + right); + } + public static Vec3 operator -(Vec3 left, Vec3 right) { return new Vec3(left.X - right.X, left.Y - right.Y, left.Z - right.Z); diff --git a/Prism-ScriptCore/Src/Prism/Physics/Colliders.cs b/Prism-ScriptCore/Src/Prism/Physics/Colliders.cs index b111cca..eb70f1e 100644 --- a/Prism-ScriptCore/Src/Prism/Physics/Colliders.cs +++ b/Prism-ScriptCore/Src/Prism/Physics/Colliders.cs @@ -4,29 +4,55 @@ namespace Prism { public class Collider { - public enum ColliderType - { - Box, - Sphere, - Capsule, - Mesh - } - - public Entity ColliderEntity { get; protected set; } - public ColliderType Type { get; protected set; } + public ulong EntityID { get; protected set; } public bool IsTrigger { get; protected set; } + private Entity entity; + private RigidBodyComponent _rigidBodyComponent; + + public Entity Entity + { + get + { + if (entity == null) + entity = new Entity(EntityID); + + return entity; + } + } + + public RigidBodyComponent RigidBody + { + get + { + if (_rigidBodyComponent == null) + _rigidBodyComponent = Entity.GetComponent(); + + return _rigidBodyComponent; + } + } + + public override string ToString() + { + string type = "Collider"; + + if (this is BoxCollider) type = "BoxCollider"; + else if (this is SphereCollider) type = "SphereCollider"; + else if (this is CapsuleCollider) type = "CapsuleCollider"; + else if (this is MeshCollider) type = "MeshCollider"; + + return "Collider(" + type + ", " + EntityID + ", " + IsTrigger + ")"; + } } public class BoxCollider : Collider { - public Vec3 Size { get; private set; } - public Vec3 Offset { get; private set; } + public Vec3 Size { get; protected set; } + public Vec3 Offset { get; protected set; } - internal BoxCollider(ulong entityID, Vec3 size, Vec3 offset, bool isTrigger) + private BoxCollider(ulong entityID, bool isTrigger, Vec3 size, Vec3 offset) { - ColliderEntity = new Entity(entityID); - Type = ColliderType.Box; + EntityID = entityID; Size = size; Offset = offset; IsTrigger = isTrigger; @@ -35,12 +61,11 @@ namespace Prism public class SphereCollider : Collider { - public float Radius { get; private set; } + public float Radius { get; protected set; } - internal SphereCollider(ulong entityID, float radius, bool isTrigger) + private SphereCollider(ulong entityID, bool isTrigger, float radius) { - ColliderEntity = new Entity(entityID); - Type = ColliderType.Box; + EntityID = entityID; Radius = radius; IsTrigger = isTrigger; } @@ -48,13 +73,12 @@ namespace Prism public class CapsuleCollider : Collider { - public float Radius { get; private set; } - public float Height { get; private set; } + public float Radius { get; protected set; } + public float Height { get; protected set; } - internal CapsuleCollider(ulong entityID, float radius, float height, bool isTrigger) + private CapsuleCollider(ulong entityID, bool isTrigger, float radius, float height) { - ColliderEntity = new Entity(entityID); - Type = ColliderType.Box; + EntityID = entityID; Radius = radius; Height = height; IsTrigger = isTrigger; @@ -63,13 +87,12 @@ namespace Prism public class MeshCollider : Collider { - public Mesh Mesh { get; private set; } + public Mesh Mesh { get; protected set; } - internal MeshCollider(ulong entityID, Mesh mesh, bool isTrigger) + private MeshCollider(ulong entityID, bool isTrigger, IntPtr filepath) { - ColliderEntity = new Entity(entityID); - Type = ColliderType.Box; - Mesh = mesh; + EntityID = entityID; + Mesh = new Mesh(filepath); IsTrigger = isTrigger; } } diff --git a/Prism-ScriptCore/Src/Prism/Physics/Physics.cs b/Prism-ScriptCore/Src/Prism/Physics/Physics.cs new file mode 100644 index 0000000..d53e128 --- /dev/null +++ b/Prism-ScriptCore/Src/Prism/Physics/Physics.cs @@ -0,0 +1,74 @@ +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +namespace Prism +{ + + [StructLayout(LayoutKind.Sequential)] + public struct RaycastHit + { + public ulong EntityID { get; private set; } + public Vec3 Position { get; private set; } + public Vec3 Normal { get; private set; } + public float Distance { get; private set; } + } + + public static class Physics + { + public static bool Raycast(Vec3 origin, Vec3 direction, float maxDistance, out RaycastHit hit) + { + return Raycast_Native(ref origin, ref direction, maxDistance, out hit); + } + + public static Collider[] OverlapBox(Vec3 origin, Vec3 halfSize) + { + return OverlapBox_Native(ref origin, ref halfSize); + } + + public static Collider[] OverlapCapsule(Vec3 origin, float radius, float halfHeight) + { + return OverlapCapsule_Native(ref origin, radius, halfHeight); + } + + public static Collider[] OverlapSphere(Vec3 origin, float radius) + { + return OverlapSphere_Native(ref origin, radius); + } + + public static int OverlapBoxNonAlloc(Vec3 origin, Vec3 halfSize, Collider[] colliders) + { + return OverlapBoxNonAlloc_Native(ref origin, ref halfSize, colliders); + } + + public static int OverlapCapsuleNonAlloc(Vec3 origin, float radius, float halfHeight, Collider[] colliders) + { + return OverlapCapsuleNonAlloc_Native(ref origin, radius, halfHeight, colliders); + } + + public static int OverlapSphereNonAlloc(Vec3 origin, float radius, Collider[] colliders) + { + return OverlapSphereNonAlloc_Native(ref origin, radius, colliders); + } + + [MethodImpl(MethodImplOptions.InternalCall)] + internal static extern bool Raycast_Native(ref Vec3 origin, ref Vec3 direction, float maxDistance, out RaycastHit hit); + + [MethodImpl(MethodImplOptions.InternalCall)] + internal static extern Collider[] OverlapBox_Native(ref Vec3 origin, ref Vec3 halfSize); + + [MethodImpl(MethodImplOptions.InternalCall)] + internal static extern Collider[] OverlapCapsule_Native(ref Vec3 origin, float radius, float halfHeight); + + [MethodImpl(MethodImplOptions.InternalCall)] + internal static extern Collider[] OverlapSphere_Native(ref Vec3 origin, float radius); + + [MethodImpl(MethodImplOptions.InternalCall)] + internal static extern int OverlapBoxNonAlloc_Native(ref Vec3 origin, ref Vec3 halfSize, Collider[] colliders); + + [MethodImpl(MethodImplOptions.InternalCall)] + internal static extern int OverlapCapsuleNonAlloc_Native(ref Vec3 origin, float radius, float halfHeight, Collider[] colliders); + + [MethodImpl(MethodImplOptions.InternalCall)] + internal static extern int OverlapSphereNonAlloc_Native(ref Vec3 origin, float radius, Collider[] colliders); + } +} \ No newline at end of file diff --git a/Prism-ScriptCore/Src/Prism/Scene/Component.cs b/Prism-ScriptCore/Src/Prism/Scene/Component.cs index 4822922..2fdf52b 100644 --- a/Prism-ScriptCore/Src/Prism/Scene/Component.cs +++ b/Prism-ScriptCore/Src/Prism/Scene/Component.cs @@ -192,6 +192,18 @@ namespace Prism VelocityChange, Acceleration } + + public float Mass + { + get { return GetMass_Native(Entity.ID); } + set { SetMass_Native(Entity.ID, value); } + } + + public uint Layer + { + get { return GetLayer_Native(Entity.ID); } + } + public void AddForce(Vec3 force, ForceMode forceMode = ForceMode.Force) { @@ -234,5 +246,14 @@ namespace Prism [MethodImpl(MethodImplOptions.InternalCall)] internal static extern void Rotate_Native(ulong entityID, ref Vec3 rotation); + + [MethodImpl(MethodImplOptions.InternalCall)] + internal static extern uint GetLayer_Native(ulong entityID); + + [MethodImpl(MethodImplOptions.InternalCall)] + internal static extern float GetMass_Native(ulong entityID); + [MethodImpl(MethodImplOptions.InternalCall)] + internal static extern float SetMass_Native(ulong entityID, float mass); + } } diff --git a/Prism/src/Prism/Core/Input.h b/Prism/src/Prism/Core/Input.h index b95acc5..b4f16ff 100644 --- a/Prism/src/Prism/Core/Input.h +++ b/Prism/src/Prism/Core/Input.h @@ -9,19 +9,12 @@ namespace Prism { - enum class CursorMode - { - Normal = 0, - Hidden = 1, - Locked = 2 - }; - class PRISM_API Input { public: static bool IsKeyPressed(KeyCode keycode); - static bool IsMouseButtonPressed(int button); + static bool IsMouseButtonPressed(MouseButton button); static float GetMouseX(); static float GetMouseY(); static std::pair GetMousePosition(); diff --git a/Prism/src/Prism/Core/KeyCodes.h b/Prism/src/Prism/Core/KeyCodes.h index cb1039a..c2ac9f5 100644 --- a/Prism/src/Prism/Core/KeyCodes.h +++ b/Prism/src/Prism/Core/KeyCodes.h @@ -7,6 +7,32 @@ namespace Prism { + enum class CursorMode + { + Normal = 0, + Hidden = 1, + Locked = 2 + }; + + typedef enum class MouseButton : uint16_t + { + Button0 = 0, + Button1 = 1, + Button2 = 2, + Button3 = 3, + Button4 = 4, + Button5 = 5, + Left = Button0, + Right = Button1, + Middle = Button2 + } Button; + + inline std::ostream& operator<<(std::ostream& os, MouseButton button) + { + os << static_cast(button); + return os; + } + typedef enum class KeyCode : uint16_t { SPACE = 32, diff --git a/Prism/src/Prism/Editor/EditorCamera.cpp b/Prism/src/Prism/Editor/EditorCamera.cpp index ef9537c..0f1482e 100644 --- a/Prism/src/Prism/Editor/EditorCamera.cpp +++ b/Prism/src/Prism/Editor/EditorCamera.cpp @@ -45,11 +45,11 @@ namespace Prism const glm::vec2 delta = (mouse - m_InitialMousePosition) * 0.003f; m_InitialMousePosition = mouse; - if (Input::IsMouseButtonPressed(GLFW_MOUSE_BUTTON_MIDDLE)) + if (Input::IsMouseButtonPressed(MouseButton::Middle)) MousePan(delta); - else if (Input::IsMouseButtonPressed(GLFW_MOUSE_BUTTON_LEFT)) + else if (Input::IsMouseButtonPressed(MouseButton::Left)) MouseRotate(delta); - else if (Input::IsMouseButtonPressed(GLFW_MOUSE_BUTTON_RIGHT)) + else if (Input::IsMouseButtonPressed(MouseButton::Right)) MouseZoom(delta.y); } diff --git a/Prism/src/Prism/Editor/PhysicsSettingsWindow.cpp b/Prism/src/Prism/Editor/PhysicsSettingsWindow.cpp new file mode 100644 index 0000000..e1dfe8b --- /dev/null +++ b/Prism/src/Prism/Editor/PhysicsSettingsWindow.cpp @@ -0,0 +1,109 @@ +// +// Created by sfd on 25-12-25. +// + +#include "PhysicsSettingsWindow.h" + +#include "imgui.h" +#include "Prism/Physics/PhysicsLayer.h" + +namespace Prism +{ + static int32_t s_SelectedLayer = -1; + static char s_NewLayerNameBuffer[50]; + + void PhysicsSettingsWindow::OnImGuiRender(bool* show) + { + if (!(*show)) + return; + + ImGui::Begin("Physics", show); + ImGui::PushID(0); + ImGui::Columns(2); + + RenderLayerList(); + ImGui::NextColumn(); + RenderSelectedLayer(); + + ImGui::PopID(); + ImGui::End(); + } + + void PhysicsSettingsWindow::RenderLayerList() + { + if (ImGui::Button("New Layer")) + { + ImGui::OpenPopup("NewLayerNamePopup"); + } + + if (ImGui::BeginPopup("NewLayerNamePopup")) + { + ImGui::InputText("##LayerNameID", s_NewLayerNameBuffer, 50); + + if (ImGui::Button("Add")) + { + PhysicsLayerManager::AddLayer(std::string(s_NewLayerNameBuffer)); + memset(s_NewLayerNameBuffer, 0, 50); + ImGui::CloseCurrentPopup(); + } + + ImGui::EndPopup(); + } + + uint32_t buttonId = 1; + + for (const auto& layer : PhysicsLayerManager::GetLayers()) + { + if (ImGui::Button(layer.Name.c_str())) + { + s_SelectedLayer = layer.LayerID; + } + + if (layer.Name != "Default") + { + ImGui::SameLine(); + ImGui::PushID(buttonId++); + if (ImGui::Button("X")) + { + PhysicsLayerManager::RemoveLayer(layer.LayerID); + } + ImGui::PopID(); + } + } + } + + + void PhysicsSettingsWindow::RenderSelectedLayer() + { + if (s_SelectedLayer == -1) + return; + + const PhysicsLayer& layerInfo = PhysicsLayerManager::GetLayer(s_SelectedLayer); + + for (const auto& layer : PhysicsLayerManager::GetLayers()) + { + if (layer.LayerID == s_SelectedLayer) + continue; + + const PhysicsLayer& otherLayerInfo = PhysicsLayerManager::GetLayer(layer.LayerID); + bool shouldCollide; + + if (layerInfo.CollidesWith == 0 || otherLayerInfo.CollidesWith == 0) + { + shouldCollide = false; + } + else + { + shouldCollide = layerInfo.CollidesWith & otherLayerInfo.BitValue; + } + + ImGui::TextUnformatted(otherLayerInfo.Name.c_str()); + ImGui::SameLine(); + if (ImGui::Checkbox(("##" + otherLayerInfo.Name).c_str(), &shouldCollide)) + { + PhysicsLayerManager::SetLayerCollision(s_SelectedLayer, layer.LayerID, shouldCollide); + } + } + } + +} diff --git a/Prism/src/Prism/Editor/PhysicsSettingsWindow.h b/Prism/src/Prism/Editor/PhysicsSettingsWindow.h new file mode 100644 index 0000000..a0d9801 --- /dev/null +++ b/Prism/src/Prism/Editor/PhysicsSettingsWindow.h @@ -0,0 +1,20 @@ +// +// Created by sfd on 25-12-25. +// + +#ifndef PHYSICSSETTINGSWINDOW_H +#define PHYSICSSETTINGSWINDOW_H + +namespace Prism +{ + class PRISM_API PhysicsSettingsWindow + { + public: + static void OnImGuiRender(bool* show); + static void RenderLayerList(); + static void RenderSelectedLayer(); + }; +} + + +#endif //PHYSICSSETTINGSWINDOW_H diff --git a/Prism/src/Prism/Editor/SceneHierachyPanel.cpp b/Prism/src/Prism/Editor/SceneHierachyPanel.cpp index d75f493..5b5e25b 100644 --- a/Prism/src/Prism/Editor/SceneHierachyPanel.cpp +++ b/Prism/src/Prism/Editor/SceneHierachyPanel.cpp @@ -12,7 +12,8 @@ #include "glm/gtx/matrix_decompose.hpp" #include "glm/gtx/quaternion.hpp" #include "Prism/Core/Application.h" -#include "Prism/Physics/PxPhysicsWrappers.h" +#include "Prism/Physics/PhysicsLayer.h" +#include "Prism/Physics/PhysicsWrappers.h" #include "Prism/Renderer/Meshfactory.h" #include "Prism/Script/ScriptEngine.h" @@ -951,7 +952,10 @@ namespace Prism // Rigidbody Type const char* rbTypeStrings[] = { "Static", "Dynamic"}; const char* currentType = rbTypeStrings[(int)rbc.BodyType]; - if (ImGui::BeginCombo("Type", currentType)) + + ImGui::TextUnformatted("Type"); + ImGui::SameLine(); + if (ImGui::BeginCombo("##TypeSelection", currentType)) { for (int type = 0; type < 2; type++) { @@ -967,6 +971,32 @@ namespace Prism ImGui::EndCombo(); } + + // Layer has been removed, set to Default layer + if (!PhysicsLayerManager::IsLayerValid(rbc.Layer)) + rbc.Layer = 0; + + uint32_t currentLayer = rbc.Layer; + const PhysicsLayer& layerInfo = PhysicsLayerManager::GetLayer(currentLayer); + ImGui::TextUnformatted("Layer"); + ImGui::SameLine(); + if (ImGui::BeginCombo("##LayerSelection", layerInfo.Name.c_str())) + { + for (const auto& layer : PhysicsLayerManager::GetLayers()) + { + const bool is_selected = (currentLayer == layer.LayerID); + if (ImGui::Selectable(layer.Name.c_str(), is_selected)) + { + currentLayer = layer.LayerID; + rbc.Layer = layer.LayerID; + } + if (is_selected) + ImGui::SetItemDefaultFocus(); + } + ImGui::EndCombo(); + } + + if (rbc.BodyType == RigidBodyComponent::Type::Dynamic) { BeginPropertyGrid(); @@ -1071,7 +1101,7 @@ namespace Prism if (!file.empty()) { mcc.CollisionMesh = Ref::Create(file); - PxPhysicsWrappers::CreateConvexMesh(mcc); + PhysicsWrappers::CreateConvexMesh(mcc); } } ImGui::EndColumns(); diff --git a/Prism/src/Prism/Physics/Physics3D.cpp b/Prism/src/Prism/Physics/Physics3D.cpp index c577d18..68ada63 100644 --- a/Prism/src/Prism/Physics/Physics3D.cpp +++ b/Prism/src/Prism/Physics/Physics3D.cpp @@ -12,16 +12,12 @@ #define PX_PHYSX_STATIC_LIB #include -#include "PxPhysicsWrappers.h" +#include "PhysicsLayer.h" +#include "PhysicsWrappers.h" namespace Prism { - static physx::PxScene* s_Scene = nullptr; - static std::vector s_SimulatedEntities; - static Entity* s_EntityStorageBuffer = nullptr; - static int s_EntityStorageBufferPosition = 0; - static std::tuple GetTransformDecomposition(const glm::mat4& transform) { glm::vec3 scale, translation, skew; @@ -32,20 +28,26 @@ namespace Prism return { translation, orientation, scale }; } + static physx::PxScene* s_Scene; + static std::vector s_SimulatedEntities; + static Entity* s_EntityStorageBuffer; + static int s_EntityStorageBufferPosition; + void Physics3D::Init() { - PxPhysicsWrappers::Initialize(); + PhysicsWrappers::Initialize(); + PhysicsLayerManager::AddLayer("Default"); } void Physics3D::Shutdown() { - PxPhysicsWrappers::Shutdown(); + PhysicsWrappers::Shutdown(); } void Physics3D::CreateScene(const SceneParams& params) { PM_CORE_ASSERT(s_Scene == nullptr, "Scene already has a Physics Scene!"); - s_Scene = PxPhysicsWrappers::CreateScene(params); + s_Scene = PhysicsWrappers::CreateScene(params); } void Physics3D::CreateActor(Entity e, int entityCount) @@ -67,53 +69,48 @@ namespace Prism if (s_EntityStorageBuffer == nullptr) s_EntityStorageBuffer = new Entity[entityCount]; - // Create Actor Body - physx::PxRigidActor* actor = PxPhysicsWrappers::CreateActor(rigidbody, e.Transform()); + physx::PxRigidActor* actor = PhysicsWrappers::CreateActor(rigidbody, e.Transform()); s_SimulatedEntities.push_back(e); Entity* entityStorage = &s_EntityStorageBuffer[s_EntityStorageBufferPosition++]; *entityStorage = e; actor->userData = (void*)entityStorage; rigidbody.RuntimeActor = actor; - // Physics Material - const physx::PxMaterial* material = PxPhysicsWrappers::CreateMaterial(e.GetComponent()); + const physx::PxMaterial* material = PhysicsWrappers::CreateMaterial(e.GetComponent()); + + const auto& transform = e.Transform(); + auto [translation, rotation, scale] = GetTransformDecomposition(transform); - auto [translation, rotationQuat, scale] = GetTransformDecomposition(e.Transform()); // Add all colliders if (e.HasComponent()) { const BoxColliderComponent& collider = e.GetComponent(); - PxPhysicsWrappers::AddBoxCollider(*actor, *material, collider, scale); + PhysicsWrappers::AddBoxCollider(*actor, *material, collider, scale); } if (e.HasComponent()) { const SphereColliderComponent& collider = e.GetComponent(); - PxPhysicsWrappers::AddSphereCollider(*actor, *material, collider, scale); + PhysicsWrappers::AddSphereCollider(*actor, *material, collider, scale); } if (e.HasComponent()) { const CapsuleColliderComponent& collider = e.GetComponent(); - PxPhysicsWrappers::AddCapsuleCollider(*actor, *material, collider, scale); + PhysicsWrappers::AddCapsuleCollider(*actor, *material, collider, scale); } if (e.HasComponent()) { - MeshColliderComponent& collider = e.GetComponent(); - PxPhysicsWrappers::AddMeshCollider(*actor, *material, collider, scale); + auto& collider = e.GetComponent(); + PhysicsWrappers::AddMeshCollider(*actor, *material, collider, scale); } - // Set collision filters - if (rigidbody.BodyType == RigidBodyComponent::Type::Static) - { - PxPhysicsWrappers::SetCollisionFilters(*actor, (uint32_t)FilterGroup::Static, (uint32_t)FilterGroup::All); - } - else if (rigidbody.BodyType == RigidBodyComponent::Type::Dynamic) - { - PxPhysicsWrappers::SetCollisionFilters(*actor, (uint32_t)FilterGroup::Dynamic, (uint32_t)FilterGroup::All); - } + if (!PhysicsLayerManager::IsLayerValid(rigidbody.Layer)) + rigidbody.Layer = 0; + + PhysicsWrappers::SetCollisionFilters(*actor, rigidbody.Layer); s_Scene->addActor(*actor); } @@ -127,7 +124,7 @@ namespace Prism { auto& transform = e.Transform(); // TODO: Come up with a better solution for scale - auto [p, r, scale] = GetTransformDecomposition(transform); + auto [position, rotation, scale] = GetTransformDecomposition(transform); const auto& rb = e.GetComponent(); const auto actor = static_cast(rb.RuntimeActor); @@ -153,10 +150,15 @@ namespace Prism s_Scene = nullptr; } + void* Physics3D::GetPhysicsScene() + { + return s_Scene; + } + bool Physics3D::ConnectPVD() { PM_CORE_INFO("Trying to connect PVD"); - const bool isconnect = PxPhysicsWrappers::ConnectPVD(); + const bool isconnect = PhysicsWrappers::ConnectPVD(); if (isconnect) PM_CORE_INFO("PVD Connected"); else @@ -164,11 +166,11 @@ namespace Prism return isconnect; } - bool Physics3D::IsPVDConnected() {return PxPhysicsWrappers::IsPVDConnected();} + bool Physics3D::IsPVDConnected() {return PhysicsWrappers::IsPVDConnected();} void Physics3D::DisconnectPVD() { - PxPhysicsWrappers::DisconnectPVD(); + PhysicsWrappers::DisconnectPVD(); } diff --git a/Prism/src/Prism/Physics/Physics3D.h b/Prism/src/Prism/Physics/Physics3D.h index c8477a2..2b1f9b0 100644 --- a/Prism/src/Prism/Physics/Physics3D.h +++ b/Prism/src/Prism/Physics/Physics3D.h @@ -27,6 +27,14 @@ namespace Prism All = Static | Dynamic | Kinematic }; + struct RaycastHit + { + uint64_t EntityID; + glm::vec3 Position; + glm::vec3 Normal; + float Distance; + }; + struct SceneParams { glm::vec3 Gravity = { 0.0F, -9.81F, 0.0F }; @@ -45,6 +53,8 @@ namespace Prism static void DestroyScene(); + static void* GetPhysicsScene(); + static bool ConnectPVD(); static bool IsPVDConnected(); static void DisconnectPVD(); diff --git a/Prism/src/Prism/Physics/PhysicsLayer.cpp b/Prism/src/Prism/Physics/PhysicsLayer.cpp new file mode 100644 index 0000000..e10c46e --- /dev/null +++ b/Prism/src/Prism/Physics/PhysicsLayer.cpp @@ -0,0 +1,168 @@ +// +// Created by sfd on 25-12-25. +// + +#include "PhysicsLayer.h" + +namespace Prism +{ + template + static bool RemoveIfExists(std::vector& vector, ConditionFunction condition) + { + for (std::vector::iterator it = vector.begin(); it != vector.end(); ++it) + { + if (condition(*it)) + { + vector.erase(it); + return true; + } + } + + return false; + } + + uint32_t PhysicsLayerManager::AddLayer(const std::string& name, bool setCollisions) + { + const uint32_t layerId = GetNextLayerID(); + const PhysicsLayer layer = { layerId, name, static_cast(BIT(layerId)) }; + s_Layers.push_back(layer); + + if (setCollisions) + { + for (const auto& layer2 : s_Layers) + { + SetLayerCollision(layer.LayerID, layer2.LayerID, true); + } + } + + return layer.LayerID; + } + + void PhysicsLayerManager::RemoveLayer(uint32_t layerId) + { + if (!IsLayerValid(layerId)) + return; + + const PhysicsLayer& layerInfo = GetLayer(layerId); + + for (auto& otherLayer : s_Layers) + { + if (otherLayer.LayerID == layerId) + continue; + + if (otherLayer.CollidesWith & layerInfo.BitValue) + { + otherLayer.CollidesWith &= ~layerInfo.BitValue; + } + } + + RemoveIfExists(s_Layers, [&](const PhysicsLayer& layer) { return layer.LayerID == layerId; }); + } + + void PhysicsLayerManager::SetLayerCollision(uint32_t layerId, uint32_t otherLayer, bool collides) + { + if (ShouldCollide(layerId, otherLayer) && collides) + return; + + PhysicsLayer& layerInfo = GetLayer(layerId); + PhysicsLayer& otherLayerInfo = GetLayer(otherLayer); + + if (collides) + { + layerInfo.CollidesWith |= otherLayerInfo.BitValue; + otherLayerInfo.CollidesWith |= layerInfo.BitValue; + } + else + { + layerInfo.CollidesWith &= ~otherLayerInfo.BitValue; + otherLayerInfo.CollidesWith &= ~layerInfo.BitValue; + } + } + + const std::vector& PhysicsLayerManager::GetLayerCollisions(uint32_t layerId) + { + const PhysicsLayer& layer = GetLayer(layerId); + + std::vector layers; + for (const auto& otherLayer : s_Layers) + { + if (otherLayer.LayerID == layerId) + continue; + + if (layer.CollidesWith & otherLayer.BitValue) + layers.push_back(otherLayer); + } + + return layers; + } + + PhysicsLayer& PhysicsLayerManager::GetLayer(uint32_t layerId) + { + for (auto& layer : s_Layers) + { + if (layer.LayerID == layerId) + { + return layer; + } + } + + return s_NullLayer; + } + + PhysicsLayer& PhysicsLayerManager::GetLayer(const std::string& layerName) + { + for (auto& layer : s_Layers) + { + if (layer.Name == layerName) + { + return layer; + } + } + + return s_NullLayer; + } + + bool PhysicsLayerManager::ShouldCollide(uint32_t layer1, uint32_t layer2) + { + return GetLayer(layer1).CollidesWith & GetLayer(layer2).BitValue; + } + + bool PhysicsLayerManager::IsLayerValid(uint32_t layerId) + { + for (const auto& layer : s_Layers) + { + if (layer.LayerID == layerId) + return true; + } + + return false; + } + + void PhysicsLayerManager::ClearLayers() + { + s_Layers.clear(); + } + + uint32_t PhysicsLayerManager::GetNextLayerID() + { + int32_t lastId = -1; + + for (const auto& layer : s_Layers) + { + if (lastId != -1) + { + if (layer.LayerID != lastId + 1) + { + return lastId + 1; + } + } + + lastId = layer.LayerID; + } + + return s_Layers.size(); + } + + std::vector PhysicsLayerManager::s_Layers; + PhysicsLayer PhysicsLayerManager::s_NullLayer = { 0, "NULL", 0, -1 }; +} \ No newline at end of file diff --git a/Prism/src/Prism/Physics/PhysicsLayer.h b/Prism/src/Prism/Physics/PhysicsLayer.h new file mode 100644 index 0000000..04ec8ff --- /dev/null +++ b/Prism/src/Prism/Physics/PhysicsLayer.h @@ -0,0 +1,51 @@ +// +// Created by sfd on 25-12-25. +// + +#ifndef PHYSICSLAYER_H +#define PHYSICSLAYER_H + + +namespace Prism +{ + + struct PhysicsLayer + { + uint32_t LayerID; + std::string Name; + uint32_t BitValue; + int32_t CollidesWith = 0; + }; + + class PhysicsLayerManager + { + public: + static uint32_t AddLayer(const std::string& name, bool setCollisions = true); + static void RemoveLayer(uint32_t layerId); + + static void SetLayerCollision(uint32_t layerId, uint32_t otherLayer, bool collides); + static const std::vector& GetLayerCollisions(uint32_t layerId); + + static const std::vector& GetLayers() { return s_Layers; } + + static PhysicsLayer& GetLayer(uint32_t layerId); + static PhysicsLayer& GetLayer(const std::string& layerName); + static uint32_t GetLayerCount() { return static_cast(s_Layers.size()); } + + static bool ShouldCollide(uint32_t layer1, uint32_t layer2); + static bool IsLayerValid(uint32_t layerId); + + static void ClearLayers(); + + private: + static uint32_t GetNextLayerID(); + + private: + static std::vector s_Layers; + static PhysicsLayer s_NullLayer; + }; + +} + + +#endif //PHYSICSLAYER_H diff --git a/Prism/src/Prism/Physics/PhysicsUtils.cpp b/Prism/src/Prism/Physics/PhysicsUtils.cpp index 673c59b..a714572 100644 --- a/Prism/src/Prism/Physics/PhysicsUtils.cpp +++ b/Prism/src/Prism/Physics/PhysicsUtils.cpp @@ -25,23 +25,23 @@ namespace Prism physx::PxVec3 ToPhysXVector(const glm::vec3& vector) { - return {vector.x, vector.y, vector.z}; + return *(physx::PxVec3*)&vector; } physx::PxVec4 ToPhysXVector(const glm::vec4& vector) { - return {vector.x, vector.y, vector.z, vector.w}; + return *(physx::PxVec4*)&vector; } physx::PxQuat ToPhysXQuat(const glm::quat& quat) { - return {quat.x, quat.y, quat.z, quat.w}; + return *(physx::PxQuat*)&quat; } glm::mat4 FromPhysXTransform(const physx::PxTransform& transform) { - glm::quat rotation = FromPhysXQuat(transform.q); - glm::vec3 position = FromPhysXVector(transform.p); + const glm::quat rotation = FromPhysXQuat(transform.q); + const glm::vec3 position = FromPhysXVector(transform.p); return glm::translate(glm::mat4(1.0F), position) * glm::toMat4(rotation); } @@ -52,20 +52,20 @@ namespace Prism glm::vec3 FromPhysXVector(const physx::PxVec3& vector) { - return {vector.x, vector.y, vector.z}; + return *(glm::vec3*)&vector; } glm::vec4 FromPhysXVector(const physx::PxVec4& vector) { - return {vector.x, vector.y, vector.z, vector.w}; + return *(glm::vec4*)&vector; } glm::quat FromPhysXQuat(const physx::PxQuat& quat) { - return {quat.w, quat.x, quat.y, quat.z}; + return *(glm::quat*)&quat; } - physx::PxFilterFlags HazelFilterShader(physx::PxFilterObjectAttributes attributes0, physx::PxFilterData filterData0, physx::PxFilterObjectAttributes attributes1, physx::PxFilterData filterData1, physx::PxPairFlags& pairFlags, const void* constantBlock, physx::PxU32 constantBlockSize) + physx::PxFilterFlags PrismFilterShader(physx::PxFilterObjectAttributes attributes0, physx::PxFilterData filterData0, physx::PxFilterObjectAttributes attributes1, physx::PxFilterData filterData1, physx::PxPairFlags& pairFlags, const void* constantBlock, physx::PxU32 constantBlockSize) { if (physx::PxFilterObjectIsTrigger(attributes0) || physx::PxFilterObjectIsTrigger(attributes1)) { @@ -79,9 +79,10 @@ namespace Prism { pairFlags |= physx::PxPairFlag::eNOTIFY_TOUCH_FOUND; pairFlags |= physx::PxPairFlag::eNOTIFY_TOUCH_LOST; + return physx::PxFilterFlag::eDEFAULT; } - return physx::PxFilterFlag::eDEFAULT; + return physx::PxFilterFlag::eSUPPRESS; } void ContactListener::onConstraintBreak(physx::PxConstraintInfo* constraints, physx::PxU32 count) @@ -92,14 +93,24 @@ namespace Prism void ContactListener::onWake(physx::PxActor** actors, physx::PxU32 count) { - PX_UNUSED(actors); - PX_UNUSED(count); + for (uint32_t i = 0; i < count; i++) + { + physx::PxActor& actor = *actors[i]; + Entity& entity = *(Entity*)actor.userData; + + PM_CORE_INFO("PhysX Actor waking up: ID: {0}, Name: {1}", static_cast(entity.GetUUID()), entity.GetComponent().Tag); + } } void ContactListener::onSleep(physx::PxActor** actors, physx::PxU32 count) { - PX_UNUSED(actors); - PX_UNUSED(count); + for (uint32_t i = 0; i < count; i++) + { + physx::PxActor& actor = *actors[i]; + Entity& entity = *(Entity*)actor.userData; + + PM_CORE_INFO("PhysX Actor going to sleep: ID: {0}, Name: {1}", static_cast(entity.GetUUID()), entity.GetComponent().Tag); + } } void ContactListener::onContact(const physx::PxContactPairHeader& pairHeader, const physx::PxContactPair* pairs, physx::PxU32 nbPairs) diff --git a/Prism/src/Prism/Physics/PhysicsUtils.h b/Prism/src/Prism/Physics/PhysicsUtils.h index 192a3b4..c77bd08 100644 --- a/Prism/src/Prism/Physics/PhysicsUtils.h +++ b/Prism/src/Prism/Physics/PhysicsUtils.h @@ -25,7 +25,7 @@ namespace Prism glm::vec4 FromPhysXVector(const physx::PxVec4& vector); glm::quat FromPhysXQuat(const physx::PxQuat& quat); - physx::PxFilterFlags HazelFilterShader(physx::PxFilterObjectAttributes attributes0, physx::PxFilterData filterData0, physx::PxFilterObjectAttributes attributes1, + physx::PxFilterFlags PrismFilterShader(physx::PxFilterObjectAttributes attributes0, physx::PxFilterData filterData0, physx::PxFilterObjectAttributes attributes1, physx::PxFilterData filterData1, physx::PxPairFlags& pairFlags, const void* constantBlock, physx::PxU32 constantBlockSize); class ContactListener final : public physx::PxSimulationEventCallback diff --git a/Prism/src/Prism/Physics/PxPhysicsWrappers.cpp b/Prism/src/Prism/Physics/PhysicsWrappers.cpp similarity index 50% rename from Prism/src/Prism/Physics/PxPhysicsWrappers.cpp rename to Prism/src/Prism/Physics/PhysicsWrappers.cpp index 7b5f83f..6b7a9cd 100644 --- a/Prism/src/Prism/Physics/PxPhysicsWrappers.cpp +++ b/Prism/src/Prism/Physics/PhysicsWrappers.cpp @@ -2,41 +2,94 @@ // Created by sfd on 25-12-20. // -#include "PxPhysicsWrappers.h" +#include "PhysicsWrappers.h" #include "Physics3D.h" #include #define GLM_ENABLE_EXPERIMENTAL #include -#define PHYSX_DEBUGGER 1 +#include "PhysicsLayer.h" +#define PHYSX_DEBUGGER namespace Prism { - static physx::PxDefaultErrorCallback s_ErrorCallback; + static PhysicsErrorCallback s_ErrorCallback; static physx::PxDefaultAllocator s_Allocator; - static physx::PxFoundation* s_Foundation; - static physx::PxPhysics* s_Physics; - static physx::PxPvd* s_VisualDebugger; + static physx::PxFoundation* s_Foundation = nullptr; + static physx::PxPhysics* s_Physics = nullptr; + static physx::PxPvd* s_VisualDebugger = nullptr; + static physx::PxOverlapHit s_OverlapBuffer[OVERLAP_MAX_COLLIDERS]; + static physx::PxSimulationFilterShader s_FilterShader = physx::PxDefaultSimulationFilterShader; static ContactListener s_ContactListener; - physx::PxScene* PxPhysicsWrappers::CreateScene(const SceneParams& sceneParams) + void PhysicsErrorCallback::reportError(physx::PxErrorCode::Enum code, const char* message, const char* file, int line) + { + const char* errorMessage = NULL; + + switch (code) + { + case physx::PxErrorCode::eNO_ERROR: errorMessage = "No Error"; break; + case physx::PxErrorCode::eDEBUG_INFO: errorMessage = "Info"; break; + case physx::PxErrorCode::eDEBUG_WARNING: errorMessage = "Warning"; break; + case physx::PxErrorCode::eINVALID_PARAMETER: errorMessage = "Invalid Parameter"; break; + case physx::PxErrorCode::eINVALID_OPERATION: errorMessage = "Invalid Operation"; break; + case physx::PxErrorCode::eOUT_OF_MEMORY: errorMessage = "Out Of Memory"; break; + case physx::PxErrorCode::eINTERNAL_ERROR: errorMessage = "Internal Error"; break; + case physx::PxErrorCode::eABORT: errorMessage = "Abort"; break; + case physx::PxErrorCode::ePERF_WARNING: errorMessage = "Performance Warning"; break; + case physx::PxErrorCode::eMASK_ALL: errorMessage = "Unknown Error"; break; + } + + switch (code) + { + case physx::PxErrorCode::eNO_ERROR: + case physx::PxErrorCode::eDEBUG_INFO: + PM_CORE_INFO("[PhysX]: {0}: {1} at {2} ({3})", errorMessage, message, file, line); + break; + case physx::PxErrorCode::eDEBUG_WARNING: + case physx::PxErrorCode::ePERF_WARNING: + PM_CORE_WARN("[PhysX]: {0}: {1} at {2} ({3})", errorMessage, message, file, line); + break; + case physx::PxErrorCode::eINVALID_PARAMETER: + case physx::PxErrorCode::eINVALID_OPERATION: + case physx::PxErrorCode::eOUT_OF_MEMORY: + case physx::PxErrorCode::eINTERNAL_ERROR: + PM_CORE_ERROR("[PhysX]: {0}: {1} at {2} ({3})", errorMessage, message, file, line); + break; + case physx::PxErrorCode::eABORT: + case physx::PxErrorCode::eMASK_ALL: + PM_CORE_FATAL("[PhysX]: {0}: {1} at {2} ({3})", errorMessage, message, file, line); + PM_CORE_ASSERT(false); + break; + } + } + + + physx::PxScene* PhysicsWrappers::CreateScene(const SceneParams& sceneParams) { physx::PxSceneDesc sceneDesc(s_Physics->getTolerancesScale()); sceneDesc.gravity = ToPhysXVector(sceneParams.Gravity); sceneDesc.cpuDispatcher = physx::PxDefaultCpuDispatcherCreate(1); - sceneDesc.filterShader = HazelFilterShader; + sceneDesc.filterShader = PrismFilterShader; sceneDesc.simulationEventCallback = &s_ContactListener; + sceneDesc.wakeCounterResetValue = 0.5f; + sceneDesc.bounceThresholdVelocity = 0.1f; + sceneDesc.frictionOffsetThreshold = 0.1f; + sceneDesc.frictionCorrelationDistance = 0.1f; + + sceneDesc.flags |= physx::PxSceneFlag::eENABLE_ACTIVE_ACTORS; + PM_CORE_ASSERT(sceneDesc.isValid()); return s_Physics->createScene(sceneDesc); } - physx::PxRigidActor* PxPhysicsWrappers::CreateActor(const RigidBodyComponent& rigidbody, const glm::mat4& transform) + physx::PxRigidActor* PhysicsWrappers::CreateActor(const RigidBodyComponent& rigidbody, const glm::mat4& transform) { physx::PxRigidActor* actor = nullptr; @@ -57,6 +110,14 @@ namespace Prism 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); + + // 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; } @@ -64,11 +125,16 @@ namespace Prism return actor; } - void PxPhysicsWrappers::SetCollisionFilters(const physx::PxRigidActor& actor, const uint32_t actorGroup, const uint32_t filters) + 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 = actorGroup; - filterData.word1 = filters; + filterData.word0 = layerInfo.BitValue; + filterData.word1 = layerInfo.CollidesWith; const physx::PxU32 numShapes = actor.getNbShapes(); @@ -81,7 +147,7 @@ namespace Prism s_Allocator.deallocate(shapes); } - void PxPhysicsWrappers::AddBoxCollider(physx::PxRigidActor& actor, const physx::PxMaterial& material, const BoxColliderComponent& collider, const glm::vec3& scale) + void PhysicsWrappers::AddBoxCollider(physx::PxRigidActor& actor, const physx::PxMaterial& material, const BoxColliderComponent& collider, const glm::vec3& scale) { glm::vec3 colliderSize = collider.Size; @@ -98,7 +164,7 @@ namespace Prism shape->setLocalPose(ToPhysXTransform(glm::translate(glm::mat4(1.0F), collider.Offset))); } - void PxPhysicsWrappers::AddSphereCollider(physx::PxRigidActor& actor, const physx::PxMaterial& material, const SphereColliderComponent& collider, const glm::vec3& scale) + void PhysicsWrappers::AddSphereCollider(physx::PxRigidActor& actor, const physx::PxMaterial& material, const SphereColliderComponent& collider, const glm::vec3& scale) { float colliderRadius = collider.Radius; @@ -111,16 +177,16 @@ namespace Prism shape->setFlag(physx::PxShapeFlag::eTRIGGER_SHAPE, collider.IsTrigger); } - void PxPhysicsWrappers::AddCapsuleCollider(physx::PxRigidActor& actor, const physx::PxMaterial& material,const CapsuleColliderComponent& collider, const glm::vec3& scale) + void PhysicsWrappers::AddCapsuleCollider(physx::PxRigidActor& actor, const physx::PxMaterial& material,const CapsuleColliderComponent& collider, const glm::vec3& scale) { float colliderRadius = collider.Radius; float colliderHeight = collider.Height; - if (scale.x != 0.0F) colliderRadius *= scale.x * 0.5f; - if (scale.y != 0.0F) colliderHeight *= scale.y; + if (scale.x != 0.0F) colliderRadius *= scale.x; + if (scale.y != 0.0F) colliderHeight *= scale.y ; - const auto capsuleGeometry = physx::PxCapsuleGeometry(colliderRadius, colliderHeight / 2.0F); + const auto capsuleGeometry = physx::PxCapsuleGeometry(colliderRadius, colliderHeight * 0.5f); physx::PxShape* shape = physx::PxRigidActorExt::createExclusiveShape(actor, capsuleGeometry, material); shape->setFlag(physx::PxShapeFlag::eSIMULATION_SHAPE, !collider.IsTrigger); @@ -130,21 +196,16 @@ namespace Prism } - void PxPhysicsWrappers::AddMeshCollider(physx::PxRigidActor& actor, const physx::PxMaterial& material,MeshColliderComponent& collider, const glm::vec3& scale) + void PhysicsWrappers::AddMeshCollider(physx::PxRigidActor& actor, const physx::PxMaterial& material,MeshColliderComponent& collider, const glm::vec3& scale) { - // TODO: Possibly take a look at https://github.com/kmammou/v-hacd for computing convex meshes from triangle meshes... - physx::PxConvexMeshGeometry triangleGeometry = physx::PxConvexMeshGeometry(CreateConvexMesh(collider)); - triangleGeometry.meshFlags = physx::PxConvexMeshGeometryFlag::eTIGHT_BOUNDS; - physx::PxShape* shape = physx::PxRigidActorExt::createExclusiveShape(actor, triangleGeometry, material); + physx::PxConvexMeshGeometry convexGeometry = physx::PxConvexMeshGeometry(CreateConvexMesh(collider)); + convexGeometry.meshFlags = physx::PxConvexMeshGeometryFlag::eTIGHT_BOUNDS; + physx::PxShape* shape = physx::PxRigidActorExt::createExclusiveShape(actor, convexGeometry, material); shape->setFlag(physx::PxShapeFlag::eSIMULATION_SHAPE, !collider.IsTrigger); shape->setFlag(physx::PxShapeFlag::eTRIGGER_SHAPE, collider.IsTrigger); - - // TODO: temp solve - // physx::PxQuat rotation(physx::PxPi / 2.0f, physx::PxVec3(1.0f, 0.0f, 0.0f)); - // shape->setLocalPose(physx::PxTransform(physx::PxVec3(0.0f), rotation)); } - physx::PxConvexMesh* PxPhysicsWrappers::CreateConvexMesh(MeshColliderComponent& collider) + physx::PxConvexMesh* PhysicsWrappers::CreateConvexMesh(MeshColliderComponent& collider) { const auto& vertices = collider.CollisionMesh->GetStaticVertices(); @@ -177,7 +238,7 @@ namespace Prism for (uint32_t i = 0; i < nbPolygons; i++) { - physx::PxHullPolygon polygon; + physx::PxHullPolygon polygon{}; mesh->getPolygonData(i, polygon); nbVertices += polygon.mNbVerts; nbFaces += (polygon.mNbVerts - 2) * 3; @@ -193,7 +254,7 @@ namespace Prism uint32_t indexCounter = 0; for (uint32_t i = 0; i < nbPolygons; i++) { - physx::PxHullPolygon polygon; + physx::PxHullPolygon polygon{}; mesh->getPolygonData(i, polygon); const uint32_t vI0 = vertCounter; @@ -221,19 +282,102 @@ namespace Prism return mesh; } - physx::PxMaterial* PxPhysicsWrappers::CreateMaterial(const PhysicsMaterialComponent& material) + physx::PxMaterial* PhysicsWrappers::CreateMaterial(const PhysicsMaterialComponent& material) { return s_Physics->createMaterial(material.StaticFriction, material.DynamicFriction, material.Bounciness); } - void PxPhysicsWrappers::Initialize() + bool PhysicsWrappers::Raycast(const glm::vec3& origin, const glm::vec3& direction, float maxDistance, RaycastHit* hit) + { + const auto* scene = static_cast(Physics3D::GetPhysicsScene()); + physx::PxRaycastBuffer hitInfo; + const bool result = scene->raycast(ToPhysXVector(origin), ToPhysXVector(glm::normalize(direction)), maxDistance, hitInfo); + + if (result) + { + Entity& entity = *static_cast(hitInfo.block.actor->userData); + + hit->EntityID = entity.GetUUID(); + hit->Position = FromPhysXVector(hitInfo.block.position); + hit->Normal = FromPhysXVector(hitInfo.block.normal); + hit->Distance = hitInfo.block.distance; + } + + return result; + } + + bool PhysicsWrappers::OverlapBox(const glm::vec3& origin, const glm::vec3& halfSize, std::array& buffer, uint32_t* count) + { + const physx::PxScene* scene = static_cast(Physics3D::GetPhysicsScene()); + + memset(s_OverlapBuffer, 0, sizeof(s_OverlapBuffer)); + physx::PxOverlapBuffer buf(s_OverlapBuffer, OVERLAP_MAX_COLLIDERS); + + const auto geometry = physx::PxBoxGeometry(halfSize.x, halfSize.y, halfSize.z); + const physx::PxTransform pose = ToPhysXTransform(glm::translate(glm::mat4(1.0F), origin)); + + const bool result = scene->overlap(geometry, pose, buf); + + if (result) + { + const uint32_t bodyCount = buf.nbTouches >= OVERLAP_MAX_COLLIDERS ? OVERLAP_MAX_COLLIDERS : buf.nbTouches; + memcpy(buffer.data(), buf.touches, bodyCount * sizeof(physx::PxOverlapHit)); + *count = bodyCount; + } + + return result; + } + + bool PhysicsWrappers::OverlapSphere(const glm::vec3& origin, float radius, std::array& buffer, uint32_t* count) + { + const physx::PxScene* scene = static_cast(Physics3D::GetPhysicsScene()); + + memset(s_OverlapBuffer, 0, sizeof(s_OverlapBuffer)); + physx::PxOverlapBuffer buf(s_OverlapBuffer, OVERLAP_MAX_COLLIDERS); + const auto geometry = physx::PxSphereGeometry(radius); + const physx::PxTransform pose = ToPhysXTransform(glm::translate(glm::mat4(1.0F), origin)); + + const bool result = scene->overlap(geometry, pose, buf); + + if (result) + { + const uint32_t bodyCount = buf.nbTouches >= OVERLAP_MAX_COLLIDERS ? OVERLAP_MAX_COLLIDERS : buf.nbTouches; + memcpy(buffer.data(), buf.touches, bodyCount * sizeof(physx::PxOverlapHit)); + *count = bodyCount; + } + + return result; + } + + bool PhysicsWrappers::OverlapCapsule(const glm::vec3& origin, float radius, float halfHeight, std::array& buffer, uint32_t* count) + { + const physx::PxScene* scene = static_cast(Physics3D::GetPhysicsScene()); + + memset(s_OverlapBuffer, 0, sizeof(s_OverlapBuffer)); + physx::PxOverlapBuffer buf(s_OverlapBuffer, OVERLAP_MAX_COLLIDERS); + const auto geometry = physx::PxCapsuleGeometry(radius, halfHeight); + const physx::PxTransform pose = ToPhysXTransform(glm::translate(glm::mat4(1.0F), origin)); + + const bool result = scene->overlap(geometry, pose, buf); + + if (result) + { + const uint32_t bodyCount = buf.nbTouches >= OVERLAP_MAX_COLLIDERS ? OVERLAP_MAX_COLLIDERS : buf.nbTouches; + memcpy(buffer.data(), buf.touches, bodyCount * sizeof(physx::PxOverlapHit)); + *count = bodyCount; + } + + return result; + } + + void PhysicsWrappers::Initialize() { PM_CORE_ASSERT(!s_Foundation, "PXPhysicsWrappers::Initializer shouldn't be called more than once!"); s_Foundation = PxCreateFoundation(PX_PHYSICS_VERSION, s_Allocator, s_ErrorCallback); PM_CORE_ASSERT(s_Foundation, "PxCreateFoundation Failed!"); - #if PHYSX_DEBUGGER + #ifdef PHYSX_DEBUGGER s_VisualDebugger = PxCreatePvd(*s_Foundation); ConnectPVD(); #endif @@ -242,16 +386,16 @@ namespace Prism PM_CORE_ASSERT(s_Physics, "PxCreatePhysics Failed!"); } - void PxPhysicsWrappers::Shutdown() + void PhysicsWrappers::Shutdown() { s_Physics->release(); s_Foundation->release(); } - bool PxPhysicsWrappers::ConnectPVD() + bool PhysicsWrappers::ConnectPVD() { bool isConnect = false; - #if PHYSX_DEBUGGER + #ifdef PHYSX_DEBUGGER physx::PxPvdTransport* transport = physx::PxDefaultPvdSocketTransportCreate("localhost", 5425, 10); if (s_VisualDebugger->isConnected()) { @@ -263,14 +407,14 @@ namespace Prism return isConnect; } - bool PxPhysicsWrappers::IsPVDConnected() + bool PhysicsWrappers::IsPVDConnected() { return s_VisualDebugger->isConnected(); } - void PxPhysicsWrappers::DisconnectPVD() + void PhysicsWrappers::DisconnectPVD() { - #if PHYSX_DEBUGGER + #ifdef PHYSX_DEBUGGER if (s_VisualDebugger->isConnected(false)) { s_VisualDebugger->disconnect(); diff --git a/Prism/src/Prism/Physics/PxPhysicsWrappers.h b/Prism/src/Prism/Physics/PhysicsWrappers.h similarity index 55% rename from Prism/src/Prism/Physics/PxPhysicsWrappers.h rename to Prism/src/Prism/Physics/PhysicsWrappers.h index 5c381c8..deec16b 100644 --- a/Prism/src/Prism/Physics/PxPhysicsWrappers.h +++ b/Prism/src/Prism/Physics/PhysicsWrappers.h @@ -2,37 +2,56 @@ // Created by sfd on 25-12-20. // -#ifndef PXPHYSICSWRAPPERS_H -#define PXPHYSICSWRAPPERS_H +#ifndef PHYSICSWRAPPERS_H +#define PHYSICSWRAPPERS_H #include "PhysicsUtils.h" #include "Prism/Scene/Components.h" +#define OVERLAP_MAX_COLLIDERS 10 + namespace Prism { + struct RaycastHit; struct SceneParams; - class PxPhysicsWrappers + class PhysicsErrorCallback final : public physx::PxErrorCallback + { + public: + void reportError(physx::PxErrorCode::Enum code, const char* message, const char* file, int line) override; + }; + + class PhysicsWrappers { public: static physx::PxScene* CreateScene(const SceneParams& sceneParams); static physx::PxRigidActor* CreateActor(const RigidBodyComponent& rigidbody, const glm::mat4& transform); - static void SetCollisionFilters(const physx::PxRigidActor& actor, uint32_t actorGroup, uint32_t filters); + 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 physx::PxConvexMesh* CreateConvexMesh(MeshColliderComponent& collider); 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); + static bool OverlapSphere(const glm::vec3& origin, float radius, std::vector& buffer); + */ + static bool OverlapBox(const glm::vec3& origin, const glm::vec3& halfSize, std::array& buffer, uint32_t* count); + static bool OverlapCapsule(const glm::vec3& origin, float radius, float halfHeight, std::array& buffer, uint32_t* count); + static bool OverlapSphere(const glm::vec3& origin, float radius, std::array& buffer, uint32_t* count); private: static void Initialize(); static void Shutdown(); + static bool ConnectPVD(); static bool IsPVDConnected(); static void DisconnectPVD(); @@ -43,4 +62,4 @@ namespace Prism } -#endif //PXPHYSICSWRAPPERS_H +#endif //PHYSICSWRAPPERS_H diff --git a/Prism/src/Prism/Platform/Windows/WindowsInput.cpp b/Prism/src/Prism/Platform/Windows/WindowsInput.cpp index 400347d..7413fed 100644 --- a/Prism/src/Prism/Platform/Windows/WindowsInput.cpp +++ b/Prism/src/Prism/Platform/Windows/WindowsInput.cpp @@ -17,11 +17,12 @@ namespace Prism const auto state = glfwGetKey(static_cast(window.GetNativeWindow()), static_cast(keycode)); return state == GLFW_PRESS || state == GLFW_REPEAT; } - bool Input::IsMouseButtonPressed(int button) + + bool Input::IsMouseButtonPressed(MouseButton button) { const auto& window = dynamic_cast(Application::Get().GetWindow()); - const auto state = glfwGetMouseButton(static_cast(window.GetNativeWindow()), button); + const auto state = glfwGetMouseButton(static_cast(window.GetNativeWindow()), static_cast(button)); return state == GLFW_PRESS; } diff --git a/Prism/src/Prism/Renderer/MeshFactory.cpp b/Prism/src/Prism/Renderer/MeshFactory.cpp index 32eb0d1..dc61882 100644 --- a/Prism/src/Prism/Renderer/MeshFactory.cpp +++ b/Prism/src/Prism/Renderer/MeshFactory.cpp @@ -53,7 +53,7 @@ namespace Prism std::vector vertices; std::vector indices; - constexpr float latitudeBands = 30; + constexpr uint32_t latitudeBands = 30; constexpr float longitudeBands = 30; for (float latitude = 0.0f; latitude <= latitudeBands; latitude++) @@ -77,10 +77,10 @@ namespace Prism for (uint32_t latitude = 0; latitude < latitudeBands; latitude++) { - for (uint32_t longitude = 0; longitude < longitudeBands; longitude++) + for (uint32_t longitude = 0; longitude < static_cast(longitudeBands); longitude++) { - const uint32_t first = (latitude * (longitudeBands + 1)) + longitude; - const uint32_t second = first + longitudeBands + 1; + const uint32_t first = (latitude * (static_cast(longitudeBands) + 1)) + longitude; + const uint32_t second = first + static_cast(longitudeBands) + 1; indices.push_back({ first, second, first + 1 }); indices.push_back({ second, second + 1, first + 1 }); @@ -120,11 +120,11 @@ namespace Prism calcV += 180.0f / (float)segments; } - float yOffset = (height - (radius * 2.0f)) * 0.5f; + float yOffset = height * 0.5f; if (yOffset < 0.0f) yOffset = 0.0f; - int top = glm::ceil(pointCount * 0.5f); + int top = static_cast(glm::ceil(pointCount * 0.5f)); for (int y = 0; y < top; y++) { @@ -136,7 +136,7 @@ namespace Prism } } - int bottom = glm::floor(pointCount * 0.5f); + int bottom = static_cast(glm::floor(pointCount * 0.5f)); for (int y = bottom; y < pointCount; y++) { diff --git a/Prism/src/Prism/Scene/Components.h b/Prism/src/Prism/Scene/Components.h index a890aef..bf26075 100644 --- a/Prism/src/Prism/Scene/Components.h +++ b/Prism/src/Prism/Scene/Components.h @@ -156,6 +156,7 @@ namespace Prism Type BodyType; float Mass = 1.0f; bool IsKinematic = false; + uint32_t Layer = 0; bool LockPositionX = false; bool LockPositionY = false; diff --git a/Prism/src/Prism/Scene/Entity.h b/Prism/src/Prism/Scene/Entity.h index 1be026a..71592e4 100644 --- a/Prism/src/Prism/Scene/Entity.h +++ b/Prism/src/Prism/Scene/Entity.h @@ -49,6 +49,7 @@ namespace Prism m_Scene->m_Registry.remove(m_EntityHandle); } + const std::string& Tag() const { return m_Scene->m_Registry.get(m_EntityHandle).Tag; } glm::mat4& Transform() { return m_Scene->m_Registry.get(m_EntityHandle); } const glm::mat4& Transform() const { return m_Scene->m_Registry.get(m_EntityHandle); } diff --git a/Prism/src/Prism/Scene/SceneSerializer.cpp b/Prism/src/Prism/Scene/SceneSerializer.cpp index a7c426f..50e09bb 100644 --- a/Prism/src/Prism/Scene/SceneSerializer.cpp +++ b/Prism/src/Prism/Scene/SceneSerializer.cpp @@ -19,7 +19,8 @@ #include -#include "Prism/Physics/PxPhysicsWrappers.h" +#include "Prism/Physics/PhysicsLayer.h" +#include "Prism/Physics/PhysicsWrappers.h" #include "Prism/Renderer/Meshfactory.h" namespace YAML @@ -340,6 +341,7 @@ namespace Prism out << YAML::Key << "BodyType" << YAML::Value << (int)rigidbodyComponent.BodyType; out << YAML::Key << "Mass" << YAML::Value << rigidbodyComponent.Mass; out << YAML::Key << "IsKinematic" << YAML::Value << rigidbodyComponent.IsKinematic; + out << YAML::Key << "Layer" << YAML::Value << rigidbodyComponent.Layer; out << YAML::Key << "Constraints"; out << YAML::BeginMap; // Constraints @@ -456,6 +458,29 @@ namespace Prism SerializeEntity(out, entity); }); out << YAML::EndSeq; + + out << YAML::Key << "PhysicsLayers"; + out << YAML::Value << YAML::BeginSeq; + for (uint32_t i = 0; i < PhysicsLayerManager::GetLayerCount(); i++) + { + const PhysicsLayer& layer = PhysicsLayerManager::GetLayer(i); + + out << YAML::BeginMap; + out << YAML::Key << "Name" << YAML::Value << layer.Name; + + out << YAML::Key << "CollidesWith" << YAML::Value; + out << YAML::BeginSeq; + for (const auto& collidingLayer : PhysicsLayerManager::GetLayerCollisions(layer.LayerID)) + { + out << YAML::BeginMap; + out << YAML::Key << "Name" << YAML::Value << collidingLayer.Name; + out << YAML::EndMap; + } + out << YAML::EndSeq; + out << YAML::EndMap; + } + out << YAML::EndSeq; + out << YAML::EndMap; std::ofstream fout(filepath); @@ -661,6 +686,7 @@ namespace Prism component.BodyType = (RigidBodyComponent::Type)rigidBodyComponent["BodyType"].as(); component.Mass = rigidBodyComponent["Mass"].as(); component.IsKinematic = rigidBodyComponent["IsKinematic"] ? rigidBodyComponent["IsKinematic"].as() : false; + component.Layer = rigidBodyComponent["Layer"] ? rigidBodyComponent["Layer"].as() : 0; component.LockPositionX = rigidBodyComponent["Constraints"]["LockPositionX"].as(); component.LockPositionY = rigidBodyComponent["Constraints"]["LockPositionY"].as(); @@ -710,12 +736,37 @@ namespace Prism auto meshPath = meshColliderComponent["AssetPath"].as(); auto& component = deserializedEntity.AddComponent(Ref::Create(meshPath)); component.IsTrigger = meshColliderComponent["IsTrigger"] ? meshColliderComponent["IsTrigger"].as() : false; - PxPhysicsWrappers::CreateConvexMesh(component); + PhysicsWrappers::CreateConvexMesh(component); PM_CORE_INFO(" Mesh Collider Asset Path: {0}", meshPath); } } } + + if (auto physicsLayers = data["PhysicsLayers"]) + { + PhysicsLayerManager::ClearLayers(); + + for (auto layer : physicsLayers) + { + PhysicsLayerManager::AddLayer(layer["Name"].as(), false); + } + + for (auto layer : physicsLayers) + { + const PhysicsLayer& layerInfo = PhysicsLayerManager::GetLayer(layer["Name"].as()); + + if (auto collidesWith = layer["CollidesWith"]) + { + for (auto collisionLayer : collidesWith) + { + const auto& otherLayer = PhysicsLayerManager::GetLayer(collisionLayer["Name"].as()); + PhysicsLayerManager::SetLayerCollision(layerInfo.LayerID, otherLayer.LayerID, true); + } + } + } + } + return true; } diff --git a/Prism/src/Prism/Script/ScriptEngine.cpp b/Prism/src/Prism/Script/ScriptEngine.cpp index 89f586b..ce02e38 100644 --- a/Prism/src/Prism/Script/ScriptEngine.cpp +++ b/Prism/src/Prism/Script/ScriptEngine.cpp @@ -18,7 +18,6 @@ #include #include #include -#include #include "imgui.h" @@ -575,6 +574,85 @@ namespace Prism } } + MonoObject* ScriptEngine::Construct(const std::string& fullName, bool callConstructor, void** parameters) + { + std::string namespaceName; + std::string className; + std::string parameterList; + + if (fullName.find('.') != std::string::npos) + { + namespaceName = fullName.substr(0, fullName.find_first_of('.')); + className = fullName.substr(fullName.find_first_of('.') + 1, (fullName.find_first_of(':') - fullName.find_first_of('.')) - 1); + + } + + if (fullName.find(':') != std::string::npos) + { + parameterList = fullName.substr(fullName.find_first_of(':')); + } + + MonoClass* clazz = mono_class_from_name(s_CoreAssemblyImage, namespaceName.c_str(), className.c_str()); + if (!clazz) { + PM_CORE_FATAL("Class not found: {0}.{1}", namespaceName, className); + return nullptr; + } + + MonoObject* obj = mono_object_new(mono_domain_get(), clazz); + + + if (callConstructor) + { + MonoMethodDesc* desc = mono_method_desc_new(parameterList.c_str(), NULL); + MonoMethod* constructor = mono_method_desc_search_in_class(desc, clazz); + + if (!constructor) { + PM_CORE_ERROR("Constructor not found: {0}", fullName); + + void* iter = nullptr; + MonoMethod* method; + while ((method = mono_class_get_methods(clazz, &iter)) != nullptr) { + PM_CORE_DEBUG("Found method: {0}",mono_method_full_name(method, true)); + } + return obj; + } + + MonoObject* exception = nullptr; + mono_runtime_invoke(constructor, obj, parameters, &exception); + } + + return obj; + } + + static std::unordered_map s_Classes; + + MonoClass* ScriptEngine::GetCoreClass(const std::string& fullName) + { + if (s_Classes.find(fullName) != s_Classes.end()) + return s_Classes[fullName]; + + std::string namespaceName; + std::string className; + + if (fullName.find('.') != std::string::npos) + { + namespaceName = fullName.substr(0, fullName.find_last_of('.')); + className = fullName.substr(fullName.find_last_of('.') + 1); + } + else + { + className = fullName; + } + + MonoClass* monoClass = mono_class_from_name(s_CoreAssemblyImage, namespaceName.c_str(), className.c_str()); + if (!monoClass) + std::cout << "mono_class_from_name failed" << std::endl; + + s_Classes[fullName] = monoClass; + + return monoClass; + } + bool ScriptEngine::IsEntityModuleValid(Entity entity) { return entity.HasComponent() && ModuleExists(entity.GetComponent().ModuleName); diff --git a/Prism/src/Prism/Script/ScriptEngine.h b/Prism/src/Prism/Script/ScriptEngine.h index 8ac10df..b92a78f 100644 --- a/Prism/src/Prism/Script/ScriptEngine.h +++ b/Prism/src/Prism/Script/ScriptEngine.h @@ -10,6 +10,7 @@ extern "C" { typedef struct _MonoObject MonoObject; typedef struct _MonoClassField MonoClassField; + typedef struct _MonoClass MonoClass; } namespace Prism @@ -126,6 +127,9 @@ namespace Prism static void OnTriggerBegin(Entity entityID); static void OnTriggerEnd(Entity entityID); + static MonoObject* Construct(const std::string& fullName, bool callConstructor = true, void** parameters = nullptr); + static MonoClass* GetCoreClass(const std::string& fullName); + static bool IsEntityModuleValid(Entity entity); static void OnScriptComponentDestroyed(const UUID &sceneID, const UUID &entityID); diff --git a/Prism/src/Prism/Script/ScriptEngineRegistry.cpp b/Prism/src/Prism/Script/ScriptEngineRegistry.cpp index 8a1baf5..d9fc3a5 100644 --- a/Prism/src/Prism/Script/ScriptEngineRegistry.cpp +++ b/Prism/src/Prism/Script/ScriptEngineRegistry.cpp @@ -4,7 +4,7 @@ #include "ScriptEngineRegistry.h" -#include "ScriptWarppers.h" +#include "ScriptWrappers.h" #include "Prism/Scene/Entity.h" #include "mono/metadata/reflection.h" @@ -51,6 +51,15 @@ namespace Prism mono_add_internal_call("Prism.Noise::PerlinNoise_Native", (const void*)Prism::Script::Prism_Noise_PerlinNoise); + mono_add_internal_call("Prism.Physics::Raycast_Native", (const void*)Prism::Script::Prism_Physics_Raycast); + mono_add_internal_call("Prism.Physics::OverlapBox_Native", (const void*)Prism::Script::Prism_Physics_OverlapBox); + mono_add_internal_call("Prism.Physics::OverlapCapsule_Native", (const void*)Prism::Script::Prism_Physics_OverlapCapsule); + mono_add_internal_call("Prism.Physics::OverlapSphere_Native", (const void*)Prism::Script::Prism_Physics_OverlapSphere); + mono_add_internal_call("Prism.Physics::OverlapBoxNonAlloc_Native", (const void*)Prism::Script::Prism_Physics_OverlapBoxNonAlloc); + mono_add_internal_call("Prism.Physics::OverlapCapsuleNonAlloc_Native", (const void*)Prism::Script::Prism_Physics_OverlapCapsuleNonAlloc); + mono_add_internal_call("Prism.Physics::OverlapSphereNonAlloc_Native", (const void*)Prism::Script::Prism_Physics_OverlapSphereNonAlloc); + + mono_add_internal_call("Prism.Entity::GetTransform_Native",(const void*)Prism::Script::Prism_Entity_GetTransform); mono_add_internal_call("Prism.Entity::SetTransform_Native",(const void*)Prism::Script::Prism_Entity_SetTransform); mono_add_internal_call("Prism.TransformComponent::GetRelativeDirection_Native", (const void*)Prism::Script::Prism_TransformComponent_GetRelativeDirection); @@ -77,6 +86,7 @@ namespace Prism // Input mono_add_internal_call("Prism.Input::IsKeyPressed_Native", (const void*)Prism::Script::Prism_Input_IsKeyPressed); + mono_add_internal_call("Prism.Input::IsMouseButtonPressed_Native", (const void*)Prism::Script::Prism_Input_IsMouseButtonPressed); mono_add_internal_call("Prism.Input::GetMousePosition_Native", (const void*)Prism::Script::Prism_Input_GetMousePosition); mono_add_internal_call("Prism.Input::SetCursorMode_Native", (const void*)Prism::Script::Prism_Input_SetCursorMode); mono_add_internal_call("Prism.Input::GetCursorMode_Native", (const void*)Prism::Script::Prism_Input_GetCursorMode); @@ -97,6 +107,9 @@ namespace Prism mono_add_internal_call("Prism.RigidBodyComponent::GetLinearVelocity_Native", (const void*)Prism::Script::Prism_RigidBodyComponent_GetLinearVelocity); mono_add_internal_call("Prism.RigidBodyComponent::SetLinearVelocity_Native", (const void*)Prism::Script::Prism_RigidBodyComponent_SetLinearVelocity); mono_add_internal_call("Prism.RigidBodyComponent::Rotate_Native", (const void*)Prism::Script::Prism_RigidBodyComponent_Rotate); + mono_add_internal_call("Prism.RigidBodyComponent::GetLayer_Native", (const void*)Prism::Script::Prism_RigidBodyComponent_GetLayer); + mono_add_internal_call("Prism.RigidBodyComponent::GetMass_Native", (const void*)Prism::Script::Prism_RigidBodyComponent_GetMass); + mono_add_internal_call("Prism.RigidBodyComponent::SetMass_Native", (const void*)Prism::Script::Prism_RigidBodyComponent_SetMass); // Material mono_add_internal_call("Prism.Material::Destructor_Native", (const void*)Prism::Script::Prism_Material_Destructor); diff --git a/Prism/src/Prism/Script/ScriptWarppers.cpp b/Prism/src/Prism/Script/ScriptWrappers.cpp similarity index 71% rename from Prism/src/Prism/Script/ScriptWarppers.cpp rename to Prism/src/Prism/Script/ScriptWrappers.cpp index 9b8296a..28dbb97 100644 --- a/Prism/src/Prism/Script/ScriptWarppers.cpp +++ b/Prism/src/Prism/Script/ScriptWrappers.cpp @@ -2,7 +2,7 @@ // Created by sfd on 25-12-6. // -#include "ScriptWarppers.h" +#include "ScriptWrappers.h" #include "ScriptEngine.h" #include "box2d/box2d.h" @@ -22,6 +22,8 @@ #include "PxRigidDynamic.h" #include "Prism/Physics/Physics3D.h" #include "Prism/Physics/PhysicsUtils.h" +#include "Prism/Physics/PhysicsWrappers.h" +#include namespace Prism { extern std::unordered_map> s_HasComponentFuncs; @@ -71,6 +73,11 @@ namespace Prism { namespace Script { return Input::IsKeyPressed(key); } + bool Prism_Input_IsMouseButtonPressed(const MouseButton button) + { + return Input::IsMouseButtonPressed(button); + } + void Prism_Input_GetMousePosition(glm::vec2* outPosition) { auto [x, y] = Input::GetMousePosition(); @@ -87,10 +94,189 @@ namespace Prism { namespace Script { return Input::GetCursorMode(); } - //////////////////////////////////////////////////////////////// + bool Prism_Physics_Raycast(const glm::vec3* origin, const glm::vec3* direction, const float maxDistance, RaycastHit* hit) + { + return PhysicsWrappers::Raycast(*origin, *direction, maxDistance, hit); + } + + // Helper function for the Overlap functions below + static void AddCollidersToArray(MonoArray* array, const std::array& hits, const uint32_t count) + { + uint32_t arrayIndex = 0; + for (uint32_t i = 0; i < count; i++) + { + Entity& entity = *static_cast(hits[i].actor->userData); + + if (entity.HasComponent()) + { + auto& boxCollider = entity.GetComponent(); + + UUID uuid = entity.GetUUID(); + void* data[] = { + &uuid, + &boxCollider.IsTrigger, + &boxCollider.Size, + &boxCollider.Offset + }; + + MonoObject* obj = ScriptEngine::Construct("Prism.BoxCollider:.ctor(ulong,bool,Vec3,Vec3)", true, data); + mono_array_set(array, MonoObject*, arrayIndex++, obj); + } + + if (entity.HasComponent()) + { + auto& sphereCollider = entity.GetComponent(); + + UUID uuid = entity.GetUUID(); + void* data[] = { + &uuid, + &sphereCollider.IsTrigger, + &sphereCollider.Radius + }; + + MonoObject* obj = ScriptEngine::Construct("Prism.SphereCollider:.ctor(ulong,bool,single)", true, data); + mono_array_set(array, MonoObject*, arrayIndex++, obj); + } + + if (entity.HasComponent()) + { + auto& capsuleCollider = entity.GetComponent(); + + UUID uuid = entity.GetUUID(); + void* data[] = { + &uuid, + &capsuleCollider.IsTrigger, + &capsuleCollider.Radius, + &capsuleCollider.Height + }; + + MonoObject* obj = ScriptEngine::Construct("Prism.CapsuleCollider:.ctor(ulong,bool,single,single)", true, data); + mono_array_set(array, MonoObject*, arrayIndex++, obj); + } + + if (entity.HasComponent()) + { + auto& meshCollider = entity.GetComponent(); + + auto mesh = new Ref(meshCollider.CollisionMesh); + UUID uuid = entity.GetUUID(); + + void* data[] = { + &uuid, + &meshCollider.IsTrigger, + &mesh + }; + + MonoObject* obj = ScriptEngine::Construct("Prism.MeshCollider:.ctor(ulong,bool,intptr)", true, data); + mono_array_set(array, MonoObject*, arrayIndex++, obj); + } + } + } + + static std::array s_OverlapBuffer; + + MonoArray* Prism_Physics_OverlapBox(const glm::vec3* origin, const glm::vec3* halfSize) + { + MonoArray* outColliders = nullptr; + memset(s_OverlapBuffer.data(), 0, OVERLAP_MAX_COLLIDERS * sizeof(physx::PxOverlapHit)); + + uint32_t count; + if (PhysicsWrappers::OverlapBox(*origin, *halfSize, s_OverlapBuffer, &count)) + { + outColliders = mono_array_new(mono_domain_get(), ScriptEngine::GetCoreClass("Prism.Collider"), count); + AddCollidersToArray(outColliders, s_OverlapBuffer, count); + } + + return outColliders; + } + + MonoArray* Prism_Physics_OverlapCapsule(const glm::vec3* origin, const float radius, const float halfHeight) + { + MonoArray* outColliders = nullptr; + memset(s_OverlapBuffer.data(), 0, OVERLAP_MAX_COLLIDERS * sizeof(physx::PxOverlapHit)); + + uint32_t count; + if (PhysicsWrappers::OverlapCapsule(*origin, radius, halfHeight, s_OverlapBuffer, &count)) + { + outColliders = mono_array_new(mono_domain_get(), ScriptEngine::GetCoreClass("Prism.Collider"), count); + AddCollidersToArray(outColliders, s_OverlapBuffer, count); + } + + return outColliders; + } + + MonoArray* Prism_Physics_OverlapSphere(const glm::vec3* origin, const float radius) + { + MonoArray* outColliders = nullptr; + memset(s_OverlapBuffer.data(), 0, OVERLAP_MAX_COLLIDERS * sizeof(physx::PxOverlapHit)); + + uint32_t count; + if (PhysicsWrappers::OverlapSphere(*origin, radius, s_OverlapBuffer, &count)) + { + outColliders = mono_array_new(mono_domain_get(), ScriptEngine::GetCoreClass("Prism.Collider"), count); + AddCollidersToArray(outColliders, s_OverlapBuffer, count); + } + + return outColliders; + } + + int32_t Prism_Physics_OverlapBoxNonAlloc(const glm::vec3* origin, const glm::vec3* halfSize, MonoArray* outColliders) + { + memset(s_OverlapBuffer.data(), 0, OVERLAP_MAX_COLLIDERS * sizeof(physx::PxOverlapHit)); + + const uint64_t arrayLength = mono_array_length(outColliders); + + uint32_t count = 0; + if (PhysicsWrappers::OverlapBox(*origin, *halfSize, s_OverlapBuffer, &count)) + { + if (count > arrayLength) + count = static_cast(arrayLength); + + AddCollidersToArray(outColliders, s_OverlapBuffer, count); + } + + return static_cast(count); + } + + int32_t Prism_Physics_OverlapCapsuleNonAlloc(const glm::vec3* origin, const float radius, const float halfHeight, MonoArray* outColliders) + { + memset(s_OverlapBuffer.data(), 0, OVERLAP_MAX_COLLIDERS * sizeof(physx::PxOverlapHit)); + + const uint64_t arrayLength = mono_array_length(outColliders); + + uint32_t count = 0; + if (PhysicsWrappers::OverlapCapsule(*origin, radius, halfHeight, s_OverlapBuffer, &count)) + { + if (count > arrayLength) + count = static_cast(arrayLength); + + AddCollidersToArray(outColliders, s_OverlapBuffer, count); + } + + return static_cast(count); + } + + int32_t Prism_Physics_OverlapSphereNonAlloc(const glm::vec3* origin, const float radius, MonoArray* outColliders) + { + memset(s_OverlapBuffer.data(), 0, OVERLAP_MAX_COLLIDERS * sizeof(physx::PxOverlapHit)); + + const uint64_t arrayLength = mono_array_length(outColliders); + + uint32_t count; + if (PhysicsWrappers::OverlapSphere(*origin, radius, s_OverlapBuffer, &count)) + { + if (count > arrayLength) + count = static_cast(arrayLength); + + AddCollidersToArray(outColliders, s_OverlapBuffer, count); + } + + return static_cast(count); + } + //////////////////////////////////////////////////////////////// - // Entity ////////////////////////////////////////////////////// + // Entity // //////////////////////////////////////////////////////////////// void Prism_Entity_GetTransform(const uint64_t entityID, glm::mat4* outTransform) @@ -117,53 +303,6 @@ namespace Prism { namespace Script { memcpy(glm::value_ptr(transformComponent.Transform), inTransform, sizeof(glm::mat4)); } - /* - void Prism_Entity_GetForwardDirection(const uint64_t entityID, glm::vec3* outForward) - { - Ref scene = ScriptEngine::GetCurrentSceneContext(); - PM_CORE_ASSERT(scene, "No active scene!"); - const auto& entityMap = scene->GetEntityMap(); - PM_CORE_ASSERT(entityMap.find(entityID) != entityMap.end(), "Invalid entity ID or entity doesn't exist in scene!"); - - Entity entity = entityMap.at(entityID); - const auto& transformComponent = entity.GetComponent(); - - auto [position, rotation, scale] = GetTransformDecomposition(transformComponent.Transform); - *outForward = glm::rotate(glm::inverse(glm::normalize(rotation)), glm::vec3(0, 0, -1)); - } - - void Prism_Entity_GetRightDirection(const uint64_t entityID, glm::vec3* outRight) - { - Ref scene = ScriptEngine::GetCurrentSceneContext(); - PM_CORE_ASSERT(scene, "No active scene!"); - const auto& entityMap = scene->GetEntityMap(); - PM_CORE_ASSERT(entityMap.find(entityID) != entityMap.end(), "Invalid entity ID or entity doesn't exist in scene!"); - - Entity entity = entityMap.at(entityID); - const auto& transformComponent = entity.GetComponent(); - - auto [position, rotation, scale] = GetTransformDecomposition(transformComponent.Transform); - *outRight = glm::rotate(glm::inverse(glm::normalize(rotation)), glm::vec3(1, 0, 0)); - } - - void Prism_Entity_GetUpDirection(const uint64_t entityID, glm::vec3* outUp) - { - Ref scene = ScriptEngine::GetCurrentSceneContext(); - PM_CORE_ASSERT(scene, "No active scene!"); - const auto& entityMap = scene->GetEntityMap(); - PM_CORE_ASSERT(entityMap.find(entityID) != entityMap.end(), "Invalid entity ID or entity doesn't exist in scene!"); - - Entity entity = entityMap.at(entityID); - const auto& transformComponent = entity.GetComponent(); - - auto [position, rotation, scale] = GetTransformDecomposition(transformComponent.Transform); - *outUp = glm::rotate(glm::inverse(glm::normalize(rotation)), glm::vec3(0, 1, 0)); - } - */ - - - - void Prism_Entity_CreateComponent(const uint64_t entityID, void* type) { Ref scene = ScriptEngine::GetCurrentSceneContext(); @@ -212,7 +351,7 @@ namespace Prism { namespace Script { const auto& transformComponent = entity.GetComponent(); auto [position, rotation, scale] = GetTransformDecomposition(transformComponent.Transform); - *outDirection = glm::rotate(glm::normalize(rotation), *inAbsoluteDirection); + *outDirection = glm::rotate(rotation, *inAbsoluteDirection); } void Prism_TransformComponent_GetRotation(const uint64_t entityID, glm::vec3* outRotation) @@ -438,27 +577,77 @@ namespace Prism { namespace Script { dynamicActor->setGlobalPose(transform); } + uint32_t Prism_RigidBodyComponent_GetLayer(const uint64_t entityID) + { + Ref scene = ScriptEngine::GetCurrentSceneContext(); + PM_CORE_ASSERT(scene, "No active scene!"); + const auto& entityMap = scene->GetEntityMap(); + PM_CORE_ASSERT(entityMap.find(entityID) != entityMap.end(), "Invalid entity ID or entity doesn't exist in scene!"); + + Entity entity = entityMap.at(entityID); + PM_CORE_ASSERT(entity.HasComponent()); + const auto& component = entity.GetComponent(); + return component.Layer; + } + + float Prism_RigidBodyComponent_GetMass(const uint64_t entityID) + { + Ref scene = ScriptEngine::GetCurrentSceneContext(); + PM_CORE_ASSERT(scene, "No active scene!"); + const auto& entityMap = scene->GetEntityMap(); + PM_CORE_ASSERT(entityMap.find(entityID) != entityMap.end(), "Invalid entity ID or entity doesn't exist in scene!"); + + Entity entity = entityMap.at(entityID); + PM_CORE_ASSERT(entity.HasComponent()); + const auto& component = entity.GetComponent(); + + const auto actor = static_cast(component.RuntimeActor); + const physx::PxRigidDynamic* dynamicActor = actor->is(); + PM_CORE_ASSERT(dynamicActor); + + return dynamicActor->getMass(); + } + + void Prism_RigidBodyComponent_SetMass(const uint64_t entityID, const float mass) + { + Ref scene = ScriptEngine::GetCurrentSceneContext(); + PM_CORE_ASSERT(scene, "No active scene!"); + const auto& entityMap = scene->GetEntityMap(); + PM_CORE_ASSERT(entityMap.find(entityID) != entityMap.end(), "Invalid entity ID or entity doesn't exist in scene!"); + + Entity entity = entityMap.at(entityID); + PM_CORE_ASSERT(entity.HasComponent()); + auto& component = entity.GetComponent(); + + auto* actor = static_cast(component.RuntimeActor); + auto* dynamicActor = actor->is(); + PM_CORE_ASSERT(dynamicActor); + + component.Mass = mass; + physx::PxRigidBodyExt::updateMassAndInertia(*dynamicActor, mass); + } + Ref* Prism_Mesh_Constructor(MonoString* filepath) { return new Ref(new Mesh(mono_string_to_utf8(filepath))); } - void Prism_Mesh_Destructor(Ref* _this) + void Prism_Mesh_Destructor(const Ref* _this) { - const Ref* instance = (Ref*)_this; + const Ref* instance = _this; delete _this; } Ref* Prism_Mesh_GetMaterial(Ref* inMesh) { - Ref& mesh = *(Ref*)inMesh; + Ref& mesh = *inMesh; return new Ref(mesh->GetMaterial()); } Ref* Prism_Mesh_GetMaterialByIndex(Ref* inMesh, const int index) { - Ref& mesh = *(Ref*)inMesh; + Ref& mesh = *inMesh; const auto& materials = mesh->GetMaterials(); PM_CORE_ASSERT(index < materials.size()); @@ -467,7 +656,7 @@ namespace Prism { namespace Script { int Prism_Mesh_GetMaterialCount(Ref* inMesh) { - Ref& mesh = *(Ref*)inMesh; + Ref& mesh = *inMesh; const auto& materials = mesh->GetMaterials(); return (int)materials.size(); } @@ -494,7 +683,7 @@ namespace Prism { namespace Script { PM_CORE_ASSERT(dataSize <= buffer.Size); // Convert RGBA32F color to RGBA8 auto pixels = static_cast(buffer.Data); - uint32_t index = 0; + for (uint32_t i = 0; i < instance->GetWidth() * instance->GetHeight(); i++) { const glm::vec4& value = mono_array_get(inData, glm::vec4, i); @@ -514,13 +703,13 @@ namespace Prism { namespace Script { void Prism_Material_SetFloat(Ref* _this, MonoString* uniform, const float value) { - Ref& instance = *(Ref*)_this; + Ref& instance = *_this; instance->Set(mono_string_to_utf8(uniform), value); } void Prism_Material_SetTexture(Ref* _this, MonoString* uniform, const Ref* texture) { - Ref& instance = *(Ref*)_this; + Ref& instance = *_this; instance->Set(mono_string_to_utf8(uniform), *texture); } @@ -531,25 +720,25 @@ namespace Prism { namespace Script { void Prism_MaterialInstance_SetFloat(Ref* _this, MonoString* uniform, const float value) { - Ref& instance = *(Ref*)_this; + Ref& instance = *_this; instance->Set(mono_string_to_utf8(uniform), value); } void Prism_MaterialInstance_SetVector3(Ref* _this, MonoString* uniform, const glm::vec3* value) { - Ref& instance = *(Ref*)_this; + Ref& instance = *_this; instance->Set(mono_string_to_utf8(uniform), *value); } void Prism_MaterialInstance_SetVector4(Ref *_this, MonoString *uniform, const glm::vec4 *value) { - Ref& instance = *(Ref*)_this; + Ref& instance = *_this; instance->Set(mono_string_to_utf8(uniform), *value); } void Prism_MaterialInstance_SetTexture(Ref* _this, MonoString* uniform, const Ref* texture) { - Ref& instance = *(Ref*)_this; + Ref& instance = *_this; instance->Set(mono_string_to_utf8(uniform), *texture); } diff --git a/Prism/src/Prism/Script/ScriptWarppers.h b/Prism/src/Prism/Script/ScriptWrappers.h similarity index 76% rename from Prism/src/Prism/Script/ScriptWarppers.h rename to Prism/src/Prism/Script/ScriptWrappers.h index aa155c2..4f6078f 100644 --- a/Prism/src/Prism/Script/ScriptWarppers.h +++ b/Prism/src/Prism/Script/ScriptWrappers.h @@ -2,8 +2,8 @@ // Created by sfd on 25-12-6. // -#ifndef SCRIPTWARPPERS_H -#define SCRIPTWARPPERS_H +#ifndef SCRIPTWRAPPERS_H +#define SCRIPTWRAPPERS_H #include "Prism/Core/Input.h" #include "Prism/Core/KeyCodes.h" #include "Prism/Core/Ref.h" @@ -24,21 +24,26 @@ namespace Prism { namespace Script { // Input bool Prism_Input_IsKeyPressed(KeyCode key); + bool Prism_Input_IsMouseButtonPressed(MouseButton button); void Prism_Input_GetMousePosition(glm::vec2* outPosition); void Prism_Input_SetCursorMode(CursorMode mode); CursorMode Prism_Input_GetCursorMode(); + // Physics + bool Prism_Physics_Raycast(const glm::vec3* origin, const glm::vec3* direction, float maxDistance, RaycastHit* hit); + MonoArray* Prism_Physics_OverlapBox(const glm::vec3* origin, const glm::vec3* halfSize); + MonoArray* Prism_Physics_OverlapCapsule(const glm::vec3* origin, float radius, float halfHeight); + MonoArray* Prism_Physics_OverlapSphere(const glm::vec3* origin, float radius); + int32_t Prism_Physics_OverlapBoxNonAlloc(const glm::vec3* origin, const glm::vec3* halfSize, MonoArray* outColliders); + int32_t Prism_Physics_OverlapCapsuleNonAlloc(const glm::vec3* origin, float radius, float halfHeight, MonoArray* outColliders); + int32_t Prism_Physics_OverlapSphereNonAlloc(const glm::vec3* origin, float radius, MonoArray* outColliders); + // Entity void Prism_Entity_CreateComponent(uint64_t entityID, void* type); bool Prism_Entity_HasComponent(uint64_t entityID, void* type); uint64_t Prism_Entity_FindEntityByTag(MonoString* tag); void Prism_Entity_GetTransform(uint64_t entityID, glm::mat4* outTransform); void Prism_Entity_SetTransform(uint64_t entityID, const glm::mat4* inTransform); - /* - void Prism_Entity_GetForwardDirection(uint64_t entityID, glm::vec3* outForward); - void Prism_Entity_GetRightDirection(uint64_t entityID, glm::vec3* outRight); - void Prism_Entity_GetUpDirection(uint64_t entityID, glm::vec3* outUp); - */ void Prism_TransformComponent_GetRelativeDirection(uint64_t entityID, glm::vec3* outDirection, const glm::vec3* inAbsoluteDirection); void Prism_TransformComponent_GetRotation(uint64_t entityID,glm::vec3* outRotation); @@ -55,6 +60,9 @@ namespace Prism { namespace Script { void Prism_RigidBodyComponent_GetLinearVelocity(uint64_t entityID, glm::vec3* outVelocity); void Prism_RigidBodyComponent_SetLinearVelocity(uint64_t entityID, glm::vec3* velocity); void Prism_RigidBodyComponent_Rotate(uint64_t entityID, glm::vec3* rotation); + uint32_t Prism_RigidBodyComponent_GetLayer(uint64_t entityID); + float Prism_RigidBodyComponent_GetMass(uint64_t entityID); + void Prism_RigidBodyComponent_SetMass(uint64_t entityID, float mass); // Renderer // Texture2D @@ -75,7 +83,7 @@ namespace Prism { namespace Script { // Mesh Ref* Prism_Mesh_Constructor(MonoString* filepath); - void Prism_Mesh_Destructor(Ref* _this); + void Prism_Mesh_Destructor(const Ref* _this); Ref* Prism_Mesh_GetMaterial(Ref* inMesh); Ref* Prism_Mesh_GetMaterialByIndex(Ref* inMesh, int index); int Prism_Mesh_GetMaterialCount(Ref* inMesh); @@ -87,4 +95,4 @@ namespace Prism { namespace Script { } } -#endif //SCRIPTWARPPERS_H +#endif //SCRIPTWRAPPERS_H