add physX colliders ,add trigger, colliders now can visible, some rotation for cs and native cpp connection

This commit is contained in:
2025-12-24 10:10:24 +08:00
parent 00d3993a77
commit f747db4e27
44 changed files with 2322 additions and 860 deletions

View File

@ -9,6 +9,7 @@
#include "glm/gtx/matrix_decompose.hpp" #include "glm/gtx/matrix_decompose.hpp"
#include "Prism/Core/Input.h" #include "Prism/Core/Input.h"
#include "Prism/Physics/Physics3D.h"
#include "Prism/Renderer/Renderer2D.h" #include "Prism/Renderer/Renderer2D.h"
#include "Prism/Script/ScriptEngine.h" #include "Prism/Script/ScriptEngine.h"
@ -172,7 +173,7 @@ namespace Prism
m_CheckerboardTex = Texture2D::Create("assets/editor/Checkerboard.tga"); m_CheckerboardTex = Texture2D::Create("assets/editor/Checkerboard.tga");
m_PlayButtonTex = Texture2D::Create("assets/editor/PlayButton.png"); m_PlayButtonTex = Texture2D::Create("assets/editor/PlayButton.png");
m_EditorScene = Ref<Scene>::Create(); m_EditorScene = Ref<Scene>::Create("untitled Scene", true);
ScriptEngine::SetSceneContext(m_EditorScene); ScriptEngine::SetSceneContext(m_EditorScene);
m_SceneHierarchyPanel = CreateScope<SceneHierarchyPanel>(m_EditorScene); m_SceneHierarchyPanel = CreateScope<SceneHierarchyPanel>(m_EditorScene);
m_SceneHierarchyPanel->SetSelectionChangedCallback(std::bind(&EditorLayer::SelectEntity, this, std::placeholders::_1)); m_SceneHierarchyPanel->SetSelectionChangedCallback(std::bind(&EditorLayer::SelectEntity, this, std::placeholders::_1));
@ -199,7 +200,7 @@ namespace Prism
if (m_DrawOnTopBoundingBoxes) if (m_DrawOnTopBoundingBoxes)
{ {
Renderer::BeginRenderPass(SceneRenderer::GetFinalRenderPass(), false); Renderer::BeginRenderPass(SceneRenderer::GetFinalRenderPass(), false);
auto viewProj = m_EditorCamera.GetViewProjection(); const auto viewProj = m_EditorCamera.GetViewProjection();
Renderer2D::BeginScene(viewProj, false); Renderer2D::BeginScene(viewProj, false);
// TODO: Renderer::DrawAABB(m_MeshEntity.GetComponent<MeshComponent>(), m_MeshEntity.GetComponent<TransformComponent>()); // TODO: Renderer::DrawAABB(m_MeshEntity.GetComponent<MeshComponent>(), m_MeshEntity.GetComponent<TransformComponent>());
Renderer2D::EndScene(); Renderer2D::EndScene();
@ -233,7 +234,7 @@ namespace Prism
const glm::vec3 rotation = glm::eulerAngles(rotationQuat); const glm::vec3 rotation = glm::eulerAngles(rotationQuat);
Renderer::BeginRenderPass(SceneRenderer::GetFinalRenderPass(), false); Renderer::BeginRenderPass(SceneRenderer::GetFinalRenderPass(), false);
auto viewProj = m_EditorCamera.GetViewProjection(); const auto viewProj = m_EditorCamera.GetViewProjection();
Renderer2D::BeginScene(viewProj, false); 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::DrawRotatedQuad({ translation.x, translation.y }, size * 2.0f, glm::degrees(rotation.z), { 1.0f, 0.0f, 1.0f, 1.0f });
Renderer2D::EndScene(); Renderer2D::EndScene();
@ -360,6 +361,21 @@ namespace Prism
ImGui::EndMenu(); 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(); ImGui::EndMenuBar();
} }
@ -914,8 +930,8 @@ namespace Prism
glm::inverse(glm::mat3(entity.Transform()) * glm::mat3(submesh.Transform)) * direction glm::inverse(glm::mat3(entity.Transform()) * glm::mat3(submesh.Transform)) * direction
}; };
float t; float t = 0;
if (bool intersects = ray.IntersectsAABB(submesh.BoundingBox, t)) if (ray.IntersectsAABB(submesh.BoundingBox, t))
{ {
const auto& triangleCache = mesh->GetTriangleCache(i); const auto& triangleCache = mesh->GetTriangleCache(i);
for (const auto& triangle : triangleCache) for (const auto& triangle : triangleCache)
@ -1029,10 +1045,10 @@ namespace Prism
void EditorLayer::OpenScene() void EditorLayer::OpenScene()
{ {
const auto& app = Application::Get(); 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()) if (!filepath.empty())
{ {
const Ref<Scene> newScene = Ref<Scene>::Create(); const Ref<Scene> newScene = Ref<Scene>::Create("EditorScene", true);
SceneSerializer serializer(newScene); SceneSerializer serializer(newScene);
serializer.Deserialize(filepath); serializer.Deserialize(filepath);
m_EditorScene = newScene; m_EditorScene = newScene;
@ -1057,7 +1073,7 @@ namespace Prism
void EditorLayer::SaveSceneAs() void EditorLayer::SaveSceneAs()
{ {
auto& app = Application::Get(); 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()) if (!filepath.empty())
{ {
SceneSerializer serializer(m_EditorScene); SceneSerializer serializer(m_EditorScene);

Binary file not shown.

View File

@ -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

View File

@ -18,6 +18,14 @@ Entities:
RigidBodyComponent: RigidBodyComponent:
BodyType: 1 BodyType: 1
Mass: 0.5 Mass: 0.5
IsKinematic: false
Constraints:
LockPositionX: false
LockPositionY: false
LockPositionZ: false
LockRotationX: true
LockRotationY: true
LockRotationZ: true
PhysicsMaterialComponent: PhysicsMaterialComponent:
StaticFriction: 1 StaticFriction: 1
DynamicFriction: 1 DynamicFriction: 1
@ -49,6 +57,14 @@ Entities:
RigidBodyComponent: RigidBodyComponent:
BodyType: 1 BodyType: 1
Mass: 1 Mass: 1
IsKinematic: false
Constraints:
LockPositionX: false
LockPositionY: false
LockPositionZ: false
LockRotationX: true
LockRotationY: true
LockRotationZ: true
PhysicsMaterialComponent: PhysicsMaterialComponent:
StaticFriction: 1 StaticFriction: 1
DynamicFriction: 1 DynamicFriction: 1
@ -86,6 +102,14 @@ Entities:
RigidBodyComponent: RigidBodyComponent:
BodyType: 0 BodyType: 0
Mass: 1 Mass: 1
IsKinematic: false
Constraints:
LockPositionX: false
LockPositionY: false
LockPositionZ: false
LockRotationX: true
LockRotationY: true
LockRotationZ: true
PhysicsMaterialComponent: PhysicsMaterialComponent:
StaticFriction: 1 StaticFriction: 1
DynamicFriction: 1 DynamicFriction: 1

View File

@ -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);
}

115
ExampleApp/Src/FPSPlayer.cs Normal file
View File

@ -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<TransformComponent>();
m_RigidBody = GetComponent<RigidBodyComponent>();
m_CurrentSpeed = WalkingSpeed;
AddCollisionBeginCallback((n) => { m_Colliding = true; });
AddCollisionEndCallback((n) => { m_Colliding = false; });
m_CameraEntity = FindEntityByTag("Camera");
m_CameraTransform = m_CameraEntity.GetComponent<TransformComponent>();
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);
}
}
}

View File

@ -22,9 +22,11 @@ namespace Example
private bool Colliding => m_CollisionCounter > 0; private bool Colliding => m_CollisionCounter > 0;
private TransformComponent m_Transform;
void OnCreate() void OnCreate()
{ {
m_PhysicsBody = GetComponent<RigidBodyComponent>(); m_PhysicsBody = GetComponent<RigidBodyComponent>();
m_Transform = GetComponent<TransformComponent>();
MeshComponent meshComponent = GetComponent<MeshComponent>(); MeshComponent meshComponent = GetComponent<MeshComponent>();
m_MeshMaterial = meshComponent.Mesh.GetMaterial(0); m_MeshMaterial = meshComponent.Mesh.GetMaterial(0);
@ -32,6 +34,8 @@ namespace Example
AddCollisionBeginCallback(OnPlayerCollisionBegin); AddCollisionBeginCallback(OnPlayerCollisionBegin);
AddCollisionEndCallback(OnPlayerCollisionEnd); AddCollisionEndCallback(OnPlayerCollisionEnd);
AddTriggerBeginCallback(OnPlayerTriggerBegin);
AddTriggerEndCallback(OnPlayerTriggerEnd);
} }
void OnPlayerCollisionBegin(float value) void OnPlayerCollisionBegin(float value)
@ -44,6 +48,16 @@ namespace Example
m_CollisionCounter--; m_CollisionCounter--;
} }
void OnPlayerTriggerBegin(float value)
{
Console.WriteLine("Player trigger begin");
}
void OnPlayerTriggerEnd(float value)
{
Console.WriteLine("Player trigger end");
}
void OnUpdate(float ts) void OnUpdate(float ts)
{ {
float movementForce = HorizontalForce; float movementForce = HorizontalForce;
@ -53,22 +67,18 @@ namespace Example
movementForce *= 0.4f; movementForce *= 0.4f;
} }
Vec3 forward = GetForwardDirection();
Vec3 right = GetRightDirection();
Vec3 up = GetUpDirection();
if (Input.IsKeyPressed(KeyCode.W)) if (Input.IsKeyPressed(KeyCode.W))
m_PhysicsBody.AddForce(forward * movementForce); m_PhysicsBody.AddForce(m_Transform.Forward * movementForce);
else if (Input.IsKeyPressed(KeyCode.S)) else if (Input.IsKeyPressed(KeyCode.S))
m_PhysicsBody.AddForce(forward * -movementForce); m_PhysicsBody.AddForce(m_Transform.Forward * -movementForce);
if (Input.IsKeyPressed(KeyCode.D)) if (Input.IsKeyPressed(KeyCode.D))
m_PhysicsBody.AddForce(right * movementForce); m_PhysicsBody.AddForce(m_Transform.Right * movementForce);
else if (Input.IsKeyPressed(KeyCode.A)) else if (Input.IsKeyPressed(KeyCode.A))
m_PhysicsBody.AddForce(right * -movementForce); m_PhysicsBody.AddForce(m_Transform.Right * -movementForce);
if (Colliding && Input.IsKeyPressed(KeyCode.Space)) if (Colliding && Input.IsKeyPressed(KeyCode.Space))
m_PhysicsBody.AddForce(up * JumpForce); m_PhysicsBody.AddForce(m_Transform.Up * JumpForce);
if (Colliding) if (Colliding)
m_MeshMaterial.Set("u_AlbedoColor", new Vec3(1.0f, 0.0f, 0.0f)); m_MeshMaterial.Set("u_AlbedoColor", new Vec3(1.0f, 0.0f, 0.0f));

View File

@ -11,10 +11,12 @@ namespace Prism
{ {
} }
private List<Action<float>> m_Collision2DBeginCallbacks = new List<Action<float>>(); private Action<float>? m_CollisionBeginCallbacks;
private List<Action<float>> m_Collision2DEndCallbacks = new List<Action<float>>(); private Action<float>? m_CollisionEndCallbacks;
private Action<float> m_CollisionBeginCallbacks; private Action<float>? m_Collision2DBeginCallbacks;
private Action<float> m_CollisionEndCallbacks; private Action<float>? m_Collision2DEndCallbacks;
private Action<float>? m_TriggerBeginCallbacks;
private Action<float>? m_TriggerEndCallbacks;
protected Entity() { ID = 0; } protected Entity() { ID = 0; }
@ -65,32 +67,14 @@ namespace Prism
SetTransform_Native(ID, ref transform); 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<float> callback) public void AddCollision2DBeginCallback(Action<float> callback)
{ {
m_Collision2DBeginCallbacks.Add(callback); m_Collision2DBeginCallbacks += callback;
} }
public void AddCollision2DEndCallback(Action<float> callback) public void AddCollision2DEndCallback(Action<float> callback)
{ {
m_Collision2DEndCallbacks.Add(callback); m_Collision2DEndCallbacks += callback;
} }
public void AddCollisionBeginCallback(Action<float> callback) public void AddCollisionBeginCallback(Action<float> callback)
@ -103,6 +87,16 @@ namespace Prism
m_CollisionEndCallbacks += callback; m_CollisionEndCallbacks += callback;
} }
public void AddTriggerBeginCallback(Action<float> callback)
{
m_TriggerBeginCallbacks += callback;
}
public void AddTriggerEndCallback(Action<float> callback)
{
m_TriggerEndCallbacks += callback;
}
private void OnCollisionBegin(float data) private void OnCollisionBegin(float data)
{ {
if (m_CollisionBeginCallbacks != null) if (m_CollisionBeginCallbacks != null)
@ -117,16 +111,29 @@ namespace Prism
private void OnCollision2DBegin(float data) private void OnCollision2DBegin(float data)
{ {
foreach (var callback in m_Collision2DBeginCallbacks) if(m_Collision2DBeginCallbacks != null)
callback.Invoke(data); m_Collision2DBeginCallbacks.Invoke(data);
} }
private void OnCollision2DEnd(float data) private void OnCollision2DEnd(float data)
{ {
foreach (var callback in m_Collision2DEndCallbacks) if(m_Collision2DEndCallbacks != null)
callback.Invoke(data); 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)] [MethodImpl(MethodImplOptions.InternalCall)]
private static extern void CreateComponent_Native(ulong entityID, Type type); private static extern void CreateComponent_Native(ulong entityID, Type type);
[MethodImpl(MethodImplOptions.InternalCall)] [MethodImpl(MethodImplOptions.InternalCall)]
@ -137,12 +144,5 @@ namespace Prism
private static extern void SetTransform_Native(ulong entityID, ref Mat4 matrix); private static extern void SetTransform_Native(ulong entityID, ref Mat4 matrix);
[MethodImpl(MethodImplOptions.InternalCall)] [MethodImpl(MethodImplOptions.InternalCall)]
private static extern ulong FindEntityByTag_Native(string tag); 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);
} }
} }

View File

@ -4,14 +4,39 @@ namespace Prism
{ {
public class Input public class Input
{ {
public enum CursorMode
{
Normal = 0,
Hidden = 1,
Locked = 2,
}
public static bool IsKeyPressed(KeyCode keycode) public static bool IsKeyPressed(KeyCode keycode)
{ {
return IsKeyPressed_Native(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)] [MethodImpl(MethodImplOptions.InternalCall)]
private static extern bool IsKeyPressed_Native(KeyCode keycode); 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();
} }
} }

View File

@ -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);
}
}
}

View File

@ -25,20 +25,23 @@ namespace Prism
} }
public void Clamp(Vec2 min, Vec2 max) { public void Clamp(Vec2 min, Vec2 max) {
if (X < min.X) X = Mathf.Clamp(X, min.X, max.X);
X = min.X; Y = Mathf.Clamp(Y, min.Y, max.Y);
if (X > max.X)
X = max.X;
if (Y < min.Y)
Y = min.Y;
if (Y > max.Y)
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) public static Vec2 operator -(Vec2 vector)
{ {
return new Vec2(-vector.X, -vector.Y); return new Vec2(-vector.X, -vector.Y);
} }
public override string ToString()
{
return $"({X}, {Y})";
}
} }
} }

View File

@ -5,6 +5,12 @@ namespace Prism
[StructLayout(LayoutKind.Sequential)] [StructLayout(LayoutKind.Sequential)]
public struct Vec3 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 X;
public float Y; public float Y;
public float Z; public float Z;
@ -40,15 +46,6 @@ namespace Prism
Z = Mathf.Clamp(Z, min.Z, max.Z); 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 { public Vec2 XY {
get { return new Vec2(X, Y); } get { return new Vec2(X, Y); }
@ -66,5 +63,56 @@ namespace Prism
set { Y = value.X; Z = value.Y; } 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})";
}
} }
} }

View File

@ -2,13 +2,13 @@ using System.Runtime.InteropServices;
namespace Prism namespace Prism
{ {
[StructLayout(LayoutKind.Explicit)] [StructLayout(LayoutKind.Sequential)]
public struct Vec4 public struct Vec4
{ {
[FieldOffset(0)] public float X; public float X;
[FieldOffset(4)] public float Y; public float Y;
[FieldOffset(8)] public float Z; public float Z;
[FieldOffset(12)] public float W; public float W;
public Vec4(float scalar) public Vec4(float scalar)
{ {

View File

@ -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;
}
}
}

View File

@ -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)] [MethodImpl(MethodImplOptions.InternalCall)]
public static extern void GetTransform_Native(ulong entityID, out Mat4 result); public static extern void GetTransform_Native(ulong entityID, out Mat4 result);
[MethodImpl(MethodImplOptions.InternalCall)] [MethodImpl(MethodImplOptions.InternalCall)]
public static extern void SetTransform_Native(ulong entityID, ref Mat4 result); 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); SetLinearVelocity_Native(Entity.ID, ref velocity);
} }
public void Rotate(Vec3 rotation)
{
Rotate_Native(Entity.ID, ref rotation);
}
// TODO: Add SetMaxLinearVelocity() as well // TODO: Add SetMaxLinearVelocity() as well
[MethodImpl(MethodImplOptions.InternalCall)] [MethodImpl(MethodImplOptions.InternalCall)]
@ -174,5 +231,8 @@ namespace Prism
internal static extern void GetLinearVelocity_Native(ulong entityID, out Vec3 velocity); internal static extern void GetLinearVelocity_Native(ulong entityID, out Vec3 velocity);
[MethodImpl(MethodImplOptions.InternalCall)] [MethodImpl(MethodImplOptions.InternalCall)]
internal static extern void SetLinearVelocity_Native(ulong entityID, ref Vec3 velocity); 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);
} }
} }

View File

@ -56,6 +56,11 @@ namespace Prism
#define PM_CORE_ASSERT(x, ...) #define PM_CORE_ASSERT(x, ...)
#endif #endif
#ifndef M_PI
#define M_PI 3.1415926f
#endif
namespace Prism namespace Prism
{ {
using byte = unsigned char; using byte = unsigned char;

View File

@ -9,6 +9,13 @@
namespace Prism namespace Prism
{ {
enum class CursorMode
{
Normal = 0,
Hidden = 1,
Locked = 2
};
class PRISM_API Input class PRISM_API Input
{ {
public: public:
@ -18,6 +25,9 @@ namespace Prism
static float GetMouseX(); static float GetMouseX();
static float GetMouseY(); static float GetMouseY();
static std::pair<float, float> GetMousePosition(); static std::pair<float, float> GetMousePosition();
static void SetCursorMode(CursorMode mode);
static CursorMode GetCursorMode();
}; };
} }

View File

@ -14,9 +14,6 @@
#include "Prism/Core/Input.h" #include "Prism/Core/Input.h"
#include "Prism/Core/Events/MouseEvent.h" #include "Prism/Core/Events/MouseEvent.h"
#ifndef M_PI
#define M_PI 3.1415926f
#endif
namespace Prism namespace Prism
{ {

View File

@ -7,10 +7,13 @@
#include "imgui.h" #include "imgui.h"
#include "assimp/matrix4x4.h" #include "assimp/matrix4x4.h"
#define GLM_ENABLE_EXPERIMENTAL #define GLM_ENABLE_EXPERIMENTAL
#include "imgui_internal.h"
#include "assimp/scene.h" #include "assimp/scene.h"
#include "glm/gtx/matrix_decompose.hpp" #include "glm/gtx/matrix_decompose.hpp"
#include "glm/gtx/quaternion.hpp" #include "glm/gtx/quaternion.hpp"
#include "Prism/Core/Application.h" #include "Prism/Core/Application.h"
#include "Prism/Physics/PxPhysicsWrappers.h"
#include "Prism/Renderer/Meshfactory.h"
#include "Prism/Script/ScriptEngine.h" #include "Prism/Script/ScriptEngine.h"
namespace Prism namespace Prism
@ -42,6 +45,19 @@ namespace Prism
m_SelectionContext = entity; m_SelectionContext = entity;
} }
template<class T>
void SceneHierarchyPanel::AddComponentPopup(const char* componentName)
{
if (!m_SelectionContext.HasComponent<T>())
{
if (ImGui::Button(componentName))
{
m_SelectionContext.AddComponent<T>();
ImGui::CloseCurrentPopup();
}
}
}
void SceneHierarchyPanel::OnImGuiRender() void SceneHierarchyPanel::OnImGuiRender()
{ {
ImGui::Begin("Scene Hierarchy"); ImGui::Begin("Scene Hierarchy");
@ -79,6 +95,21 @@ namespace Prism
if (ImGui::BeginPopup("AddComponentPanel")) if (ImGui::BeginPopup("AddComponentPanel"))
{ {
AddComponentPopup<CameraComponent>("Camera");
AddComponentPopup<MeshComponent>("Mesh");
AddComponentPopup<ScriptComponent>("Script");
AddComponentPopup<SpriteRendererComponent>("SpriteRenderer");
AddComponentPopup<RigidBody2DComponent>("RigidBody2D");
AddComponentPopup<BoxCollider2DComponent>("BoxCollider2D");
AddComponentPopup<CircleCollider2DComponent>("CircleCollider2D");
AddComponentPopup<RigidBodyComponent>("RigidBody");
AddComponentPopup<PhysicsMaterialComponent>("PhysicsMaterial");
AddComponentPopup<BoxColliderComponent>("BoxCollider");
AddComponentPopup<SphereColliderComponent>("SphereCollider");
AddComponentPopup<CapsuleColliderComponent>("CapsuleCollider");
AddComponentPopup<MeshColliderComponent>("MeshCollider");
/*
if (!m_SelectionContext.HasComponent<CameraComponent>()) if (!m_SelectionContext.HasComponent<CameraComponent>())
{ {
if (ImGui::Button("Camera")) if (ImGui::Button("Camera"))
@ -168,6 +199,15 @@ namespace Prism
} }
} }
if (!m_SelectionContext.HasComponent<CapsuleColliderComponent>())
{
if (ImGui::Button("Capsule Collider"))
{
m_SelectionContext.AddComponent<CapsuleColliderComponent>();
ImGui::CloseCurrentPopup();
}
}
if (!m_SelectionContext.HasComponent<MeshColliderComponent>()) if (!m_SelectionContext.HasComponent<MeshColliderComponent>())
{ {
if (ImGui::Button("Mesh Collider")) if (ImGui::Button("Mesh Collider"))
@ -176,6 +216,7 @@ namespace Prism
ImGui::CloseCurrentPopup(); ImGui::CloseCurrentPopup();
} }
} }
*/
ImGui::EndPopup(); ImGui::EndPopup();
} }
@ -334,6 +375,7 @@ namespace Prism
{ {
PushID(); PushID();
ImGui::Columns(2); ImGui::Columns(2);
ImGui::SetColumnWidth(0, 100);
} }
static bool Property(const char* label, std::string& value, bool error = false) static bool Property(const char* label, std::string& value, bool error = false)
@ -434,7 +476,7 @@ namespace Prism
return modified; 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; bool modified = false;
@ -448,7 +490,7 @@ namespace Prism
// itoa(s_Counter++, s_IDBuffer + 2, 16); // itoa(s_Counter++, s_IDBuffer + 2, 16);
snprintf(s_IDBuffer + 2, 14, "%x", s_Counter++); 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; modified = true;
ImGui::PopItemWidth(); ImGui::PopItemWidth();
@ -640,8 +682,12 @@ namespace Prism
ImGui::NextColumn(); ImGui::NextColumn();
ImGui::PushItemWidth(-1); 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; updateTransform = true;
} }
@ -850,13 +896,13 @@ namespace Prism
DrawComponent<RigidBody2DComponent>("Rigidbody 2D", entity, [](RigidBody2DComponent& rb2dComponent) DrawComponent<RigidBody2DComponent>("Rigidbody 2D", entity, [](RigidBody2DComponent& rb2dComponent)
{ {
// Rigidbody2D Type // Rigidbody2D Type
const char* rb2dTypeStrings[] = { "Static", "Dynamic", "Kinematic" }; const char* rb2dTypeStrings[] = { "Static", "Dynamic"};
const char* currentType = rb2dTypeStrings[(int)rb2dComponent.BodyType]; const char* currentType = rb2dTypeStrings[(int)rb2dComponent.BodyType];
if (ImGui::BeginCombo("Type", currentType)) 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)) if (ImGui::Selectable(rb2dTypeStrings[type], is_selected))
{ {
currentType = rb2dTypeStrings[type]; currentType = rb2dTypeStrings[type];
@ -903,11 +949,11 @@ namespace Prism
DrawComponent<RigidBodyComponent>("Rigidbody", entity, [](RigidBodyComponent& rbc) DrawComponent<RigidBodyComponent>("Rigidbody", entity, [](RigidBodyComponent& rbc)
{ {
// Rigidbody Type // Rigidbody Type
const char* rbTypeStrings[] = { "Static", "Dynamic", "Kinematic" }; const char* rbTypeStrings[] = { "Static", "Dynamic"};
const char* currentType = rbTypeStrings[(int)rbc.BodyType]; const char* currentType = rbTypeStrings[(int)rbc.BodyType];
if (ImGui::BeginCombo("Type", currentType)) 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]); bool is_selected = (currentType == rbTypeStrings[type]);
if (ImGui::Selectable(rbTypeStrings[type], is_selected)) if (ImGui::Selectable(rbTypeStrings[type], is_selected))
@ -925,20 +971,23 @@ namespace Prism
{ {
BeginPropertyGrid(); BeginPropertyGrid();
Property("Mass", rbc.Mass); Property("Mass", rbc.Mass);
Property("Is Kinematic", rbc.IsKinematic);
EndPropertyGrid();
if (ImGui::TreeNode("RigidBodyConstraints", "Constraints")) if (ImGui::TreeNode("RigidBodyConstraints", "Constraints"))
{ {
BeginPropertyGrid();
Property("Position: X", rbc.LockPositionX); Property("Position: X", rbc.LockPositionX);
Property("Position: Y", rbc.LockPositionY); Property("Position: Y", rbc.LockPositionY);
Property("Position: Z", rbc.LockPositionZ); Property("Position: Z", rbc.LockPositionZ);
Property("Rotation: X", rbc.LockRotationX); Property("Rotation: X", rbc.LockRotationX);
Property("Rotation: Y", rbc.LockRotationY); Property("Rotation: Y", rbc.LockRotationY);
Property("Rotation: Z", rbc.LockRotationZ); Property("Rotation: Z", rbc.LockRotationZ);
EndPropertyGrid();
ImGui::TreePop(); ImGui::TreePop();
} }
EndPropertyGrid();
} }
}); });
@ -946,9 +995,9 @@ namespace Prism
{ {
BeginPropertyGrid(); BeginPropertyGrid();
Property("Static Friction", pmc.StaticFriction); Property("Static Friction", pmc.StaticFriction, 0.01f, 0.0f, 1.0f);
Property("Dynamic Friction", pmc.DynamicFriction); Property("Dynamic Friction", pmc.DynamicFriction, 0.01f, 0.0f, 1.0f);
Property("Bounciness", pmc.Bounciness); Property("Bounciness", pmc.Bounciness, 0.01f, 0.0f, 1.0f);
EndPropertyGrid(); EndPropertyGrid();
}); });
@ -957,8 +1006,12 @@ namespace Prism
{ {
BeginPropertyGrid(); BeginPropertyGrid();
Property("Size", bcc.Size); if (Property("Size", bcc.Size))
//Property("Offset", bcc.Offset); {
bcc.DebugMesh = MeshFactory::CreateBox(bcc.Size);
}
Property("IsTrigger", bcc.IsTrigger);
EndPropertyGrid(); EndPropertyGrid();
}); });
@ -967,22 +1020,47 @@ namespace Prism
{ {
BeginPropertyGrid(); BeginPropertyGrid();
Property("Radius", scc.Radius); if (Property("Radius", scc.Radius))
{
scc.DebugMesh = MeshFactory::CreateSphere(scc.Radius);
}
Property("IsTrigger", scc.IsTrigger);
EndPropertyGrid(); EndPropertyGrid();
}); });
DrawComponent<MeshColliderComponent>("Mesh Collider", entity, [](MeshColliderComponent& mc) DrawComponent<CapsuleColliderComponent>("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<MeshColliderComponent>("Mesh Collider", entity, [](MeshColliderComponent& mcc)
{ {
ImGui::Columns(3); ImGui::Columns(3);
ImGui::SetColumnWidth(0, 100); ImGui::SetColumnWidth(0, 100);
ImGui::SetColumnWidth(1, 300); ImGui::SetColumnWidth(1, 250);
ImGui::SetColumnWidth(2, 40); ImGui::SetColumnWidth(2, 40);
ImGui::Text("File Path"); ImGui::Text("File Path");
ImGui::NextColumn(); ImGui::NextColumn();
ImGui::PushItemWidth(-1); ImGui::PushItemWidth(-1);
if (mc.CollisionMesh) if (mcc.CollisionMesh)
ImGui::InputText("##meshfilepath", (char*)mc.CollisionMesh->GetFilePath().c_str(), 256, ImGuiInputTextFlags_ReadOnly); ImGui::InputText("##meshfilepath", (char*)mcc.CollisionMesh->GetFilePath().c_str(), 256, ImGuiInputTextFlags_ReadOnly);
else else
ImGui::InputText("##meshfilepath", (char*)"Null", 256, ImGuiInputTextFlags_ReadOnly); ImGui::InputText("##meshfilepath", (char*)"Null", 256, ImGuiInputTextFlags_ReadOnly);
ImGui::PopItemWidth(); ImGui::PopItemWidth();
@ -991,8 +1069,16 @@ namespace Prism
{ {
std::string file = Application::Get().OpenFile(); std::string file = Application::Get().OpenFile();
if (!file.empty()) if (!file.empty())
mc.CollisionMesh = Ref<Mesh>::Create(file); {
mcc.CollisionMesh = Ref<Mesh>::Create(file);
PxPhysicsWrappers::CreateConvexMesh(mcc);
}
} }
ImGui::EndColumns();
BeginPropertyGrid();
Property("Is Trigger", mcc.IsTrigger);
EndPropertyGrid();
}); });
} }

View File

@ -27,6 +27,9 @@ namespace Prism
void DrawMeshNode(const Ref<Mesh>& mesh, uint32_t& imguiMeshID); void DrawMeshNode(const Ref<Mesh>& mesh, uint32_t& imguiMeshID);
void DrawComponents(Entity entity); void DrawComponents(Entity entity);
void MeshNodeHierarchy(const Ref<Mesh>& mesh, aiNode* node, const glm::mat4& parentTransform = glm::mat4(1.0f), uint32_t level = 0); void MeshNodeHierarchy(const Ref<Mesh>& mesh, aiNode* node, const glm::mat4& parentTransform = glm::mat4(1.0f), uint32_t level = 0);
template <class T>
void AddComponentPopup(const char* componentName);
private: private:
Ref<Scene> m_Context; Ref<Scene> m_Context;
Entity m_SelectionContext; Entity m_SelectionContext;

View File

@ -6,198 +6,170 @@
#define GLM_ENABLE_EXPERIMENTAL #define GLM_ENABLE_EXPERIMENTAL
#include <glm/gtx/quaternion.hpp> #include <glm/gtx/quaternion.hpp>
#include <glm/gtx/matrix_decompose.hpp> #include "glm/gtx/matrix_decompose.hpp"
#include <glm/gtc/type_ptr.hpp> #include "Prism/Scene/Entity.h"
#include <cooking/PxCooking.h>
#define PX_PHYSX_STATIC_LIB
#include <PxPhysicsAPI.h>
#include "PxPhysicsWrappers.h"
namespace Prism namespace Prism
{ {
// TODO: Kinematic Actors static physx::PxScene* s_Scene = nullptr;
// TODO: Rotation/Position Locking static std::vector<Entity> s_SimulatedEntities;
// TODO: Collision "layers" static Entity* s_EntityStorageBuffer = nullptr;
// TODO: Expose more of the API to scripts static int s_EntityStorageBufferPosition = 0;
// TODO: Connect/Disconnect PVD
// TODO: Collider Shape Rendering
// TODO: Relative Transformations for scripts
static physx::PxSimulationFilterShader s_DefaultFilterShader = physx::PxDefaultSimulationFilterShader; static std::tuple<glm::vec3, glm::quat, glm::vec3> GetTransformDecomposition(const glm::mat4& transform)
static std::tuple<glm::vec3, glm::quat, glm::vec3> 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)
{ {
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<RigidBodyComponent>())
{
PM_CORE_WARN("Trying to create PhysX actor from a non-rigidbody actor!");
return;
}
if (!e.HasComponent<PhysicsMaterialComponent>())
{
PM_CORE_WARN("Trying to create PhysX actor without a PhysicsMaterialComponent!");
return;
}
RigidBodyComponent& rigidbody = e.GetComponent<RigidBodyComponent>();
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<PhysicsMaterialComponent>());
auto [translation, rotationQuat, scale] = GetTransformDecomposition(e.Transform());
// Add all colliders
if (e.HasComponent<BoxColliderComponent>())
{
const BoxColliderComponent& collider = e.GetComponent<BoxColliderComponent>();
PxPhysicsWrappers::AddBoxCollider(*actor, *material, collider, scale);
}
if (e.HasComponent<SphereColliderComponent>())
{
const SphereColliderComponent& collider = e.GetComponent<SphereColliderComponent>();
PxPhysicsWrappers::AddSphereCollider(*actor, *material, collider, scale);
}
if (e.HasComponent<CapsuleColliderComponent>())
{
const CapsuleColliderComponent& collider = e.GetComponent<CapsuleColliderComponent>();
PxPhysicsWrappers::AddCapsuleCollider(*actor, *material, collider, scale);
}
if (e.HasComponent<MeshColliderComponent>())
{
MeshColliderComponent& collider = e.GetComponent<MeshColliderComponent>();
PxPhysicsWrappers::AddMeshCollider(*actor, *material, collider, scale);
}
// Set collision filters
if (rigidbody.BodyType == RigidBodyComponent::Type::Static) 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) else if (rigidbody.BodyType == RigidBodyComponent::Type::Dynamic)
{ {
physx::PxRigidDynamic* dynamicActor = s_PXPhysicsFactory->createRigidDynamic(CreatePose(transform)); PxPhysicsWrappers::SetCollisionFilters(*actor, (uint32_t)FilterGroup::Dynamic, (uint32_t)FilterGroup::All);
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;
} }
actor->setActorFlag(physx::PxActorFlag::eVISUALIZATION, true); s_Scene->addActor(*actor);
scene->addActor(*actor);
return 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>& mesh) for (Entity& e : s_SimulatedEntities)
{
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<int>(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++)
{ {
physx::PxShape* shape = shapes[i]; auto& transform = e.Transform();
shape->setFlag(physx::PxShapeFlag::eVISUALIZATION, true); // TODO: Come up with a better solution for scale
shape->setSimulationFilterData(filterData); auto [p, r, scale] = GetTransformDecomposition(transform);
} const auto& rb = e.GetComponent<RigidBodyComponent>();
const auto actor = static_cast<physx::PxRigidActor*>(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; void Physics3D::DestroyScene()
physx::PxDefaultAllocator Physics3D::s_PXAllocator; {
physx::PxFoundation* Physics3D::s_PXFoundation; delete[] s_EntityStorageBuffer;
physx::PxPhysics* Physics3D::s_PXPhysicsFactory; s_EntityStorageBuffer = nullptr;
physx::PxPvd* Physics3D::s_PXPvd; 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();
}
}

View File

@ -4,10 +4,10 @@
#ifndef PHYSXMANAGER_H #ifndef PHYSXMANAGER_H
#define PHYSXMANAGER_H #define PHYSXMANAGER_H
#define PX_PHYSX_STATIC_LIB
#include <PxPhysicsAPI.h>
#include "glm/glm.hpp" #include "glm/glm.hpp"
#include "Prism/Scene/Components.h" #include "Prism/Scene/Components.h"
#include "Prism/Scene/Entity.h"
namespace Prism namespace Prism
{ {
@ -21,10 +21,15 @@ namespace Prism
enum class FilterGroup : uint32_t enum class FilterGroup : uint32_t
{ {
Static = BIT(0), Static = BIT(0),
Dynamic = BIT(1), Dynamic = BIT(1),
Kinematic = BIT(2), 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 class PRISM_API Physics3D
@ -33,22 +38,16 @@ namespace Prism
static void Init(); static void Init();
static void Shutdown(); static void Shutdown();
static physx::PxSceneDesc CreateSceneDesc(); static void CreateScene(const SceneParams& params);
static physx::PxScene* CreateScene(const physx::PxSceneDesc& sceneDesc); static void CreateActor(Entity e, int entityCount);
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>& mesh);
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 bool ConnectPVD();
static physx::PxDefaultErrorCallback s_PXErrorCallback; static bool IsPVDConnected();
static physx::PxDefaultAllocator s_PXAllocator; static void DisconnectPVD();
static physx::PxFoundation* s_PXFoundation;
static physx::PxPhysics* s_PXPhysicsFactory;
static physx::PxPvd* s_PXPvd;
}; };
} }

View File

@ -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<Entity*>(pairHeader.actors[0]->userData);
const Entity& b = *static_cast<Entity*>(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<Entity*>(pairs->triggerActor->userData);
const Entity& b = *static_cast<Entity*>(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);
}
}

View File

@ -0,0 +1,46 @@
//
// Created by sfd on 25-12-20.
//
#ifndef PHYSICSUTILS_H
#define PHYSICSUTILS_H
#define PX_PHYSX_STATIC_LIB
#include <PxPhysicsAPI.h>
#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

View File

@ -0,0 +1,282 @@
//
// Created by sfd on 25-12-20.
//
#include "PxPhysicsWrappers.h"
#include "Physics3D.h"
#include <cooking/PxCooking.h>
#define GLM_ENABLE_EXPERIMENTAL
#include <glm/gtx/rotate_vector.hpp>
#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<physx::PxShape**>(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<physx::PxU32>(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<Vertex> collisionVertices;
std::vector<Index> 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 <glm/gtx/rotate_vector.hpp>
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<uint32_t>(polygon.mNbVerts) - 1; vI++)
{
collisionIndices[indexCounter].V1 = static_cast<uint32_t>(vI0);
collisionIndices[indexCounter].V2 = static_cast<uint32_t>(vI0 + vI + 1);
collisionIndices[indexCounter].V3 = static_cast<uint32_t>(vI0 + vI);
indexCounter++;
}
}
collider.ProcessedMesh = Ref<Mesh>::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
}
}

View File

@ -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

View File

@ -42,6 +42,20 @@ namespace Prism
double xpos, ypos; double xpos, ypos;
glfwGetCursorPos(static_cast<GLFWwindow*>(window.GetNativeWindow()), &xpos, &ypos); glfwGetCursorPos(static_cast<GLFWwindow*>(window.GetNativeWindow()), &xpos, &ypos);
return {(float)xpos, (float)ypos}; return {static_cast<float>(xpos), static_cast<float>(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<WindowsWindow&>(Application::Get().GetWindow());
glfwSetInputMode(static_cast<GLFWwindow*>(window.GetNativeWindow()), GLFW_CURSOR, GLFW_CURSOR_NORMAL + static_cast<int>(mode));
}
CursorMode Input::GetCursorMode()
{
const auto& window = dynamic_cast<WindowsWindow&>(Application::Get().GetWindow());
return static_cast<CursorMode>(glfwGetInputMode(static_cast<GLFWwindow*>(window.GetNativeWindow()), GLFW_CURSOR) - GLFW_CURSOR_NORMAL);
} }
} }

View File

@ -43,9 +43,8 @@ namespace Prism
glfwPollEvents(); glfwPollEvents();
glfwSwapBuffers(m_Window); 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]); 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) void WindowsWindow::SetVSync(bool enable)

View File

@ -507,6 +507,30 @@ namespace Prism
m_Pipeline = Pipeline::Create(pipelineSpecification); m_Pipeline = Pipeline::Create(pipelineSpecification);
} }
Mesh::Mesh(const std::vector<Vertex>& vertices, const std::vector<Index>& indices)
: m_StaticVertices(vertices), m_Indices(indices), m_IsAnimated(false)
{
Submesh submesh;
submesh.BaseVertex = 0;
submesh.BaseIndex = 0;
submesh.IndexCount = static_cast<uint32_t>(indices.size()) * 3;
submesh.Transform = glm::mat4(1.0F);
m_Submeshes.push_back(submesh);
m_VertexBuffer = VertexBuffer::Create(m_StaticVertices.data(), static_cast<uint32_t>(m_StaticVertices.size()) * sizeof(Vertex));
m_IndexBuffer = IndexBuffer::Create(m_Indices.data(), static_cast<uint32_t>(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; Mesh::~Mesh() = default;
void Mesh::OnUpdate(TimeStep deltaTime) void Mesh::OnUpdate(TimeStep deltaTime)
@ -706,14 +730,14 @@ namespace Prism
if (nodeAnim->mNumRotationKeys == 1) if (nodeAnim->mNumRotationKeys == 1)
{ {
// No interpolation necessary for single value // No interpolation necessary for single value
auto v = nodeAnim->mRotationKeys[0].mValue; const auto v = nodeAnim->mRotationKeys[0].mValue;
return glm::quat(v.w, v.x, v.y, v.z); return {v.w, v.x, v.y, v.z};
} }
uint32_t RotationIndex = FindRotation(animationTime, nodeAnim); const uint32_t RotationIndex = FindRotation(animationTime, nodeAnim);
uint32_t NextRotationIndex = (RotationIndex + 1); const uint32_t NextRotationIndex = (RotationIndex + 1);
PM_CORE_ASSERT(NextRotationIndex < nodeAnim->mNumRotationKeys); 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; float Factor = (animationTime - (float)nodeAnim->mRotationKeys[RotationIndex].mTime) / DeltaTime;
PM_CORE_ASSERT(Factor <= 1.0f, "Factor must be below 1.0f"); PM_CORE_ASSERT(Factor <= 1.0f, "Factor must be below 1.0f");
Factor = glm::clamp(Factor, 0.0f, 1.0f); Factor = glm::clamp(Factor, 0.0f, 1.0f);
@ -722,7 +746,7 @@ namespace Prism
auto q = aiQuaternion(); auto q = aiQuaternion();
aiQuaternion::Interpolate(q, StartRotationQ, EndRotationQ, Factor); aiQuaternion::Interpolate(q, StartRotationQ, EndRotationQ, Factor);
q = q.Normalize(); 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) glm::vec3 Mesh::InterpolateScale(const float animationTime, const aiNodeAnim* nodeAnim)

View File

@ -107,6 +107,7 @@ namespace Prism
Mesh(const std::string& filename); Mesh(const std::string& filename);
Mesh(const std::vector<Vertex>& vertices, const std::vector<Index>& indices);
~Mesh(); ~Mesh();
void OnUpdate(TimeStep deltaTime); void OnUpdate(TimeStep deltaTime);

View File

@ -0,0 +1,172 @@
//
// Created by sfd on 25-12-21.
//
#include "Meshfactory.h"
namespace Prism
{
Ref<Mesh> MeshFactory::CreateBox(const glm::vec3& size)
{
std::vector<Vertex> 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<Index> 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<Mesh>::Create(vertices, indices);
}
Prism::Ref<Prism::Mesh> MeshFactory::CreateSphere(float radius)
{
std::vector<Vertex> vertices;
std::vector<Index> 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<Mesh>::Create(vertices, indices);
}
Ref<Mesh> MeshFactory::CreateCapsule(float radius, float height)
{
std::vector<Vertex> vertices;
std::vector<Index> 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<Mesh>::Create(vertices, indices);
}
}

View File

@ -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<Mesh> CreateBox(const glm::vec3& size);
static Ref<Mesh> CreateSphere(float radius);
static Ref<Mesh> CreateCapsule(float radius, float height);
};
}
#endif //MESHFACTORY_H

View File

@ -15,138 +15,164 @@
namespace Prism namespace Prism
{ {
struct SceneRendererData struct SceneRendererData
{ {
const Scene* ActiveScene = nullptr; const Scene* ActiveScene = nullptr;
struct SceneInfo struct SceneInfo
{ {
SceneRendererCamera SceneCamera; SceneRendererCamera SceneCamera;
// Resources // Resources
Ref<MaterialInstance> SkyboxMaterial; Ref<MaterialInstance> SkyboxMaterial;
Environment SceneEnvironment; Environment SceneEnvironment;
Light ActiveLight; Light ActiveLight;
} SceneData; } SceneData;
Ref<Texture2D> BRDFLUT; Ref<Texture2D> BRDFLUT;
Ref<Shader> CompositeShader; Ref<Shader> CompositeShader;
Ref<RenderPass> GeoPass; Ref<RenderPass> GeoPass;
Ref<RenderPass> CompositePass; Ref<RenderPass> CompositePass;
struct DrawCommand struct DrawCommand
{ {
Ref<Mesh> mesh; Ref<Mesh> mesh;
Ref<MaterialInstance> Material; Ref<MaterialInstance> Material;
glm::mat4 Transform; glm::mat4 Transform;
}; };
std::vector<DrawCommand> DrawList; std::vector<DrawCommand> DrawList;
std::vector<DrawCommand> SelectedMeshDrawList; std::vector<DrawCommand> SelectedMeshDrawList;
std::vector<DrawCommand> ColliderDrawList;
// Grid // Grid
Ref<MaterialInstance> GridMaterial; Ref<MaterialInstance> GridMaterial;
Ref<MaterialInstance> OutlineMaterial; Ref<MaterialInstance> OutlineMaterial;
Ref<MaterialInstance> ColliderMaterial;
SceneRendererOptions Options; SceneRendererOptions Options;
}; };
static SceneRendererData s_Data; static SceneRendererData s_Data;
void SceneRenderer::Init() void SceneRenderer::Init()
{ {
FramebufferSpecification geoFramebufferSpec; FramebufferSpecification geoFramebufferSpec;
geoFramebufferSpec.Width = 1280; geoFramebufferSpec.Width = 1280;
geoFramebufferSpec.Height = 720; geoFramebufferSpec.Height = 720;
geoFramebufferSpec.Format = FramebufferFormat::RGBA16F; geoFramebufferSpec.Format = FramebufferFormat::RGBA16F;
geoFramebufferSpec.Samples = 8; geoFramebufferSpec.Samples = 8;
geoFramebufferSpec.ClearColor = { 0.1f, 0.1f, 0.1f, 1.0f }; geoFramebufferSpec.ClearColor = { 0.1f, 0.1f, 0.1f, 1.0f };
RenderPassSpecification geoRenderPassSpec; RenderPassSpecification geoRenderPassSpec;
geoRenderPassSpec.TargetFramebuffer = FrameBuffer::Create(geoFramebufferSpec); geoRenderPassSpec.TargetFramebuffer = FrameBuffer::Create(geoFramebufferSpec);
s_Data.GeoPass = RenderPass::Create(geoRenderPassSpec); s_Data.GeoPass = RenderPass::Create(geoRenderPassSpec);
FramebufferSpecification compFramebufferSpec; FramebufferSpecification compFramebufferSpec;
compFramebufferSpec.Width = 1280; compFramebufferSpec.Width = 1280;
compFramebufferSpec.Height = 720; compFramebufferSpec.Height = 720;
compFramebufferSpec.Format = FramebufferFormat::RGBA8; compFramebufferSpec.Format = FramebufferFormat::RGBA8;
compFramebufferSpec.ClearColor = { 0.5f, 0.1f, 0.1f, 1.0f }; compFramebufferSpec.ClearColor = { 0.5f, 0.1f, 0.1f, 1.0f };
RenderPassSpecification compRenderPassSpec; RenderPassSpecification compRenderPassSpec;
compRenderPassSpec.TargetFramebuffer = FrameBuffer::Create(compFramebufferSpec); compRenderPassSpec.TargetFramebuffer = FrameBuffer::Create(compFramebufferSpec);
s_Data.CompositePass = RenderPass::Create(compRenderPassSpec); s_Data.CompositePass = RenderPass::Create(compRenderPassSpec);
s_Data.CompositeShader = Shader::Create("assets/shaders/SceneComposite.glsl"); 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 // Grid
const auto gridShader = Shader::Create("assets/shaders/Grid.glsl"); const auto gridShader = Shader::Create("assets/shaders/Grid.glsl");
s_Data.GridMaterial = MaterialInstance::Create(Material::Create(gridShader)); s_Data.GridMaterial = MaterialInstance::Create(Material::Create(gridShader));
constexpr float gridScale = 16.025f; constexpr float gridScale = 16.025f;
constexpr float gridSize = 0.025f; constexpr float gridSize = 0.025f;
s_Data.GridMaterial->Set("u_Scale", gridScale); s_Data.GridMaterial->Set("u_Scale", gridScale);
s_Data.GridMaterial->Set("u_Res", gridSize); s_Data.GridMaterial->Set("u_Res", gridSize);
// outline // outline
const auto outlineShader = Shader::Create("assets/shaders/Outline.glsl"); const auto outlineShader = Shader::Create("assets/shaders/Outline.glsl");
s_Data.OutlineMaterial = MaterialInstance::Create(Material::Create(outlineShader)); s_Data.OutlineMaterial = MaterialInstance::Create(Material::Create(outlineShader));
s_Data.OutlineMaterial->SetFlag(MaterialFlag::DepthTest, false); 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) void SceneRenderer::SetViewportSize(uint32_t width, uint32_t height)
{ {
s_Data.GeoPass->GetSpecification().TargetFramebuffer->Resize(width, height); s_Data.GeoPass->GetSpecification().TargetFramebuffer->Resize(width, height);
s_Data.CompositePass->GetSpecification().TargetFramebuffer->Resize(width, height); s_Data.CompositePass->GetSpecification().TargetFramebuffer->Resize(width, height);
} }
void SceneRenderer::BeginScene(const Scene* scene, const SceneRendererCamera& camera) void SceneRenderer::BeginScene(const Scene* scene, const SceneRendererCamera& camera)
{ {
PM_CORE_ASSERT(!s_Data.ActiveScene); PM_CORE_ASSERT(!s_Data.ActiveScene);
s_Data.ActiveScene = scene; s_Data.ActiveScene = scene;
s_Data.SceneData.SceneCamera = camera; s_Data.SceneData.SceneCamera = camera;
s_Data.SceneData.SkyboxMaterial = scene->m_SkyboxMaterial; s_Data.SceneData.SkyboxMaterial = scene->m_SkyboxMaterial;
s_Data.SceneData.SceneEnvironment = scene->m_Environment; s_Data.SceneData.SceneEnvironment = scene->m_Environment;
s_Data.SceneData.ActiveLight = scene->m_Light; s_Data.SceneData.ActiveLight = scene->m_Light;
} }
void SceneRenderer::EndScene() void SceneRenderer::EndScene()
{ {
PM_CORE_ASSERT(s_Data.ActiveScene); PM_CORE_ASSERT(s_Data.ActiveScene);
s_Data.ActiveScene = nullptr; s_Data.ActiveScene = nullptr;
FlushDrawList(); FlushDrawList();
} }
void SceneRenderer::SubmitMesh(const Ref<Mesh>& mesh, const glm::mat4& transform, const Ref<MaterialInstance>& overrideMaterial) void SceneRenderer::SubmitMesh(const Ref<Mesh>& mesh, const glm::mat4& transform, const Ref<MaterialInstance>& overrideMaterial)
{ {
// TODO: Culling, sorting, etc. // 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>& mesh, const glm::mat4& transform) void SceneRenderer::SubmitSelectedMesh(const Ref<Mesh>& mesh, const glm::mat4& transform)
{ {
s_Data.SelectedMeshDrawList.push_back({ mesh, nullptr, 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<Shader> equirectangularConversionShader, envFilteringShader, envIrradianceShader; static Ref<Shader> equirectangularConversionShader, envFilteringShader, envIrradianceShader;
std::pair<Ref<TextureCube>, Ref<TextureCube>> SceneRenderer::CreateEnvironmentMap(const std::string& filepath) std::pair<Ref<TextureCube>, Ref<TextureCube>> SceneRenderer::CreateEnvironmentMap(const std::string& filepath)
{ {
constexpr uint32_t cubemapSize = 2048; constexpr uint32_t cubemapSize = 2048;
constexpr uint32_t irradianceMapSize = 32; constexpr uint32_t irradianceMapSize = 32;
Ref<TextureCube> envUnfiltered = TextureCube::Create(TextureFormat::Float16, cubemapSize, cubemapSize); Ref<TextureCube> envUnfiltered = TextureCube::Create(TextureFormat::Float16, cubemapSize, cubemapSize);
if (!equirectangularConversionShader) if (!equirectangularConversionShader)
equirectangularConversionShader = Shader::Create("assets/shaders/EquirectangularToCubeMap.glsl"); equirectangularConversionShader = Shader::Create("assets/shaders/EquirectangularToCubeMap.glsl");
Ref<Texture2D> envEquirect = Texture2D::Create(filepath); Ref<Texture2D> envEquirect = Texture2D::Create(filepath);
if (envEquirect->GetFormat() != TextureFormat::Float16) if (envEquirect->GetFormat() != TextureFormat::Float16)
PM_CORE_WARN("Texture is not HDR!"); PM_CORE_WARN("Texture is not HDR!");
equirectangularConversionShader->Bind(); equirectangularConversionShader->Bind();
envEquirect->Bind(); envEquirect->Bind();
@ -198,46 +224,48 @@ namespace Prism
}); });
return { envFiltered, irradianceMap }; return { envFiltered, irradianceMap };
} }
Ref<RenderPass> SceneRenderer::GetFinalRenderPass() Ref<RenderPass> SceneRenderer::GetFinalRenderPass()
{ {
return s_Data.CompositePass; return s_Data.CompositePass;
} }
Ref<Texture2D> SceneRenderer::GetFinalColorBuffer() Ref<Texture2D> SceneRenderer::GetFinalColorBuffer()
{ {
PM_CORE_ASSERT(false, "Not implemented"); PM_CORE_ASSERT(false, "Not implemented");
return nullptr; return nullptr;
} }
uint32_t SceneRenderer::GetFinalColorBufferRendererID() uint32_t SceneRenderer::GetFinalColorBufferRendererID()
{ {
return s_Data.CompositePass->GetSpecification().TargetFramebuffer->GetColorAttachmentRendererID(); return s_Data.CompositePass->GetSpecification().TargetFramebuffer->GetColorAttachmentRendererID();
} }
SceneRendererOptions& SceneRenderer::GetOptions() SceneRendererOptions& SceneRenderer::GetOptions()
{ {
return s_Data.Options; return s_Data.Options;
} }
void SceneRenderer::FlushDrawList() void SceneRenderer::FlushDrawList()
{ {
PM_CORE_ASSERT(!s_Data.ActiveScene); PM_CORE_ASSERT(!s_Data.ActiveScene);
GeometryPass(); GeometryPass();
CompositePass(); CompositePass();
s_Data.DrawList.clear(); s_Data.DrawList.clear();
s_Data.SelectedMeshDrawList.clear(); s_Data.SelectedMeshDrawList.clear();
s_Data.SceneData = {}; s_Data.ColliderDrawList.clear();
} s_Data.SceneData = {};
}
void SceneRenderer::GeometryPass() void SceneRenderer::GeometryPass()
{ {
bool outline = s_Data.SelectedMeshDrawList.size() > 0; const bool outline = s_Data.SelectedMeshDrawList.size() > 0;
const bool collider = s_Data.ColliderDrawList.size() > 0;
if (outline) if (outline || collider)
{ {
Renderer::Submit([]() Renderer::Submit([]()
{ {
@ -247,7 +275,7 @@ namespace Prism
Renderer::BeginRenderPass(s_Data.GeoPass); Renderer::BeginRenderPass(s_Data.GeoPass);
if (outline) if (outline || collider)
{ {
Renderer::Submit([]() Renderer::Submit([]()
{ {
@ -283,32 +311,6 @@ namespace Prism
Renderer::SubmitMesh(dc.mesh, dc.Transform, overrideMaterial); 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) 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 // Grid
const auto option = GetOptions(); const auto option = GetOptions();

View File

@ -7,6 +7,7 @@
#include "Mesh.h" #include "Mesh.h"
#include "RenderPass.h" #include "RenderPass.h"
#include "Texture.h" #include "Texture.h"
#include "Prism/Scene/Components.h"
#include "Prism/Scene/Scene.h" #include "Prism/Scene/Scene.h"
@ -37,6 +38,11 @@ namespace Prism
static void SubmitMesh(const Ref<Mesh>& mesh, const glm::mat4& transform = glm::mat4(1.0f), const Ref<MaterialInstance>& overrideMaterial = nullptr); static void SubmitMesh(const Ref<Mesh>& mesh, const glm::mat4& transform = glm::mat4(1.0f), const Ref<MaterialInstance>& overrideMaterial = nullptr);
static void SubmitSelectedMesh(const Ref<Mesh>& mesh, const glm::mat4& transform = glm::mat4(1.0f)); static void SubmitSelectedMesh(const Ref<Mesh>& 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<TextureCube>, Ref<TextureCube>> CreateEnvironmentMap(const std::string& filepath); static std::pair<Ref<TextureCube>, Ref<TextureCube>> CreateEnvironmentMap(const std::string& filepath);
static Ref<RenderPass> GetFinalRenderPass(); static Ref<RenderPass> GetFinalRenderPass();

View File

@ -12,7 +12,6 @@
#include "glm/glm.hpp" #include "glm/glm.hpp"
#include "Prism/Core/Ref.h" #include "Prism/Core/Ref.h"
#include "Prism/Core/UUID.h" #include "Prism/Core/UUID.h"
#include "Prism/Renderer/Camera.h"
#include "Prism/Renderer/Mesh.h" #include "Prism/Renderer/Mesh.h"
namespace Prism namespace Prism
@ -141,9 +140,11 @@ namespace Prism
struct SphereColliderComponent 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<Mesh> DebugMesh;
SphereColliderComponent() = default; SphereColliderComponent() = default;
SphereColliderComponent(const SphereColliderComponent& other) = default; SphereColliderComponent(const SphereColliderComponent& other) = default;
@ -151,9 +152,10 @@ namespace Prism
struct RigidBodyComponent struct RigidBodyComponent
{ {
enum class Type { Static, Dynamic, Kinematic }; enum class Type { Static, Dynamic};
Type BodyType; Type BodyType;
float Mass = 1.0f; float Mass = 1.0f;
bool IsKinematic = false;
bool LockPositionX = false; bool LockPositionX = false;
bool LockPositionY = false; bool LockPositionY = false;
@ -183,6 +185,10 @@ namespace Prism
{ {
glm::vec3 Size = { 1.0f, 1.0f, 1.0f }; glm::vec3 Size = { 1.0f, 1.0f, 1.0f };
glm::vec3 Offset = { 0.0f, 0.0f, 0.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<Mesh> DebugMesh;
BoxColliderComponent() = default; BoxColliderComponent() = default;
BoxColliderComponent(const BoxColliderComponent& other) = default; BoxColliderComponent(const BoxColliderComponent& other) = default;
@ -192,6 +198,9 @@ namespace Prism
{ {
float Radius = 0.5f; float Radius = 0.5f;
float Height = 1.0f; float Height = 1.0f;
bool IsTrigger = false;
Ref<Mesh> DebugMesh;
CapsuleColliderComponent() = default; CapsuleColliderComponent() = default;
CapsuleColliderComponent(const CapsuleColliderComponent& other) = default; CapsuleColliderComponent(const CapsuleColliderComponent& other) = default;
@ -200,6 +209,8 @@ namespace Prism
struct MeshColliderComponent struct MeshColliderComponent
{ {
Ref<Prism::Mesh> CollisionMesh; Ref<Prism::Mesh> CollisionMesh;
Ref<Prism::Mesh> ProcessedMesh;
bool IsTrigger = false;
MeshColliderComponent() = default; MeshColliderComponent() = default;
MeshColliderComponent(const MeshColliderComponent& other) = default; MeshColliderComponent(const MeshColliderComponent& other) = default;

View File

@ -15,17 +15,14 @@
#include <glm/gtx/matrix_decompose.hpp> #include <glm/gtx/matrix_decompose.hpp>
#include "Prism/Physics/Physics3D.h" #include "Prism/Physics/Physics3D.h"
#define PX_PHYSX_STATIC_LIB
#include <PxPhysicsAPI.h>
namespace Prism namespace Prism
{ {
// TODO: THIS SHOULD MOVE TO PHYSICS FILE!
std::unordered_map<UUID, Scene*> s_ActiveScenes; std::unordered_map<UUID, Scene*> s_ActiveScenes;
static physx::PxDefaultErrorCallback s_PXErrorCallback;
static physx::PxDefaultAllocator s_PXAllocator;
static physx::PxFoundation* s_PXFoundation;
static uint32_t s_SceneIDCounter = 0; static uint32_t s_SceneIDCounter = 0;
struct SceneComponent 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) { 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<ScriptComponent>() && ScriptEngine::ModuleExists(a.GetComponent<ScriptComponent>().ModuleName))
ScriptEngine::OnCollisionBegin(a);
if (b.HasComponent<ScriptComponent>() && ScriptEngine::ModuleExists(b.GetComponent<ScriptComponent>().ModuleName))
ScriptEngine::OnCollisionBegin(b);
}
else if (pairs->flags == physx::PxContactPairFlag::eACTOR_PAIR_LOST_TOUCH)
{
if (a.HasComponent<ScriptComponent>() && ScriptEngine::ModuleExists(a.GetComponent<ScriptComponent>().ModuleName))
ScriptEngine::OnCollisionEnd(a);
if (b.HasComponent<ScriptComponent>() && ScriptEngine::ModuleExists(b.GetComponent<ScriptComponent>().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) void OnTransformConstruct(entt::registry& registry, entt::entity entity)
@ -189,8 +122,8 @@ namespace Prism
return { filepath, radiance, irradiance }; return { filepath, radiance, irradiance };
} }
Scene::Scene(const std::string& debugName) Scene::Scene(const std::string& debugName, const bool isEditorScene)
: m_SceneID(++s_SceneIDCounter), m_DebugName(debugName) : m_SceneID(++s_SceneIDCounter), m_DebugName(debugName)
{ {
m_Registry.on_construct<TransformComponent>().connect<&OnTransformConstruct>(); m_Registry.on_construct<TransformComponent>().connect<&OnTransformConstruct>();
m_Registry.on_construct<ScriptComponent>().connect<&OnScriptComponentConstruct>(); m_Registry.on_construct<ScriptComponent>().connect<&OnScriptComponentConstruct>();
@ -198,34 +131,22 @@ namespace Prism
m_SceneEntity = m_Registry.create(); m_SceneEntity = m_Registry.create();
m_Registry.emplace<SceneComponent>(m_SceneEntity, m_SceneID); m_Registry.emplace<SceneComponent>(m_SceneEntity, m_SceneID);
// TODO: Obviously not necessary in all cases
Box2DWorldComponent& b2World = m_Registry.emplace<Box2DWorldComponent>(m_SceneEntity, b2Vec2{ 0.0f, -9.8f }); Box2DWorldComponent& b2World = m_Registry.emplace<Box2DWorldComponent>(m_SceneEntity, b2Vec2{ 0.0f, -9.8f });
s_ActiveScenes[m_SceneID] = this; s_ActiveScenes[m_SceneID] = this;
physx::PxSceneDesc sceneDesc = Physics3D::CreateSceneDesc(); if (!isEditorScene)
sceneDesc.gravity = physx::PxVec3(0.0f, -9.8f, 0.0f);
sceneDesc.simulationEventCallback = &s_PhysXContactListener;
const PhysXSceneComponent& physxWorld = m_Registry.emplace<PhysXSceneComponent>(m_SceneEntity, Physics3D::CreateScene(sceneDesc));
physx::PxPvdSceneClient* pvdClient = physxWorld.World->getScenePvdClient();
if(pvdClient)
{ {
pvdClient->setScenePvdFlag(physx::PxPvdSceneFlag::eTRANSMIT_CONSTRAINTS, true); SceneParams sceneDesc;
pvdClient->setScenePvdFlag(physx::PxPvdSceneFlag::eTRANSMIT_CONTACTS, true); sceneDesc.Gravity = glm::vec3(0.0F, -9.81F, 0.0F);
pvdClient->setScenePvdFlag(physx::PxPvdSceneFlag::eTRANSMIT_SCENEQUERIES, true); Physics3D::CreateScene(sceneDesc);
}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!");
} }
PM_CORE_ASSERT(physxWorld.World);
Init(); Init();
} }
Scene::~Scene() Scene::~Scene()
{ {
m_Registry.on_destroy<ScriptComponent>().disconnect(); m_Registry.on_destroy<ScriptComponent>().disconnect();
@ -243,24 +164,22 @@ namespace Prism
void Scene::OnShutdown() void Scene::OnShutdown()
{ {
/*
auto b2WorldView = m_Registry.view<Box2DWorldComponent>(); auto b2WorldView = m_Registry.view<Box2DWorldComponent>();
b2DestroyWorld(m_Registry.get<Box2DWorldComponent>(m_SceneEntity).World); b2DestroyWorld(m_Registry.get<Box2DWorldComponent>(m_SceneEntity).World);
*/
auto physxView = m_Registry.view<PhysXSceneComponent>();
m_Registry.get<PhysXSceneComponent>(m_SceneEntity).World->release();
} }
void Scene::OnUpdate(TimeStep ts) void Scene::OnUpdate(TimeStep ts)
{ {
// Update all entities // Update all entities
{ {
auto view = m_Registry.view<ScriptComponent>(); const auto view = m_Registry.view<ScriptComponent>();
for (auto entity : view) for (const auto entity : view)
{ {
UUID entityID = m_Registry.get<IDComponent>(entity).ID;
Entity e = { entity, this }; Entity e = { entity, this };
if (ScriptEngine::ModuleExists(e.GetComponent<ScriptComponent>().ModuleName)) if (ScriptEngine::ModuleExists(e.GetComponent<ScriptComponent>().ModuleName))
ScriptEngine::OnUpdateEntity(m_SceneID, entityID, ts); ScriptEngine::OnUpdateEntity(e, ts);
} }
} }
@ -296,65 +215,7 @@ namespace Prism
} }
} }
// PhysX Physics Physics3D::Simulate(ts);
auto physxView = m_Registry.view<PhysXSceneComponent>();
physx::PxScene* physxScene = m_Registry.get<PhysXSceneComponent>(physxView.front()).World;
constexpr float stepSize = 0.016666660f;
physxScene->simulate(stepSize);
physxScene->fetchResults(true);
{
auto view = m_Registry.view<RigidBodyComponent>();
for (auto entity : view)
{
Entity e = { entity, this };
auto& transform = e.Transform();
RigidBodyComponent& rb = e.GetComponent<RigidBodyComponent>();
physx::PxRigidActor* actor = static_cast<physx::PxRigidActor*>(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));
}
}
}
} }
void Scene::OnRenderRuntime(TimeStep ts) void Scene::OnRenderRuntime(TimeStep ts)
@ -425,13 +286,60 @@ namespace Prism
meshComponent.Mesh->OnUpdate(ts); meshComponent.Mesh->OnUpdate(ts);
// TODO: Should we render (logically) // TODO: Should we render (logically)
SceneRenderer::SubmitMesh(meshComponent, transformComponent);
if (m_SelectedEntity == entity)
SceneRenderer::SubmitSelectedMesh(meshComponent, transformComponent);
else
SceneRenderer::SubmitMesh(meshComponent, transformComponent);
} }
} }
{
auto view = m_Registry.view<BoxColliderComponent>();
for (auto entity : view)
{
Entity e = { entity, this };
auto& collider = e.GetComponent<BoxColliderComponent>();
if (m_SelectedEntity == entity)
SceneRenderer::SubmitColliderMesh(collider, e.GetComponent<TransformComponent>());
}
}
{
const auto view = m_Registry.view<SphereColliderComponent>();
for (auto entity : view)
{
Entity e = { entity, this };
auto& collider = e.GetComponent<SphereColliderComponent>();
if (m_SelectedEntity == entity)
SceneRenderer::SubmitColliderMesh(collider, e.GetComponent<TransformComponent>());
}
}
{
const auto view = m_Registry.view<CapsuleColliderComponent>();
for (auto entity : view)
{
Entity e = { entity, this };
auto& collider = e.GetComponent<CapsuleColliderComponent>();
if (m_SelectedEntity == entity)
SceneRenderer::SubmitColliderMesh(collider, e.GetComponent<TransformComponent>());
}
}
{
const auto view = m_Registry.view<MeshColliderComponent>();
for (auto entity : view)
{
Entity e = { entity, this };
auto& collider = e.GetComponent<MeshColliderComponent>();
if (m_SelectedEntity == entity)
{
SceneRenderer::SubmitColliderMesh(collider, e.GetComponent<TransformComponent>());
}
}
}
SceneRenderer::EndScene(); SceneRenderer::EndScene();
///////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////
@ -568,159 +476,21 @@ namespace Prism
} }
} }
{
auto physxView = m_Registry.view<PhysXSceneComponent>(); auto view = m_Registry.view<RigidBodyComponent>();
physx::PxScene* physxWorld = m_Registry.get<PhysXSceneComponent>(physxView.front()).World; for (auto entity : view)
{
{ Entity e = { entity, this };
auto view = m_Registry.view<RigidBodyComponent>(); Physics3D::CreateActor(e, (int)view.size());
m_Physics3DBodyEntityBuffer = new Entity[view.size()]; }
uint32_t physicsBodyEntityBufferIndex = 0; }
for (auto entity : view)
{
Entity e = { entity, this };
UUID entityID = e.GetComponent<IDComponent>().ID;
auto& transform = e.Transform();
auto& rigidbody = m_Registry.get<RigidBodyComponent>(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<BoxColliderComponent>();
for (auto entity : view)
{
Entity e = { entity, this };
auto& transform = e.Transform();
auto& boxCollider = m_Registry.get<BoxColliderComponent>(entity);
if (e.HasComponent<RigidBodyComponent>())
{
auto& rigidBody = e.GetComponent<RigidBodyComponent>();
auto& physicsMaterial = e.GetComponent<PhysicsMaterialComponent>();
PM_CORE_ASSERT(rigidBody.RuntimeActor);
physx::PxRigidActor* actor = static_cast<physx::PxRigidActor*>(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<SphereColliderComponent>();
for (auto entity : view)
{
Entity e = { entity, this };
auto& transform = e.Transform();
auto& sphereCollider = m_Registry.get<SphereColliderComponent>(entity);
if (e.HasComponent<RigidBodyComponent>())
{
auto& rigidBody = e.GetComponent<RigidBodyComponent>();
auto& physicsMaterial = e.GetComponent<PhysicsMaterialComponent>();
PM_CORE_ASSERT(rigidBody.RuntimeActor);
physx::PxRigidActor* actor = static_cast<physx::PxRigidActor*>(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<physx::PxRigidDynamic>();
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<CapsuleColliderComponent>();
for (auto entity : view)
{
Entity e = { entity, this };
auto& transform = e.Transform();
auto& capsuleCollider = m_Registry.get<CapsuleColliderComponent>(entity);
if (e.HasComponent<RigidBodyComponent>())
{
auto& rigidBody = e.GetComponent<RigidBodyComponent>();
auto& physicsMaterial = e.GetComponent<PhysicsMaterialComponent>();
PM_CORE_ASSERT(rigidBody.RuntimeActor);
physx::PxRigidActor* actor = static_cast<physx::PxRigidActor*>(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<MeshColliderComponent>();
for (auto entity : meshView)
{
Entity e = { entity, this };
auto& transform = e.Transform();
auto& meshCollider = m_Registry.get<MeshColliderComponent>(entity);
if (e.HasComponent<RigidBodyComponent>())
{
auto& rigidBody = e.GetComponent<RigidBodyComponent>();
auto& physicsMaterial = e.GetComponent<PhysicsMaterialComponent>();
PM_CORE_ASSERT(rigidBody.RuntimeActor);
physx::PxRigidActor* actor = static_cast<physx::PxRigidActor*>(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<RigidBodyComponent>();
for (auto entity : rbView)
{
Entity e = { entity, this };
auto& rigidBody = e.GetComponent<RigidBodyComponent>();
PM_CORE_ASSERT(rigidBody.RuntimeActor);
physx::PxRigidActor* actor = static_cast<physx::PxRigidActor*>(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);
}
}
m_IsPlaying = true; m_IsPlaying = true;
} }
void Scene::OnRuntimeStop() void Scene::OnRuntimeStop()
{ {
auto physxView = m_Registry.view<PhysXSceneComponent>(); Physics3D::DestroyScene();
m_Registry.get<PhysXSceneComponent>(m_SceneEntity).World->release();
delete[] m_Physics3DBodyEntityBuffer; delete[] m_Physics3DBodyEntityBuffer;
delete[] m_Physics2DBodyEntityBuffer; delete[] m_Physics2DBodyEntityBuffer;
@ -836,6 +606,7 @@ namespace Prism
CopyComponentIfExists<PhysicsMaterialComponent>(newEntity.m_EntityHandle, entity.m_EntityHandle, m_Registry); CopyComponentIfExists<PhysicsMaterialComponent>(newEntity.m_EntityHandle, entity.m_EntityHandle, m_Registry);
CopyComponentIfExists<BoxColliderComponent>(newEntity.m_EntityHandle, entity.m_EntityHandle, m_Registry); CopyComponentIfExists<BoxColliderComponent>(newEntity.m_EntityHandle, entity.m_EntityHandle, m_Registry);
CopyComponentIfExists<SphereColliderComponent>(newEntity.m_EntityHandle, entity.m_EntityHandle, m_Registry); CopyComponentIfExists<SphereColliderComponent>(newEntity.m_EntityHandle, entity.m_EntityHandle, m_Registry);
CopyComponentIfExists<CapsuleColliderComponent>(newEntity.m_EntityHandle, entity.m_EntityHandle, m_Registry);
CopyComponentIfExists<MeshColliderComponent>(newEntity.m_EntityHandle, entity.m_EntityHandle, m_Registry); CopyComponentIfExists<MeshColliderComponent>(newEntity.m_EntityHandle, entity.m_EntityHandle, m_Registry);
} }
@ -884,6 +655,7 @@ namespace Prism
CopyComponent<PhysicsMaterialComponent>(target->m_Registry, m_Registry, enttMap); CopyComponent<PhysicsMaterialComponent>(target->m_Registry, m_Registry, enttMap);
CopyComponent<BoxColliderComponent>(target->m_Registry, m_Registry, enttMap); CopyComponent<BoxColliderComponent>(target->m_Registry, m_Registry, enttMap);
CopyComponent<SphereColliderComponent>(target->m_Registry, m_Registry, enttMap); CopyComponent<SphereColliderComponent>(target->m_Registry, m_Registry, enttMap);
CopyComponent<CapsuleColliderComponent>(target->m_Registry, m_Registry, enttMap);
CopyComponent<MeshColliderComponent>(target->m_Registry, m_Registry, enttMap); CopyComponent<MeshColliderComponent>(target->m_Registry, m_Registry, enttMap);
const auto& entityInstanceMap = ScriptEngine::GetEntityInstanceMap(); const auto& entityInstanceMap = ScriptEngine::GetEntityInstanceMap();

View File

@ -40,7 +40,7 @@ namespace Prism
class PRISM_API Scene : public RefCounted class PRISM_API Scene : public RefCounted
{ {
public: public:
Scene(const std::string& debugName = "Scene"); Scene(const std::string& debugName = "Scene", bool isEditorScene = false);
~Scene(); ~Scene();
void Init(); void Init();

View File

@ -9,7 +9,7 @@
namespace Prism namespace Prism
{ {
class SceneCamera : public Camera class PRISM_API SceneCamera : public Camera
{ {
public: public:
enum class ProjectionType { Perspective = 0, Orthographic = 1 }; enum class ProjectionType { Perspective = 0, Orthographic = 1 };

View File

@ -20,6 +20,9 @@
#include <iostream> #include <iostream>
#include <fstream> #include <fstream>
#include "Prism/Physics/PxPhysicsWrappers.h"
#include "Prism/Renderer/Meshfactory.h"
namespace YAML namespace YAML
{ {
@ -195,7 +198,7 @@ namespace Prism
auto& transform = entity.GetComponent<TransformComponent>().Transform; auto& transform = entity.GetComponent<TransformComponent>().Transform;
auto[pos, rot, scale] = GetTransformDecomposition(transform); auto[pos, rot, scale] = GetTransformDecomposition(transform);
out << YAML::Key << "Position" << YAML::Value << pos; 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::Key << "Scale" << YAML::Value << scale;
out << YAML::EndMap; // TransformComponent out << YAML::EndMap; // TransformComponent
@ -337,6 +340,7 @@ namespace Prism
auto& rigidbodyComponent = entity.GetComponent<RigidBodyComponent>(); auto& rigidbodyComponent = entity.GetComponent<RigidBodyComponent>();
out << YAML::Key << "BodyType" << YAML::Value << (int)rigidbodyComponent.BodyType; out << YAML::Key << "BodyType" << YAML::Value << (int)rigidbodyComponent.BodyType;
out << YAML::Key << "Mass" << YAML::Value << rigidbodyComponent.Mass; out << YAML::Key << "Mass" << YAML::Value << rigidbodyComponent.Mass;
out << YAML::Key << "IsKinematic" << YAML::Value << rigidbodyComponent.IsKinematic;
out << YAML::Key << "Constraints"; out << YAML::Key << "Constraints";
out << YAML::BeginMap; // Constraints out << YAML::BeginMap; // Constraints
@ -358,7 +362,7 @@ namespace Prism
out << YAML::Key << "PhysicsMaterialComponent"; out << YAML::Key << "PhysicsMaterialComponent";
out << YAML::BeginMap; // PhysicsMaterialComponent out << YAML::BeginMap; // PhysicsMaterialComponent
auto& physicsMaterial = entity.GetComponent<PhysicsMaterialComponent>(); const auto& physicsMaterial = entity.GetComponent<PhysicsMaterialComponent>();
out << YAML::Key << "StaticFriction" << YAML::Value << physicsMaterial.StaticFriction; out << YAML::Key << "StaticFriction" << YAML::Value << physicsMaterial.StaticFriction;
out << YAML::Key << "DynamicFriction" << YAML::Value << physicsMaterial.DynamicFriction; out << YAML::Key << "DynamicFriction" << YAML::Value << physicsMaterial.DynamicFriction;
out << YAML::Key << "Bounciness" << YAML::Value << physicsMaterial.Bounciness; out << YAML::Key << "Bounciness" << YAML::Value << physicsMaterial.Bounciness;
@ -371,9 +375,10 @@ namespace Prism
out << YAML::Key << "BoxColliderComponent"; out << YAML::Key << "BoxColliderComponent";
out << YAML::BeginMap; // BoxColliderComponent out << YAML::BeginMap; // BoxColliderComponent
auto& boxColliderComponent = entity.GetComponent<BoxColliderComponent>(); const auto& boxColliderComponent = entity.GetComponent<BoxColliderComponent>();
out << YAML::Key << "Offset" << YAML::Value << boxColliderComponent.Offset; out << YAML::Key << "Offset" << YAML::Value << boxColliderComponent.Offset;
out << YAML::Key << "Size" << YAML::Value << boxColliderComponent.Size; out << YAML::Key << "Size" << YAML::Value << boxColliderComponent.Size;
out << YAML::Key << "IsTrigger" << YAML::Value << boxColliderComponent.IsTrigger;
out << YAML::EndMap; // BoxColliderComponent out << YAML::EndMap; // BoxColliderComponent
} }
@ -383,19 +388,34 @@ namespace Prism
out << YAML::Key << "SphereColliderComponent"; out << YAML::Key << "SphereColliderComponent";
out << YAML::BeginMap; // SphereColliderComponent out << YAML::BeginMap; // SphereColliderComponent
auto& sphereColliderComponent = entity.GetComponent<SphereColliderComponent>(); const auto& sphereColliderComponent = entity.GetComponent<SphereColliderComponent>();
out << YAML::Key << "Radius" << YAML::Value << sphereColliderComponent.Radius; out << YAML::Key << "Radius" << YAML::Value << sphereColliderComponent.Radius;
out << YAML::Key << "IsTrigger" << YAML::Value << sphereColliderComponent.IsTrigger;
out << YAML::EndMap; // SphereColliderComponent out << YAML::EndMap; // SphereColliderComponent
} }
if (entity.HasComponent<CapsuleColliderComponent>())
{
out << YAML::Key << "CapsuleColliderComponent";
out << YAML::BeginMap; // CapsuleColliderComponent
const auto& capsuleColliderComponent = entity.GetComponent<CapsuleColliderComponent>();
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<MeshColliderComponent>()) if (entity.HasComponent<MeshColliderComponent>())
{ {
out << YAML::Key << "MeshColliderComponent"; out << YAML::Key << "MeshColliderComponent";
out << YAML::BeginMap; // MeshColliderComponent out << YAML::BeginMap; // MeshColliderComponent
auto mesh = entity.GetComponent<MeshColliderComponent>().CollisionMesh; auto meshColliderComponent = entity.GetComponent<MeshColliderComponent>();
out << YAML::Key << "AssetPath" << YAML::Value << mesh->GetFilePath(); out << YAML::Key << "AssetPath" << YAML::Value << meshColliderComponent.CollisionMesh->GetFilePath();
out << YAML::Key << "IsTrigger" << YAML::Value << meshColliderComponent.IsTrigger;
out << YAML::EndMap; // MeshColliderComponent out << YAML::EndMap; // MeshColliderComponent
} }
@ -527,15 +547,17 @@ namespace Prism
{ {
for (auto field : storedFields) for (auto field : storedFields)
{ {
std::string name = field["Name"].as<std::string>(); auto name = field["Name"].as<std::string>();
FieldType type = (FieldType)field["Type"].as<uint32_t>(); auto type = (FieldType)field["Type"].as<uint32_t>();
EntityInstanceData& data = ScriptEngine::GetEntityInstanceData(m_Scene->GetUUID(), uuid); EntityInstanceData& data = ScriptEngine::GetEntityInstanceData(m_Scene->GetUUID(), uuid);
auto& moduleFieldMap = data.ModuleFieldMap; auto& moduleFieldMap = data.ModuleFieldMap;
auto& publicFields = moduleFieldMap[moduleName]; auto& publicFields = moduleFieldMap[moduleName];
if (publicFields.find(name) == publicFields.end()) if (publicFields.find(name) == publicFields.end())
{ {
PublicField pf = { name, type }; // PublicField pf = { name, type };
publicFields.emplace(name, std::move(pf)); // 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"]; auto dataNode = field["Data"];
switch (type) switch (type)
@ -639,13 +661,15 @@ namespace Prism
auto& component = deserializedEntity.AddComponent<RigidBodyComponent>(); auto& component = deserializedEntity.AddComponent<RigidBodyComponent>();
component.BodyType = (RigidBodyComponent::Type)rigidBodyComponent["BodyType"].as<int>(); component.BodyType = (RigidBodyComponent::Type)rigidBodyComponent["BodyType"].as<int>();
component.Mass = rigidBodyComponent["Mass"].as<float>(); component.Mass = rigidBodyComponent["Mass"].as<float>();
component.IsKinematic = rigidBodyComponent["IsKinematic"] ? rigidBodyComponent["IsKinematic"].as<bool>() : false;
component.LockPositionX = rigidBodyComponent["Constraints"]["LockPositionX"].as<bool>();
component.LockPositionY = rigidBodyComponent["Constraints"]["LockPositionY"].as<bool>();
component.LockPositionZ = rigidBodyComponent["Constraints"]["LockPositionZ"].as<bool>();
component.LockRotationX = rigidBodyComponent["Constraints"]["LockRotationX"].as<bool>();
component.LockRotationY = rigidBodyComponent["Constraints"]["LockRotationY"].as<bool>();
component.LockRotationZ = rigidBodyComponent["Constraints"]["LockRotationZ"].as<bool>();
component.LockPositionX = rigidBodyComponent["LockPositionX"] ? rigidBodyComponent["LockPositionX"].as<bool>() : false;
component.LockPositionY = rigidBodyComponent["LockPositionY"] ? rigidBodyComponent["LockPositionY"].as<bool>() : false;
component.LockPositionZ = rigidBodyComponent["LockPositionZ"] ? rigidBodyComponent["LockPositionZ"].as<bool>() : false;
component.LockRotationX = rigidBodyComponent["LockRotationX"] ? rigidBodyComponent["LockRotationX"].as<bool>() : false;
component.LockRotationY = rigidBodyComponent["LockRotationY"] ? rigidBodyComponent["LockRotationY"].as<bool>() : false;
component.LockRotationZ = rigidBodyComponent["LockRotationZ"] ? rigidBodyComponent["LockRotationZ"].as<bool>() : false;
} }
if (auto physicsMaterialComponent = entity["PhysicsMaterialComponent"]) if (auto physicsMaterialComponent = entity["PhysicsMaterialComponent"])
@ -661,18 +685,33 @@ namespace Prism
auto& component = deserializedEntity.AddComponent<BoxColliderComponent>(); auto& component = deserializedEntity.AddComponent<BoxColliderComponent>();
component.Offset = boxColliderComponent["Offset"].as<glm::vec3>(); component.Offset = boxColliderComponent["Offset"].as<glm::vec3>();
component.Size = boxColliderComponent["Size"].as<glm::vec3>(); component.Size = boxColliderComponent["Size"].as<glm::vec3>();
component.IsTrigger = boxColliderComponent["IsTrigger"] ? boxColliderComponent["IsTrigger"].as<bool>() : false;
component.DebugMesh = MeshFactory::CreateBox(component.Size);
} }
if (auto sphereColliderComponent = entity["SphereColliderComponent"]) if (auto sphereColliderComponent = entity["SphereColliderComponent"])
{ {
auto& component = deserializedEntity.AddComponent<SphereColliderComponent>(); auto& component = deserializedEntity.AddComponent<SphereColliderComponent>();
component.Radius = sphereColliderComponent["Radius"].as<float>(); component.Radius = sphereColliderComponent["Radius"].as<float>();
component.IsTrigger = sphereColliderComponent["IsTrigger"] ? sphereColliderComponent["IsTrigger"].as<bool>() : false;
component.DebugMesh = MeshFactory::CreateSphere(component.Radius);
}
if (auto capsuleColliderComponent = entity["CapsuleColliderComponent"])
{
auto& component = deserializedEntity.AddComponent<CapsuleColliderComponent>();
component.Radius = capsuleColliderComponent["Radius"].as<float>();
component.Height = capsuleColliderComponent["Height"].as<float>();
component.IsTrigger = capsuleColliderComponent["IsTrigger"] ? capsuleColliderComponent["IsTrigger"].as<bool>() : false;
component.DebugMesh = MeshFactory::CreateCapsule(component.Radius, component.Height);
} }
if (auto meshColliderComponent = entity["MeshColliderComponent"]) if (auto meshColliderComponent = entity["MeshColliderComponent"])
{ {
auto meshPath = meshColliderComponent["AssetPath"].as<std::string>(); auto meshPath = meshColliderComponent["AssetPath"].as<std::string>();
deserializedEntity.AddComponent<MeshColliderComponent>(Ref<Mesh>::Create(meshPath)); auto& component = deserializedEntity.AddComponent<MeshColliderComponent>(Ref<Mesh>::Create(meshPath));
component.IsTrigger = meshColliderComponent["IsTrigger"] ? meshColliderComponent["IsTrigger"].as<bool>() : false;
PxPhysicsWrappers::CreateConvexMesh(component);
PM_CORE_INFO(" Mesh Collider Asset Path: {0}", meshPath); PM_CORE_INFO(" Mesh Collider Asset Path: {0}", meshPath);
} }

View File

@ -45,6 +45,7 @@ namespace Prism
std::string NamespaceName; std::string NamespaceName;
MonoClass* Class = nullptr; MonoClass* Class = nullptr;
MonoMethod* Constructor = nullptr;
MonoMethod* OnCreateMethod = nullptr; MonoMethod* OnCreateMethod = nullptr;
MonoMethod* OnDestroyMethod = nullptr; MonoMethod* OnDestroyMethod = nullptr;
MonoMethod* OnUpdateMethod = nullptr; MonoMethod* OnUpdateMethod = nullptr;
@ -52,17 +53,22 @@ namespace Prism
// Physics // Physics
MonoMethod* OnCollisionBeginMethod = nullptr; MonoMethod* OnCollisionBeginMethod = nullptr;
MonoMethod* OnCollisionEndMethod = nullptr; MonoMethod* OnCollisionEndMethod = nullptr;
MonoMethod* OnTriggerBeginMethod = nullptr;
MonoMethod* OnTriggerEndMethod = nullptr;
MonoMethod* OnCollision2DBeginMethod = nullptr; MonoMethod* OnCollision2DBeginMethod = nullptr;
MonoMethod* OnCollision2DEndMethod = nullptr; MonoMethod* OnCollision2DEndMethod = nullptr;
void InitClassMethods(MonoImage* image) void InitClassMethods(MonoImage* image)
{ {
Constructor = GetMethod(s_CoreAssemblyImage, "Prism.Entity:.ctor(ulong)");
OnCreateMethod = GetMethod(image, FullName + ":OnCreate()"); OnCreateMethod = GetMethod(image, FullName + ":OnCreate()");
OnUpdateMethod = GetMethod(image, FullName + ":OnUpdate(single)"); OnUpdateMethod = GetMethod(image, FullName + ":OnUpdate(single)");
// Physics (Entity class) // Physics (Entity class)
OnCollision2DBeginMethod = GetMethod(s_CoreAssemblyImage, "Prism.Entity:OnCollision2DBegin(single)"); OnCollision2DBeginMethod = GetMethod(s_CoreAssemblyImage, "Prism.Entity:OnCollision2DBegin(single)");
OnCollision2DEndMethod = GetMethod(s_CoreAssemblyImage, "Prism.Entity:OnCollision2DEnd(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)"); OnCollisionBeginMethod = GetMethod(s_CoreAssemblyImage, "Prism.Entity:OnCollisionBegin(single)");
OnCollisionEndMethod = GetMethod(s_CoreAssemblyImage, "Prism.Entity:OnCollisionEnd(single)"); OnCollisionEndMethod = GetMethod(s_CoreAssemblyImage, "Prism.Entity:OnCollisionEnd(single)");
@ -415,7 +421,7 @@ namespace Prism
return s_SceneContext; 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(dst) != s_EntityInstanceMap.end());
PM_CORE_ASSERT(s_EntityInstanceMap.find(src) != s_EntityInstanceMap.end()); PM_CORE_ASSERT(s_EntityInstanceMap.find(src) != s_EntityInstanceMap.end());
@ -442,19 +448,14 @@ namespace Prism
void ScriptEngine::OnCreateEntity(Entity entity) void ScriptEngine::OnCreateEntity(Entity entity)
{ {
OnCreateEntity(entity.m_Scene->GetUUID(), entity.GetComponent<IDComponent>().ID); EntityInstance& entityInstance = GetEntityInstanceData(entity.GetSceneUUID(), entity.GetUUID()).Instance;
}
void ScriptEngine::OnCreateEntity(UUID sceneID, UUID entityID)
{
EntityInstance& entityInstance = GetEntityInstanceData(sceneID, entityID).Instance;
if (entityInstance.ScriptClass->OnCreateMethod) if (entityInstance.ScriptClass->OnCreateMethod)
CallMethod(entityInstance.GetInstance(), 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) if (entityInstance.ScriptClass->OnUpdateMethod)
{ {
void* args[] = { &ts }; void* args[] = { &ts };
@ -462,14 +463,10 @@ namespace Prism
} }
} }
void ScriptEngine::OnCollision2DBegin(Entity entity) void ScriptEngine::OnCollision2DBegin(Entity entity)
{ {
OnCollision2DBegin(entity.m_Scene->GetUUID(), entity.GetComponent<IDComponent>().ID); EntityInstance& entityInstance = GetEntityInstanceData(entity.GetSceneUUID(), entity.GetUUID()).Instance;
}
void ScriptEngine::OnCollision2DBegin(const UUID &sceneID, const UUID &entityID)
{
EntityInstance& entityInstance = GetEntityInstanceData(sceneID, entityID).Instance;
if (entityInstance.ScriptClass->OnCollision2DBeginMethod) if (entityInstance.ScriptClass->OnCollision2DBeginMethod)
{ {
float value = 5.0f; float value = 5.0f;
@ -481,12 +478,7 @@ namespace Prism
void ScriptEngine::OnCollision2DEnd(Entity entity) void ScriptEngine::OnCollision2DEnd(Entity entity)
{ {
OnCollision2DEnd(entity.m_Scene->GetUUID(), entity.GetComponent<IDComponent>().ID); EntityInstance& entityInstance = GetEntityInstanceData(entity.GetSceneUUID(), entity.GetUUID()).Instance;
}
void ScriptEngine::OnCollision2DEnd(const UUID &sceneID, const UUID &entityID)
{
EntityInstance& entityInstance = GetEntityInstanceData(sceneID, entityID).Instance;
if (entityInstance.ScriptClass->OnCollision2DEndMethod) if (entityInstance.ScriptClass->OnCollision2DEndMethod)
{ {
float value = 5.0f; float value = 5.0f;
@ -498,12 +490,7 @@ namespace Prism
void ScriptEngine::OnCollisionBegin(Entity entity) void ScriptEngine::OnCollisionBegin(Entity entity)
{ {
OnCollisionBegin(entity.m_Scene->GetUUID(), entity.GetComponent<IDComponent>().ID); EntityInstance& entityInstance = GetEntityInstanceData(entity.GetSceneUUID(), entity.GetUUID()).Instance;
}
void ScriptEngine::OnCollisionBegin(const UUID& sceneID, const UUID& entityID)
{
EntityInstance& entityInstance = GetEntityInstanceData(sceneID, entityID).Instance;
if (entityInstance.ScriptClass->OnCollisionBeginMethod) if (entityInstance.ScriptClass->OnCollisionBeginMethod)
{ {
float value = 5.0f; float value = 5.0f;
@ -514,12 +501,7 @@ namespace Prism
void ScriptEngine::OnCollisionEnd(Entity entity) void ScriptEngine::OnCollisionEnd(Entity entity)
{ {
OnCollisionEnd(entity.m_Scene->GetUUID(), entity.GetComponent<IDComponent>().ID); EntityInstance& entityInstance = GetEntityInstanceData(entity.GetSceneUUID(), entity.GetUUID()).Instance;
}
void ScriptEngine::OnCollisionEnd(const UUID& sceneID, const UUID& entityID)
{
EntityInstance& entityInstance = GetEntityInstanceData(sceneID, entityID).Instance;
if (entityInstance.ScriptClass->OnCollisionEndMethod) if (entityInstance.ScriptClass->OnCollisionEndMethod)
{ {
float value = 5.0f; 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<ScriptComponent>() && ModuleExists(entity.GetComponent<ScriptComponent>().ModuleName);
}
void ScriptEngine::OnScriptComponentDestroyed(const UUID &sceneID, const UUID &entityID) void ScriptEngine::OnScriptComponentDestroyed(const UUID &sceneID, const UUID &entityID)
{ {
PM_CORE_ASSERT(s_EntityInstanceMap.find(sceneID) != s_EntityInstanceMap.end()); PM_CORE_ASSERT(s_EntityInstanceMap.find(sceneID) != s_EntityInstanceMap.end());
@ -646,11 +655,14 @@ namespace Prism
PM_CORE_ASSERT(entityInstance.ScriptClass); PM_CORE_ASSERT(entityInstance.ScriptClass);
entityInstance.Handle = Instantiate(*entityInstance.ScriptClass); entityInstance.Handle = Instantiate(*entityInstance.ScriptClass);
/*
MonoProperty* entityIDPropery = mono_class_get_property_from_name(entityInstance.ScriptClass->Class, "ID"); MonoProperty* entityIDPropery = mono_class_get_property_from_name(entityInstance.ScriptClass->Class, "ID");
mono_property_get_get_method(entityIDPropery); mono_property_get_get_method(entityIDPropery);
MonoMethod* entityIDSetMethod = mono_property_get_set_method(entityIDPropery); MonoMethod* entityIDSetMethod = mono_property_get_set_method(entityIDPropery);
*/
void* param[] = { &id }; void* param[] = { &id };
CallMethod(entityInstance.GetInstance(), entityIDSetMethod, param); CallMethod(entityInstance.GetInstance(), entityInstance.ScriptClass->Constructor, param);
// Set all public fields to appropriate values // Set all public fields to appropriate values
ScriptModuleFieldMap& moduleFieldMap = entityInstanceData.ModuleFieldMap; ScriptModuleFieldMap& moduleFieldMap = entityInstanceData.ModuleFieldMap;

View File

@ -112,21 +112,21 @@ namespace Prism
static void SetSceneContext(const Ref<Scene>& scene); static void SetSceneContext(const Ref<Scene>& scene);
static const Ref<Scene>& GetCurrentSceneContext(); static const Ref<Scene>& 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(Entity entity);
static void OnCreateEntity(UUID sceneID, UUID entityID); static void OnUpdateEntity(Entity entity, TimeStep ts);
static void OnUpdateEntity(UUID sceneID, UUID entityID, TimeStep ts);
static void OnCollision2DBegin(Entity entity); static void OnCollision2DBegin(Entity entity);
static void OnCollision2DBegin(const UUID &sceneID, const UUID &entityID);
static void OnCollision2DEnd(Entity entity); static void OnCollision2DEnd(Entity entity);
static void OnCollision2DEnd(const UUID &sceneID, const UUID &entityID);
static void OnCollisionBegin(Entity entity); static void OnCollisionBegin(Entity entity);
static void OnCollisionBegin(const UUID& sceneID, const UUID& entityID);
static void OnCollisionEnd(Entity entity); 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); static void OnScriptComponentDestroyed(const UUID &sceneID, const UUID &entityID);

View File

@ -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::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.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::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::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::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::CreateComponent_Native",(const void*)Prism::Script::Prism_Entity_CreateComponent);
mono_add_internal_call("Prism.Entity::HasComponent_Native",(const void*)Prism::Script::Prism_Entity_HasComponent); 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::GetMesh_Native",(const void*)Prism::Script::Prism_MeshComponent_GetMesh);
mono_add_internal_call("Prism.MeshComponent::SetMesh_Native",(const void*)Prism::Script::Prism_MeshComponent_SetMesh); 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::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::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::GetLinearVelocity_Native", (const void *)Prism::Script::Prism_RigidBody2DComponent_GetLinearVelocity);
mono_add_internal_call("Prism.RigidBody2DComponent::SetLinearVelocity_Native", (const void *)Prism::Script::Prism_RigidBody2DComponent_SetLinearVelocity); 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::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::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.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::AddForce_Native", (const void*)Prism::Script::Prism_RigidBodyComponent_AddForce);
mono_add_internal_call("Prism.RigidBodyComponent::AddTorque_Native", Prism::Script::Prism_RigidBodyComponent_AddTorque); mono_add_internal_call("Prism.RigidBodyComponent::AddTorque_Native", (const void*)Prism::Script::Prism_RigidBodyComponent_AddTorque);
mono_add_internal_call("Prism.RigidBodyComponent::GetLinearVelocity_Native", Prism::Script::Prism_RigidBodyComponent_GetLinearVelocity); mono_add_internal_call("Prism.RigidBodyComponent::GetLinearVelocity_Native", (const void*)Prism::Script::Prism_RigidBodyComponent_GetLinearVelocity);
mono_add_internal_call("Prism.RigidBodyComponent::SetLinearVelocity_Native", Prism::Script::Prism_RigidBodyComponent_SetLinearVelocity); 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::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::SetFloat_Native", (const void*)Prism::Script::Prism_Material_SetFloat);
mono_add_internal_call("Prism.Material::SetTexture_Native", (const void*)Prism::Script::Prism_Material_SetTexture); mono_add_internal_call("Prism.Material::SetTexture_Native", (const void*)Prism::Script::Prism_Material_SetTexture);

View File

@ -21,6 +21,7 @@
#include "PxRigidActor.h" #include "PxRigidActor.h"
#include "PxRigidDynamic.h" #include "PxRigidDynamic.h"
#include "Prism/Physics/Physics3D.h" #include "Prism/Physics/Physics3D.h"
#include "Prism/Physics/PhysicsUtils.h"
namespace Prism { namespace Prism {
extern std::unordered_map<MonoType*, std::function<bool(Entity&)>> s_HasComponentFuncs; extern std::unordered_map<MonoType*, std::function<bool(Entity&)>> s_HasComponentFuncs;
@ -70,6 +71,22 @@ namespace Prism { namespace Script {
return Input::IsKeyPressed(key); 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<TransformComponent>(); auto& transformComponent = entity.GetComponent<TransformComponent>();
memcpy(glm::value_ptr(transformComponent.Transform), inTransform, sizeof(glm::mat4)); memcpy(glm::value_ptr(transformComponent.Transform), inTransform, sizeof(glm::mat4));
} }
/*
void Prism_Entity_GetForwardDirection(const uint64_t entityID, glm::vec3* outForward) void Prism_Entity_GetForwardDirection(const uint64_t entityID, glm::vec3* outForward)
{ {
Ref<Scene> scene = ScriptEngine::GetCurrentSceneContext(); Ref<Scene> scene = ScriptEngine::GetCurrentSceneContext();
@ -140,6 +159,7 @@ namespace Prism { namespace Script {
auto [position, rotation, scale] = GetTransformDecomposition(transformComponent.Transform); auto [position, rotation, scale] = GetTransformDecomposition(transformComponent.Transform);
*outUp = glm::rotate(glm::inverse(glm::normalize(rotation)), glm::vec3(0, 1, 0)); *outUp = glm::rotate(glm::inverse(glm::normalize(rotation)), glm::vec3(0, 1, 0));
} }
*/
@ -181,6 +201,50 @@ namespace Prism { namespace Script {
return 0; return 0;
} }
void Prism_TransformComponent_GetRelativeDirection(const uint64_t entityID, glm::vec3* outDirection, const glm::vec3* inAbsoluteDirection)
{
Ref<Scene> 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<TransformComponent>();
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> 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<TransformComponent>();
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> 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) void* Prism_MeshComponent_GetMesh(const uint64_t entityID)
{ {
Ref<Scene> scene = ScriptEngine::GetCurrentSceneContext(); Ref<Scene> scene = ScriptEngine::GetCurrentSceneContext();
@ -262,14 +326,16 @@ namespace Prism { namespace Script {
Entity entity = entityMap.at(entityID); Entity entity = entityMap.at(entityID);
PM_CORE_ASSERT(entity.HasComponent<RigidBodyComponent>()); PM_CORE_ASSERT(entity.HasComponent<RigidBodyComponent>());
const auto& component = entity.GetComponent<RigidBodyComponent>(); const auto& component = entity.GetComponent<RigidBodyComponent>();
physx::PxRigidActor* actor = (physx::PxRigidActor*)component.RuntimeActor; if (component.IsKinematic)
physx::PxRigidDynamic* dynamicActor = actor->is<physx::PxRigidDynamic>(); {
PM_CORE_WARN("Cannot add a force to a kinematic actor! EntityID({0})", entityID);
// 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)
return; return;
}
auto* actor = static_cast<physx::PxRigidActor*>(component.RuntimeActor);
auto* dynamicActor = actor->is<physx::PxRigidDynamic>();
PM_CORE_ASSERT(dynamicActor);
PM_CORE_ASSERT(force); PM_CORE_ASSERT(force);
dynamicActor->addForce({ force->x, force->y, force->z }, (physx::PxForceMode::Enum)forceMode); 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); Entity entity = entityMap.at(entityID);
PM_CORE_ASSERT(entity.HasComponent<RigidBodyComponent>()); PM_CORE_ASSERT(entity.HasComponent<RigidBodyComponent>());
const auto& component = entity.GetComponent<RigidBodyComponent>(); const auto& component = entity.GetComponent<RigidBodyComponent>();
physx::PxRigidActor* actor = (physx::PxRigidActor*)component.RuntimeActor; if (component.IsKinematic)
physx::PxRigidDynamic* dynamicActor = actor->is<physx::PxRigidDynamic>(); {
PM_CORE_WARN("Cannot add torque to a kinematic actor! EntityID({0})", entityID);
// 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)
return; return;
}
const auto actor = static_cast<physx::PxRigidActor*>(component.RuntimeActor);
auto* dynamicActor = actor->is<physx::PxRigidDynamic>();
PM_CORE_ASSERT(dynamicActor);
PM_CORE_ASSERT(torque); PM_CORE_ASSERT(torque);
dynamicActor->addTorque({ torque->x, torque->y, torque->z }, (physx::PxForceMode::Enum)forceMode); 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); Entity entity = entityMap.at(entityID);
PM_CORE_ASSERT(entity.HasComponent<RigidBodyComponent>()); PM_CORE_ASSERT(entity.HasComponent<RigidBodyComponent>());
const auto& component = entity.GetComponent<RigidBodyComponent>(); const auto& component = entity.GetComponent<RigidBodyComponent>();
physx::PxRigidActor* actor = (physx::PxRigidActor*)component.RuntimeActor; if (component.IsKinematic)
const physx::PxRigidDynamic* dynamicActor = actor->is<physx::PxRigidDynamic>(); {
PM_CORE_WARN("Cannot add torque to a kinematic actor! EntityID({0})", entityID);
// 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)
return; return;
}
const auto actor = static_cast<physx::PxRigidActor*>(component.RuntimeActor);
const physx::PxRigidDynamic* dynamicActor = actor->is<physx::PxRigidDynamic>();
PM_CORE_ASSERT(dynamicActor);
PM_CORE_ASSERT(outVelocity); PM_CORE_ASSERT(outVelocity);
physx::PxVec3 velocity = dynamicActor->getLinearVelocity(); physx::PxVec3 velocity = dynamicActor->getLinearVelocity();
@ -329,19 +400,44 @@ namespace Prism { namespace Script {
Entity entity = entityMap.at(entityID); Entity entity = entityMap.at(entityID);
PM_CORE_ASSERT(entity.HasComponent<RigidBodyComponent>()); PM_CORE_ASSERT(entity.HasComponent<RigidBodyComponent>());
const auto& component = entity.GetComponent<RigidBodyComponent>(); const auto& component = entity.GetComponent<RigidBodyComponent>();
physx::PxRigidActor* actor = (physx::PxRigidActor*)component.RuntimeActor; if (component.IsKinematic)
physx::PxRigidDynamic* dynamicActor = actor->is<physx::PxRigidDynamic>(); {
PM_CORE_WARN("Cannot add torque to a kinematic actor! EntityID({0})", entityID);
// 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)
return; return;
}
const auto actor = static_cast<physx::PxRigidActor*>(component.RuntimeActor);
auto* dynamicActor = actor->is<physx::PxRigidDynamic>();
PM_CORE_ASSERT(dynamicActor);
PM_CORE_ASSERT(velocity); PM_CORE_ASSERT(velocity);
dynamicActor->setLinearVelocity({ velocity->x, velocity->y, velocity->z }); dynamicActor->setLinearVelocity({ velocity->x, velocity->y, velocity->z });
} }
void Prism_RigidBodyComponent_Rotate(uint64_t entityID, glm::vec3* rotation)
{
Ref<Scene> 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<RigidBodyComponent>());
const auto& component = entity.GetComponent<RigidBodyComponent>();
const auto actor = static_cast<physx::PxRigidActor*>(component.RuntimeActor);
auto* dynamicActor = actor->is<physx::PxRigidDynamic>();
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<Mesh>* Prism_Mesh_Constructor(MonoString* filepath) Ref<Mesh>* Prism_Mesh_Constructor(MonoString* filepath)
{ {
@ -350,7 +446,7 @@ namespace Prism { namespace Script {
void Prism_Mesh_Destructor(Ref<Mesh>* _this) void Prism_Mesh_Destructor(Ref<Mesh>* _this)
{ {
Ref<Mesh>* instance = (Ref<Mesh>*)_this; const Ref<Mesh>* instance = (Ref<Mesh>*)_this;
delete _this; delete _this;
} }

View File

@ -4,6 +4,7 @@
#ifndef SCRIPTWARPPERS_H #ifndef SCRIPTWARPPERS_H
#define SCRIPTWARPPERS_H #define SCRIPTWARPPERS_H
#include "Prism/Core/Input.h"
#include "Prism/Core/KeyCodes.h" #include "Prism/Core/KeyCodes.h"
#include "Prism/Core/Ref.h" #include "Prism/Core/Ref.h"
#include "Prism/Physics/Physics3D.h" #include "Prism/Physics/Physics3D.h"
@ -23,30 +24,37 @@ namespace Prism { namespace Script {
// Input // Input
bool Prism_Input_IsKeyPressed(KeyCode key); bool Prism_Input_IsKeyPressed(KeyCode key);
void Prism_Input_GetMousePosition(glm::vec2* outPosition);
void Prism_Input_SetCursorMode(CursorMode mode);
CursorMode Prism_Input_GetCursorMode();
// Entity // 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); void Prism_Entity_CreateComponent(uint64_t entityID, void* type);
bool Prism_Entity_HasComponent(uint64_t entityID, void* type); bool Prism_Entity_HasComponent(uint64_t entityID, void* type);
uint64_t Prism_Entity_FindEntityByTag(MonoString* tag); 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_TransformComponent_GetRelativeDirection(uint64_t entityID, glm::vec3* outDirection, const glm::vec3* inAbsoluteDirection);
void Prism_MeshComponent_SetMesh(uint64_t entityID, const Ref<Mesh>* inMesh); void Prism_TransformComponent_GetRotation(uint64_t entityID,glm::vec3* outRotation);
void Prism_TransformComponent_SetRotation(uint64_t entityID,const glm::vec3* inRotation);
// 2D Physic // 2D Physic
void Prism_RigidBody2DComponent_ApplyLinearImpulse(uint64_t entityID, const glm::vec2* impulse, const glm::vec2* offset, bool wake); 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_GetLinearVelocity(uint64_t entityID, glm::vec2* outVelocity);
void Prism_RigidBody2DComponent_SetLinearVelocity(uint64_t entityID, const glm::vec2* velocity); 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_AddForce(uint64_t entityID, glm::vec3* force, ForceMode forceMode);
void Prism_RigidBodyComponent_AddTorque(uint64_t entityID, glm::vec3* torque, 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_GetLinearVelocity(uint64_t entityID, glm::vec3* outVelocity);
void Prism_RigidBodyComponent_SetLinearVelocity(uint64_t entityID, glm::vec3* velocity); void Prism_RigidBodyComponent_SetLinearVelocity(uint64_t entityID, glm::vec3* velocity);
void Prism_RigidBodyComponent_Rotate(uint64_t entityID, glm::vec3* rotation);
// Renderer // Renderer
// Texture2D // Texture2D
@ -73,6 +81,9 @@ namespace Prism { namespace Script {
int Prism_Mesh_GetMaterialCount(Ref<Mesh>* inMesh); int Prism_Mesh_GetMaterialCount(Ref<Mesh>* inMesh);
void* Prism_MeshFactory_CreatePlane(float width, float height); void* Prism_MeshFactory_CreatePlane(float width, float height);
void* Prism_MeshComponent_GetMesh(uint64_t entityID);
void Prism_MeshComponent_SetMesh(uint64_t entityID, const Ref<Mesh>* inMesh);
} } } }