diff --git a/Editor/Editor/EditorLayer.cpp b/Editor/Editor/EditorLayer.cpp index 0b32dea..0dd6a2d 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/Physics/Physics3D.h" #include "Prism/Renderer/Renderer2D.h" #include "Prism/Script/ScriptEngine.h" @@ -172,7 +173,7 @@ namespace Prism m_CheckerboardTex = Texture2D::Create("assets/editor/Checkerboard.tga"); m_PlayButtonTex = Texture2D::Create("assets/editor/PlayButton.png"); - m_EditorScene = Ref::Create(); + m_EditorScene = Ref::Create("untitled Scene", true); ScriptEngine::SetSceneContext(m_EditorScene); m_SceneHierarchyPanel = CreateScope(m_EditorScene); m_SceneHierarchyPanel->SetSelectionChangedCallback(std::bind(&EditorLayer::SelectEntity, this, std::placeholders::_1)); @@ -199,7 +200,7 @@ namespace Prism if (m_DrawOnTopBoundingBoxes) { Renderer::BeginRenderPass(SceneRenderer::GetFinalRenderPass(), false); - auto viewProj = m_EditorCamera.GetViewProjection(); + const auto viewProj = m_EditorCamera.GetViewProjection(); Renderer2D::BeginScene(viewProj, false); // TODO: Renderer::DrawAABB(m_MeshEntity.GetComponent(), m_MeshEntity.GetComponent()); Renderer2D::EndScene(); @@ -233,7 +234,7 @@ namespace Prism const glm::vec3 rotation = glm::eulerAngles(rotationQuat); Renderer::BeginRenderPass(SceneRenderer::GetFinalRenderPass(), false); - auto viewProj = m_EditorCamera.GetViewProjection(); + const auto viewProj = m_EditorCamera.GetViewProjection(); Renderer2D::BeginScene(viewProj, false); Renderer2D::DrawRotatedQuad({ translation.x, translation.y }, size * 2.0f, glm::degrees(rotation.z), { 1.0f, 0.0f, 1.0f, 1.0f }); Renderer2D::EndScene(); @@ -360,6 +361,21 @@ namespace Prism ImGui::EndMenu(); } + if (ImGui::BeginMenu("Tools")) + { + // PhysX Debugger + if (ImGui::MenuItem("Connect to PVD")) + { + Physics3D::ConnectPVD(); + } + if (ImGui::MenuItem("Disconnect from PVD", nullptr, nullptr, Physics3D::IsPVDConnected())) + { + Physics3D::DisconnectPVD(); + } + + ImGui::EndMenu(); + } + ImGui::EndMenuBar(); } @@ -914,8 +930,8 @@ namespace Prism glm::inverse(glm::mat3(entity.Transform()) * glm::mat3(submesh.Transform)) * direction }; - float t; - if (bool intersects = ray.IntersectsAABB(submesh.BoundingBox, t)) + float t = 0; + if (ray.IntersectsAABB(submesh.BoundingBox, t)) { const auto& triangleCache = mesh->GetTriangleCache(i); for (const auto& triangle : triangleCache) @@ -1029,10 +1045,10 @@ namespace Prism void EditorLayer::OpenScene() { const auto& app = Application::Get(); - const std::string filepath = app.OpenFile("Hazel Scene (*.hsc)\0*.hsc\0"); + const std::string filepath = app.OpenFile("Prism Scene (*.hsc)\0*.hsc\0"); if (!filepath.empty()) { - const Ref newScene = Ref::Create(); + const Ref newScene = Ref::Create("EditorScene", true); SceneSerializer serializer(newScene); serializer.Deserialize(filepath); m_EditorScene = newScene; @@ -1057,7 +1073,7 @@ namespace Prism void EditorLayer::SaveSceneAs() { auto& app = Application::Get(); - std::string filepath = app.SaveFile("Hazel Scene (*.hsc)\0*.hsc\0"); + std::string filepath = app.SaveFile("Prism Scene (*.hsc)\0*.hsc\0"); if (!filepath.empty()) { SceneSerializer serializer(m_EditorScene); diff --git a/Editor/assets/meshes/Capsule.fbx b/Editor/assets/meshes/Capsule.fbx new file mode 100644 index 0000000..22157fc Binary files /dev/null and b/Editor/assets/meshes/Capsule.fbx differ diff --git a/Editor/assets/scenes/FPSDemo.scene b/Editor/assets/scenes/FPSDemo.scene new file mode 100644 index 0000000..41c07aa --- /dev/null +++ b/Editor/assets/scenes/FPSDemo.scene @@ -0,0 +1,167 @@ +Scene: Scene Name +Environment: + AssetPath: assets/env/pink_sunrise_4k.hdr + Light: + Direction: [-0.787, -0.73299998, 1] + Radiance: [1, 1, 1] + Multiplier: 0.514999986 +Entities: + - Entity: 3247025703490125974 + TagComponent: + Tag: Player + TransformComponent: + Position: [2.80803752, 1.5, 0] + Rotation: [1, 0, 0, 0] + Scale: [2, 2, 2] + ScriptComponent: + ModuleName: FPSExample.FPSPlayer + StoredFields: + - Name: WalkingSpeed + Type: 1 + Data: 20 + - Name: RunSpeed + Type: 1 + Data: 50 + - Name: JumpForce + Type: 1 + Data: 50 + MeshComponent: + AssetPath: assets/meshes/Capsule.fbx + RigidBodyComponent: + BodyType: 1 + Mass: 1 + IsKinematic: false + Constraints: + LockPositionX: false + LockPositionY: false + LockPositionZ: false + LockRotationX: true + LockRotationY: false + LockRotationZ: true + PhysicsMaterialComponent: + StaticFriction: 0.100000001 + DynamicFriction: 0.100000001 + Bounciness: 0.100000001 + MeshColliderComponent: + AssetPath: assets/meshes/Capsule.fbx + IsTrigger: false + - Entity: 11149966982516343187 + TagComponent: + Tag: Mesh Collider + TransformComponent: + Position: [-2.60455179, 1, -0.00171399117] + Rotation: [1, 0, 0, 0] + Scale: [1, 1, 1] + MeshComponent: + AssetPath: assets/meshes/Sphere1m.fbx + RigidBodyComponent: + BodyType: 1 + Mass: 0.100000001 + IsKinematic: false + Constraints: + LockPositionX: false + LockPositionY: false + LockPositionZ: false + LockRotationX: false + LockRotationY: false + LockRotationZ: false + PhysicsMaterialComponent: + StaticFriction: 1 + DynamicFriction: 1 + Bounciness: 0.100000001 + MeshColliderComponent: + AssetPath: assets/meshes/Sphere1m.fbx + IsTrigger: false + - Entity: 10169503531257462571 + TagComponent: + Tag: Box + TransformComponent: + Position: [0, 1.5, 0] + Rotation: [1, 0, 0, 0] + Scale: [2, 2, 2] + MeshComponent: + AssetPath: assets/meshes/Cube1m.fbx + RigidBodyComponent: + BodyType: 1 + Mass: 0.5 + IsKinematic: false + Constraints: + LockPositionX: false + LockPositionY: false + LockPositionZ: false + LockRotationX: false + LockRotationY: false + LockRotationZ: false + PhysicsMaterialComponent: + StaticFriction: 1 + DynamicFriction: 1 + Bounciness: 0 + BoxColliderComponent: + Offset: [0, 0, 0] + Size: [1, 1, 1] + IsTrigger: false + - Entity: 14057422478420564497 + TagComponent: + Tag: Sphere + TransformComponent: + Position: [-3.98769951, 1, -1.96695328e-06] + Rotation: [1, 0, 0, 0] + Scale: [1, 1, 1] + MeshComponent: + AssetPath: assets/meshes/Sphere1m.fbx + RigidBodyComponent: + BodyType: 1 + Mass: 1 + IsKinematic: false + Constraints: + LockPositionX: false + LockPositionY: false + LockPositionZ: false + LockRotationX: true + LockRotationY: true + LockRotationZ: true + PhysicsMaterialComponent: + StaticFriction: 0.100000001 + DynamicFriction: 0.100000001 + Bounciness: 0.100000001 + SphereColliderComponent: + Radius: 0.5 + IsTrigger: false + - Entity: 5178862374589434728 + TagComponent: + Tag: Camera + TransformComponent: + Position: [2.80800009, 2.25, 0] + Rotation: [1, 0, 0, 0] + Scale: [1, 1, 1] + CameraComponent: + Camera: some camera data... + Primary: true + - Entity: 18306113171518048249 + TagComponent: + Tag: Box + TransformComponent: + Position: [0, 0, 0] + Rotation: [1, 0, 0, 0] + Scale: [50, 1, 50] + MeshComponent: + AssetPath: assets/meshes/Cube1m.fbx + RigidBodyComponent: + BodyType: 0 + Mass: 1 + IsKinematic: false + Constraints: + LockPositionX: false + LockPositionY: false + LockPositionZ: false + LockRotationX: false + LockRotationY: false + LockRotationZ: false + PhysicsMaterialComponent: + StaticFriction: 1 + DynamicFriction: 1 + Bounciness: 0 + BoxColliderComponent: + Offset: [0, 0, 0] + Size: [1, 1, 1] + IsTrigger: false diff --git a/Editor/assets/scenes/Physics3DTest.scene b/Editor/assets/scenes/Physics3DTest.scene index 5172996..3d0e70e 100644 --- a/Editor/assets/scenes/Physics3DTest.scene +++ b/Editor/assets/scenes/Physics3DTest.scene @@ -18,6 +18,14 @@ Entities: RigidBodyComponent: BodyType: 1 Mass: 0.5 + IsKinematic: false + Constraints: + LockPositionX: false + LockPositionY: false + LockPositionZ: false + LockRotationX: true + LockRotationY: true + LockRotationZ: true PhysicsMaterialComponent: StaticFriction: 1 DynamicFriction: 1 @@ -49,6 +57,14 @@ Entities: RigidBodyComponent: BodyType: 1 Mass: 1 + IsKinematic: false + Constraints: + LockPositionX: false + LockPositionY: false + LockPositionZ: false + LockRotationX: true + LockRotationY: true + LockRotationZ: true PhysicsMaterialComponent: StaticFriction: 1 DynamicFriction: 1 @@ -86,6 +102,14 @@ Entities: RigidBodyComponent: BodyType: 0 Mass: 1 + IsKinematic: false + Constraints: + LockPositionX: false + LockPositionY: false + LockPositionZ: false + LockRotationX: true + LockRotationY: true + LockRotationZ: true PhysicsMaterialComponent: StaticFriction: 1 DynamicFriction: 1 diff --git a/Editor/assets/shaders/Collider.glsl b/Editor/assets/shaders/Collider.glsl new file mode 100644 index 0000000..d991def --- /dev/null +++ b/Editor/assets/shaders/Collider.glsl @@ -0,0 +1,24 @@ +// Collider Shader + +#type vertex +#version 450 + +layout(location = 0) in vec3 a_Position; + +uniform mat4 u_ViewProjection; +uniform mat4 u_Transform; + +void main() +{ + gl_Position = u_ViewProjection * u_Transform * vec4(a_Position, 1.0); +} + +#type fragment +#version 450 + +layout(location = 0) out vec4 color; + +void main() +{ + color = vec4(0.1, 1.0, 0.1, 1.0); +} diff --git a/ExampleApp/Src/FPSPlayer.cs b/ExampleApp/Src/FPSPlayer.cs new file mode 100644 index 0000000..998b0b7 --- /dev/null +++ b/ExampleApp/Src/FPSPlayer.cs @@ -0,0 +1,115 @@ +using System; +using Prism; + +namespace FPSExample +{ + public class FPSPlayer : Entity + { + public float WalkingSpeed = 10.0F; + 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); + + private bool m_Colliding = false; + private float m_CurrentSpeed; + + private RigidBodyComponent m_RigidBody; + private TransformComponent m_Transform; + private TransformComponent m_CameraTransform; + + private Entity m_CameraEntity; + + private Vec2 m_LastMousePosition; + private float m_CameraRotationX = 0.0f; + private float m_RotationY = 0.0f; + + void OnCreate() + { + m_Transform = GetComponent(); + m_RigidBody = GetComponent(); + + m_CurrentSpeed = WalkingSpeed; + + AddCollisionBeginCallback((n) => { m_Colliding = true; }); + AddCollisionEndCallback((n) => { m_Colliding = false; }); + + m_CameraEntity = FindEntityByTag("Camera"); + + m_CameraTransform = m_CameraEntity.GetComponent(); + m_LastMousePosition = Input.GetMousePosition(); + + Input.SetCursorMode(Input.CursorMode.Locked); + } + + void OnUpdate(float ts) + { + Forward = m_Transform.Forward; + + if (Input.IsKeyPressed(KeyCode.Escape) && Input.GetCursorMode() == Input.CursorMode.Locked) + { + Input.SetCursorMode(Input.CursorMode.Normal); + } + + m_CurrentSpeed = Input.IsKeyPressed(KeyCode.LeftControl) ? RunSpeed : WalkingSpeed; + + UpdateRotation(ts); + UpdateMovement(); + UpdateCameraTransform(); + } + + private void UpdateRotation(float ts) + { + Vec2 currentMousePosition = Input.GetMousePosition(); + Vec2 delta = m_LastMousePosition - currentMousePosition; + if (delta.X != 0) + { + m_RotationY += delta.X * MouseSensitivity * ts; + } + + m_RigidBody.Rotate(new Vec3(0.0F, delta.X * MouseSensitivity, 0.0f) * ts); + + if (delta.Y != 0.0F) + { + m_CameraRotationX += delta.Y * MouseSensitivity * ts; + m_CameraRotationX = Mathf.Clamp(m_CameraRotationX, -80.0f, 80.0f); + } + + m_LastMousePosition = currentMousePosition; + } + + private void UpdateMovement() + { + + if (Input.IsKeyPressed(KeyCode.W)) + m_RigidBody.AddForce(m_Transform.Forward * m_CurrentSpeed); + else if (Input.IsKeyPressed(KeyCode.S)) + m_RigidBody.AddForce(m_Transform.Forward * -m_CurrentSpeed); + + if (Input.IsKeyPressed(KeyCode.A)) + m_RigidBody.AddForce(m_Transform.Right * -m_CurrentSpeed); + else if (Input.IsKeyPressed(KeyCode.D)) + m_RigidBody.AddForce(m_Transform.Right * m_CurrentSpeed); + + if (Input.IsKeyPressed(KeyCode.Space) && m_Colliding) + m_RigidBody.AddForce(Vec3.Up * JumpForce); + + } + + private void UpdateCameraTransform(){ + + // TODO: This workflow needs to be improved. (Will be fixed by object parenting) + + Mat4 cameraTransform = m_CameraTransform.Transform; + Vec3 cameraTranslation = cameraTransform.Translation; + Vec3 translation = m_Transform.Transform.Translation; + cameraTranslation.XZ = translation.XZ; + cameraTranslation.Y = translation.Y + 1.5F; + cameraTransform.Translation = cameraTranslation; + m_CameraTransform.Transform = cameraTransform; + + m_CameraTransform.Rotation = new Vec3(m_CameraRotationX, m_RotationY, 0.0f); + + } + } +} \ No newline at end of file diff --git a/ExampleApp/Src/PlayerSphere.cs b/ExampleApp/Src/PlayerSphere.cs index 06c28ca..67dae8c 100644 --- a/ExampleApp/Src/PlayerSphere.cs +++ b/ExampleApp/Src/PlayerSphere.cs @@ -22,9 +22,11 @@ namespace Example private bool Colliding => m_CollisionCounter > 0; + private TransformComponent m_Transform; void OnCreate() { m_PhysicsBody = GetComponent(); + m_Transform = GetComponent(); MeshComponent meshComponent = GetComponent(); m_MeshMaterial = meshComponent.Mesh.GetMaterial(0); @@ -32,6 +34,8 @@ namespace Example AddCollisionBeginCallback(OnPlayerCollisionBegin); AddCollisionEndCallback(OnPlayerCollisionEnd); + AddTriggerBeginCallback(OnPlayerTriggerBegin); + AddTriggerEndCallback(OnPlayerTriggerEnd); } void OnPlayerCollisionBegin(float value) @@ -44,6 +48,16 @@ namespace Example m_CollisionCounter--; } + void OnPlayerTriggerBegin(float value) + { + Console.WriteLine("Player trigger begin"); + } + + void OnPlayerTriggerEnd(float value) + { + Console.WriteLine("Player trigger end"); + } + void OnUpdate(float ts) { float movementForce = HorizontalForce; @@ -53,22 +67,18 @@ namespace Example movementForce *= 0.4f; } - Vec3 forward = GetForwardDirection(); - Vec3 right = GetRightDirection(); - Vec3 up = GetUpDirection(); - if (Input.IsKeyPressed(KeyCode.W)) - m_PhysicsBody.AddForce(forward * movementForce); + m_PhysicsBody.AddForce(m_Transform.Forward * movementForce); else if (Input.IsKeyPressed(KeyCode.S)) - m_PhysicsBody.AddForce(forward * -movementForce); + m_PhysicsBody.AddForce(m_Transform.Forward * -movementForce); if (Input.IsKeyPressed(KeyCode.D)) - m_PhysicsBody.AddForce(right * movementForce); + m_PhysicsBody.AddForce(m_Transform.Right * movementForce); else if (Input.IsKeyPressed(KeyCode.A)) - m_PhysicsBody.AddForce(right * -movementForce); + m_PhysicsBody.AddForce(m_Transform.Right * -movementForce); if (Colliding && Input.IsKeyPressed(KeyCode.Space)) - m_PhysicsBody.AddForce(up * JumpForce); + m_PhysicsBody.AddForce(m_Transform.Up * JumpForce); if (Colliding) m_MeshMaterial.Set("u_AlbedoColor", new Vec3(1.0f, 0.0f, 0.0f)); diff --git a/Prism-ScriptCore/Src/Prism/Entity.cs b/Prism-ScriptCore/Src/Prism/Entity.cs index 3044e35..fd34361 100644 --- a/Prism-ScriptCore/Src/Prism/Entity.cs +++ b/Prism-ScriptCore/Src/Prism/Entity.cs @@ -11,10 +11,12 @@ namespace Prism { } - private List> m_Collision2DBeginCallbacks = new List>(); - private List> m_Collision2DEndCallbacks = new List>(); - private Action m_CollisionBeginCallbacks; - private Action m_CollisionEndCallbacks; + private Action? m_CollisionBeginCallbacks; + private Action? m_CollisionEndCallbacks; + private Action? m_Collision2DBeginCallbacks; + private Action? m_Collision2DEndCallbacks; + private Action? m_TriggerBeginCallbacks; + private Action? m_TriggerEndCallbacks; protected Entity() { ID = 0; } @@ -65,32 +67,14 @@ namespace Prism SetTransform_Native(ID, ref transform); } - public Vec3 GetForwardDirection() - { - GetForwardDirection_Native(ID, out Vec3 forward); - return forward; - } - - public Vec3 GetRightDirection() - { - GetRightDirection_Native(ID, out Vec3 right); - return right; - } - - public Vec3 GetUpDirection() - { - GetUpDirection_Native(ID, out Vec3 up); - return up; - } - public void AddCollision2DBeginCallback(Action callback) { - m_Collision2DBeginCallbacks.Add(callback); + m_Collision2DBeginCallbacks += callback; } public void AddCollision2DEndCallback(Action callback) { - m_Collision2DEndCallbacks.Add(callback); + m_Collision2DEndCallbacks += callback; } public void AddCollisionBeginCallback(Action callback) @@ -103,6 +87,16 @@ namespace Prism m_CollisionEndCallbacks += callback; } + public void AddTriggerBeginCallback(Action callback) + { + m_TriggerBeginCallbacks += callback; + } + + public void AddTriggerEndCallback(Action callback) + { + m_TriggerEndCallbacks += callback; + } + private void OnCollisionBegin(float data) { if (m_CollisionBeginCallbacks != null) @@ -117,16 +111,29 @@ namespace Prism private void OnCollision2DBegin(float data) { - foreach (var callback in m_Collision2DBeginCallbacks) - callback.Invoke(data); + if(m_Collision2DBeginCallbacks != null) + m_Collision2DBeginCallbacks.Invoke(data); } private void OnCollision2DEnd(float data) { - foreach (var callback in m_Collision2DEndCallbacks) - callback.Invoke(data); + if(m_Collision2DEndCallbacks != null) + m_Collision2DEndCallbacks.Invoke(data); } + private void OnTriggerBegin(float data) + { + if (m_TriggerBeginCallbacks != null) + m_TriggerBeginCallbacks.Invoke(data); + } + + private void OnTriggerEnd(float data) + { + if (m_TriggerEndCallbacks != null) + m_TriggerEndCallbacks.Invoke(data); + } + + [MethodImpl(MethodImplOptions.InternalCall)] private static extern void CreateComponent_Native(ulong entityID, Type type); [MethodImpl(MethodImplOptions.InternalCall)] @@ -137,12 +144,5 @@ namespace Prism private static extern void SetTransform_Native(ulong entityID, ref Mat4 matrix); [MethodImpl(MethodImplOptions.InternalCall)] private static extern ulong FindEntityByTag_Native(string tag); - - [MethodImpl(MethodImplOptions.InternalCall)] - private static extern void GetForwardDirection_Native(ulong entityID, out Vec3 forward); - [MethodImpl(MethodImplOptions.InternalCall)] - private static extern void GetRightDirection_Native(ulong entityID, out Vec3 right); - [MethodImpl(MethodImplOptions.InternalCall)] - private static extern void GetUpDirection_Native(ulong entityID, out Vec3 up); } } diff --git a/Prism-ScriptCore/Src/Prism/Input.cs b/Prism-ScriptCore/Src/Prism/Input.cs index 32db526..443bb9d 100644 --- a/Prism-ScriptCore/Src/Prism/Input.cs +++ b/Prism-ScriptCore/Src/Prism/Input.cs @@ -4,14 +4,39 @@ namespace Prism { public class Input { + public enum CursorMode + { + Normal = 0, + Hidden = 1, + Locked = 2, + } public static bool IsKeyPressed(KeyCode keycode) { return IsKeyPressed_Native(keycode); } + public static Vec2 GetMousePosition() + { + GetMousePosition_Native(out Vec2 position); + return position; + } + + public static void SetCursorMode(CursorMode mode) => SetCursorMode_Native(mode); + public static CursorMode GetCursorMode() => GetCursorMode_Native(); + + + [MethodImpl(MethodImplOptions.InternalCall)] private static extern bool IsKeyPressed_Native(KeyCode keycode); + [MethodImpl(MethodImplOptions.InternalCall)] + private static extern void GetMousePosition_Native(out Vec2 position); + + [MethodImpl(MethodImplOptions.InternalCall)] + private static extern void SetCursorMode_Native(CursorMode mode); + + [MethodImpl(MethodImplOptions.InternalCall)] + private static extern CursorMode GetCursorMode_Native(); } } \ No newline at end of file diff --git a/Prism-ScriptCore/Src/Prism/Math/Queternion.cs b/Prism-ScriptCore/Src/Prism/Math/Queternion.cs new file mode 100644 index 0000000..b96d161 --- /dev/null +++ b/Prism-ScriptCore/Src/Prism/Math/Queternion.cs @@ -0,0 +1,56 @@ +using System; +using System.Runtime.InteropServices; + +namespace Prism +{ + [StructLayout(LayoutKind.Sequential)] + public struct Quaternion + { + public float X; + public float Y; + public float Z; + public float W; + + public Quaternion(float x, float y, float z, float w) + { + X = x; + Y = y; + Z = z; + W = w; + } + + public Quaternion(float w, Vec3 xyz) + { + X = xyz.X; + Y = xyz.Y; + Z = xyz.Z; + W = w; + } + + public Quaternion(Vec3 eulerAngles) + { + Vec3 c = Vec3.Cos(eulerAngles * 0.5F); + Vec3 s = Vec3.Sin(eulerAngles * 0.5F); + + W = c.X * c.Y * c.Z + s.X * s.Y * s.Z; + X = s.X * c.Y * c.Z - c.X * s.Y * s.Z; + Y = c.X * s.Y * c.Z + s.X * c.Y * s.Z; + Z = c.X * c.Y * s.Z - s.X * s.Y * c.Z; + } + + public static Quaternion AngleAxis(float angle, Vec3 axis) + { + float s = (float)Math.Sin(angle * 0.5F); + return new Quaternion(s, axis * s); + } + + public static Quaternion operator*(Quaternion a, Quaternion b) + { + float w = a.W * b.W - a.X * b.X - a.Y * b.Y - a.Z * b.Z; + float x = a.W * b.X + a.X * b.W + a.Y * b.Z - a.Z * b.Y; + float y = a.W * b.Y + a.Y * b.W + a.Z * b.X - a.X * b.Z; + float z = a.W * b.Z + a.Z * b.W + a.X * b.Y - a.Y * b.X; + return new Quaternion(x, y, z, w); + } + } +} diff --git a/Prism-ScriptCore/Src/Prism/Math/Vec2.cs b/Prism-ScriptCore/Src/Prism/Math/Vec2.cs index 73f0702..4696906 100644 --- a/Prism-ScriptCore/Src/Prism/Math/Vec2.cs +++ b/Prism-ScriptCore/Src/Prism/Math/Vec2.cs @@ -25,20 +25,23 @@ namespace Prism } public void Clamp(Vec2 min, Vec2 max) { - if (X < min.X) - X = min.X; - if (X > max.X) - X = max.X; - - if (Y < min.Y) - Y = min.Y; - if (Y > max.Y) - Y = max.Y; + X = Mathf.Clamp(X, min.X, max.X); + Y = Mathf.Clamp(Y, min.Y, max.Y); } + public static Vec2 operator -(Vec2 l, Vec2 r) + { + return new Vec2(l.X - r.X, l.Y - r.Y); + } + public static Vec2 operator -(Vec2 vector) { return new Vec2(-vector.X, -vector.Y); } + + public override string ToString() + { + return $"({X}, {Y})"; + } } } \ No newline at end of file diff --git a/Prism-ScriptCore/Src/Prism/Math/Vec3.cs b/Prism-ScriptCore/Src/Prism/Math/Vec3.cs index 6ff2443..313ad1d 100644 --- a/Prism-ScriptCore/Src/Prism/Math/Vec3.cs +++ b/Prism-ScriptCore/Src/Prism/Math/Vec3.cs @@ -5,6 +5,12 @@ namespace Prism [StructLayout(LayoutKind.Sequential)] public struct Vec3 { + public static Vec3 Zero = new Vec3(0.0f, 0.0f, 0.0f); + + public static Vec3 Forward = new Vec3(0.0f, 0.0f, -1.0f); + public static Vec3 Right = new Vec3(1.0f, 0.0f, 0.0f); + public static Vec3 Up = new Vec3(0.0f, 1.0f, 0.0f); + public float X; public float Y; public float Z; @@ -40,15 +46,6 @@ namespace Prism Z = Mathf.Clamp(Z, min.Z, max.Z); } - public static Vec3 operator *(Vec3 left, float scalar) - { - return new Vec3(left.X * scalar, left.Y * scalar, left.Z * scalar); - } - - public static Vec3 operator *(float scalar, Vec3 right) - { - return new Vec3(scalar * right.X, scalar * right.Y, scalar * right.Z); - } public Vec2 XY { get { return new Vec2(X, Y); } @@ -66,5 +63,56 @@ namespace Prism set { Y = value.X; Z = value.Y; } } + + public static Vec3 operator *(Vec3 left, float scalar) + { + return new Vec3(left.X * scalar, left.Y * scalar, left.Z * scalar); + } + + public static Vec3 operator *(float scalar, Vec3 right) + { + return new Vec3(scalar * right.X, scalar * right.Y, scalar * right.Z); + } + + public static Vec3 operator +(Vec3 left, Vec3 right) + { + return new Vec3(left.X + right.X, left.Y + right.Y, left.Z + right.Z); + } + + public static Vec3 operator -(Vec3 left, Vec3 right) + { + return new Vec3(left.X - right.X, left.Y - right.Y, left.Z - right.Z); + } + + public static Vec3 operator /(Vec3 left, Vec3 right) + { + return new Vec3(left.X / right.X, left.Y / right.Y, left.Z / right.Z); + } + + public static Vec3 operator /(Vec3 left, float scalar) + { + return new Vec3(left.X / scalar, left.Y / scalar, left.Z / scalar); + } + + public static Vec3 operator-(Vec3 vector) + { + return new Vec3(-vector.X, -vector.Y, -vector.Z); + } + + public static Vec3 Cos(Vec3 vector) + { + return new Vec3((float)Math.Cos(vector.X), (float)Math.Cos(vector.Y), (float)Math.Cos(vector.Z)); + } + + public static Vec3 Sin(Vec3 vector) + { + return new Vec3((float)Math.Sin(vector.X), (float)Math.Sin(vector.Y), (float)Math.Sin(vector.Z)); + } + + public override string ToString() + { + return $"({X}, {Y}, {Z})"; + } + } } \ No newline at end of file diff --git a/Prism-ScriptCore/Src/Prism/Math/Vec4.cs b/Prism-ScriptCore/Src/Prism/Math/Vec4.cs index 55cd5d0..29e2edb 100644 --- a/Prism-ScriptCore/Src/Prism/Math/Vec4.cs +++ b/Prism-ScriptCore/Src/Prism/Math/Vec4.cs @@ -2,13 +2,13 @@ using System.Runtime.InteropServices; namespace Prism { - [StructLayout(LayoutKind.Explicit)] + [StructLayout(LayoutKind.Sequential)] public struct Vec4 { - [FieldOffset(0)] public float X; - [FieldOffset(4)] public float Y; - [FieldOffset(8)] public float Z; - [FieldOffset(12)] public float W; + public float X; + public float Y; + public float Z; + public float W; public Vec4(float scalar) { diff --git a/Prism-ScriptCore/Src/Prism/Physics/Colliders.cs b/Prism-ScriptCore/Src/Prism/Physics/Colliders.cs new file mode 100644 index 0000000..b111cca --- /dev/null +++ b/Prism-ScriptCore/Src/Prism/Physics/Colliders.cs @@ -0,0 +1,77 @@ +using System; + +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 bool IsTrigger { get; protected set; } + + } + + public class BoxCollider : Collider + { + public Vec3 Size { get; private set; } + public Vec3 Offset { get; private set; } + + internal BoxCollider(ulong entityID, Vec3 size, Vec3 offset, bool isTrigger) + { + ColliderEntity = new Entity(entityID); + Type = ColliderType.Box; + Size = size; + Offset = offset; + IsTrigger = isTrigger; + } + } + + public class SphereCollider : Collider + { + public float Radius { get; private set; } + + internal SphereCollider(ulong entityID, float radius, bool isTrigger) + { + ColliderEntity = new Entity(entityID); + Type = ColliderType.Box; + Radius = radius; + IsTrigger = isTrigger; + } + } + + public class CapsuleCollider : Collider + { + public float Radius { get; private set; } + public float Height { get; private set; } + + internal CapsuleCollider(ulong entityID, float radius, float height, bool isTrigger) + { + ColliderEntity = new Entity(entityID); + Type = ColliderType.Box; + Radius = radius; + Height = height; + IsTrigger = isTrigger; + } + } + + public class MeshCollider : Collider + { + public Mesh Mesh { get; private set; } + + internal MeshCollider(ulong entityID, Mesh mesh, bool isTrigger) + { + ColliderEntity = new Entity(entityID); + Type = ColliderType.Box; + Mesh = mesh; + IsTrigger = isTrigger; + } + } +} + diff --git a/Prism-ScriptCore/Src/Prism/Scene/Component.cs b/Prism-ScriptCore/Src/Prism/Scene/Component.cs index a2e1611..4822922 100644 --- a/Prism-ScriptCore/Src/Prism/Scene/Component.cs +++ b/Prism-ScriptCore/Src/Prism/Scene/Component.cs @@ -46,11 +46,62 @@ namespace Prism } } + public Vec3 Rotation + { + get + { + GetRotation_Native(Entity.ID, out Vec3 rotation); + return rotation; + } + set + { + SetRotation_Native(Entity.ID, ref value); + } + } + + public Vec3 Forward + { + get + { + GetRelativeDirection_Native(Entity.ID, out Vec3 result, ref Vec3.Forward); + return result; + } + } + + public Vec3 Right + { + get + { + GetRelativeDirection_Native(Entity.ID, out Vec3 result, ref Vec3.Right); + return result; + } + } + + public Vec3 Up + { + get + { + GetRelativeDirection_Native(Entity.ID, out Vec3 result, ref Vec3.Up); + return result; + } + } + + [MethodImpl(MethodImplOptions.InternalCall)] public static extern void GetTransform_Native(ulong entityID, out Mat4 result); [MethodImpl(MethodImplOptions.InternalCall)] public static extern void SetTransform_Native(ulong entityID, ref Mat4 result); + + [MethodImpl(MethodImplOptions.InternalCall)] + public static extern void GetRelativeDirection_Native(ulong entityID, out Vec3 result, ref Vec3 direction); + + [MethodImpl(MethodImplOptions.InternalCall)] + public static extern void GetRotation_Native(ulong entityID, out Vec3 rotation); + + [MethodImpl(MethodImplOptions.InternalCall)] + public static extern void SetRotation_Native(ulong entityID, ref Vec3 rotation); + } @@ -163,6 +214,12 @@ namespace Prism SetLinearVelocity_Native(Entity.ID, ref velocity); } + public void Rotate(Vec3 rotation) + { + Rotate_Native(Entity.ID, ref rotation); + } + + // TODO: Add SetMaxLinearVelocity() as well [MethodImpl(MethodImplOptions.InternalCall)] @@ -174,5 +231,8 @@ namespace Prism internal static extern void GetLinearVelocity_Native(ulong entityID, out Vec3 velocity); [MethodImpl(MethodImplOptions.InternalCall)] internal static extern void SetLinearVelocity_Native(ulong entityID, ref Vec3 velocity); + + [MethodImpl(MethodImplOptions.InternalCall)] + internal static extern void Rotate_Native(ulong entityID, ref Vec3 rotation); } } diff --git a/Prism/src/Prism/Core/Core.h b/Prism/src/Prism/Core/Core.h index 493c028..6625b0c 100644 --- a/Prism/src/Prism/Core/Core.h +++ b/Prism/src/Prism/Core/Core.h @@ -56,6 +56,11 @@ namespace Prism #define PM_CORE_ASSERT(x, ...) #endif + +#ifndef M_PI +#define M_PI 3.1415926f +#endif + namespace Prism { using byte = unsigned char; diff --git a/Prism/src/Prism/Core/Input.h b/Prism/src/Prism/Core/Input.h index 0d9be3d..b95acc5 100644 --- a/Prism/src/Prism/Core/Input.h +++ b/Prism/src/Prism/Core/Input.h @@ -9,6 +9,13 @@ namespace Prism { + enum class CursorMode + { + Normal = 0, + Hidden = 1, + Locked = 2 + }; + class PRISM_API Input { public: @@ -18,6 +25,9 @@ namespace Prism static float GetMouseX(); static float GetMouseY(); static std::pair GetMousePosition(); + + static void SetCursorMode(CursorMode mode); + static CursorMode GetCursorMode(); }; } diff --git a/Prism/src/Prism/Editor/EditorCamera.cpp b/Prism/src/Prism/Editor/EditorCamera.cpp index cceb4db..ef9537c 100644 --- a/Prism/src/Prism/Editor/EditorCamera.cpp +++ b/Prism/src/Prism/Editor/EditorCamera.cpp @@ -14,9 +14,6 @@ #include "Prism/Core/Input.h" #include "Prism/Core/Events/MouseEvent.h" -#ifndef M_PI -#define M_PI 3.1415926f -#endif namespace Prism { diff --git a/Prism/src/Prism/Editor/SceneHierachyPanel.cpp b/Prism/src/Prism/Editor/SceneHierachyPanel.cpp index b5d2a40..d75f493 100644 --- a/Prism/src/Prism/Editor/SceneHierachyPanel.cpp +++ b/Prism/src/Prism/Editor/SceneHierachyPanel.cpp @@ -7,10 +7,13 @@ #include "imgui.h" #include "assimp/matrix4x4.h" #define GLM_ENABLE_EXPERIMENTAL +#include "imgui_internal.h" #include "assimp/scene.h" #include "glm/gtx/matrix_decompose.hpp" #include "glm/gtx/quaternion.hpp" #include "Prism/Core/Application.h" +#include "Prism/Physics/PxPhysicsWrappers.h" +#include "Prism/Renderer/Meshfactory.h" #include "Prism/Script/ScriptEngine.h" namespace Prism @@ -42,6 +45,19 @@ namespace Prism m_SelectionContext = entity; } + template + void SceneHierarchyPanel::AddComponentPopup(const char* componentName) + { + if (!m_SelectionContext.HasComponent()) + { + if (ImGui::Button(componentName)) + { + m_SelectionContext.AddComponent(); + ImGui::CloseCurrentPopup(); + } + } + } + void SceneHierarchyPanel::OnImGuiRender() { ImGui::Begin("Scene Hierarchy"); @@ -79,6 +95,21 @@ namespace Prism if (ImGui::BeginPopup("AddComponentPanel")) { + AddComponentPopup("Camera"); + AddComponentPopup("Mesh"); + AddComponentPopup("Script"); + AddComponentPopup("SpriteRenderer"); + AddComponentPopup("RigidBody2D"); + AddComponentPopup("BoxCollider2D"); + AddComponentPopup("CircleCollider2D"); + AddComponentPopup("RigidBody"); + AddComponentPopup("PhysicsMaterial"); + AddComponentPopup("BoxCollider"); + AddComponentPopup("SphereCollider"); + AddComponentPopup("CapsuleCollider"); + AddComponentPopup("MeshCollider"); + + /* if (!m_SelectionContext.HasComponent()) { if (ImGui::Button("Camera")) @@ -168,6 +199,15 @@ namespace Prism } } + if (!m_SelectionContext.HasComponent()) + { + if (ImGui::Button("Capsule Collider")) + { + m_SelectionContext.AddComponent(); + ImGui::CloseCurrentPopup(); + } + } + if (!m_SelectionContext.HasComponent()) { if (ImGui::Button("Mesh Collider")) @@ -176,6 +216,7 @@ namespace Prism ImGui::CloseCurrentPopup(); } } + */ ImGui::EndPopup(); } @@ -334,6 +375,7 @@ namespace Prism { PushID(); ImGui::Columns(2); + ImGui::SetColumnWidth(0, 100); } static bool Property(const char* label, std::string& value, bool error = false) @@ -434,7 +476,7 @@ namespace Prism return modified; } - static bool Property(const char* label, float& value, float delta = 0.1f) + static bool Property(const char* label, float& value, float delta = 0.1f, float min = 0.0f, float max = 0.0f) { bool modified = false; @@ -448,7 +490,7 @@ namespace Prism // itoa(s_Counter++, s_IDBuffer + 2, 16); snprintf(s_IDBuffer + 2, 14, "%x", s_Counter++); - if (ImGui::DragFloat(s_IDBuffer, &value, delta)) + if (ImGui::DragFloat(s_IDBuffer, &value, delta, min, max)) modified = true; ImGui::PopItemWidth(); @@ -640,8 +682,12 @@ namespace Prism ImGui::NextColumn(); ImGui::PushItemWidth(-1); - if (ImGui::DragFloat3("##scale", glm::value_ptr(scale), 0.25f)) + if (ImGui::DragFloat3("##scale", glm::value_ptr(scale), 0.05f)) { + if (scale.x == 0) scale.x = 0.01f; + if (scale.y == 0) scale.y = 0.01f; + if (scale.z == 0) scale.z = 0.01f; + updateTransform = true; } @@ -850,13 +896,13 @@ namespace Prism DrawComponent("Rigidbody 2D", entity, [](RigidBody2DComponent& rb2dComponent) { // Rigidbody2D Type - const char* rb2dTypeStrings[] = { "Static", "Dynamic", "Kinematic" }; + const char* rb2dTypeStrings[] = { "Static", "Dynamic"}; const char* currentType = rb2dTypeStrings[(int)rb2dComponent.BodyType]; if (ImGui::BeginCombo("Type", currentType)) { - for (int type = 0; type < 3; type++) + for (int type = 0; type < 2; type++) { - bool is_selected = (currentType == rb2dTypeStrings[type]); + const bool is_selected = (currentType == rb2dTypeStrings[type]); if (ImGui::Selectable(rb2dTypeStrings[type], is_selected)) { currentType = rb2dTypeStrings[type]; @@ -903,11 +949,11 @@ namespace Prism DrawComponent("Rigidbody", entity, [](RigidBodyComponent& rbc) { // Rigidbody Type - const char* rbTypeStrings[] = { "Static", "Dynamic", "Kinematic" }; + const char* rbTypeStrings[] = { "Static", "Dynamic"}; const char* currentType = rbTypeStrings[(int)rbc.BodyType]; if (ImGui::BeginCombo("Type", currentType)) { - for (int type = 0; type < 3; type++) + for (int type = 0; type < 2; type++) { bool is_selected = (currentType == rbTypeStrings[type]); if (ImGui::Selectable(rbTypeStrings[type], is_selected)) @@ -925,20 +971,23 @@ namespace Prism { BeginPropertyGrid(); Property("Mass", rbc.Mass); + Property("Is Kinematic", rbc.IsKinematic); + EndPropertyGrid(); if (ImGui::TreeNode("RigidBodyConstraints", "Constraints")) { + BeginPropertyGrid(); Property("Position: X", rbc.LockPositionX); Property("Position: Y", rbc.LockPositionY); Property("Position: Z", rbc.LockPositionZ); Property("Rotation: X", rbc.LockRotationX); Property("Rotation: Y", rbc.LockRotationY); Property("Rotation: Z", rbc.LockRotationZ); + EndPropertyGrid(); ImGui::TreePop(); } - EndPropertyGrid(); } }); @@ -946,9 +995,9 @@ namespace Prism { BeginPropertyGrid(); - Property("Static Friction", pmc.StaticFriction); - Property("Dynamic Friction", pmc.DynamicFriction); - Property("Bounciness", pmc.Bounciness); + Property("Static Friction", pmc.StaticFriction, 0.01f, 0.0f, 1.0f); + Property("Dynamic Friction", pmc.DynamicFriction, 0.01f, 0.0f, 1.0f); + Property("Bounciness", pmc.Bounciness, 0.01f, 0.0f, 1.0f); EndPropertyGrid(); }); @@ -957,8 +1006,12 @@ namespace Prism { BeginPropertyGrid(); - Property("Size", bcc.Size); - //Property("Offset", bcc.Offset); + if (Property("Size", bcc.Size)) + { + bcc.DebugMesh = MeshFactory::CreateBox(bcc.Size); + } + + Property("IsTrigger", bcc.IsTrigger); EndPropertyGrid(); }); @@ -967,22 +1020,47 @@ namespace Prism { BeginPropertyGrid(); - Property("Radius", scc.Radius); + if (Property("Radius", scc.Radius)) + { + scc.DebugMesh = MeshFactory::CreateSphere(scc.Radius); + } + + Property("IsTrigger", scc.IsTrigger); EndPropertyGrid(); }); - DrawComponent("Mesh Collider", entity, [](MeshColliderComponent& mc) + DrawComponent("Capsule Collider", entity, [](CapsuleColliderComponent& ccc) + { + BeginPropertyGrid(); + + bool changed = false; + + if (Property("Radius", ccc.Radius)) changed = true; + if (Property("Height", ccc.Height)) changed = true; + + Property("Is Trigger", ccc.IsTrigger); + + if (changed) + { + ccc.DebugMesh = MeshFactory::CreateCapsule(ccc.Radius, ccc.Height); + } + + EndPropertyGrid(); + }); + + + DrawComponent("Mesh Collider", entity, [](MeshColliderComponent& mcc) { ImGui::Columns(3); ImGui::SetColumnWidth(0, 100); - ImGui::SetColumnWidth(1, 300); + ImGui::SetColumnWidth(1, 250); ImGui::SetColumnWidth(2, 40); ImGui::Text("File Path"); ImGui::NextColumn(); ImGui::PushItemWidth(-1); - if (mc.CollisionMesh) - ImGui::InputText("##meshfilepath", (char*)mc.CollisionMesh->GetFilePath().c_str(), 256, ImGuiInputTextFlags_ReadOnly); + if (mcc.CollisionMesh) + ImGui::InputText("##meshfilepath", (char*)mcc.CollisionMesh->GetFilePath().c_str(), 256, ImGuiInputTextFlags_ReadOnly); else ImGui::InputText("##meshfilepath", (char*)"Null", 256, ImGuiInputTextFlags_ReadOnly); ImGui::PopItemWidth(); @@ -991,8 +1069,16 @@ namespace Prism { std::string file = Application::Get().OpenFile(); if (!file.empty()) - mc.CollisionMesh = Ref::Create(file); + { + mcc.CollisionMesh = Ref::Create(file); + PxPhysicsWrappers::CreateConvexMesh(mcc); + } } + ImGui::EndColumns(); + + BeginPropertyGrid(); + Property("Is Trigger", mcc.IsTrigger); + EndPropertyGrid(); }); } diff --git a/Prism/src/Prism/Editor/SceneHierachyPanel.h b/Prism/src/Prism/Editor/SceneHierachyPanel.h index 3ac9ca9..4ab6f6d 100644 --- a/Prism/src/Prism/Editor/SceneHierachyPanel.h +++ b/Prism/src/Prism/Editor/SceneHierachyPanel.h @@ -27,6 +27,9 @@ namespace Prism void DrawMeshNode(const Ref& mesh, uint32_t& imguiMeshID); void DrawComponents(Entity entity); void MeshNodeHierarchy(const Ref& mesh, aiNode* node, const glm::mat4& parentTransform = glm::mat4(1.0f), uint32_t level = 0); + + template + void AddComponentPopup(const char* componentName); private: Ref m_Context; Entity m_SelectionContext; diff --git a/Prism/src/Prism/Physics/Physics3D.cpp b/Prism/src/Prism/Physics/Physics3D.cpp index 63d3f46..c577d18 100644 --- a/Prism/src/Prism/Physics/Physics3D.cpp +++ b/Prism/src/Prism/Physics/Physics3D.cpp @@ -6,198 +6,170 @@ #define GLM_ENABLE_EXPERIMENTAL #include -#include -#include -#include +#include "glm/gtx/matrix_decompose.hpp" +#include "Prism/Scene/Entity.h" + +#define PX_PHYSX_STATIC_LIB +#include + +#include "PxPhysicsWrappers.h" + namespace Prism { - // TODO: Kinematic Actors - // TODO: Rotation/Position Locking - // TODO: Collision "layers" - // TODO: Expose more of the API to scripts - // TODO: Connect/Disconnect PVD - // TODO: Collider Shape Rendering - // TODO: Relative Transformations for scripts + static physx::PxScene* s_Scene = nullptr; + static std::vector s_SimulatedEntities; + static Entity* s_EntityStorageBuffer = nullptr; + static int s_EntityStorageBufferPosition = 0; - static physx::PxSimulationFilterShader s_DefaultFilterShader = physx::PxDefaultSimulationFilterShader; - - static std::tuple GetTransformDecomposition(const glm::mat4& transform) - { - glm::vec3 scale, translation, skew; - glm::vec4 perspective; - glm::quat orientation; - glm::decompose(transform, scale, orientation, translation, skew, perspective); - - return { translation, orientation, scale }; - } - - static 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)) - { - pairFlags = physx::PxPairFlag::eTRIGGER_DEFAULT; - return physx::PxFilterFlag::eDEFAULT; - } - - pairFlags = physx::PxPairFlag::eCONTACT_DEFAULT; - - if ((filterData0.word0 & filterData1.word1) || (filterData1.word0 & filterData0.word1)) - { - pairFlags |= physx::PxPairFlag::eNOTIFY_TOUCH_FOUND; - pairFlags |= physx::PxPairFlag::eNOTIFY_TOUCH_LOST; - } - - return physx::PxFilterFlag::eDEFAULT; - } - - - void Physics3D::Init() - { - PM_CORE_ASSERT(!s_PXFoundation, "PhysXManager::Init shouldn't be called more than once!"); - - s_PXFoundation = PxCreateFoundation(PX_PHYSICS_VERSION, s_PXAllocator, s_PXErrorCallback); - PM_CORE_ASSERT(s_PXFoundation, "PxCreateFoundation Failed!"); - - PM_CORE_INFO("Try to connect PVD..."); - s_PXPvd = PxCreatePvd(*s_PXFoundation); - physx::PxPvdTransport* transport = physx::PxDefaultPvdSocketTransportCreate("localhost", 5425, 100000000); - const bool isConnect = s_PXPvd->connect(*transport, physx::PxPvdInstrumentationFlag::eALL); - if (isConnect) - { - PM_CORE_INFO("PVD connect success"); - }else - { - PM_CORE_ERROR("PVD connect failed"); - } - - s_PXPhysicsFactory = PxCreatePhysics(PX_PHYSICS_VERSION, *s_PXFoundation, physx::PxTolerancesScale(), true, isConnect ? s_PXPvd : nullptr); - PM_CORE_ASSERT(s_PXPhysicsFactory, "PxCreatePhysics Failed!"); - } - - void Physics3D::Shutdown() - { - s_PXPhysicsFactory->release(); - s_PXFoundation->release(); - } - - physx::PxSceneDesc Physics3D::CreateSceneDesc() - { - physx::PxSceneDesc sceneDesc(s_PXPhysicsFactory->getTolerancesScale()); - if (!sceneDesc.cpuDispatcher) - { - physx::PxDefaultCpuDispatcher* mCpuDispatcher = physx::PxDefaultCpuDispatcherCreate(4); - PM_CORE_ASSERT(mCpuDispatcher); - sceneDesc.cpuDispatcher = mCpuDispatcher; - } - - if (!sceneDesc.filterShader) - sceneDesc.filterShader = PrismFilterShader; - - return sceneDesc; - } - - physx::PxScene* Physics3D::CreateScene(const physx::PxSceneDesc& sceneDesc) - { - return s_PXPhysicsFactory->createScene(sceneDesc); - } - - physx::PxRigidActor* Physics3D::CreateAndAddActor(physx::PxScene* scene, const RigidBodyComponent& rigidbody, const glm::mat4& transform) + static std::tuple GetTransformDecomposition(const glm::mat4& transform) { - physx::PxRigidActor* actor = nullptr; + glm::vec3 scale, translation, skew; + glm::vec4 perspective; + glm::quat orientation; + glm::decompose(transform, scale, orientation, translation, skew, perspective); + return { translation, orientation, scale }; + } + + void Physics3D::Init() + { + PxPhysicsWrappers::Initialize(); + } + + void Physics3D::Shutdown() + { + PxPhysicsWrappers::Shutdown(); + } + + void Physics3D::CreateScene(const SceneParams& params) + { + PM_CORE_ASSERT(s_Scene == nullptr, "Scene already has a Physics Scene!"); + s_Scene = PxPhysicsWrappers::CreateScene(params); + } + + void Physics3D::CreateActor(Entity e, int entityCount) + { + if (!e.HasComponent()) + { + PM_CORE_WARN("Trying to create PhysX actor from a non-rigidbody actor!"); + return; + } + + if (!e.HasComponent()) + { + PM_CORE_WARN("Trying to create PhysX actor without a PhysicsMaterialComponent!"); + return; + } + + RigidBodyComponent& rigidbody = e.GetComponent(); + + if (s_EntityStorageBuffer == nullptr) + s_EntityStorageBuffer = new Entity[entityCount]; + + // Create Actor Body + physx::PxRigidActor* actor = PxPhysicsWrappers::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()); + + auto [translation, rotationQuat, scale] = GetTransformDecomposition(e.Transform()); + + // Add all colliders + if (e.HasComponent()) + { + const BoxColliderComponent& collider = e.GetComponent(); + PxPhysicsWrappers::AddBoxCollider(*actor, *material, collider, scale); + } + + if (e.HasComponent()) + { + const SphereColliderComponent& collider = e.GetComponent(); + PxPhysicsWrappers::AddSphereCollider(*actor, *material, collider, scale); + } + + if (e.HasComponent()) + { + const CapsuleColliderComponent& collider = e.GetComponent(); + PxPhysicsWrappers::AddCapsuleCollider(*actor, *material, collider, scale); + } + + if (e.HasComponent()) + { + MeshColliderComponent& collider = e.GetComponent(); + PxPhysicsWrappers::AddMeshCollider(*actor, *material, collider, scale); + } + + // Set collision filters if (rigidbody.BodyType == RigidBodyComponent::Type::Static) { - actor = s_PXPhysicsFactory->createRigidStatic(CreatePose(transform)); + PxPhysicsWrappers::SetCollisionFilters(*actor, (uint32_t)FilterGroup::Static, (uint32_t)FilterGroup::All); } else if (rigidbody.BodyType == RigidBodyComponent::Type::Dynamic) { - physx::PxRigidDynamic* dynamicActor = s_PXPhysicsFactory->createRigidDynamic(CreatePose(transform)); - physx::PxRigidBodyExt::updateMassAndInertia(*dynamicActor, rigidbody.Mass); - - dynamicActor->setRigidDynamicLockFlag(physx::PxRigidDynamicLockFlag::eLOCK_LINEAR_X, rigidbody.LockPositionX); - dynamicActor->setRigidDynamicLockFlag(physx::PxRigidDynamicLockFlag::eLOCK_LINEAR_Y, rigidbody.LockPositionY); - dynamicActor->setRigidDynamicLockFlag(physx::PxRigidDynamicLockFlag::eLOCK_LINEAR_Z, rigidbody.LockPositionZ); - dynamicActor->setRigidDynamicLockFlag(physx::PxRigidDynamicLockFlag::eLOCK_ANGULAR_X, rigidbody.LockRotationX); - dynamicActor->setRigidDynamicLockFlag(physx::PxRigidDynamicLockFlag::eLOCK_ANGULAR_Y, rigidbody.LockRotationY); - dynamicActor->setRigidDynamicLockFlag(physx::PxRigidDynamicLockFlag::eLOCK_ANGULAR_Z, rigidbody.LockRotationZ); - - actor = dynamicActor; + PxPhysicsWrappers::SetCollisionFilters(*actor, (uint32_t)FilterGroup::Dynamic, (uint32_t)FilterGroup::All); } - actor->setActorFlag(physx::PxActorFlag::eVISUALIZATION, true); - - scene->addActor(*actor); - - return actor; + s_Scene->addActor(*actor); } - physx::PxMaterial* Physics3D::CreateMaterial(float staticFriction, float dynamicFriction, float restitution) + void Physics3D::Simulate(TimeStep ts) { - return s_PXPhysicsFactory->createMaterial(staticFriction, dynamicFriction, restitution); - } + s_Scene->simulate(ts); + s_Scene->fetchResults(true); - physx::PxConvexMesh* Physics3D::CreateMeshCollider(const Ref& mesh) - { - const auto& vertices = mesh->GetStaticVertices(); - const auto& indices = mesh->GetIndices(); - const physx::PxCookingParams cookingParams(s_PXPhysicsFactory->getTolerancesScale()); - - physx::PxConvexMeshDesc convexDesc; - convexDesc.points.count = (physx::PxU32)vertices.size(); - convexDesc.points.stride = sizeof(Vertex); - convexDesc.points.data = vertices.data(); - convexDesc.flags = physx::PxConvexFlag::eCOMPUTE_CONVEX; - - const physx::PxDefaultMemoryOutputStream buf; - physx::PxConvexMeshCookingResult::Enum result; - - physx::PxConvexMesh* convexMesh = PxCreateConvexMesh( - cookingParams, // 第一步准备的烹饪参数 - convexDesc, // 第二步准备的网格描述 - *PxGetStandaloneInsertionCallback(), // 便捷的回调函数,用于将资源插入物理SDK - &result // [可选] 获取烹饪结果详情 - ); - if (!convexMesh) { - PM_CORE_ERROR("Failed to create convex mesh. Cooking result code: {}", static_cast(result)); - return nullptr; - } - - return convexMesh; - } - - physx::PxTransform Physics3D::CreatePose(const glm::mat4& transform) - { - auto [translation, rotationQuat, scale] = GetTransformDecomposition(transform); - const glm::vec3 rotation = glm::eulerAngles(rotationQuat); - - physx::PxTransform physxTransform(physx::PxVec3(translation.x, translation.y, translation.z)); - physxTransform.rotate(physx::PxVec3(rotation.x, rotation.y, rotation.z)); - return physxTransform; - } - - void Physics3D::SetCollisionFilters(physx::PxRigidActor* actor, uint32_t filterGroup, uint32_t filterMask) - { - physx::PxFilterData filterData; - filterData.word0 = filterGroup; // word0 = own ID - filterData.word1 = filterMask; // word1 = ID mask to filter pairs that trigger a - // contact callback; - const physx::PxU32 numShapes = actor->getNbShapes(); - physx::PxShape** shapes = (physx::PxShape**)s_PXAllocator.allocate(sizeof(physx::PxShape*) * numShapes, "", "", 0); - actor->getShapes(shapes, numShapes); - for (physx::PxU32 i = 0; i < numShapes; i++) + for (Entity& e : s_SimulatedEntities) { - physx::PxShape* shape = shapes[i]; - shape->setFlag(physx::PxShapeFlag::eVISUALIZATION, true); - shape->setSimulationFilterData(filterData); - } + auto& transform = e.Transform(); + // TODO: Come up with a better solution for scale + auto [p, r, scale] = GetTransformDecomposition(transform); + const auto& rb = e.GetComponent(); + const auto actor = static_cast(rb.RuntimeActor); - s_PXAllocator.deallocate(shapes); + if (rb.BodyType == RigidBodyComponent::Type::Dynamic) + { + transform = FromPhysXTransform(actor->getGlobalPose()) * glm::scale(glm::mat4(1.0f), scale); + } + else if (rb.BodyType == RigidBodyComponent::Type::Static) + { + actor->setGlobalPose(ToPhysXTransform(transform)); + } + } } - physx::PxDefaultErrorCallback Physics3D::s_PXErrorCallback; - physx::PxDefaultAllocator Physics3D::s_PXAllocator; - physx::PxFoundation* Physics3D::s_PXFoundation; - physx::PxPhysics* Physics3D::s_PXPhysicsFactory; - physx::PxPvd* Physics3D::s_PXPvd; -} \ No newline at end of file + void Physics3D::DestroyScene() + { + delete[] s_EntityStorageBuffer; + s_EntityStorageBuffer = nullptr; + s_EntityStorageBufferPosition = 0; + + s_SimulatedEntities.clear(); + s_Scene->release(); + s_Scene = nullptr; + } + + bool Physics3D::ConnectPVD() + { + PM_CORE_INFO("Trying to connect PVD"); + const bool isconnect = PxPhysicsWrappers::ConnectPVD(); + if (isconnect) + PM_CORE_INFO("PVD Connected"); + else + PM_CORE_WARN("canot connect PVD!"); + return isconnect; + } + + bool Physics3D::IsPVDConnected() {return PxPhysicsWrappers::IsPVDConnected();} + + void Physics3D::DisconnectPVD() + { + PxPhysicsWrappers::DisconnectPVD(); + } + + +} diff --git a/Prism/src/Prism/Physics/Physics3D.h b/Prism/src/Prism/Physics/Physics3D.h index 59deea3..c8477a2 100644 --- a/Prism/src/Prism/Physics/Physics3D.h +++ b/Prism/src/Prism/Physics/Physics3D.h @@ -4,10 +4,10 @@ #ifndef PHYSXMANAGER_H #define PHYSXMANAGER_H -#define PX_PHYSX_STATIC_LIB -#include #include "glm/glm.hpp" #include "Prism/Scene/Components.h" +#include "Prism/Scene/Entity.h" + namespace Prism { @@ -21,10 +21,15 @@ namespace Prism enum class FilterGroup : uint32_t { - Static = BIT(0), - Dynamic = BIT(1), + Static = BIT(0), + Dynamic = BIT(1), Kinematic = BIT(2), - All = Static | Dynamic | Kinematic + All = Static | Dynamic | Kinematic + }; + + struct SceneParams + { + glm::vec3 Gravity = { 0.0F, -9.81F, 0.0F }; }; class PRISM_API Physics3D @@ -33,22 +38,16 @@ namespace Prism static void Init(); static void Shutdown(); - static physx::PxSceneDesc CreateSceneDesc(); - static physx::PxScene* CreateScene(const physx::PxSceneDesc& sceneDesc); - static physx::PxRigidActor* CreateAndAddActor(physx::PxScene* scene, const RigidBodyComponent& rigidbody, const glm::mat4& transform); - static physx::PxMaterial* CreateMaterial(float staticFriction, float dynamicFriction, float restitution); - static physx::PxConvexMesh* CreateMeshCollider(const Ref& mesh); + static void CreateScene(const SceneParams& params); + static void CreateActor(Entity e, int entityCount); - static physx::PxTransform CreatePose(const glm::mat4& transform); + static void Simulate(TimeStep ts); - static void SetCollisionFilters(physx::PxRigidActor* actor, uint32_t filterGroup, uint32_t filterMask); + static void DestroyScene(); - // private: - static physx::PxDefaultErrorCallback s_PXErrorCallback; - static physx::PxDefaultAllocator s_PXAllocator; - static physx::PxFoundation* s_PXFoundation; - static physx::PxPhysics* s_PXPhysicsFactory; - static physx::PxPvd* s_PXPvd; + static bool ConnectPVD(); + static bool IsPVDConnected(); + static void DisconnectPVD(); }; } diff --git a/Prism/src/Prism/Physics/PhysicsUtils.cpp b/Prism/src/Prism/Physics/PhysicsUtils.cpp new file mode 100644 index 0000000..673c59b --- /dev/null +++ b/Prism/src/Prism/Physics/PhysicsUtils.cpp @@ -0,0 +1,149 @@ +// +// Created by sfd on 25-12-20. +// + +#include "PhysicsUtils.h" + +#define GLM_ENABLE_EXPERIMENTAL +#include "glm/gtx/quaternion.hpp" +#include "Prism/Script/ScriptEngine.h" + + +namespace Prism +{ + physx::PxTransform ToPhysXTransform(const glm::mat4& matrix) + { + const physx::PxQuat r = ToPhysXQuat(glm::normalize(glm::toQuat(matrix))); + const physx::PxVec3 p = ToPhysXVector(glm::vec3(matrix[3])); + return physx::PxTransform{p, r}; + } + + physx::PxMat44 ToPhysXMatrix(const glm::mat4& matrix) + { + return *(physx::PxMat44*)&matrix; + } + + physx::PxVec3 ToPhysXVector(const glm::vec3& vector) + { + return {vector.x, vector.y, vector.z}; + } + + physx::PxVec4 ToPhysXVector(const glm::vec4& vector) + { + return {vector.x, vector.y, vector.z, vector.w}; + } + + physx::PxQuat ToPhysXQuat(const glm::quat& quat) + { + return {quat.x, quat.y, quat.z, quat.w}; + } + + glm::mat4 FromPhysXTransform(const physx::PxTransform& transform) + { + glm::quat rotation = FromPhysXQuat(transform.q); + glm::vec3 position = FromPhysXVector(transform.p); + return glm::translate(glm::mat4(1.0F), position) * glm::toMat4(rotation); + } + + glm::mat4 FromPhysXMatrix(const physx::PxMat44& matrix) + { + return *(glm::mat4*)&matrix; + } + + glm::vec3 FromPhysXVector(const physx::PxVec3& vector) + { + return {vector.x, vector.y, vector.z}; + } + + glm::vec4 FromPhysXVector(const physx::PxVec4& vector) + { + return {vector.x, vector.y, vector.z, vector.w}; + } + + glm::quat FromPhysXQuat(const physx::PxQuat& quat) + { + return {quat.w, quat.x, quat.y, quat.z}; + } + + physx::PxFilterFlags HazelFilterShader(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)) + { + pairFlags = physx::PxPairFlag::eTRIGGER_DEFAULT; + return physx::PxFilterFlag::eDEFAULT; + } + + pairFlags = physx::PxPairFlag::eCONTACT_DEFAULT; + + if ((filterData0.word0 & filterData1.word1) || (filterData1.word0 & filterData0.word1)) + { + pairFlags |= physx::PxPairFlag::eNOTIFY_TOUCH_FOUND; + pairFlags |= physx::PxPairFlag::eNOTIFY_TOUCH_LOST; + } + + return physx::PxFilterFlag::eDEFAULT; + } + + void ContactListener::onConstraintBreak(physx::PxConstraintInfo* constraints, physx::PxU32 count) + { + PX_UNUSED(constraints); + PX_UNUSED(count); + } + + void ContactListener::onWake(physx::PxActor** actors, physx::PxU32 count) + { + PX_UNUSED(actors); + PX_UNUSED(count); + } + + void ContactListener::onSleep(physx::PxActor** actors, physx::PxU32 count) + { + PX_UNUSED(actors); + PX_UNUSED(count); + } + + void ContactListener::onContact(const physx::PxContactPairHeader& pairHeader, const physx::PxContactPair* pairs, physx::PxU32 nbPairs) + { + const Entity& a = *static_cast(pairHeader.actors[0]->userData); + const Entity& b = *static_cast(pairHeader.actors[1]->userData); + + if (pairs->flags == physx::PxContactPairFlag::eACTOR_PAIR_HAS_FIRST_TOUCH) + { + if (ScriptEngine::IsEntityModuleValid(a)) ScriptEngine::OnCollisionBegin(a); + if (ScriptEngine::IsEntityModuleValid(b)) ScriptEngine::OnCollisionBegin(b); + } + else if (pairs->flags == physx::PxContactPairFlag::eACTOR_PAIR_LOST_TOUCH) + { + if (ScriptEngine::IsEntityModuleValid(a)) ScriptEngine::OnCollisionEnd(a); + if (ScriptEngine::IsEntityModuleValid(b)) ScriptEngine::OnCollisionEnd(b); + } + } + + void ContactListener::onTrigger(physx::PxTriggerPair* pairs, physx::PxU32 count) + { + + const Entity& a = *static_cast(pairs->triggerActor->userData); + const Entity& b = *static_cast(pairs->otherActor->userData); + + if (pairs->status == physx::PxPairFlag::eNOTIFY_TOUCH_FOUND) + { + if (ScriptEngine::IsEntityModuleValid(a)) ScriptEngine::OnTriggerBegin(a); + if (ScriptEngine::IsEntityModuleValid(b)) ScriptEngine::OnTriggerBegin(b); + } + else if (pairs->status == physx::PxPairFlag::eNOTIFY_TOUCH_LOST) + { + if (ScriptEngine::IsEntityModuleValid(a)) ScriptEngine::OnTriggerEnd(a); + if (ScriptEngine::IsEntityModuleValid(b)) ScriptEngine::OnTriggerEnd(b); + } + + PX_UNUSED(count); + } + + void ContactListener::onAdvance(const physx::PxRigidBody* const* bodyBuffer, const physx::PxTransform* poseBuffer, const physx::PxU32 count) + { + PX_UNUSED(bodyBuffer); + PX_UNUSED(poseBuffer); + PX_UNUSED(count); + } + +} diff --git a/Prism/src/Prism/Physics/PhysicsUtils.h b/Prism/src/Prism/Physics/PhysicsUtils.h new file mode 100644 index 0000000..192a3b4 --- /dev/null +++ b/Prism/src/Prism/Physics/PhysicsUtils.h @@ -0,0 +1,46 @@ +// +// Created by sfd on 25-12-20. +// + +#ifndef PHYSICSUTILS_H +#define PHYSICSUTILS_H + +#define PX_PHYSX_STATIC_LIB +#include + +#include "glm/glm.hpp" + +namespace Prism +{ + + physx::PxTransform ToPhysXTransform(const glm::mat4& matrix); + physx::PxMat44 ToPhysXMatrix(const glm::mat4& matrix); + physx::PxVec3 ToPhysXVector(const glm::vec3& vector); + physx::PxVec4 ToPhysXVector(const glm::vec4& vector); + physx::PxQuat ToPhysXQuat(const glm::quat& quat); + + glm::mat4 FromPhysXTransform(const physx::PxTransform& transform); + glm::mat4 FromPhysXMatrix(const physx::PxMat44& matrix); + glm::vec3 FromPhysXVector(const physx::PxVec3& vector); + 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::PxFilterData filterData1, physx::PxPairFlags& pairFlags, const void* constantBlock, physx::PxU32 constantBlockSize); + + class ContactListener final : public physx::PxSimulationEventCallback + { + public: + virtual void onConstraintBreak(physx::PxConstraintInfo* constraints, physx::PxU32 count) override; + virtual void onWake(physx::PxActor** actors, physx::PxU32 count) override; + virtual void onSleep(physx::PxActor** actors, physx::PxU32 count) override; + virtual void onContact(const physx::PxContactPairHeader& pairHeader, const physx::PxContactPair* pairs, physx::PxU32 nbPairs) override; + virtual void onTrigger(physx::PxTriggerPair* pairs, physx::PxU32 count) override; + virtual void onAdvance(const physx::PxRigidBody* const* bodyBuffer, const physx::PxTransform* poseBuffer, physx::PxU32 count) override; + }; + + +} + + +#endif //PHYSICSUTILS_H diff --git a/Prism/src/Prism/Physics/PxPhysicsWrappers.cpp b/Prism/src/Prism/Physics/PxPhysicsWrappers.cpp new file mode 100644 index 0000000..7b5f83f --- /dev/null +++ b/Prism/src/Prism/Physics/PxPhysicsWrappers.cpp @@ -0,0 +1,282 @@ +// +// Created by sfd on 25-12-20. +// + +#include "PxPhysicsWrappers.h" +#include "Physics3D.h" +#include + +#define GLM_ENABLE_EXPERIMENTAL +#include + +#define PHYSX_DEBUGGER 1 + +namespace Prism +{ + static physx::PxDefaultErrorCallback s_ErrorCallback; + static physx::PxDefaultAllocator s_Allocator; + static physx::PxFoundation* s_Foundation; + static physx::PxPhysics* s_Physics; + static physx::PxPvd* s_VisualDebugger; + + static physx::PxSimulationFilterShader s_FilterShader = physx::PxDefaultSimulationFilterShader; + + static ContactListener s_ContactListener; + + physx::PxScene* PxPhysicsWrappers::CreateScene(const SceneParams& sceneParams) + { + physx::PxSceneDesc sceneDesc(s_Physics->getTolerancesScale()); + + sceneDesc.gravity = ToPhysXVector(sceneParams.Gravity); + sceneDesc.cpuDispatcher = physx::PxDefaultCpuDispatcherCreate(1); + sceneDesc.filterShader = HazelFilterShader; + sceneDesc.simulationEventCallback = &s_ContactListener; + + PM_CORE_ASSERT(sceneDesc.isValid()); + return s_Physics->createScene(sceneDesc); + } + + physx::PxRigidActor* PxPhysicsWrappers::CreateActor(const RigidBodyComponent& rigidbody, const glm::mat4& transform) + { + physx::PxRigidActor* actor = nullptr; + + if (rigidbody.BodyType == RigidBodyComponent::Type::Static) + { + actor = s_Physics->createRigidStatic(ToPhysXTransform(transform)); + } + else if (rigidbody.BodyType == RigidBodyComponent::Type::Dynamic) + { + physx::PxRigidDynamic* dynamicActor = s_Physics->createRigidDynamic(ToPhysXTransform(transform)); + + dynamicActor->setRigidBodyFlag(physx::PxRigidBodyFlag::eKINEMATIC, rigidbody.IsKinematic); + + dynamicActor->setRigidDynamicLockFlag(physx::PxRigidDynamicLockFlag::eLOCK_LINEAR_X, rigidbody.LockPositionX); + dynamicActor->setRigidDynamicLockFlag(physx::PxRigidDynamicLockFlag::eLOCK_LINEAR_Y, rigidbody.LockPositionY); + dynamicActor->setRigidDynamicLockFlag(physx::PxRigidDynamicLockFlag::eLOCK_LINEAR_Z, rigidbody.LockPositionZ); + dynamicActor->setRigidDynamicLockFlag(physx::PxRigidDynamicLockFlag::eLOCK_ANGULAR_X, rigidbody.LockRotationX); + dynamicActor->setRigidDynamicLockFlag(physx::PxRigidDynamicLockFlag::eLOCK_ANGULAR_Y, rigidbody.LockRotationY); + dynamicActor->setRigidDynamicLockFlag(physx::PxRigidDynamicLockFlag::eLOCK_ANGULAR_Z, rigidbody.LockRotationZ); + + physx::PxRigidBodyExt::updateMassAndInertia(*dynamicActor, rigidbody.Mass); + actor = dynamicActor; + } + + return actor; + } + + void PxPhysicsWrappers::SetCollisionFilters(const physx::PxRigidActor& actor, const uint32_t actorGroup, const uint32_t filters) + { + physx::PxFilterData filterData; + filterData.word0 = actorGroup; + filterData.word1 = filters; + + const physx::PxU32 numShapes = actor.getNbShapes(); + + const auto shapes = static_cast(s_Allocator.allocate(sizeof(physx::PxShape*) * numShapes, "", "", 0)); + actor.getShapes(shapes, numShapes); + + for (physx::PxU32 i = 0; i < numShapes; i++) + shapes[i]->setSimulationFilterData(filterData); + + s_Allocator.deallocate(shapes); + } + + void PxPhysicsWrappers::AddBoxCollider(physx::PxRigidActor& actor, const physx::PxMaterial& material, const BoxColliderComponent& collider, const glm::vec3& scale) + { + glm::vec3 colliderSize = collider.Size; + + if (scale.x != 0.0f) colliderSize.x *= scale.x; + if (scale.y != 0.0f) colliderSize.y *= scale.y; + if (scale.z != 0.0f) colliderSize.z *= scale.z; + + const auto boxGeometry = physx::PxBoxGeometry(colliderSize.x / 2.0f, colliderSize.y / 2.0f, colliderSize.z / 2.0f); + + physx::PxShape* shape = physx::PxRigidActorExt::createExclusiveShape(actor, boxGeometry, material); + shape->setFlag(physx::PxShapeFlag::eSIMULATION_SHAPE, !collider.IsTrigger); + shape->setFlag(physx::PxShapeFlag::eTRIGGER_SHAPE, collider.IsTrigger); + + shape->setLocalPose(ToPhysXTransform(glm::translate(glm::mat4(1.0F), collider.Offset))); + } + + void PxPhysicsWrappers::AddSphereCollider(physx::PxRigidActor& actor, const physx::PxMaterial& material, const SphereColliderComponent& collider, const glm::vec3& scale) + { + float colliderRadius = collider.Radius; + + if (scale.x != 0.0f) colliderRadius *= scale.x; + + const auto sphereGeometry = physx::PxSphereGeometry(colliderRadius); + + physx::PxShape* shape = physx::PxRigidActorExt::createExclusiveShape(actor, sphereGeometry, material); + shape->setFlag(physx::PxShapeFlag::eSIMULATION_SHAPE, !collider.IsTrigger); + 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) + { + 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; + + + const auto capsuleGeometry = physx::PxCapsuleGeometry(colliderRadius, colliderHeight / 2.0F); + + physx::PxShape* shape = physx::PxRigidActorExt::createExclusiveShape(actor, capsuleGeometry, material); + shape->setFlag(physx::PxShapeFlag::eSIMULATION_SHAPE, !collider.IsTrigger); + shape->setFlag(physx::PxShapeFlag::eTRIGGER_SHAPE, collider.IsTrigger); + + shape->setLocalPose(physx::PxTransform(physx::PxQuat(physx::PxHalfPi, physx::PxVec3(0, 0, 1)))); + } + + + void PxPhysicsWrappers::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); + 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) + { + const auto& vertices = collider.CollisionMesh->GetStaticVertices(); + + const physx::PxCookingParams cookingParams(s_Physics->getTolerancesScale()); + + physx::PxConvexMeshDesc convexDesc; + convexDesc.points.count = static_cast(vertices.size()); + convexDesc.points.stride = sizeof(Vertex); + convexDesc.points.data = vertices.data(); + convexDesc.flags = physx::PxConvexFlag::eCOMPUTE_CONVEX; + + physx::PxDefaultMemoryOutputStream buf; + physx::PxConvexMeshCookingResult::Enum result; + physx::PxConvexMesh* mesh = PxCreateConvexMesh( + cookingParams, // 第一步准备的烹饪参数 + convexDesc, // 第二步准备的网格描述 + *PxGetStandaloneInsertionCallback(), // 便捷的回调函数,用于将资源插入物理SDK + &result // [可选] 获取烹饪结果详情 + ); + if (!collider.ProcessedMesh) + { + // Based On: https://github.com/EpicGames/UnrealEngine/blob/08ee319f80ef47dbf0988e14b546b65214838ec4/Engine/Source/ThirdParty/PhysX3/NvCloth/samples/SampleBase/renderer/ConvexRenderMesh.cpp + + const uint32_t nbPolygons = mesh->getNbPolygons(); + const physx::PxVec3* convexVertices = mesh->getVertices(); + const physx::PxU8* convexIndices = mesh->getIndexBuffer(); + + uint32_t nbVertices = 0; + uint32_t nbFaces = 0; + + for (uint32_t i = 0; i < nbPolygons; i++) + { + physx::PxHullPolygon polygon; + mesh->getPolygonData(i, polygon); + nbVertices += polygon.mNbVerts; + nbFaces += (polygon.mNbVerts - 2) * 3; + } + + std::vector collisionVertices; + std::vector collisionIndices; + + collisionVertices.resize(nbVertices); + collisionIndices.resize(nbFaces / 3); + + uint32_t vertCounter = 0; + uint32_t indexCounter = 0; + for (uint32_t i = 0; i < nbPolygons; i++) + { + physx::PxHullPolygon polygon; + mesh->getPolygonData(i, polygon); + + const uint32_t vI0 = vertCounter; + for (uint32_t vI = 0; vI < polygon.mNbVerts; vI++) + { + // collisionVertices[vertCounter].Position = FromPhysXVector(convexVertices[convexIndices[polygon.mIndexBase + vI]]); + // TODO: temp solve + // this glm::rotate need #include + collisionVertices[vertCounter].Position = glm::rotate(FromPhysXVector(convexVertices[convexIndices[polygon.mIndexBase + vI]]), glm::radians(90.0f), { 1.0f, 0.0f, 0.0f}); + vertCounter++; + } + + for (uint32_t vI = 1; vI < static_cast(polygon.mNbVerts) - 1; vI++) + { + collisionIndices[indexCounter].V1 = static_cast(vI0); + collisionIndices[indexCounter].V2 = static_cast(vI0 + vI + 1); + collisionIndices[indexCounter].V3 = static_cast(vI0 + vI); + indexCounter++; + } + } + + collider.ProcessedMesh = Ref::Create(collisionVertices, collisionIndices); + } + + return mesh; + } + + physx::PxMaterial* PxPhysicsWrappers::CreateMaterial(const PhysicsMaterialComponent& material) + { + return s_Physics->createMaterial(material.StaticFriction, material.DynamicFriction, material.Bounciness); + } + + void PxPhysicsWrappers::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 + s_VisualDebugger = PxCreatePvd(*s_Foundation); + ConnectPVD(); + #endif + + s_Physics = PxCreatePhysics(PX_PHYSICS_VERSION, *s_Foundation, physx::PxTolerancesScale(), true, s_VisualDebugger); + PM_CORE_ASSERT(s_Physics, "PxCreatePhysics Failed!"); + } + + void PxPhysicsWrappers::Shutdown() + { + s_Physics->release(); + s_Foundation->release(); + } + + bool PxPhysicsWrappers::ConnectPVD() + { + bool isConnect = false; + #if PHYSX_DEBUGGER + physx::PxPvdTransport* transport = physx::PxDefaultPvdSocketTransportCreate("localhost", 5425, 10); + if (s_VisualDebugger->isConnected()) + { + PM_CORE_WARN("PVD is already connected, reconnecting"); + s_VisualDebugger->disconnect(); + } + isConnect = s_VisualDebugger->connect(*transport, physx::PxPvdInstrumentationFlag::eALL); + #endif + return isConnect; + } + + bool PxPhysicsWrappers::IsPVDConnected() + { + return s_VisualDebugger->isConnected(); + } + + void PxPhysicsWrappers::DisconnectPVD() + { + #if PHYSX_DEBUGGER + if (s_VisualDebugger->isConnected(false)) + { + s_VisualDebugger->disconnect(); + PM_CORE_INFO("PVD is disconnected"); + } + #endif + } + +} \ No newline at end of file diff --git a/Prism/src/Prism/Physics/PxPhysicsWrappers.h b/Prism/src/Prism/Physics/PxPhysicsWrappers.h new file mode 100644 index 0000000..5c381c8 --- /dev/null +++ b/Prism/src/Prism/Physics/PxPhysicsWrappers.h @@ -0,0 +1,46 @@ +// +// Created by sfd on 25-12-20. +// + +#ifndef PXPHYSICSWRAPPERS_H +#define PXPHYSICSWRAPPERS_H + +#include "PhysicsUtils.h" +#include "Prism/Scene/Components.h" + +namespace Prism +{ + struct SceneParams; + + class PxPhysicsWrappers + { + 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 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); + + private: + static void Initialize(); + static void Shutdown(); + + static bool ConnectPVD(); + static bool IsPVDConnected(); + static void DisconnectPVD(); + + private: + friend class Physics3D; + }; +} + + +#endif //PXPHYSICSWRAPPERS_H diff --git a/Prism/src/Prism/Platform/Windows/WindowsInput.cpp b/Prism/src/Prism/Platform/Windows/WindowsInput.cpp index 072c25e..400347d 100644 --- a/Prism/src/Prism/Platform/Windows/WindowsInput.cpp +++ b/Prism/src/Prism/Platform/Windows/WindowsInput.cpp @@ -42,6 +42,20 @@ namespace Prism double xpos, ypos; glfwGetCursorPos(static_cast(window.GetNativeWindow()), &xpos, &ypos); - return {(float)xpos, (float)ypos}; + return {static_cast(xpos), static_cast(ypos)}; + } + + // TODO: A better way to do this is to handle it internally, and simply move the cursor the opposite side + // of the screen when it reaches the edge + void Input::SetCursorMode(CursorMode mode) + { + const auto& window = dynamic_cast(Application::Get().GetWindow()); + glfwSetInputMode(static_cast(window.GetNativeWindow()), GLFW_CURSOR, GLFW_CURSOR_NORMAL + static_cast(mode)); + } + + CursorMode Input::GetCursorMode() + { + const auto& window = dynamic_cast(Application::Get().GetWindow()); + return static_cast(glfwGetInputMode(static_cast(window.GetNativeWindow()), GLFW_CURSOR) - GLFW_CURSOR_NORMAL); } } diff --git a/Prism/src/Prism/Platform/Windows/WindowsWindow.cpp b/Prism/src/Prism/Platform/Windows/WindowsWindow.cpp index cc6b6e1..ab0fa83 100644 --- a/Prism/src/Prism/Platform/Windows/WindowsWindow.cpp +++ b/Prism/src/Prism/Platform/Windows/WindowsWindow.cpp @@ -43,9 +43,8 @@ namespace Prism glfwPollEvents(); glfwSwapBuffers(m_Window); - ImGuiMouseCursor imgui_cursor = ImGui::GetMouseCursor(); + const ImGuiMouseCursor imgui_cursor = ImGui::GetMouseCursor(); glfwSetCursor(m_Window, m_ImGuiMouseCursors[imgui_cursor] ? m_ImGuiMouseCursors[imgui_cursor] : m_ImGuiMouseCursors[ImGuiMouseCursor_Arrow]); - glfwSetInputMode(m_Window, GLFW_CURSOR, GLFW_CURSOR_NORMAL); } void WindowsWindow::SetVSync(bool enable) diff --git a/Prism/src/Prism/Renderer/Mesh.cpp b/Prism/src/Prism/Renderer/Mesh.cpp index 9b6512b..ca13b8c 100644 --- a/Prism/src/Prism/Renderer/Mesh.cpp +++ b/Prism/src/Prism/Renderer/Mesh.cpp @@ -507,6 +507,30 @@ namespace Prism m_Pipeline = Pipeline::Create(pipelineSpecification); } + Mesh::Mesh(const std::vector& vertices, const std::vector& indices) + : m_StaticVertices(vertices), m_Indices(indices), m_IsAnimated(false) + { + Submesh submesh; + submesh.BaseVertex = 0; + submesh.BaseIndex = 0; + submesh.IndexCount = static_cast(indices.size()) * 3; + submesh.Transform = glm::mat4(1.0F); + m_Submeshes.push_back(submesh); + + m_VertexBuffer = VertexBuffer::Create(m_StaticVertices.data(), static_cast(m_StaticVertices.size()) * sizeof(Vertex)); + m_IndexBuffer = IndexBuffer::Create(m_Indices.data(), static_cast(m_Indices.size()) * sizeof(Index)); + + PipelineSpecification pipelineSpecification; + pipelineSpecification.Layout = { + { ShaderDataType::Float3, "a_Position" }, + { ShaderDataType::Float3, "a_Normal" }, + { ShaderDataType::Float3, "a_Tangent" }, + { ShaderDataType::Float3, "a_Binormal" }, + { ShaderDataType::Float2, "a_TexCoord" }, + }; + m_Pipeline = Pipeline::Create(pipelineSpecification); + } + Mesh::~Mesh() = default; void Mesh::OnUpdate(TimeStep deltaTime) @@ -706,14 +730,14 @@ namespace Prism if (nodeAnim->mNumRotationKeys == 1) { // No interpolation necessary for single value - auto v = nodeAnim->mRotationKeys[0].mValue; - return glm::quat(v.w, v.x, v.y, v.z); + const auto v = nodeAnim->mRotationKeys[0].mValue; + return {v.w, v.x, v.y, v.z}; } - uint32_t RotationIndex = FindRotation(animationTime, nodeAnim); - uint32_t NextRotationIndex = (RotationIndex + 1); + const uint32_t RotationIndex = FindRotation(animationTime, nodeAnim); + const uint32_t NextRotationIndex = (RotationIndex + 1); PM_CORE_ASSERT(NextRotationIndex < nodeAnim->mNumRotationKeys); - float DeltaTime = (float)(nodeAnim->mRotationKeys[NextRotationIndex].mTime - nodeAnim->mRotationKeys[RotationIndex].mTime); + const float DeltaTime = (float)(nodeAnim->mRotationKeys[NextRotationIndex].mTime - nodeAnim->mRotationKeys[RotationIndex].mTime); float Factor = (animationTime - (float)nodeAnim->mRotationKeys[RotationIndex].mTime) / DeltaTime; PM_CORE_ASSERT(Factor <= 1.0f, "Factor must be below 1.0f"); Factor = glm::clamp(Factor, 0.0f, 1.0f); @@ -722,7 +746,7 @@ namespace Prism auto q = aiQuaternion(); aiQuaternion::Interpolate(q, StartRotationQ, EndRotationQ, Factor); q = q.Normalize(); - return glm::quat(q.w, q.x, q.y, q.z); + return {q.w, q.x, q.y, q.z}; } glm::vec3 Mesh::InterpolateScale(const float animationTime, const aiNodeAnim* nodeAnim) diff --git a/Prism/src/Prism/Renderer/Mesh.h b/Prism/src/Prism/Renderer/Mesh.h index d986578..697d038 100644 --- a/Prism/src/Prism/Renderer/Mesh.h +++ b/Prism/src/Prism/Renderer/Mesh.h @@ -107,6 +107,7 @@ namespace Prism Mesh(const std::string& filename); + Mesh(const std::vector& vertices, const std::vector& indices); ~Mesh(); void OnUpdate(TimeStep deltaTime); diff --git a/Prism/src/Prism/Renderer/MeshFactory.cpp b/Prism/src/Prism/Renderer/MeshFactory.cpp new file mode 100644 index 0000000..32eb0d1 --- /dev/null +++ b/Prism/src/Prism/Renderer/MeshFactory.cpp @@ -0,0 +1,172 @@ +// +// Created by sfd on 25-12-21. +// + +#include "Meshfactory.h" + +namespace Prism +{ + Ref MeshFactory::CreateBox(const glm::vec3& size) + { + std::vector vertices; + vertices.resize(8); + vertices[0].Position = { -size.x / 2.0f, -size.y / 2.0f, size.z / 2.0f }; + vertices[1].Position = { size.x / 2.0f, -size.y / 2.0f, size.z / 2.0f }; + vertices[2].Position = { size.x / 2.0f, size.y / 2.0f, size.z / 2.0f }; + vertices[3].Position = { -size.x / 2.0f, size.y / 2.0f, size.z / 2.0f }; + vertices[4].Position = { -size.x / 2.0f, -size.y / 2.0f, -size.z / 2.0f }; + vertices[5].Position = { size.x / 2.0f, -size.y / 2.0f, -size.z / 2.0f }; + vertices[6].Position = { size.x / 2.0f, size.y / 2.0f, -size.z / 2.0f }; + vertices[7].Position = { -size.x / 2.0f, size.y / 2.0f, -size.z / 2.0f }; + + vertices[0].Normal = { -1.0f, -1.0f, 1.0f }; + vertices[1].Normal = { 1.0f, -1.0f, 1.0f }; + vertices[2].Normal = { 1.0f, 1.0f, 1.0f }; + vertices[3].Normal = { -1.0f, 1.0f, 1.0f }; + vertices[4].Normal = { -1.0f, -1.0f, -1.0f }; + vertices[5].Normal = { 1.0f, -1.0f, -1.0f }; + vertices[6].Normal = { 1.0f, 1.0f, -1.0f }; + vertices[7].Normal = { -1.0f, 1.0f, -1.0f }; + + std::vector indices; + indices.resize(12); + indices = { + { 0, 1, 2 }, + { 2, 3, 0 }, + { 1, 5, 6 }, + { 6, 2, 1 }, + { 7, 6, 5 }, + { 5, 4, 7 }, + { 4, 0, 3 }, + { 3, 7, 4 }, + { 4, 5, 1 }, + { 1, 0, 4 }, + { 3, 2, 6 }, + { 6, 7, 3 } + }; + + return Ref::Create(vertices, indices); + } + + Prism::Ref MeshFactory::CreateSphere(float radius) + { + std::vector vertices; + std::vector indices; + + constexpr float latitudeBands = 30; + constexpr float longitudeBands = 30; + + for (float latitude = 0.0f; latitude <= latitudeBands; latitude++) + { + const float theta = latitude * M_PI / latitudeBands; + const float sinTheta = glm::sin(theta); + float cosTheta = glm::cos(theta); + + for (float longitude = 0.0f; longitude <= longitudeBands; longitude++) + { + const float phi = longitude * 2 * M_PI / longitudeBands; + const float sinPhi = glm::sin(phi); + const float cosPhi = glm::cos(phi); + + Vertex vertex; + vertex.Normal = { cosPhi * sinTheta, cosTheta, sinPhi * sinTheta }; + vertex.Position = { radius * vertex.Normal.x, radius * vertex.Normal.y, radius * vertex.Normal.z }; + vertices.push_back(vertex); + } + } + + for (uint32_t latitude = 0; latitude < latitudeBands; latitude++) + { + for (uint32_t longitude = 0; longitude < longitudeBands; longitude++) + { + const uint32_t first = (latitude * (longitudeBands + 1)) + longitude; + const uint32_t second = first + longitudeBands + 1; + + indices.push_back({ first, second, first + 1 }); + indices.push_back({ second, second + 1, first + 1 }); + } + } + + return Ref::Create(vertices, indices); + } + + Ref MeshFactory::CreateCapsule(float radius, float height) + { + std::vector vertices; + std::vector indices; + + constexpr int segments = 30; + constexpr int pointCount = segments + 1; + + float pointsX[pointCount]; + float pointsY[pointCount]; + float pointsZ[pointCount]; + float pointsR[pointCount]; + + float calcH = 0.0f; + float calcV = 0.0f; + + for (int i = 0; i < pointCount; i++) + { + float calcHRadians = glm::radians(calcH); + float calcVRadians = glm::radians(calcV); + + pointsX[i] = glm::sin(calcHRadians); + pointsZ[i] = glm::cos(calcHRadians); + pointsY[i] = glm::cos(calcVRadians); + pointsR[i] = glm::sin(calcVRadians); + + calcH += 360.0f / (float)segments; + calcV += 180.0f / (float)segments; + } + + float yOffset = (height - (radius * 2.0f)) * 0.5f; + if (yOffset < 0.0f) + yOffset = 0.0f; + + int top = glm::ceil(pointCount * 0.5f); + + for (int y = 0; y < top; y++) + { + for (int x = 0; x < pointCount; x++) + { + Vertex vertex; + vertex.Position = glm::vec3( pointsX[x] * pointsR[y], pointsY[y] + yOffset, pointsZ[x] * pointsR[y] ) * radius; + vertices.push_back(vertex); + } + } + + int bottom = glm::floor(pointCount * 0.5f); + + for (int y = bottom; y < pointCount; y++) + { + for (int x = 0; x < pointCount; x++) + { + Vertex vertex; + vertex.Position = glm::vec3(pointsX[x] * pointsR[y], -yOffset + pointsY[y], pointsZ[x] * pointsR[y]) * radius; + vertices.push_back(vertex); + } + } + + for (int y = 0; y < segments + 1; y++) + { + for (int x = 0; x < segments; x++) + { + Index index1; + index1.V1 = ((y + 0) * (segments + 1)) + x + 0; + index1.V2 = ((y + 1) * (segments + 1)) + x + 0; + index1.V3 = ((y + 1) * (segments + 1)) + x + 1; + indices.push_back(index1); + + Index index2; + index2.V1 = ((y + 0) * (segments + 1)) + x + 1; + index2.V2 = ((y + 0) * (segments + 1)) + x + 0; + index2.V3 = ((y + 1) * (segments + 1)) + x + 1; + indices.push_back(index2); + } + } + + return Ref::Create(vertices, indices); + } + +} \ No newline at end of file diff --git a/Prism/src/Prism/Renderer/MeshFactory.h b/Prism/src/Prism/Renderer/MeshFactory.h new file mode 100644 index 0000000..71edb50 --- /dev/null +++ b/Prism/src/Prism/Renderer/MeshFactory.h @@ -0,0 +1,22 @@ +// +// Created by sfd on 25-12-21. +// + +#ifndef MESHFACTORY_H +#define MESHFACTORY_H + +#include "Mesh.h" + +namespace Prism +{ + class MeshFactory + { + public: + static Ref CreateBox(const glm::vec3& size); + static Ref CreateSphere(float radius); + static Ref CreateCapsule(float radius, float height); + }; +} + + +#endif //MESHFACTORY_H diff --git a/Prism/src/Prism/Renderer/SceneRenderer.cpp b/Prism/src/Prism/Renderer/SceneRenderer.cpp index b0db3d6..cbb81bd 100644 --- a/Prism/src/Prism/Renderer/SceneRenderer.cpp +++ b/Prism/src/Prism/Renderer/SceneRenderer.cpp @@ -15,138 +15,164 @@ namespace Prism { - struct SceneRendererData - { - const Scene* ActiveScene = nullptr; - struct SceneInfo - { - SceneRendererCamera SceneCamera; + struct SceneRendererData + { + const Scene* ActiveScene = nullptr; + struct SceneInfo + { + SceneRendererCamera SceneCamera; - // Resources - Ref SkyboxMaterial; - Environment SceneEnvironment; - Light ActiveLight; - } SceneData; + // Resources + Ref SkyboxMaterial; + Environment SceneEnvironment; + Light ActiveLight; + } SceneData; - Ref BRDFLUT; - Ref CompositeShader; + Ref BRDFLUT; + Ref CompositeShader; - Ref GeoPass; - Ref CompositePass; + Ref GeoPass; + Ref CompositePass; - struct DrawCommand - { - Ref mesh; - Ref Material; - glm::mat4 Transform; - }; - std::vector DrawList; - std::vector SelectedMeshDrawList; + struct DrawCommand + { + Ref mesh; + Ref Material; + glm::mat4 Transform; + }; + std::vector DrawList; + std::vector SelectedMeshDrawList; + std::vector ColliderDrawList; - // Grid - Ref GridMaterial; - Ref OutlineMaterial; + // Grid + Ref GridMaterial; + Ref OutlineMaterial; + Ref ColliderMaterial; SceneRendererOptions Options; - }; + }; - static SceneRendererData s_Data; + static SceneRendererData s_Data; - void SceneRenderer::Init() - { - FramebufferSpecification geoFramebufferSpec; - geoFramebufferSpec.Width = 1280; - geoFramebufferSpec.Height = 720; - geoFramebufferSpec.Format = FramebufferFormat::RGBA16F; - geoFramebufferSpec.Samples = 8; - geoFramebufferSpec.ClearColor = { 0.1f, 0.1f, 0.1f, 1.0f }; + void SceneRenderer::Init() + { + FramebufferSpecification geoFramebufferSpec; + geoFramebufferSpec.Width = 1280; + geoFramebufferSpec.Height = 720; + geoFramebufferSpec.Format = FramebufferFormat::RGBA16F; + geoFramebufferSpec.Samples = 8; + geoFramebufferSpec.ClearColor = { 0.1f, 0.1f, 0.1f, 1.0f }; - RenderPassSpecification geoRenderPassSpec; - geoRenderPassSpec.TargetFramebuffer = FrameBuffer::Create(geoFramebufferSpec); - s_Data.GeoPass = RenderPass::Create(geoRenderPassSpec); + RenderPassSpecification geoRenderPassSpec; + geoRenderPassSpec.TargetFramebuffer = FrameBuffer::Create(geoFramebufferSpec); + s_Data.GeoPass = RenderPass::Create(geoRenderPassSpec); - FramebufferSpecification compFramebufferSpec; - compFramebufferSpec.Width = 1280; - compFramebufferSpec.Height = 720; - compFramebufferSpec.Format = FramebufferFormat::RGBA8; - compFramebufferSpec.ClearColor = { 0.5f, 0.1f, 0.1f, 1.0f }; + FramebufferSpecification compFramebufferSpec; + compFramebufferSpec.Width = 1280; + compFramebufferSpec.Height = 720; + compFramebufferSpec.Format = FramebufferFormat::RGBA8; + compFramebufferSpec.ClearColor = { 0.5f, 0.1f, 0.1f, 1.0f }; - RenderPassSpecification compRenderPassSpec; - compRenderPassSpec.TargetFramebuffer = FrameBuffer::Create(compFramebufferSpec); - s_Data.CompositePass = RenderPass::Create(compRenderPassSpec); + RenderPassSpecification compRenderPassSpec; + compRenderPassSpec.TargetFramebuffer = FrameBuffer::Create(compFramebufferSpec); + s_Data.CompositePass = RenderPass::Create(compRenderPassSpec); s_Data.CompositeShader = Shader::Create("assets/shaders/SceneComposite.glsl"); - s_Data.BRDFLUT = Texture2D::Create("assets/textures/BRDF_LUT.tga"); + s_Data.BRDFLUT = Texture2D::Create("assets/textures/BRDF_LUT.tga"); - // Grid - const auto gridShader = Shader::Create("assets/shaders/Grid.glsl"); - s_Data.GridMaterial = MaterialInstance::Create(Material::Create(gridShader)); - constexpr float gridScale = 16.025f; - constexpr float gridSize = 0.025f; - s_Data.GridMaterial->Set("u_Scale", gridScale); - s_Data.GridMaterial->Set("u_Res", gridSize); + // Grid + const auto gridShader = Shader::Create("assets/shaders/Grid.glsl"); + s_Data.GridMaterial = MaterialInstance::Create(Material::Create(gridShader)); + constexpr float gridScale = 16.025f; + constexpr float gridSize = 0.025f; + s_Data.GridMaterial->Set("u_Scale", gridScale); + s_Data.GridMaterial->Set("u_Res", gridSize); // outline - const auto outlineShader = Shader::Create("assets/shaders/Outline.glsl"); - s_Data.OutlineMaterial = MaterialInstance::Create(Material::Create(outlineShader)); - s_Data.OutlineMaterial->SetFlag(MaterialFlag::DepthTest, false); + const auto outlineShader = Shader::Create("assets/shaders/Outline.glsl"); + s_Data.OutlineMaterial = MaterialInstance::Create(Material::Create(outlineShader)); + s_Data.OutlineMaterial->SetFlag(MaterialFlag::DepthTest, false); - } + // Collider + const auto colliderShader = Shader::Create("assets/shaders/Collider.glsl"); + s_Data.ColliderMaterial = MaterialInstance::Create(Material::Create(colliderShader)); + s_Data.ColliderMaterial->SetFlag(MaterialFlag::DepthTest, false); + } - void SceneRenderer::SetViewportSize(uint32_t width, uint32_t height) - { - s_Data.GeoPass->GetSpecification().TargetFramebuffer->Resize(width, height); - s_Data.CompositePass->GetSpecification().TargetFramebuffer->Resize(width, height); - } + void SceneRenderer::SetViewportSize(uint32_t width, uint32_t height) + { + s_Data.GeoPass->GetSpecification().TargetFramebuffer->Resize(width, height); + s_Data.CompositePass->GetSpecification().TargetFramebuffer->Resize(width, height); + } - void SceneRenderer::BeginScene(const Scene* scene, const SceneRendererCamera& camera) - { - PM_CORE_ASSERT(!s_Data.ActiveScene); + void SceneRenderer::BeginScene(const Scene* scene, const SceneRendererCamera& camera) + { + PM_CORE_ASSERT(!s_Data.ActiveScene); - s_Data.ActiveScene = scene; + s_Data.ActiveScene = scene; - s_Data.SceneData.SceneCamera = camera; - s_Data.SceneData.SkyboxMaterial = scene->m_SkyboxMaterial; - s_Data.SceneData.SceneEnvironment = scene->m_Environment; - s_Data.SceneData.ActiveLight = scene->m_Light; - } + s_Data.SceneData.SceneCamera = camera; + s_Data.SceneData.SkyboxMaterial = scene->m_SkyboxMaterial; + s_Data.SceneData.SceneEnvironment = scene->m_Environment; + s_Data.SceneData.ActiveLight = scene->m_Light; + } - void SceneRenderer::EndScene() - { - PM_CORE_ASSERT(s_Data.ActiveScene); + void SceneRenderer::EndScene() + { + PM_CORE_ASSERT(s_Data.ActiveScene); - s_Data.ActiveScene = nullptr; + s_Data.ActiveScene = nullptr; - FlushDrawList(); - } + FlushDrawList(); + } - void SceneRenderer::SubmitMesh(const Ref& mesh, const glm::mat4& transform, const Ref& overrideMaterial) - { - // TODO: Culling, sorting, etc. + void SceneRenderer::SubmitMesh(const Ref& mesh, const glm::mat4& transform, const Ref& overrideMaterial) + { + // TODO: Culling, sorting, etc. - s_Data.DrawList.push_back({ mesh, overrideMaterial, transform }); - } + s_Data.DrawList.push_back({ mesh, overrideMaterial, transform }); + } - void SceneRenderer::SubmitSelectedMesh(const Ref& mesh, const glm::mat4& transform) - { + void SceneRenderer::SubmitSelectedMesh(const Ref& mesh, const glm::mat4& transform) + { s_Data.SelectedMeshDrawList.push_back({ mesh, nullptr, transform }); - } + } + + void SceneRenderer::SubmitColliderMesh(const BoxColliderComponent& component, const glm::mat4& parentTransform) + { + s_Data.ColliderDrawList.push_back({ component.DebugMesh, nullptr, glm::translate(parentTransform, component.Offset)}); + } + + void SceneRenderer::SubmitColliderMesh(const SphereColliderComponent& component, const glm::mat4& parentTransform) + { + s_Data.ColliderDrawList.push_back({ component.DebugMesh, nullptr, parentTransform }); + } + + void SceneRenderer::SubmitColliderMesh(const CapsuleColliderComponent& component, const glm::mat4& parentTransform) + { + s_Data.ColliderDrawList.push_back({ component.DebugMesh, nullptr, parentTransform }); + } + + void SceneRenderer::SubmitColliderMesh(const MeshColliderComponent& component, const glm::mat4& parentTransform) + { + s_Data.ColliderDrawList.push_back({ component.ProcessedMesh, nullptr, parentTransform }); + } - static Ref equirectangularConversionShader, envFilteringShader, envIrradianceShader; + static Ref equirectangularConversionShader, envFilteringShader, envIrradianceShader; - std::pair, Ref> SceneRenderer::CreateEnvironmentMap(const std::string& filepath) - { - constexpr uint32_t cubemapSize = 2048; - constexpr uint32_t irradianceMapSize = 32; + std::pair, Ref> SceneRenderer::CreateEnvironmentMap(const std::string& filepath) + { + constexpr uint32_t cubemapSize = 2048; + constexpr uint32_t irradianceMapSize = 32; Ref envUnfiltered = TextureCube::Create(TextureFormat::Float16, cubemapSize, cubemapSize); if (!equirectangularConversionShader) equirectangularConversionShader = Shader::Create("assets/shaders/EquirectangularToCubeMap.glsl"); Ref envEquirect = Texture2D::Create(filepath); - if (envEquirect->GetFormat() != TextureFormat::Float16) - PM_CORE_WARN("Texture is not HDR!"); + if (envEquirect->GetFormat() != TextureFormat::Float16) + PM_CORE_WARN("Texture is not HDR!"); equirectangularConversionShader->Bind(); envEquirect->Bind(); @@ -198,46 +224,48 @@ namespace Prism }); return { envFiltered, irradianceMap }; - } + } - Ref SceneRenderer::GetFinalRenderPass() - { - return s_Data.CompositePass; - } + Ref SceneRenderer::GetFinalRenderPass() + { + return s_Data.CompositePass; + } - Ref SceneRenderer::GetFinalColorBuffer() - { - PM_CORE_ASSERT(false, "Not implemented"); - return nullptr; - } + Ref SceneRenderer::GetFinalColorBuffer() + { + PM_CORE_ASSERT(false, "Not implemented"); + return nullptr; + } - uint32_t SceneRenderer::GetFinalColorBufferRendererID() - { + uint32_t SceneRenderer::GetFinalColorBufferRendererID() + { return s_Data.CompositePass->GetSpecification().TargetFramebuffer->GetColorAttachmentRendererID(); - } + } - SceneRendererOptions& SceneRenderer::GetOptions() - { - return s_Data.Options; - } + SceneRendererOptions& SceneRenderer::GetOptions() + { + return s_Data.Options; + } - void SceneRenderer::FlushDrawList() - { - PM_CORE_ASSERT(!s_Data.ActiveScene); + void SceneRenderer::FlushDrawList() + { + PM_CORE_ASSERT(!s_Data.ActiveScene); - GeometryPass(); - CompositePass(); + GeometryPass(); + CompositePass(); - s_Data.DrawList.clear(); + s_Data.DrawList.clear(); s_Data.SelectedMeshDrawList.clear(); - s_Data.SceneData = {}; - } + s_Data.ColliderDrawList.clear(); + s_Data.SceneData = {}; + } - void SceneRenderer::GeometryPass() - { - bool outline = s_Data.SelectedMeshDrawList.size() > 0; + void SceneRenderer::GeometryPass() + { + const bool outline = s_Data.SelectedMeshDrawList.size() > 0; + const bool collider = s_Data.ColliderDrawList.size() > 0; - if (outline) + if (outline || collider) { Renderer::Submit([]() { @@ -247,7 +275,7 @@ namespace Prism Renderer::BeginRenderPass(s_Data.GeoPass); - if (outline) + if (outline || collider) { Renderer::Submit([]() { @@ -283,32 +311,6 @@ namespace Prism Renderer::SubmitMesh(dc.mesh, dc.Transform, overrideMaterial); } - if (outline) - { - Renderer::Submit([]() - { - glStencilFunc(GL_ALWAYS, 1, 0xff); - glStencilMask(0xff); - }); - } - - for (auto& dc : s_Data.SelectedMeshDrawList) - { - auto baseMaterial = dc.mesh->GetMaterial(); - baseMaterial->Set("u_ViewProjectionMatrix", viewProjection); - baseMaterial->Set("u_CameraPosition", cameraPosition); - - // Environment (TODO: don't do this per mesh) - baseMaterial->Set("u_EnvRadianceTex", s_Data.SceneData.SceneEnvironment.RadianceMap); - baseMaterial->Set("u_EnvIrradianceTex", s_Data.SceneData.SceneEnvironment.IrradianceMap); - baseMaterial->Set("u_BRDFLUTTexture", s_Data.BRDFLUT); - - // Set lights (TODO: move to light environment and don't do per mesh) - baseMaterial->Set("lights", s_Data.SceneData.ActiveLight); - - auto overrideMaterial = nullptr; // dc.Material; - Renderer::SubmitMesh(dc.mesh, dc.Transform, overrideMaterial); - } if (outline) { @@ -349,6 +351,47 @@ namespace Prism }); } + if (collider) + { + Renderer::Submit([]() + { + glStencilFunc(GL_NOTEQUAL, 1, 0xff); + glStencilMask(0); + + glLineWidth(1); + glEnable(GL_LINE_SMOOTH); + glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); + glDisable(GL_DEPTH_TEST); + }); + + s_Data.ColliderMaterial->Set("u_ViewProjection", viewProjection); + for (auto& dc : s_Data.ColliderDrawList) + { + if (dc.mesh) + Renderer::SubmitMesh(dc.mesh, dc.Transform, s_Data.ColliderMaterial); + } + + Renderer::Submit([]() + { + glPointSize(1); + glPolygonMode(GL_FRONT_AND_BACK, GL_POINT); + }); + + for (auto& dc : s_Data.ColliderDrawList) + { + if (dc.mesh) + Renderer::SubmitMesh(dc.mesh, dc.Transform, s_Data.ColliderMaterial); + } + + Renderer::Submit([]() + { + glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); + glStencilMask(0xff); + glStencilFunc(GL_ALWAYS, 1, 0xff); + glEnable(GL_DEPTH_TEST); + }); + } + // Grid const auto option = GetOptions(); diff --git a/Prism/src/Prism/Renderer/SceneRenderer.h b/Prism/src/Prism/Renderer/SceneRenderer.h index d9ea37f..26bc4bd 100644 --- a/Prism/src/Prism/Renderer/SceneRenderer.h +++ b/Prism/src/Prism/Renderer/SceneRenderer.h @@ -7,6 +7,7 @@ #include "Mesh.h" #include "RenderPass.h" #include "Texture.h" +#include "Prism/Scene/Components.h" #include "Prism/Scene/Scene.h" @@ -37,6 +38,11 @@ namespace Prism static void SubmitMesh(const Ref& mesh, const glm::mat4& transform = glm::mat4(1.0f), const Ref& overrideMaterial = nullptr); static void SubmitSelectedMesh(const Ref& mesh, const glm::mat4& transform = glm::mat4(1.0f)); + static void SubmitColliderMesh(const BoxColliderComponent& component, const glm::mat4& parentTransform = glm::mat4(1.0f)); + static void SubmitColliderMesh(const SphereColliderComponent& component, const glm::mat4& parentTransform = glm::mat4(1.0f)); + static void SubmitColliderMesh(const CapsuleColliderComponent& component, const glm::mat4& parentTransform = glm::mat4(1.0f)); + static void SubmitColliderMesh(const MeshColliderComponent& component, const glm::mat4& parentTransform = glm::mat4(1.0f)); + static std::pair, Ref> CreateEnvironmentMap(const std::string& filepath); static Ref GetFinalRenderPass(); diff --git a/Prism/src/Prism/Scene/Components.h b/Prism/src/Prism/Scene/Components.h index 2ff10d7..a890aef 100644 --- a/Prism/src/Prism/Scene/Components.h +++ b/Prism/src/Prism/Scene/Components.h @@ -12,7 +12,6 @@ #include "glm/glm.hpp" #include "Prism/Core/Ref.h" #include "Prism/Core/UUID.h" -#include "Prism/Renderer/Camera.h" #include "Prism/Renderer/Mesh.h" namespace Prism @@ -141,9 +140,11 @@ namespace Prism struct SphereColliderComponent { - float Radius = 1.0f; + float Radius = 0.5f; + bool IsTrigger = false; - // TODO: Physics Material + // The mesh that will be drawn in the editor to show the collision bounds + Ref DebugMesh; SphereColliderComponent() = default; SphereColliderComponent(const SphereColliderComponent& other) = default; @@ -151,9 +152,10 @@ namespace Prism struct RigidBodyComponent { - enum class Type { Static, Dynamic, Kinematic }; + enum class Type { Static, Dynamic}; Type BodyType; float Mass = 1.0f; + bool IsKinematic = false; bool LockPositionX = false; bool LockPositionY = false; @@ -183,6 +185,10 @@ namespace Prism { glm::vec3 Size = { 1.0f, 1.0f, 1.0f }; glm::vec3 Offset = { 0.0f, 0.0f, 0.0f }; + bool IsTrigger = false; + + // The mesh that will be drawn in the editor to show the collision bounds + Ref DebugMesh; BoxColliderComponent() = default; BoxColliderComponent(const BoxColliderComponent& other) = default; @@ -192,6 +198,9 @@ namespace Prism { float Radius = 0.5f; float Height = 1.0f; + bool IsTrigger = false; + + Ref DebugMesh; CapsuleColliderComponent() = default; CapsuleColliderComponent(const CapsuleColliderComponent& other) = default; @@ -200,6 +209,8 @@ namespace Prism struct MeshColliderComponent { Ref CollisionMesh; + Ref ProcessedMesh; + bool IsTrigger = false; MeshColliderComponent() = default; MeshColliderComponent(const MeshColliderComponent& other) = default; diff --git a/Prism/src/Prism/Scene/Scene.cpp b/Prism/src/Prism/Scene/Scene.cpp index 3f9c42a..589f9fb 100644 --- a/Prism/src/Prism/Scene/Scene.cpp +++ b/Prism/src/Prism/Scene/Scene.cpp @@ -15,17 +15,14 @@ #include #include "Prism/Physics/Physics3D.h" +#define PX_PHYSX_STATIC_LIB +#include namespace Prism { - // TODO: THIS SHOULD MOVE TO PHYSICS FILE! std::unordered_map s_ActiveScenes; - static physx::PxDefaultErrorCallback s_PXErrorCallback; - static physx::PxDefaultAllocator s_PXAllocator; - static physx::PxFoundation* s_PXFoundation; - static uint32_t s_SceneIDCounter = 0; struct SceneComponent @@ -45,11 +42,6 @@ namespace Prism } }; - struct PhysXSceneComponent - { - // NOTE: PhysX does some internal ref counting, and thus doesn't allow unique_ptr - physx::PxScene* World; - }; void ProcessContactEvents(const b2WorldId worldId) { @@ -85,65 +77,6 @@ namespace Prism } } - class PhysXContactListener : public physx::PxSimulationEventCallback - { - public: - virtual void onConstraintBreak(physx::PxConstraintInfo* constraints, physx::PxU32 count) override - { - PX_UNUSED(constraints); - PX_UNUSED(count); - } - - virtual void onWake(physx::PxActor** actors, physx::PxU32 count) override - { - PX_UNUSED(actors); - PX_UNUSED(count); - } - - virtual void onSleep(physx::PxActor** actors, physx::PxU32 count) override - { - PX_UNUSED(actors); - PX_UNUSED(count); - } - - virtual void onContact(const physx::PxContactPairHeader& pairHeader, const physx::PxContactPair* pairs, physx::PxU32 nbPairs) override - { - Entity& a = *(Entity*)pairHeader.actors[0]->userData; - Entity& b = *(Entity*)pairHeader.actors[1]->userData; - - if (pairs->flags == physx::PxContactPairFlag::eACTOR_PAIR_HAS_FIRST_TOUCH) - { - if (a.HasComponent() && ScriptEngine::ModuleExists(a.GetComponent().ModuleName)) - ScriptEngine::OnCollisionBegin(a); - - if (b.HasComponent() && ScriptEngine::ModuleExists(b.GetComponent().ModuleName)) - ScriptEngine::OnCollisionBegin(b); - } - else if (pairs->flags == physx::PxContactPairFlag::eACTOR_PAIR_LOST_TOUCH) - { - if (a.HasComponent() && ScriptEngine::ModuleExists(a.GetComponent().ModuleName)) - ScriptEngine::OnCollisionEnd(a); - - if (b.HasComponent() && ScriptEngine::ModuleExists(b.GetComponent().ModuleName)) - ScriptEngine::OnCollisionEnd(b); - } - } - - virtual void onTrigger(physx::PxTriggerPair* pairs, physx::PxU32 count) override - { - PX_UNUSED(pairs); - PX_UNUSED(count); - } - - virtual void onAdvance(const physx::PxRigidBody* const* bodyBuffer, const physx::PxTransform* poseBuffer, const physx::PxU32 count) override - { - PX_UNUSED(bodyBuffer); - PX_UNUSED(poseBuffer); - PX_UNUSED(count); - } - }; - - static PhysXContactListener s_PhysXContactListener; void OnTransformConstruct(entt::registry& registry, entt::entity entity) @@ -189,8 +122,8 @@ namespace Prism return { filepath, radiance, irradiance }; } - Scene::Scene(const std::string& debugName) - : m_SceneID(++s_SceneIDCounter), m_DebugName(debugName) + Scene::Scene(const std::string& debugName, const bool isEditorScene) + : m_SceneID(++s_SceneIDCounter), m_DebugName(debugName) { m_Registry.on_construct().connect<&OnTransformConstruct>(); m_Registry.on_construct().connect<&OnScriptComponentConstruct>(); @@ -198,34 +131,22 @@ namespace Prism m_SceneEntity = m_Registry.create(); m_Registry.emplace(m_SceneEntity, m_SceneID); - // TODO: Obviously not necessary in all cases Box2DWorldComponent& b2World = m_Registry.emplace(m_SceneEntity, b2Vec2{ 0.0f, -9.8f }); s_ActiveScenes[m_SceneID] = this; - physx::PxSceneDesc sceneDesc = Physics3D::CreateSceneDesc(); - sceneDesc.gravity = physx::PxVec3(0.0f, -9.8f, 0.0f); - sceneDesc.simulationEventCallback = &s_PhysXContactListener; - - const PhysXSceneComponent& physxWorld = m_Registry.emplace(m_SceneEntity, Physics3D::CreateScene(sceneDesc)); - physx::PxPvdSceneClient* pvdClient = physxWorld.World->getScenePvdClient(); - if(pvdClient) + if (!isEditorScene) { - pvdClient->setScenePvdFlag(physx::PxPvdSceneFlag::eTRANSMIT_CONSTRAINTS, true); - pvdClient->setScenePvdFlag(physx::PxPvdSceneFlag::eTRANSMIT_CONTACTS, true); - pvdClient->setScenePvdFlag(physx::PxPvdSceneFlag::eTRANSMIT_SCENEQUERIES, true); - }else - { - PM_CORE_WARN("you are using pvd to debug: "); - PM_CORE_WARN("PvdSceneClient is null is pvd running or you are using release/profile PhysX?"); - PM_CORE_WARN("to using Pvd, should using debug/checked version to build!"); + SceneParams sceneDesc; + sceneDesc.Gravity = glm::vec3(0.0F, -9.81F, 0.0F); + Physics3D::CreateScene(sceneDesc); } - PM_CORE_ASSERT(physxWorld.World); Init(); } + Scene::~Scene() { m_Registry.on_destroy().disconnect(); @@ -243,24 +164,22 @@ namespace Prism void Scene::OnShutdown() { + /* auto b2WorldView = m_Registry.view(); b2DestroyWorld(m_Registry.get(m_SceneEntity).World); - - auto physxView = m_Registry.view(); - m_Registry.get(m_SceneEntity).World->release(); + */ } void Scene::OnUpdate(TimeStep ts) { // Update all entities { - auto view = m_Registry.view(); - for (auto entity : view) + const auto view = m_Registry.view(); + for (const auto entity : view) { - UUID entityID = m_Registry.get(entity).ID; Entity e = { entity, this }; if (ScriptEngine::ModuleExists(e.GetComponent().ModuleName)) - ScriptEngine::OnUpdateEntity(m_SceneID, entityID, ts); + ScriptEngine::OnUpdateEntity(e, ts); } } @@ -296,65 +215,7 @@ namespace Prism } } - // PhysX Physics - auto physxView = m_Registry.view(); - physx::PxScene* physxScene = m_Registry.get(physxView.front()).World; - - constexpr float stepSize = 0.016666660f; - physxScene->simulate(stepSize); - physxScene->fetchResults(true); - - { - auto view = m_Registry.view(); - for (auto entity : view) - { - Entity e = { entity, this }; - auto& transform = e.Transform(); - RigidBodyComponent& rb = e.GetComponent(); - physx::PxRigidActor* actor = static_cast(rb.RuntimeActor); - const auto& position = actor->getGlobalPose().p; - const physx::PxQuat& physicsBodyRotation = actor->getGlobalPose().q; - - auto [translation, rotationQuat, scale] = GetTransformDecomposition(transform); - - if (rb.BodyType == RigidBodyComponent::Type::Dynamic) - { - /* - // If the rigidbody is dynamic, the position of the entity is determined by the rigidbody - // TODO: Get rotation from RigidActor - float xAngle, yAngle, zAngle; - physx::PxVec3 axis; - physicsBodyRotation.toRadiansAndUnitAxis(xAngle, axis); - physicsBodyRotation.toRadiansAndUnitAxis(yAngle, axis); - physicsBodyRotation.toRadiansAndUnitAxis(zAngle, axis); - - transform = glm::translate(glm::mat4(1.0f), { position.x, position.y, position.z }) * - glm::toMat4(glm::quat({ xAngle, yAngle, zAngle })) * - glm::scale(glm::mat4(1.0f), scale); - */ - - // 获取物理引擎的位置和旋转 - physx::PxTransform globalPose = actor->getGlobalPose(); - const physx::PxVec3& pos = globalPose.p; - const physx::PxQuat& physicsQuat = globalPose.q; - - glm::quat glmQuat{physicsQuat.w, physicsQuat.x, physicsQuat.y, physicsQuat.z}; - - // 使用转换后的四元数创建变换矩阵 - transform = glm::translate(glm::mat4(1.0f), - glm::vec3(pos.x, pos.y, pos.z)) * - glm::toMat4(glmQuat) * - glm::scale(glm::mat4(1.0f), scale); - - } - else if (rb.BodyType == RigidBodyComponent::Type::Static) - { - // If the rigidbody is static, make sure the actor is at the entitys position - actor->setGlobalPose(Physics3D::CreatePose(transform)); - } - } - } - + Physics3D::Simulate(ts); } void Scene::OnRenderRuntime(TimeStep ts) @@ -425,13 +286,60 @@ namespace Prism meshComponent.Mesh->OnUpdate(ts); // TODO: Should we render (logically) - - if (m_SelectedEntity == entity) - SceneRenderer::SubmitSelectedMesh(meshComponent, transformComponent); - else - SceneRenderer::SubmitMesh(meshComponent, transformComponent); + SceneRenderer::SubmitMesh(meshComponent, transformComponent); } } + + { + auto view = m_Registry.view(); + for (auto entity : view) + { + Entity e = { entity, this }; + auto& collider = e.GetComponent(); + + if (m_SelectedEntity == entity) + SceneRenderer::SubmitColliderMesh(collider, e.GetComponent()); + } + } + + { + const auto view = m_Registry.view(); + for (auto entity : view) + { + Entity e = { entity, this }; + auto& collider = e.GetComponent(); + + if (m_SelectedEntity == entity) + SceneRenderer::SubmitColliderMesh(collider, e.GetComponent()); + } + } + + { + const auto view = m_Registry.view(); + for (auto entity : view) + { + Entity e = { entity, this }; + auto& collider = e.GetComponent(); + + if (m_SelectedEntity == entity) + SceneRenderer::SubmitColliderMesh(collider, e.GetComponent()); + } + } + + { + const auto view = m_Registry.view(); + for (auto entity : view) + { + Entity e = { entity, this }; + auto& collider = e.GetComponent(); + + if (m_SelectedEntity == entity) + { + SceneRenderer::SubmitColliderMesh(collider, e.GetComponent()); + } + } + } + SceneRenderer::EndScene(); ///////////////////////////////////////////////////////////////////// @@ -568,159 +476,21 @@ namespace Prism } } - - auto physxView = m_Registry.view(); - physx::PxScene* physxWorld = m_Registry.get(physxView.front()).World; - - { - auto view = m_Registry.view(); - m_Physics3DBodyEntityBuffer = new Entity[view.size()]; - uint32_t physicsBodyEntityBufferIndex = 0; - - for (auto entity : view) - { - Entity e = { entity, this }; - UUID entityID = e.GetComponent().ID; - auto& transform = e.Transform(); - auto& rigidbody = m_Registry.get(entity); - - physx::PxRigidActor* actor = Physics3D::CreateAndAddActor(physxWorld, rigidbody, transform); - PM_CORE_ASSERT(actor); - - Entity* entityStorage = &m_Physics3DBodyEntityBuffer[physicsBodyEntityBufferIndex++]; - *entityStorage = e; - actor->userData = (void*)entityStorage; - - rigidbody.RuntimeActor = actor; - } - } - - { - auto view = m_Registry.view(); - for (auto entity : view) - { - Entity e = { entity, this }; - auto& transform = e.Transform(); - - auto& boxCollider = m_Registry.get(entity); - if (e.HasComponent()) - { - auto& rigidBody = e.GetComponent(); - auto& physicsMaterial = e.GetComponent(); - PM_CORE_ASSERT(rigidBody.RuntimeActor); - physx::PxRigidActor* actor = static_cast(rigidBody.RuntimeActor); - - physx::PxBoxGeometry boxGeometry = physx::PxBoxGeometry(boxCollider.Size.x / 2.0F, boxCollider.Size.y / 2.0F, boxCollider.Size.z / 2.0F); - physx::PxMaterial* material = Physics3D::CreateMaterial(physicsMaterial.StaticFriction, physicsMaterial.DynamicFriction, physicsMaterial.Bounciness); - physx::PxShape* shape = physx::PxRigidActorExt::createExclusiveShape(*actor, boxGeometry, *material); - shape->setLocalPose(Physics3D::CreatePose(glm::translate(glm::mat4(1.0F), boxCollider.Offset))); - } - } - } - - { - auto view = m_Registry.view(); - for (auto entity : view) - { - Entity e = { entity, this }; - auto& transform = e.Transform(); - - auto& sphereCollider = m_Registry.get(entity); - if (e.HasComponent()) - { - auto& rigidBody = e.GetComponent(); - auto& physicsMaterial = e.GetComponent(); - PM_CORE_ASSERT(rigidBody.RuntimeActor); - physx::PxRigidActor* actor = static_cast(rigidBody.RuntimeActor); - physx::PxSphereGeometry sphereGeometry = physx::PxSphereGeometry(sphereCollider.Radius); - physx::PxMaterial* material = Physics3D::CreateMaterial(physicsMaterial.StaticFriction, physicsMaterial.DynamicFriction, physicsMaterial.Bounciness); - physx::PxRigidActorExt::createExclusiveShape(*actor, sphereGeometry, *material); - - physx::PxRigidDynamic* rigidBodyActor = actor->is(); - - if (rigidBodyActor) - { - rigidBodyActor->setRigidDynamicLockFlag(physx::PxRigidDynamicLockFlag::eLOCK_ANGULAR_X, true); - rigidBodyActor->setRigidDynamicLockFlag(physx::PxRigidDynamicLockFlag::eLOCK_ANGULAR_Y, true); - rigidBodyActor->setRigidDynamicLockFlag(physx::PxRigidDynamicLockFlag::eLOCK_ANGULAR_Z, true); - } - } - } - } - - { - auto view = m_Registry.view(); - for (auto entity : view) - { - Entity e = { entity, this }; - auto& transform = e.Transform(); - - auto& capsuleCollider = m_Registry.get(entity); - if (e.HasComponent()) - { - auto& rigidBody = e.GetComponent(); - auto& physicsMaterial = e.GetComponent(); - PM_CORE_ASSERT(rigidBody.RuntimeActor); - physx::PxRigidActor* actor = static_cast(rigidBody.RuntimeActor); - physx::PxCapsuleGeometry capsuleGeometry = physx::PxCapsuleGeometry(capsuleCollider.Radius, capsuleCollider.Height / 2.0F); - physx::PxMaterial* material = Physics3D::CreateMaterial(physicsMaterial.StaticFriction, physicsMaterial.DynamicFriction, physicsMaterial.Bounciness); - physx::PxShape* shape = physx::PxRigidActorExt::createExclusiveShape(*actor, capsuleGeometry, *material); - - // Make sure that the capsule is facing up (+Y) - shape->setLocalPose(physx::PxTransform(physx::PxQuat(physx::PxHalfPi, physx::PxVec3(0, 0, 1)))); - } - } - } - - { - auto meshView = m_Registry.view(); - for (auto entity : meshView) - { - Entity e = { entity, this }; - auto& transform = e.Transform(); - - auto& meshCollider = m_Registry.get(entity); - if (e.HasComponent()) - { - auto& rigidBody = e.GetComponent(); - auto& physicsMaterial = e.GetComponent(); - PM_CORE_ASSERT(rigidBody.RuntimeActor); - physx::PxRigidActor* actor = static_cast(rigidBody.RuntimeActor); - - physx::PxConvexMesh* triangleMesh = Physics3D::CreateMeshCollider(meshCollider); - PM_CORE_ASSERT(triangleMesh); - - physx::PxConvexMeshGeometry triangleGeometry = physx::PxConvexMeshGeometry(triangleMesh); - physx::PxMaterial* material = Physics3D::CreateMaterial(physicsMaterial.StaticFriction, physicsMaterial.DynamicFriction, physicsMaterial.Bounciness); - physx::PxRigidActorExt::createExclusiveShape(*actor, triangleGeometry, *material); - } - } - - // Setup Collision Filters - auto rbView = m_Registry.view(); - for (auto entity : rbView) - { - Entity e = { entity, this }; - auto& rigidBody = e.GetComponent(); - PM_CORE_ASSERT(rigidBody.RuntimeActor); - physx::PxRigidActor* actor = static_cast(rigidBody.RuntimeActor); - - if (rigidBody.BodyType == RigidBodyComponent::Type::Static) - Physics3D::SetCollisionFilters(actor, (uint32_t)FilterGroup::Static, (uint32_t)FilterGroup::All); - else if (rigidBody.BodyType == RigidBodyComponent::Type::Dynamic) - Physics3D::SetCollisionFilters(actor, (uint32_t)FilterGroup::Dynamic, (uint32_t)FilterGroup::All); - } - } - + { + auto view = m_Registry.view(); + for (auto entity : view) + { + Entity e = { entity, this }; + Physics3D::CreateActor(e, (int)view.size()); + } + } m_IsPlaying = true; } void Scene::OnRuntimeStop() { - auto physxView = m_Registry.view(); - m_Registry.get(m_SceneEntity).World->release(); - + Physics3D::DestroyScene(); delete[] m_Physics3DBodyEntityBuffer; delete[] m_Physics2DBodyEntityBuffer; @@ -836,6 +606,7 @@ namespace Prism CopyComponentIfExists(newEntity.m_EntityHandle, entity.m_EntityHandle, m_Registry); CopyComponentIfExists(newEntity.m_EntityHandle, entity.m_EntityHandle, m_Registry); CopyComponentIfExists(newEntity.m_EntityHandle, entity.m_EntityHandle, m_Registry); + CopyComponentIfExists(newEntity.m_EntityHandle, entity.m_EntityHandle, m_Registry); CopyComponentIfExists(newEntity.m_EntityHandle, entity.m_EntityHandle, m_Registry); } @@ -884,6 +655,7 @@ namespace Prism CopyComponent(target->m_Registry, m_Registry, enttMap); CopyComponent(target->m_Registry, m_Registry, enttMap); CopyComponent(target->m_Registry, m_Registry, enttMap); + CopyComponent(target->m_Registry, m_Registry, enttMap); CopyComponent(target->m_Registry, m_Registry, enttMap); const auto& entityInstanceMap = ScriptEngine::GetEntityInstanceMap(); diff --git a/Prism/src/Prism/Scene/Scene.h b/Prism/src/Prism/Scene/Scene.h index 8fa00e6..bfbad15 100644 --- a/Prism/src/Prism/Scene/Scene.h +++ b/Prism/src/Prism/Scene/Scene.h @@ -40,7 +40,7 @@ namespace Prism class PRISM_API Scene : public RefCounted { public: - Scene(const std::string& debugName = "Scene"); + Scene(const std::string& debugName = "Scene", bool isEditorScene = false); ~Scene(); void Init(); diff --git a/Prism/src/Prism/Scene/SceneCamera.h b/Prism/src/Prism/Scene/SceneCamera.h index a08959b..50e5a7b 100644 --- a/Prism/src/Prism/Scene/SceneCamera.h +++ b/Prism/src/Prism/Scene/SceneCamera.h @@ -9,7 +9,7 @@ namespace Prism { - class SceneCamera : public Camera + class PRISM_API SceneCamera : public Camera { public: enum class ProjectionType { Perspective = 0, Orthographic = 1 }; diff --git a/Prism/src/Prism/Scene/SceneSerializer.cpp b/Prism/src/Prism/Scene/SceneSerializer.cpp index 7a88d2d..6edc4ca 100644 --- a/Prism/src/Prism/Scene/SceneSerializer.cpp +++ b/Prism/src/Prism/Scene/SceneSerializer.cpp @@ -20,6 +20,9 @@ #include #include +#include "Prism/Physics/PxPhysicsWrappers.h" +#include "Prism/Renderer/Meshfactory.h" + namespace YAML { @@ -195,7 +198,7 @@ namespace Prism auto& transform = entity.GetComponent().Transform; auto[pos, rot, scale] = GetTransformDecomposition(transform); out << YAML::Key << "Position" << YAML::Value << pos; - out << YAML::Key << "Rotation" << YAML::Value << rot; + out << YAML::Key << "Rotation" << YAML::Value << rot; // Quat rotation out << YAML::Key << "Scale" << YAML::Value << scale; out << YAML::EndMap; // TransformComponent @@ -337,6 +340,7 @@ namespace Prism auto& rigidbodyComponent = entity.GetComponent(); 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 << "Constraints"; out << YAML::BeginMap; // Constraints @@ -358,7 +362,7 @@ namespace Prism out << YAML::Key << "PhysicsMaterialComponent"; out << YAML::BeginMap; // PhysicsMaterialComponent - auto& physicsMaterial = entity.GetComponent(); + const auto& physicsMaterial = entity.GetComponent(); out << YAML::Key << "StaticFriction" << YAML::Value << physicsMaterial.StaticFriction; out << YAML::Key << "DynamicFriction" << YAML::Value << physicsMaterial.DynamicFriction; out << YAML::Key << "Bounciness" << YAML::Value << physicsMaterial.Bounciness; @@ -371,9 +375,10 @@ namespace Prism out << YAML::Key << "BoxColliderComponent"; out << YAML::BeginMap; // BoxColliderComponent - auto& boxColliderComponent = entity.GetComponent(); + const auto& boxColliderComponent = entity.GetComponent(); out << YAML::Key << "Offset" << YAML::Value << boxColliderComponent.Offset; out << YAML::Key << "Size" << YAML::Value << boxColliderComponent.Size; + out << YAML::Key << "IsTrigger" << YAML::Value << boxColliderComponent.IsTrigger; out << YAML::EndMap; // BoxColliderComponent } @@ -383,19 +388,34 @@ namespace Prism out << YAML::Key << "SphereColliderComponent"; out << YAML::BeginMap; // SphereColliderComponent - auto& sphereColliderComponent = entity.GetComponent(); + const auto& sphereColliderComponent = entity.GetComponent(); out << YAML::Key << "Radius" << YAML::Value << sphereColliderComponent.Radius; + out << YAML::Key << "IsTrigger" << YAML::Value << sphereColliderComponent.IsTrigger; out << YAML::EndMap; // SphereColliderComponent } + if (entity.HasComponent()) + { + out << YAML::Key << "CapsuleColliderComponent"; + out << YAML::BeginMap; // CapsuleColliderComponent + + const auto& capsuleColliderComponent = entity.GetComponent(); + out << YAML::Key << "Radius" << YAML::Value << capsuleColliderComponent.Radius; + out << YAML::Key << "Height" << YAML::Value << capsuleColliderComponent.Height; + out << YAML::Key << "IsTrigger" << YAML::Value << capsuleColliderComponent.IsTrigger; + + out << YAML::EndMap; // CapsuleColliderComponent + } + if (entity.HasComponent()) { out << YAML::Key << "MeshColliderComponent"; out << YAML::BeginMap; // MeshColliderComponent - auto mesh = entity.GetComponent().CollisionMesh; - out << YAML::Key << "AssetPath" << YAML::Value << mesh->GetFilePath(); + auto meshColliderComponent = entity.GetComponent(); + out << YAML::Key << "AssetPath" << YAML::Value << meshColliderComponent.CollisionMesh->GetFilePath(); + out << YAML::Key << "IsTrigger" << YAML::Value << meshColliderComponent.IsTrigger; out << YAML::EndMap; // MeshColliderComponent } @@ -527,15 +547,17 @@ namespace Prism { for (auto field : storedFields) { - std::string name = field["Name"].as(); - FieldType type = (FieldType)field["Type"].as(); + auto name = field["Name"].as(); + auto type = (FieldType)field["Type"].as(); EntityInstanceData& data = ScriptEngine::GetEntityInstanceData(m_Scene->GetUUID(), uuid); auto& moduleFieldMap = data.ModuleFieldMap; auto& publicFields = moduleFieldMap[moduleName]; if (publicFields.find(name) == publicFields.end()) { - PublicField pf = { name, type }; - publicFields.emplace(name, std::move(pf)); + // PublicField pf = { name, type }; + // publicFields.emplace(name, std::move(pf)); + PM_CORE_WARN("Script field '{0}' not found in current Script file! ignore this.", name); + continue; } auto dataNode = field["Data"]; switch (type) @@ -639,13 +661,15 @@ namespace Prism auto& component = deserializedEntity.AddComponent(); component.BodyType = (RigidBodyComponent::Type)rigidBodyComponent["BodyType"].as(); component.Mass = rigidBodyComponent["Mass"].as(); + component.IsKinematic = rigidBodyComponent["IsKinematic"] ? rigidBodyComponent["IsKinematic"].as() : false; + + component.LockPositionX = rigidBodyComponent["Constraints"]["LockPositionX"].as(); + component.LockPositionY = rigidBodyComponent["Constraints"]["LockPositionY"].as(); + component.LockPositionZ = rigidBodyComponent["Constraints"]["LockPositionZ"].as(); + component.LockRotationX = rigidBodyComponent["Constraints"]["LockRotationX"].as(); + component.LockRotationY = rigidBodyComponent["Constraints"]["LockRotationY"].as(); + component.LockRotationZ = rigidBodyComponent["Constraints"]["LockRotationZ"].as(); - component.LockPositionX = rigidBodyComponent["LockPositionX"] ? rigidBodyComponent["LockPositionX"].as() : false; - component.LockPositionY = rigidBodyComponent["LockPositionY"] ? rigidBodyComponent["LockPositionY"].as() : false; - component.LockPositionZ = rigidBodyComponent["LockPositionZ"] ? rigidBodyComponent["LockPositionZ"].as() : false; - component.LockRotationX = rigidBodyComponent["LockRotationX"] ? rigidBodyComponent["LockRotationX"].as() : false; - component.LockRotationY = rigidBodyComponent["LockRotationY"] ? rigidBodyComponent["LockRotationY"].as() : false; - component.LockRotationZ = rigidBodyComponent["LockRotationZ"] ? rigidBodyComponent["LockRotationZ"].as() : false; } if (auto physicsMaterialComponent = entity["PhysicsMaterialComponent"]) @@ -661,18 +685,33 @@ namespace Prism auto& component = deserializedEntity.AddComponent(); component.Offset = boxColliderComponent["Offset"].as(); component.Size = boxColliderComponent["Size"].as(); + component.IsTrigger = boxColliderComponent["IsTrigger"] ? boxColliderComponent["IsTrigger"].as() : false; + component.DebugMesh = MeshFactory::CreateBox(component.Size); } if (auto sphereColliderComponent = entity["SphereColliderComponent"]) { auto& component = deserializedEntity.AddComponent(); component.Radius = sphereColliderComponent["Radius"].as(); + component.IsTrigger = sphereColliderComponent["IsTrigger"] ? sphereColliderComponent["IsTrigger"].as() : false; + component.DebugMesh = MeshFactory::CreateSphere(component.Radius); + } + + if (auto capsuleColliderComponent = entity["CapsuleColliderComponent"]) + { + auto& component = deserializedEntity.AddComponent(); + component.Radius = capsuleColliderComponent["Radius"].as(); + component.Height = capsuleColliderComponent["Height"].as(); + component.IsTrigger = capsuleColliderComponent["IsTrigger"] ? capsuleColliderComponent["IsTrigger"].as() : false; + component.DebugMesh = MeshFactory::CreateCapsule(component.Radius, component.Height); } if (auto meshColliderComponent = entity["MeshColliderComponent"]) { auto meshPath = meshColliderComponent["AssetPath"].as(); - deserializedEntity.AddComponent(Ref::Create(meshPath)); + auto& component = deserializedEntity.AddComponent(Ref::Create(meshPath)); + component.IsTrigger = meshColliderComponent["IsTrigger"] ? meshColliderComponent["IsTrigger"].as() : false; + PxPhysicsWrappers::CreateConvexMesh(component); PM_CORE_INFO(" Mesh Collider Asset Path: {0}", meshPath); } diff --git a/Prism/src/Prism/Script/ScriptEngine.cpp b/Prism/src/Prism/Script/ScriptEngine.cpp index 68b0eac..87ca3fa 100644 --- a/Prism/src/Prism/Script/ScriptEngine.cpp +++ b/Prism/src/Prism/Script/ScriptEngine.cpp @@ -45,6 +45,7 @@ namespace Prism std::string NamespaceName; MonoClass* Class = nullptr; + MonoMethod* Constructor = nullptr; MonoMethod* OnCreateMethod = nullptr; MonoMethod* OnDestroyMethod = nullptr; MonoMethod* OnUpdateMethod = nullptr; @@ -52,17 +53,22 @@ namespace Prism // Physics MonoMethod* OnCollisionBeginMethod = nullptr; MonoMethod* OnCollisionEndMethod = nullptr; + MonoMethod* OnTriggerBeginMethod = nullptr; + MonoMethod* OnTriggerEndMethod = nullptr; MonoMethod* OnCollision2DBeginMethod = nullptr; MonoMethod* OnCollision2DEndMethod = nullptr; void InitClassMethods(MonoImage* image) { + Constructor = GetMethod(s_CoreAssemblyImage, "Prism.Entity:.ctor(ulong)"); OnCreateMethod = GetMethod(image, FullName + ":OnCreate()"); OnUpdateMethod = GetMethod(image, FullName + ":OnUpdate(single)"); // Physics (Entity class) OnCollision2DBeginMethod = GetMethod(s_CoreAssemblyImage, "Prism.Entity:OnCollision2DBegin(single)"); OnCollision2DEndMethod = GetMethod(s_CoreAssemblyImage, "Prism.Entity:OnCollision2DEnd(single)"); + OnTriggerBeginMethod = GetMethod(s_CoreAssemblyImage, "Prism.Entity:OnTriggerBegin(single)"); + OnTriggerEndMethod = GetMethod(s_CoreAssemblyImage, "Prism.Entity:OnTriggerEnd(single)"); OnCollisionBeginMethod = GetMethod(s_CoreAssemblyImage, "Prism.Entity:OnCollisionBegin(single)"); OnCollisionEndMethod = GetMethod(s_CoreAssemblyImage, "Prism.Entity:OnCollisionEnd(single)"); @@ -415,7 +421,7 @@ namespace Prism return s_SceneContext; } - void ScriptEngine::CopyEntityScriptData(UUID dst, UUID src) + void ScriptEngine::CopyEntityScriptData(const UUID& dst, const UUID& src) { PM_CORE_ASSERT(s_EntityInstanceMap.find(dst) != s_EntityInstanceMap.end()); PM_CORE_ASSERT(s_EntityInstanceMap.find(src) != s_EntityInstanceMap.end()); @@ -442,19 +448,14 @@ namespace Prism void ScriptEngine::OnCreateEntity(Entity entity) { - OnCreateEntity(entity.m_Scene->GetUUID(), entity.GetComponent().ID); - } - - void ScriptEngine::OnCreateEntity(UUID sceneID, UUID entityID) - { - EntityInstance& entityInstance = GetEntityInstanceData(sceneID, entityID).Instance; + EntityInstance& entityInstance = GetEntityInstanceData(entity.GetSceneUUID(), entity.GetUUID()).Instance; if (entityInstance.ScriptClass->OnCreateMethod) CallMethod(entityInstance.GetInstance(), entityInstance.ScriptClass->OnCreateMethod); } - void ScriptEngine::OnUpdateEntity(UUID sceneID, UUID entityID, TimeStep ts) + void ScriptEngine::OnUpdateEntity(Entity entity, TimeStep ts) { - EntityInstance& entityInstance = GetEntityInstanceData(sceneID, entityID).Instance; + EntityInstance& entityInstance = GetEntityInstanceData( entity.GetSceneUUID(), entity.GetUUID()).Instance; if (entityInstance.ScriptClass->OnUpdateMethod) { void* args[] = { &ts }; @@ -462,14 +463,10 @@ namespace Prism } } + void ScriptEngine::OnCollision2DBegin(Entity entity) { - OnCollision2DBegin(entity.m_Scene->GetUUID(), entity.GetComponent().ID); - } - - void ScriptEngine::OnCollision2DBegin(const UUID &sceneID, const UUID &entityID) - { - EntityInstance& entityInstance = GetEntityInstanceData(sceneID, entityID).Instance; + EntityInstance& entityInstance = GetEntityInstanceData(entity.GetSceneUUID(), entity.GetUUID()).Instance; if (entityInstance.ScriptClass->OnCollision2DBeginMethod) { float value = 5.0f; @@ -481,12 +478,7 @@ namespace Prism void ScriptEngine::OnCollision2DEnd(Entity entity) { - OnCollision2DEnd(entity.m_Scene->GetUUID(), entity.GetComponent().ID); - } - - void ScriptEngine::OnCollision2DEnd(const UUID &sceneID, const UUID &entityID) - { - EntityInstance& entityInstance = GetEntityInstanceData(sceneID, entityID).Instance; + EntityInstance& entityInstance = GetEntityInstanceData(entity.GetSceneUUID(), entity.GetUUID()).Instance; if (entityInstance.ScriptClass->OnCollision2DEndMethod) { float value = 5.0f; @@ -498,12 +490,7 @@ namespace Prism void ScriptEngine::OnCollisionBegin(Entity entity) { - OnCollisionBegin(entity.m_Scene->GetUUID(), entity.GetComponent().ID); - } - - void ScriptEngine::OnCollisionBegin(const UUID& sceneID, const UUID& entityID) - { - EntityInstance& entityInstance = GetEntityInstanceData(sceneID, entityID).Instance; + EntityInstance& entityInstance = GetEntityInstanceData(entity.GetSceneUUID(), entity.GetUUID()).Instance; if (entityInstance.ScriptClass->OnCollisionBeginMethod) { float value = 5.0f; @@ -514,12 +501,7 @@ namespace Prism void ScriptEngine::OnCollisionEnd(Entity entity) { - OnCollisionEnd(entity.m_Scene->GetUUID(), entity.GetComponent().ID); - } - - void ScriptEngine::OnCollisionEnd(const UUID& sceneID, const UUID& entityID) - { - EntityInstance& entityInstance = GetEntityInstanceData(sceneID, entityID).Instance; + EntityInstance& entityInstance = GetEntityInstanceData(entity.GetSceneUUID(), entity.GetUUID()).Instance; if (entityInstance.ScriptClass->OnCollisionEndMethod) { float value = 5.0f; @@ -528,6 +510,33 @@ namespace Prism } } + void ScriptEngine::OnTriggerBegin(Entity entity) + { + EntityInstance& entityInstance = GetEntityInstanceData(entity.GetSceneUUID(), entity.GetUUID()).Instance; + if (entityInstance.ScriptClass->OnTriggerBeginMethod) + { + float value = 5.0f; + void* args[] = { &value }; + CallMethod(entityInstance.GetInstance(), entityInstance.ScriptClass->OnTriggerBeginMethod, args); + } + } + + void ScriptEngine::OnTriggerEnd(Entity entity) + { + EntityInstance& entityInstance = GetEntityInstanceData(entity.GetSceneUUID(), entity.GetUUID()).Instance; + if (entityInstance.ScriptClass->OnTriggerEndMethod) + { + float value = 5.0f; + void* args[] = { &value }; + CallMethod(entityInstance.GetInstance(), entityInstance.ScriptClass->OnTriggerEndMethod, args); + } + } + + bool ScriptEngine::IsEntityModuleValid(Entity entity) + { + return entity.HasComponent() && ModuleExists(entity.GetComponent().ModuleName); + } + void ScriptEngine::OnScriptComponentDestroyed(const UUID &sceneID, const UUID &entityID) { PM_CORE_ASSERT(s_EntityInstanceMap.find(sceneID) != s_EntityInstanceMap.end()); @@ -646,11 +655,14 @@ namespace Prism PM_CORE_ASSERT(entityInstance.ScriptClass); entityInstance.Handle = Instantiate(*entityInstance.ScriptClass); + /* MonoProperty* entityIDPropery = mono_class_get_property_from_name(entityInstance.ScriptClass->Class, "ID"); mono_property_get_get_method(entityIDPropery); MonoMethod* entityIDSetMethod = mono_property_get_set_method(entityIDPropery); + */ + void* param[] = { &id }; - CallMethod(entityInstance.GetInstance(), entityIDSetMethod, param); + CallMethod(entityInstance.GetInstance(), entityInstance.ScriptClass->Constructor, param); // Set all public fields to appropriate values ScriptModuleFieldMap& moduleFieldMap = entityInstanceData.ModuleFieldMap; diff --git a/Prism/src/Prism/Script/ScriptEngine.h b/Prism/src/Prism/Script/ScriptEngine.h index 64e568d..8ac10df 100644 --- a/Prism/src/Prism/Script/ScriptEngine.h +++ b/Prism/src/Prism/Script/ScriptEngine.h @@ -112,21 +112,21 @@ namespace Prism static void SetSceneContext(const Ref& scene); static const Ref& GetCurrentSceneContext(); - static void CopyEntityScriptData(UUID dst, UUID src); + static void CopyEntityScriptData(const UUID& dst, const UUID& src); static void OnCreateEntity(Entity entity); - static void OnCreateEntity(UUID sceneID, UUID entityID); - static void OnUpdateEntity(UUID sceneID, UUID entityID, TimeStep ts); + static void OnUpdateEntity(Entity entity, TimeStep ts); static void OnCollision2DBegin(Entity entity); - static void OnCollision2DBegin(const UUID &sceneID, const UUID &entityID); static void OnCollision2DEnd(Entity entity); - static void OnCollision2DEnd(const UUID &sceneID, const UUID &entityID); static void OnCollisionBegin(Entity entity); - static void OnCollisionBegin(const UUID& sceneID, const UUID& entityID); static void OnCollisionEnd(Entity entity); - static void OnCollisionEnd(const UUID& sceneID, const UUID& entityID); + + static void OnTriggerBegin(Entity entityID); + static void OnTriggerEnd(Entity entityID); + + 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 0bbd233..8a1baf5 100644 --- a/Prism/src/Prism/Script/ScriptEngineRegistry.cpp +++ b/Prism/src/Prism/Script/ScriptEngineRegistry.cpp @@ -53,9 +53,20 @@ namespace Prism 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); + + + mono_add_internal_call("Prism.TransformComponent::GetTransform_Native", (const void*)Prism::Script::Prism_Entity_GetTransform); + mono_add_internal_call("Prism.TransformComponent::SetTransform_Native", (const void*)Prism::Script::Prism_Entity_SetTransform); + mono_add_internal_call("Prism.TransformComponent::GetRotation_Native", (const void*)Prism::Script::Prism_TransformComponent_GetRotation); + mono_add_internal_call("Prism.TransformComponent::SetRotation_Native", (const void*)Prism::Script::Prism_TransformComponent_SetRotation); + + /* mono_add_internal_call("Prism.Entity::GetForwardDirection_Native", Prism::Script::Prism_Entity_GetForwardDirection); mono_add_internal_call("Prism.Entity::GetRightDirection_Native", Prism::Script::Prism_Entity_GetRightDirection); mono_add_internal_call("Prism.Entity::GetUpDirection_Native", Prism::Script::Prism_Entity_GetUpDirection); + */ + mono_add_internal_call("Prism.Entity::CreateComponent_Native",(const void*)Prism::Script::Prism_Entity_CreateComponent); mono_add_internal_call("Prism.Entity::HasComponent_Native",(const void*)Prism::Script::Prism_Entity_HasComponent); @@ -64,21 +75,30 @@ namespace Prism mono_add_internal_call("Prism.MeshComponent::GetMesh_Native",(const void*)Prism::Script::Prism_MeshComponent_GetMesh); mono_add_internal_call("Prism.MeshComponent::SetMesh_Native",(const void*)Prism::Script::Prism_MeshComponent_SetMesh); + // Input mono_add_internal_call("Prism.Input::IsKeyPressed_Native", (const void*)Prism::Script::Prism_Input_IsKeyPressed); + 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); + // 2D Physic mono_add_internal_call("Prism.RigidBody2DComponent::ApplyLinearImpulse_Native", (const void*)Prism::Script::Prism_RigidBody2DComponent_ApplyLinearImpulse); mono_add_internal_call("Prism.RigidBody2DComponent::GetLinearVelocity_Native", (const void *)Prism::Script::Prism_RigidBody2DComponent_GetLinearVelocity); mono_add_internal_call("Prism.RigidBody2DComponent::SetLinearVelocity_Native", (const void *)Prism::Script::Prism_RigidBody2DComponent_SetLinearVelocity); + // Renderer + // Texture2D mono_add_internal_call("Prism.Texture2D::Constructor_Native", (const void*)Prism::Script::Prism_Texture2D_Constructor); mono_add_internal_call("Prism.Texture2D::Destructor_Native", (const void*)Prism::Script::Prism_Texture2D_Destructor); mono_add_internal_call("Prism.Texture2D::SetData_Native", (const void*)Prism::Script::Prism_Texture2D_SetData); - mono_add_internal_call("Prism.RigidBodyComponent::AddForce_Native", Prism::Script::Prism_RigidBodyComponent_AddForce); - mono_add_internal_call("Prism.RigidBodyComponent::AddTorque_Native", Prism::Script::Prism_RigidBodyComponent_AddTorque); - mono_add_internal_call("Prism.RigidBodyComponent::GetLinearVelocity_Native", Prism::Script::Prism_RigidBodyComponent_GetLinearVelocity); - mono_add_internal_call("Prism.RigidBodyComponent::SetLinearVelocity_Native", Prism::Script::Prism_RigidBodyComponent_SetLinearVelocity); + mono_add_internal_call("Prism.RigidBodyComponent::AddForce_Native", (const void*)Prism::Script::Prism_RigidBodyComponent_AddForce); + mono_add_internal_call("Prism.RigidBodyComponent::AddTorque_Native", (const void*)Prism::Script::Prism_RigidBodyComponent_AddTorque); + 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); + // Material mono_add_internal_call("Prism.Material::Destructor_Native", (const void*)Prism::Script::Prism_Material_Destructor); mono_add_internal_call("Prism.Material::SetFloat_Native", (const void*)Prism::Script::Prism_Material_SetFloat); mono_add_internal_call("Prism.Material::SetTexture_Native", (const void*)Prism::Script::Prism_Material_SetTexture); diff --git a/Prism/src/Prism/Script/ScriptWarppers.cpp b/Prism/src/Prism/Script/ScriptWarppers.cpp index f270e80..9b8296a 100644 --- a/Prism/src/Prism/Script/ScriptWarppers.cpp +++ b/Prism/src/Prism/Script/ScriptWarppers.cpp @@ -21,6 +21,7 @@ #include "PxRigidActor.h" #include "PxRigidDynamic.h" #include "Prism/Physics/Physics3D.h" +#include "Prism/Physics/PhysicsUtils.h" namespace Prism { extern std::unordered_map> s_HasComponentFuncs; @@ -70,6 +71,22 @@ namespace Prism { namespace Script { return Input::IsKeyPressed(key); } + void Prism_Input_GetMousePosition(glm::vec2* outPosition) + { + auto [x, y] = Input::GetMousePosition(); + *outPosition = { x, y }; + } + + void Prism_Input_SetCursorMode(const CursorMode mode) + { + Input::SetCursorMode(mode); + } + + CursorMode Prism_Input_GetCursorMode() + { + return Input::GetCursorMode(); + } + //////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////// @@ -99,6 +116,8 @@ namespace Prism { namespace Script { auto& transformComponent = entity.GetComponent(); 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(); @@ -140,6 +159,7 @@ namespace Prism { namespace Script { auto [position, rotation, scale] = GetTransformDecomposition(transformComponent.Transform); *outUp = glm::rotate(glm::inverse(glm::normalize(rotation)), glm::vec3(0, 1, 0)); } + */ @@ -181,6 +201,50 @@ namespace Prism { namespace Script { return 0; } + void Prism_TransformComponent_GetRelativeDirection(const uint64_t entityID, glm::vec3* outDirection, const glm::vec3* inAbsoluteDirection) + { + 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); + *outDirection = glm::rotate(glm::normalize(rotation), *inAbsoluteDirection); + } + + void Prism_TransformComponent_GetRotation(const uint64_t entityID, glm::vec3* outRotation) + { + 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); + *outRotation = glm::degrees(glm::eulerAngles(rotation)); + } + + void Prism_TransformComponent_SetRotation(const uint64_t entityID, const glm::vec3* inRotation) + { + 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); + auto& transform = entity.Transform(); + + auto [position, rotation, scale] = GetTransformDecomposition(transform); + transform = glm::translate(glm::mat4(1.0f), position) * + glm::toMat4(glm::quat(glm::radians(*inRotation))) * + glm::scale(glm::mat4(1.0f), scale); + } + void* Prism_MeshComponent_GetMesh(const uint64_t entityID) { Ref scene = ScriptEngine::GetCurrentSceneContext(); @@ -262,14 +326,16 @@ namespace Prism { namespace Script { Entity entity = entityMap.at(entityID); PM_CORE_ASSERT(entity.HasComponent()); - const auto& component = entity.GetComponent(); - physx::PxRigidActor* actor = (physx::PxRigidActor*)component.RuntimeActor; - physx::PxRigidDynamic* dynamicActor = actor->is(); - - // We don't want to assert since scripts might want to be able to switch - // between a static and dynamic actor at runtime - if (!dynamicActor) + const auto& component = entity.GetComponent(); + if (component.IsKinematic) + { + PM_CORE_WARN("Cannot add a force to a kinematic actor! EntityID({0})", entityID); return; + } + + auto* actor = static_cast(component.RuntimeActor); + auto* dynamicActor = actor->is(); + PM_CORE_ASSERT(dynamicActor); PM_CORE_ASSERT(force); dynamicActor->addForce({ force->x, force->y, force->z }, (physx::PxForceMode::Enum)forceMode); @@ -284,14 +350,16 @@ namespace Prism { namespace Script { Entity entity = entityMap.at(entityID); PM_CORE_ASSERT(entity.HasComponent()); - const auto& component = entity.GetComponent(); - physx::PxRigidActor* actor = (physx::PxRigidActor*)component.RuntimeActor; - physx::PxRigidDynamic* dynamicActor = actor->is(); - - // We don't want to assert since scripts might want to be able to switch - // between a static and dynamic actor at runtime - if (!dynamicActor) + const auto& component = entity.GetComponent(); + if (component.IsKinematic) + { + PM_CORE_WARN("Cannot add torque to a kinematic actor! EntityID({0})", entityID); return; + } + + const auto actor = static_cast(component.RuntimeActor); + auto* dynamicActor = actor->is(); + PM_CORE_ASSERT(dynamicActor); PM_CORE_ASSERT(torque); dynamicActor->addTorque({ torque->x, torque->y, torque->z }, (physx::PxForceMode::Enum)forceMode); @@ -306,14 +374,17 @@ namespace Prism { namespace Script { Entity entity = entityMap.at(entityID); PM_CORE_ASSERT(entity.HasComponent()); - const auto& component = entity.GetComponent(); - physx::PxRigidActor* actor = (physx::PxRigidActor*)component.RuntimeActor; - const physx::PxRigidDynamic* dynamicActor = actor->is(); - - // We don't want to assert since scripts might want to be able to switch - // between a static and dynamic actor at runtime - if (!dynamicActor) + const auto& component = entity.GetComponent(); + if (component.IsKinematic) + { + PM_CORE_WARN("Cannot add torque to a kinematic actor! EntityID({0})", entityID); return; + } + + const auto actor = static_cast(component.RuntimeActor); + const physx::PxRigidDynamic* dynamicActor = actor->is(); + PM_CORE_ASSERT(dynamicActor); + PM_CORE_ASSERT(outVelocity); physx::PxVec3 velocity = dynamicActor->getLinearVelocity(); @@ -329,19 +400,44 @@ namespace Prism { namespace Script { Entity entity = entityMap.at(entityID); PM_CORE_ASSERT(entity.HasComponent()); - const auto& component = entity.GetComponent(); - physx::PxRigidActor* actor = (physx::PxRigidActor*)component.RuntimeActor; - physx::PxRigidDynamic* dynamicActor = actor->is(); - - // We don't want to assert since scripts might want to be able to switch - // between a static and dynamic actor at runtime - if (!dynamicActor) + const auto& component = entity.GetComponent(); + if (component.IsKinematic) + { + PM_CORE_WARN("Cannot add torque to a kinematic actor! EntityID({0})", entityID); return; + } + + const auto actor = static_cast(component.RuntimeActor); + auto* dynamicActor = actor->is(); + PM_CORE_ASSERT(dynamicActor); PM_CORE_ASSERT(velocity); dynamicActor->setLinearVelocity({ velocity->x, velocity->y, velocity->z }); } + void Prism_RigidBodyComponent_Rotate(uint64_t entityID, glm::vec3* rotation) + { + 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); + auto* dynamicActor = actor->is(); + PM_CORE_ASSERT(dynamicActor); + + physx::PxTransform transform = dynamicActor->getGlobalPose(); + transform.q *= (physx::PxQuat(glm::radians(rotation->x), { 1.0F, 0.0F, 0.0F }) + * physx::PxQuat(glm::radians(rotation->y), { 0.0F, 1.0F, 0.0F }) + * physx::PxQuat(glm::radians(rotation->z), { 0.0F, 0.0F, 1.0F })); + + dynamicActor->setGlobalPose(transform); + } + Ref* Prism_Mesh_Constructor(MonoString* filepath) { @@ -350,7 +446,7 @@ namespace Prism { namespace Script { void Prism_Mesh_Destructor(Ref* _this) { - Ref* instance = (Ref*)_this; + const Ref* instance = (Ref*)_this; delete _this; } diff --git a/Prism/src/Prism/Script/ScriptWarppers.h b/Prism/src/Prism/Script/ScriptWarppers.h index 0c0fd80..aa155c2 100644 --- a/Prism/src/Prism/Script/ScriptWarppers.h +++ b/Prism/src/Prism/Script/ScriptWarppers.h @@ -4,6 +4,7 @@ #ifndef SCRIPTWARPPERS_H #define SCRIPTWARPPERS_H +#include "Prism/Core/Input.h" #include "Prism/Core/KeyCodes.h" #include "Prism/Core/Ref.h" #include "Prism/Physics/Physics3D.h" @@ -23,30 +24,37 @@ namespace Prism { namespace Script { // Input bool Prism_Input_IsKeyPressed(KeyCode key); + void Prism_Input_GetMousePosition(glm::vec2* outPosition); + void Prism_Input_SetCursorMode(CursorMode mode); + CursorMode Prism_Input_GetCursorMode(); // Entity - 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_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_MeshComponent_GetMesh(uint64_t entityID); - void Prism_MeshComponent_SetMesh(uint64_t entityID, const Ref* inMesh); + void Prism_TransformComponent_GetRelativeDirection(uint64_t entityID, glm::vec3* outDirection, const glm::vec3* inAbsoluteDirection); + void Prism_TransformComponent_GetRotation(uint64_t entityID,glm::vec3* outRotation); + void Prism_TransformComponent_SetRotation(uint64_t entityID,const glm::vec3* inRotation); // 2D Physic void Prism_RigidBody2DComponent_ApplyLinearImpulse(uint64_t entityID, const glm::vec2* impulse, const glm::vec2* offset, bool wake); void Prism_RigidBody2DComponent_GetLinearVelocity(uint64_t entityID, glm::vec2* outVelocity); void Prism_RigidBody2DComponent_SetLinearVelocity(uint64_t entityID, const glm::vec2* velocity); + // 3D Physic void Prism_RigidBodyComponent_AddForce(uint64_t entityID, glm::vec3* force, ForceMode forceMode); void Prism_RigidBodyComponent_AddTorque(uint64_t entityID, glm::vec3* torque, ForceMode forceMode); 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); // Renderer // Texture2D @@ -73,6 +81,9 @@ namespace Prism { namespace Script { int Prism_Mesh_GetMaterialCount(Ref* inMesh); void* Prism_MeshFactory_CreatePlane(float width, float height); + + void* Prism_MeshComponent_GetMesh(uint64_t entityID); + void Prism_MeshComponent_SetMesh(uint64_t entityID, const Ref* inMesh); } }