add overlapBox/Sphere/Capsule function, fixed OnWake/OnSleep not work

This commit is contained in:
2025-12-28 22:40:48 +08:00
parent d0eed3a33d
commit 9a44dd8d79
34 changed files with 1439 additions and 280 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/Editor/PhysicsSettingsWindow.h"
#include "Prism/Physics/Physics3D.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"
@ -192,7 +193,7 @@ namespace Prism
{ {
case SceneState::Edit: case SceneState::Edit:
{ {
// if (m_ViewportPanelFocused) if (m_ViewportPanelHovered || m_ViewportPanelFocused)
m_EditorCamera.OnUpdate(deltaTime); m_EditorCamera.OnUpdate(deltaTime);
m_EditorScene->OnRenderEditor(deltaTime, m_EditorCamera); m_EditorScene->OnRenderEditor(deltaTime, m_EditorCamera);
@ -361,6 +362,13 @@ namespace Prism
ImGui::EndMenu(); ImGui::EndMenu();
} }
if (ImGui::BeginMenu("Edit"))
{
ImGui::MenuItem("Physics Settings", nullptr, &m_ShowPhysicsSettings);
ImGui::EndMenu();
}
if (ImGui::BeginMenu("Tools")) if (ImGui::BeginMenu("Tools"))
{ {
// PhysX Debugger // PhysX Debugger
@ -380,6 +388,7 @@ namespace Prism
} }
m_SceneHierarchyPanel->OnImGuiRender(); m_SceneHierarchyPanel->OnImGuiRender();
PhysicsSettingsWindow::OnImGuiRender(&m_ShowPhysicsSettings);
ImGui::Begin("Materials"); ImGui::Begin("Materials");
@ -682,9 +691,13 @@ namespace Prism
{ {
if (ImGui::TreeNode(shader->GetName().c_str())) if (ImGui::TreeNode(shader->GetName().c_str()))
{ {
std::string buttonName = "Reload##" + shader->GetName();
if (ImGui::Button(buttonName.c_str())) const std::string buttonName = shader->GetName();
if (ImGui::Button(("Reload##" + buttonName).c_str()))
{
PM_CLIENT_INFO("Reloading Shader: {0}", buttonName);
shader->Reload(); shader->Reload();
}
ImGui::TreePop(); ImGui::TreePop();
} }
} }
@ -735,7 +748,7 @@ namespace Prism
ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(0, 0)); ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(0, 0));
ImGui::Begin("Viewport"); ImGui::Begin("Viewport");
m_ViewportPanelMouseOver = ImGui::IsWindowHovered(); m_ViewportPanelHovered = ImGui::IsWindowHovered();
m_ViewportPanelFocused = ImGui::IsWindowFocused(); m_ViewportPanelFocused = ImGui::IsWindowFocused();
auto viewportOffset = ImGui::GetCursorPos(); // includes tab bar auto viewportOffset = ImGui::GetCursorPos(); // includes tab bar
@ -809,7 +822,7 @@ namespace Prism
{ {
if (m_SceneState == SceneState::Edit) if (m_SceneState == SceneState::Edit)
{ {
if (m_ViewportPanelMouseOver) if (m_ViewportPanelHovered)
m_EditorCamera.OnEvent(e); m_EditorCamera.OnEvent(e);
m_EditorScene->OnEvent(e); m_EditorScene->OnEvent(e);
@ -857,42 +870,49 @@ namespace Prism
if (Input::IsKeyPressed(KeyCode::LEFT_CONTROL)) if (Input::IsKeyPressed(KeyCode::LEFT_CONTROL))
{ {
switch (e.GetKeyCode()) const bool IsShiftPressed = Input::IsKeyPressed(KeyCode::LEFT_SHIFT);
if (!IsShiftPressed)
{ {
case KeyCode::O: switch (e.GetKeyCode())
OpenScene();
break;
case KeyCode::S:
SaveScene();
break;
case KeyCode::B:
// Toggle bounding boxes
m_UIShowBoundingBoxes = !m_UIShowBoundingBoxes;
ShowBoundingBoxes(m_UIShowBoundingBoxes, m_UIShowBoundingBoxesOnTop);
break;
case KeyCode::D:
if (m_SelectionContext.size())
{ {
Entity selectedEntity = m_SelectionContext[0].Entity; case KeyCode::O:
m_EditorScene->DuplicateEntity(selectedEntity); OpenScene();
break;
case KeyCode::S:
SaveScene();
break;
case KeyCode::B:
// Toggle bounding boxes
m_UIShowBoundingBoxes = !m_UIShowBoundingBoxes;
ShowBoundingBoxes(m_UIShowBoundingBoxes, m_UIShowBoundingBoxesOnTop);
break;
case KeyCode::D:
if (m_SelectionContext.size())
{
const Entity selectedEntity = m_SelectionContext[0].Entity;
m_EditorScene->DuplicateEntity(selectedEntity);
}
break;
case KeyCode::G:
// Toggle grid
SceneRenderer::GetOptions().ShowGrid = !SceneRenderer::GetOptions().ShowGrid;
break;
} }
break;
case KeyCode::G:
// Toggle grid
SceneRenderer::GetOptions().ShowGrid = !SceneRenderer::GetOptions().ShowGrid;
break;
} }
if (Input::IsKeyPressed(PM_KEY_LEFT_SHIFT)) if (IsShiftPressed) {
{
switch (e.GetKeyCode()) switch (e.GetKeyCode())
{ {
case KeyCode::S: case KeyCode::S:
SaveSceneAs(); SaveSceneAs();
break; break;
default:
break;
} }
} }
// TODO: ALT TAB
} }
return false; return false;
@ -902,7 +922,7 @@ namespace Prism
{ {
auto [mx, my] = Input::GetMousePosition(); auto [mx, my] = Input::GetMousePosition();
if (e.GetMouseButton() == PM_MOUSE_BUTTON_LEFT && !Input::IsKeyPressed(KeyCode::LEFT_ALT) && !ImGuizmo::IsOver() && m_SceneState != SceneState::Play) if (m_ViewportPanelHovered && e.GetMouseButton() == PM_MOUSE_BUTTON_LEFT && !Input::IsKeyPressed(KeyCode::LEFT_ALT) && !ImGuizmo::IsOver() && m_SceneState != SceneState::Play)
{ {
auto [mouseX, mouseY] = GetMouseViewportSpace(); auto [mouseX, mouseY] = GetMouseViewportSpace();
if (mouseX > -1.0f && mouseX < 1.0f && mouseY > -1.0f && mouseY < 1.0f) if (mouseX > -1.0f && mouseX < 1.0f && mouseY > -1.0f && mouseY < 1.0f)
@ -912,9 +932,9 @@ namespace Prism
m_SelectionContext.clear(); m_SelectionContext.clear();
m_EditorScene->SetSelectedEntity({}); m_EditorScene->SetSelectedEntity({});
const auto meshEntities = m_EditorScene->GetAllEntitiesWith<MeshComponent>(); const auto meshEntities = m_EditorScene->GetAllEntitiesWith<MeshComponent>();
for (auto e : meshEntities) for (const auto aEntity : meshEntities)
{ {
Entity entity = { e, m_EditorScene.Raw() }; Entity entity = { aEntity, m_EditorScene.Raw() };
auto mesh = entity.GetComponent<MeshComponent>().Mesh; auto mesh = entity.GetComponent<MeshComponent>().Mesh;
if (!mesh) if (!mesh)
@ -970,9 +990,7 @@ namespace Prism
SelectedSubmesh selection; SelectedSubmesh selection;
if (entity.HasComponent<MeshComponent>()) if (entity.HasComponent<MeshComponent>())
{ {
auto& meshComp = entity.GetComponent<MeshComponent>(); if (auto& meshComp = entity.GetComponent<MeshComponent>(); meshComp.Mesh)
if (meshComp.Mesh)
{ {
selection.Mesh = &meshComp.Mesh->GetSubmeshes()[0]; selection.Mesh = &meshComp.Mesh->GetSubmeshes()[0];
} }
@ -1066,6 +1084,7 @@ namespace Prism
void EditorLayer::SaveScene() void EditorLayer::SaveScene()
{ {
PM_CLIENT_INFO("Saving scene to: {0}", m_SceneFilePath);
SceneSerializer serializer(m_EditorScene); SceneSerializer serializer(m_EditorScene);
serializer.Serialize(m_SceneFilePath); serializer.Serialize(m_SceneFilePath);
} }
@ -1076,6 +1095,7 @@ namespace Prism
std::string filepath = app.SaveFile("Prism Scene (*.hsc)\0*.hsc\0"); std::string filepath = app.SaveFile("Prism Scene (*.hsc)\0*.hsc\0");
if (!filepath.empty()) if (!filepath.empty())
{ {
PM_CLIENT_INFO("Saving scene to: {0}", m_SceneFilePath);
SceneSerializer serializer(m_EditorScene); SceneSerializer serializer(m_EditorScene);
serializer.Serialize(filepath); serializer.Serialize(filepath);
@ -1112,6 +1132,8 @@ namespace Prism
m_SelectionContext.clear(); m_SelectionContext.clear();
ScriptEngine::SetSceneContext(m_EditorScene); ScriptEngine::SetSceneContext(m_EditorScene);
m_SceneHierarchyPanel->SetContext(m_EditorScene); m_SceneHierarchyPanel->SetContext(m_EditorScene);
Input::SetCursorMode(CursorMode::Normal);
} }
float EditorLayer::GetSnapValue() float EditorLayer::GetSnapValue()

View File

@ -143,8 +143,9 @@ namespace Prism
}; };
SceneType m_SceneType; SceneType m_SceneType;
bool m_ViewportPanelMouseOver = false; bool m_ViewportPanelHovered = false;
bool m_ViewportPanelFocused = false; bool m_ViewportPanelFocused = false;
bool m_ShowPhysicsSettings = false;
enum class SceneState enum class SceneState
{ {

View File

@ -2,15 +2,15 @@ Scene: Scene Name
Environment: Environment:
AssetPath: assets/env/pink_sunrise_4k.hdr AssetPath: assets/env/pink_sunrise_4k.hdr
Light: Light:
Direction: [-0.787, -0.73299998, 1] Direction: [-0.787, -0.733, 1]
Radiance: [1, 1, 1] Radiance: [1, 1, 1]
Multiplier: 0.514999986 Multiplier: 0.515
Entities: Entities:
- Entity: 3247025703490125974 - Entity: 3247025703490125974
TagComponent: TagComponent:
Tag: Player Tag: Player
TransformComponent: TransformComponent:
Position: [2.80803752, 1.5, 0] Position: [2.8080375, 1.5, 0]
Rotation: [1, 0, 0, 0] Rotation: [1, 0, 0, 0]
Scale: [2, 2, 2] Scale: [2, 2, 2]
ScriptComponent: ScriptComponent:
@ -25,23 +25,30 @@ Entities:
- Name: JumpForce - Name: JumpForce
Type: 1 Type: 1
Data: 50 Data: 50
- Name: MouseSensitivity
Type: 1
Data: 10
- Name: Distance
Type: 1
Data: 0
MeshComponent: MeshComponent:
AssetPath: assets/meshes/Capsule.fbx AssetPath: assets/meshes/Capsule.fbx
RigidBodyComponent: RigidBodyComponent:
BodyType: 1 BodyType: 1
Mass: 1 Mass: 1
IsKinematic: false IsKinematic: false
Layer: 1
Constraints: Constraints:
LockPositionX: false LockPositionX: false
LockPositionY: false LockPositionY: false
LockPositionZ: false LockPositionZ: false
LockRotationX: true LockRotationX: true
LockRotationY: false LockRotationY: true
LockRotationZ: true LockRotationZ: true
PhysicsMaterialComponent: PhysicsMaterialComponent:
StaticFriction: 0.100000001 StaticFriction: 0.1
DynamicFriction: 0.100000001 DynamicFriction: 0.1
Bounciness: 0.100000001 Bounciness: 0.1
MeshColliderComponent: MeshColliderComponent:
AssetPath: assets/meshes/Capsule.fbx AssetPath: assets/meshes/Capsule.fbx
IsTrigger: false IsTrigger: false
@ -49,15 +56,16 @@ Entities:
TagComponent: TagComponent:
Tag: Mesh Collider Tag: Mesh Collider
TransformComponent: TransformComponent:
Position: [-2.60455179, 1, -0.00171399117] Position: [-2.6045518, 1, -0.0017139912]
Rotation: [1, 0, 0, 0] Rotation: [1, 0, 0, 0]
Scale: [1, 1, 1] Scale: [1, 1, 1]
MeshComponent: MeshComponent:
AssetPath: assets/meshes/Sphere1m.fbx AssetPath: assets/meshes/Sphere1m.fbx
RigidBodyComponent: RigidBodyComponent:
BodyType: 1 BodyType: 1
Mass: 0.100000001 Mass: 0.1
IsKinematic: false IsKinematic: false
Layer: 1
Constraints: Constraints:
LockPositionX: false LockPositionX: false
LockPositionY: false LockPositionY: false
@ -68,7 +76,7 @@ Entities:
PhysicsMaterialComponent: PhysicsMaterialComponent:
StaticFriction: 1 StaticFriction: 1
DynamicFriction: 1 DynamicFriction: 1
Bounciness: 0.100000001 Bounciness: 0.1
MeshColliderComponent: MeshColliderComponent:
AssetPath: assets/meshes/Sphere1m.fbx AssetPath: assets/meshes/Sphere1m.fbx
IsTrigger: false IsTrigger: false
@ -85,6 +93,7 @@ Entities:
BodyType: 1 BodyType: 1
Mass: 0.5 Mass: 0.5
IsKinematic: false IsKinematic: false
Layer: 0
Constraints: Constraints:
LockPositionX: false LockPositionX: false
LockPositionY: false LockPositionY: false
@ -104,7 +113,7 @@ Entities:
TagComponent: TagComponent:
Tag: Sphere Tag: Sphere
TransformComponent: TransformComponent:
Position: [-3.98769951, 1, -1.96695328e-06] Position: [-3.9876995, 1, -1.9669533e-06]
Rotation: [1, 0, 0, 0] Rotation: [1, 0, 0, 0]
Scale: [1, 1, 1] Scale: [1, 1, 1]
MeshComponent: MeshComponent:
@ -113,17 +122,18 @@ Entities:
BodyType: 1 BodyType: 1
Mass: 1 Mass: 1
IsKinematic: false IsKinematic: false
Layer: 1
Constraints: Constraints:
LockPositionX: false LockPositionX: false
LockPositionY: false LockPositionY: false
LockPositionZ: false LockPositionZ: false
LockRotationX: true LockRotationX: false
LockRotationY: true LockRotationY: false
LockRotationZ: true LockRotationZ: false
PhysicsMaterialComponent: PhysicsMaterialComponent:
StaticFriction: 0.100000001 StaticFriction: 0.1
DynamicFriction: 0.100000001 DynamicFriction: 0.1
Bounciness: 0.100000001 Bounciness: 0.1
SphereColliderComponent: SphereColliderComponent:
Radius: 0.5 Radius: 0.5
IsTrigger: false IsTrigger: false
@ -131,7 +141,7 @@ Entities:
TagComponent: TagComponent:
Tag: Camera Tag: Camera
TransformComponent: TransformComponent:
Position: [2.80800009, 2.25, 0] Position: [2.808, 2.25, 0]
Rotation: [1, 0, 0, 0] Rotation: [1, 0, 0, 0]
Scale: [1, 1, 1] Scale: [1, 1, 1]
CameraComponent: CameraComponent:
@ -150,6 +160,7 @@ Entities:
BodyType: 0 BodyType: 0
Mass: 1 Mass: 1
IsKinematic: false IsKinematic: false
Layer: 0
Constraints: Constraints:
LockPositionX: false LockPositionX: false
LockPositionY: false LockPositionY: false
@ -165,3 +176,7 @@ Entities:
Offset: [0, 0, 0] Offset: [0, 0, 0]
Size: [1, 1, 1] Size: [1, 1, 1]
IsTrigger: false IsTrigger: false
PhysicsLayers:
- Name: Default
CollidesWith:
[]

View File

@ -1,4 +1,3 @@
using System;
using Prism; using Prism;
namespace FPSExample namespace FPSExample
@ -9,7 +8,7 @@ namespace FPSExample
public float RunSpeed = 20.0F; public float RunSpeed = 20.0F;
public float JumpForce = 50.0F; public float JumpForce = 50.0F;
public float MouseSensitivity = 10.0F; public float MouseSensitivity = 10.0F;
public Vec3 Forward = new Vec3(0.0f, 0.0f, 1.0f); public float Distance = 5.0F;
private bool m_Colliding = false; private bool m_Colliding = false;
private float m_CurrentSpeed; private float m_CurrentSpeed;
@ -44,12 +43,11 @@ namespace FPSExample
void OnUpdate(float ts) void OnUpdate(float ts)
{ {
Forward = m_Transform.Forward;
if (Input.IsKeyPressed(KeyCode.Escape) && Input.GetCursorMode() == Input.CursorMode.Locked) if (Input.IsKeyPressed(KeyCode.Escape) && Input.GetCursorMode() == Input.CursorMode.Locked)
{
Input.SetCursorMode(Input.CursorMode.Normal); Input.SetCursorMode(Input.CursorMode.Normal);
}
if(Input.IsMouseButtonPressed(Input.MouseButton.Left) && Input.GetCursorMode() == Input.CursorMode.Normal)
Input.SetCursorMode(Input.CursorMode.Locked);
m_CurrentSpeed = Input.IsKeyPressed(KeyCode.LeftControl) ? RunSpeed : WalkingSpeed; m_CurrentSpeed = Input.IsKeyPressed(KeyCode.LeftControl) ? RunSpeed : WalkingSpeed;
@ -78,9 +76,33 @@ namespace FPSExample
m_LastMousePosition = currentMousePosition; m_LastMousePosition = currentMousePosition;
} }
Collider[] colliders = new Collider[10];
private void UpdateMovement() private void UpdateMovement()
{ {
RaycastHit hitInfo;
if (Input.IsKeyPressed(KeyCode.H) &&
Physics.Raycast(m_CameraTransform.Transform.Translation + (m_CameraTransform.Forward * 5.0f),
m_CameraTransform.Forward, 20.0f, out hitInfo))
{
FindEntityByID(hitInfo.EntityID).GetComponent<MeshComponent>().Mesh.GetMaterial(0).Set("u_AlbedoColor", new Vec3(1.0f ,0.0f, 0.0f));
}
if (Input.IsKeyPressed(KeyCode.I))
{
// NOTE: The NonAlloc version of Overlap functions should be used when possible since it doesn't allocate a new array
// whenever you call it. The normal versions allocates a brand new array every time.
int numColliders = Physics.OverlapBoxNonAlloc(m_Transform.Transform.Translation, new Vec3(1.0F), colliders);
Console.WriteLine("Colliders: {0}", numColliders);
// When using NonAlloc it's not safe to use a foreach loop since some of the colliders may not exist
for (int i = 0; i < numColliders; i++)
{
Console.WriteLine(colliders[i]);
}
}
if (Input.IsKeyPressed(KeyCode.W)) if (Input.IsKeyPressed(KeyCode.W))
m_RigidBody.AddForce(m_Transform.Forward * m_CurrentSpeed); m_RigidBody.AddForce(m_Transform.Forward * m_CurrentSpeed);
else if (Input.IsKeyPressed(KeyCode.S)) else if (Input.IsKeyPressed(KeyCode.S))
@ -105,7 +127,7 @@ namespace FPSExample
Vec3 translation = m_Transform.Transform.Translation; Vec3 translation = m_Transform.Transform.Translation;
cameraTranslation.XZ = translation.XZ; cameraTranslation.XZ = translation.XZ;
cameraTranslation.Y = translation.Y + 1.5F; cameraTranslation.Y = translation.Y + 1.5F;
cameraTransform.Translation = cameraTranslation; cameraTransform.Translation = cameraTranslation + m_CameraTransform.Forward * -Mathf.Clamp(Distance, 0, 10);
m_CameraTransform.Transform = cameraTransform; m_CameraTransform.Transform = cameraTransform;
m_CameraTransform.Rotation = new Vec3(m_CameraRotationX, m_RotationY, 0.0f); m_CameraTransform.Rotation = new Vec3(m_CameraRotationX, m_RotationY, 0.0f);

View File

@ -55,6 +55,12 @@ namespace Prism
return new Entity(entityID); return new Entity(entityID);
} }
public Entity FindEntityByID(ulong entityID)
{
// TODO: to verify it
return new Entity(entityID);
}
public Mat4 GetTransform() public Mat4 GetTransform()
{ {
Mat4 mat4Instance; Mat4 mat4Instance;

View File

@ -10,12 +10,31 @@ namespace Prism
Hidden = 1, Hidden = 1,
Locked = 2, Locked = 2,
} }
public enum MouseButton
{
Button0 = 0,
Button1 = 1,
Button2 = 2,
Button3 = 3,
Button4 = 4,
Button5 = 5,
Left = Button0,
Right = Button1,
Middle = Button2
}
public static bool IsKeyPressed(KeyCode keycode) public static bool IsKeyPressed(KeyCode keycode)
{ {
return IsKeyPressed_Native(keycode); return IsKeyPressed_Native(keycode);
} }
public static bool IsMouseButtonPressed(MouseButton button)
{
return IsMouseButtonPressed_Native(button);
}
public static Vec2 GetMousePosition() public static Vec2 GetMousePosition()
{ {
GetMousePosition_Native(out Vec2 position); GetMousePosition_Native(out Vec2 position);
@ -30,6 +49,9 @@ namespace Prism
[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 bool IsMouseButtonPressed_Native(MouseButton button);
[MethodImpl(MethodImplOptions.InternalCall)] [MethodImpl(MethodImplOptions.InternalCall)]
private static extern void GetMousePosition_Native(out Vec2 position); private static extern void GetMousePosition_Native(out Vec2 position);

View File

@ -46,6 +46,25 @@ namespace Prism
Z = Mathf.Clamp(Z, min.Z, max.Z); Z = Mathf.Clamp(Z, min.Z, max.Z);
} }
public float Length()
{
return (float)Math.Sqrt(X * X + Y * Y + Z * Z);
}
public Vec3 Normalized()
{
float length = Length();
return new Vec3(X / length, Y / length, Z / length);
}
public void Normalize()
{
float length = Length();
X = X / length;
Y = Y / length;
Z = Z / length;
}
public Vec2 XY { public Vec2 XY {
get { return new Vec2(X, Y); } get { return new Vec2(X, Y); }
@ -79,6 +98,11 @@ namespace Prism
return new Vec3(left.X + right.X, left.Y + right.Y, left.Z + right.Z); return new Vec3(left.X + right.X, left.Y + right.Y, left.Z + right.Z);
} }
public static Vec3 operator +(Vec3 left, float right)
{
return new Vec3(left.X + right, left.Y + right, left.Z + right);
}
public static Vec3 operator -(Vec3 left, Vec3 right) public static Vec3 operator -(Vec3 left, Vec3 right)
{ {
return new Vec3(left.X - right.X, left.Y - right.Y, left.Z - right.Z); return new Vec3(left.X - right.X, left.Y - right.Y, left.Z - right.Z);

View File

@ -4,29 +4,55 @@ namespace Prism
{ {
public class Collider public class Collider
{ {
public enum ColliderType public ulong EntityID { get; protected set; }
{
Box,
Sphere,
Capsule,
Mesh
}
public Entity ColliderEntity { get; protected set; }
public ColliderType Type { get; protected set; }
public bool IsTrigger { get; protected set; } public bool IsTrigger { get; protected set; }
private Entity entity;
private RigidBodyComponent _rigidBodyComponent;
public Entity Entity
{
get
{
if (entity == null)
entity = new Entity(EntityID);
return entity;
}
}
public RigidBodyComponent RigidBody
{
get
{
if (_rigidBodyComponent == null)
_rigidBodyComponent = Entity.GetComponent<RigidBodyComponent>();
return _rigidBodyComponent;
}
}
public override string ToString()
{
string type = "Collider";
if (this is BoxCollider) type = "BoxCollider";
else if (this is SphereCollider) type = "SphereCollider";
else if (this is CapsuleCollider) type = "CapsuleCollider";
else if (this is MeshCollider) type = "MeshCollider";
return "Collider(" + type + ", " + EntityID + ", " + IsTrigger + ")";
}
} }
public class BoxCollider : Collider public class BoxCollider : Collider
{ {
public Vec3 Size { get; private set; } public Vec3 Size { get; protected set; }
public Vec3 Offset { get; private set; } public Vec3 Offset { get; protected set; }
internal BoxCollider(ulong entityID, Vec3 size, Vec3 offset, bool isTrigger) private BoxCollider(ulong entityID, bool isTrigger, Vec3 size, Vec3 offset)
{ {
ColliderEntity = new Entity(entityID); EntityID = entityID;
Type = ColliderType.Box;
Size = size; Size = size;
Offset = offset; Offset = offset;
IsTrigger = isTrigger; IsTrigger = isTrigger;
@ -35,12 +61,11 @@ namespace Prism
public class SphereCollider : Collider public class SphereCollider : Collider
{ {
public float Radius { get; private set; } public float Radius { get; protected set; }
internal SphereCollider(ulong entityID, float radius, bool isTrigger) private SphereCollider(ulong entityID, bool isTrigger, float radius)
{ {
ColliderEntity = new Entity(entityID); EntityID = entityID;
Type = ColliderType.Box;
Radius = radius; Radius = radius;
IsTrigger = isTrigger; IsTrigger = isTrigger;
} }
@ -48,13 +73,12 @@ namespace Prism
public class CapsuleCollider : Collider public class CapsuleCollider : Collider
{ {
public float Radius { get; private set; } public float Radius { get; protected set; }
public float Height { get; private set; } public float Height { get; protected set; }
internal CapsuleCollider(ulong entityID, float radius, float height, bool isTrigger) private CapsuleCollider(ulong entityID, bool isTrigger, float radius, float height)
{ {
ColliderEntity = new Entity(entityID); EntityID = entityID;
Type = ColliderType.Box;
Radius = radius; Radius = radius;
Height = height; Height = height;
IsTrigger = isTrigger; IsTrigger = isTrigger;
@ -63,13 +87,12 @@ namespace Prism
public class MeshCollider : Collider public class MeshCollider : Collider
{ {
public Mesh Mesh { get; private set; } public Mesh Mesh { get; protected set; }
internal MeshCollider(ulong entityID, Mesh mesh, bool isTrigger) private MeshCollider(ulong entityID, bool isTrigger, IntPtr filepath)
{ {
ColliderEntity = new Entity(entityID); EntityID = entityID;
Type = ColliderType.Box; Mesh = new Mesh(filepath);
Mesh = mesh;
IsTrigger = isTrigger; IsTrigger = isTrigger;
} }
} }

View File

@ -0,0 +1,74 @@
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
namespace Prism
{
[StructLayout(LayoutKind.Sequential)]
public struct RaycastHit
{
public ulong EntityID { get; private set; }
public Vec3 Position { get; private set; }
public Vec3 Normal { get; private set; }
public float Distance { get; private set; }
}
public static class Physics
{
public static bool Raycast(Vec3 origin, Vec3 direction, float maxDistance, out RaycastHit hit)
{
return Raycast_Native(ref origin, ref direction, maxDistance, out hit);
}
public static Collider[] OverlapBox(Vec3 origin, Vec3 halfSize)
{
return OverlapBox_Native(ref origin, ref halfSize);
}
public static Collider[] OverlapCapsule(Vec3 origin, float radius, float halfHeight)
{
return OverlapCapsule_Native(ref origin, radius, halfHeight);
}
public static Collider[] OverlapSphere(Vec3 origin, float radius)
{
return OverlapSphere_Native(ref origin, radius);
}
public static int OverlapBoxNonAlloc(Vec3 origin, Vec3 halfSize, Collider[] colliders)
{
return OverlapBoxNonAlloc_Native(ref origin, ref halfSize, colliders);
}
public static int OverlapCapsuleNonAlloc(Vec3 origin, float radius, float halfHeight, Collider[] colliders)
{
return OverlapCapsuleNonAlloc_Native(ref origin, radius, halfHeight, colliders);
}
public static int OverlapSphereNonAlloc(Vec3 origin, float radius, Collider[] colliders)
{
return OverlapSphereNonAlloc_Native(ref origin, radius, colliders);
}
[MethodImpl(MethodImplOptions.InternalCall)]
internal static extern bool Raycast_Native(ref Vec3 origin, ref Vec3 direction, float maxDistance, out RaycastHit hit);
[MethodImpl(MethodImplOptions.InternalCall)]
internal static extern Collider[] OverlapBox_Native(ref Vec3 origin, ref Vec3 halfSize);
[MethodImpl(MethodImplOptions.InternalCall)]
internal static extern Collider[] OverlapCapsule_Native(ref Vec3 origin, float radius, float halfHeight);
[MethodImpl(MethodImplOptions.InternalCall)]
internal static extern Collider[] OverlapSphere_Native(ref Vec3 origin, float radius);
[MethodImpl(MethodImplOptions.InternalCall)]
internal static extern int OverlapBoxNonAlloc_Native(ref Vec3 origin, ref Vec3 halfSize, Collider[] colliders);
[MethodImpl(MethodImplOptions.InternalCall)]
internal static extern int OverlapCapsuleNonAlloc_Native(ref Vec3 origin, float radius, float halfHeight, Collider[] colliders);
[MethodImpl(MethodImplOptions.InternalCall)]
internal static extern int OverlapSphereNonAlloc_Native(ref Vec3 origin, float radius, Collider[] colliders);
}
}

View File

@ -192,6 +192,18 @@ namespace Prism
VelocityChange, VelocityChange,
Acceleration Acceleration
} }
public float Mass
{
get { return GetMass_Native(Entity.ID); }
set { SetMass_Native(Entity.ID, value); }
}
public uint Layer
{
get { return GetLayer_Native(Entity.ID); }
}
public void AddForce(Vec3 force, ForceMode forceMode = ForceMode.Force) public void AddForce(Vec3 force, ForceMode forceMode = ForceMode.Force)
{ {
@ -234,5 +246,14 @@ namespace Prism
[MethodImpl(MethodImplOptions.InternalCall)] [MethodImpl(MethodImplOptions.InternalCall)]
internal static extern void Rotate_Native(ulong entityID, ref Vec3 rotation); internal static extern void Rotate_Native(ulong entityID, ref Vec3 rotation);
[MethodImpl(MethodImplOptions.InternalCall)]
internal static extern uint GetLayer_Native(ulong entityID);
[MethodImpl(MethodImplOptions.InternalCall)]
internal static extern float GetMass_Native(ulong entityID);
[MethodImpl(MethodImplOptions.InternalCall)]
internal static extern float SetMass_Native(ulong entityID, float mass);
} }
} }

View File

@ -9,19 +9,12 @@
namespace Prism namespace Prism
{ {
enum class CursorMode
{
Normal = 0,
Hidden = 1,
Locked = 2
};
class PRISM_API Input class PRISM_API Input
{ {
public: public:
static bool IsKeyPressed(KeyCode keycode); static bool IsKeyPressed(KeyCode keycode);
static bool IsMouseButtonPressed(int button); static bool IsMouseButtonPressed(MouseButton button);
static float GetMouseX(); static float GetMouseX();
static float GetMouseY(); static float GetMouseY();
static std::pair<float, float> GetMousePosition(); static std::pair<float, float> GetMousePosition();

View File

@ -7,6 +7,32 @@
namespace Prism namespace Prism
{ {
enum class CursorMode
{
Normal = 0,
Hidden = 1,
Locked = 2
};
typedef enum class MouseButton : uint16_t
{
Button0 = 0,
Button1 = 1,
Button2 = 2,
Button3 = 3,
Button4 = 4,
Button5 = 5,
Left = Button0,
Right = Button1,
Middle = Button2
} Button;
inline std::ostream& operator<<(std::ostream& os, MouseButton button)
{
os << static_cast<int32_t>(button);
return os;
}
typedef enum class KeyCode : uint16_t typedef enum class KeyCode : uint16_t
{ {
SPACE = 32, SPACE = 32,

View File

@ -45,11 +45,11 @@ namespace Prism
const glm::vec2 delta = (mouse - m_InitialMousePosition) * 0.003f; const glm::vec2 delta = (mouse - m_InitialMousePosition) * 0.003f;
m_InitialMousePosition = mouse; m_InitialMousePosition = mouse;
if (Input::IsMouseButtonPressed(GLFW_MOUSE_BUTTON_MIDDLE)) if (Input::IsMouseButtonPressed(MouseButton::Middle))
MousePan(delta); MousePan(delta);
else if (Input::IsMouseButtonPressed(GLFW_MOUSE_BUTTON_LEFT)) else if (Input::IsMouseButtonPressed(MouseButton::Left))
MouseRotate(delta); MouseRotate(delta);
else if (Input::IsMouseButtonPressed(GLFW_MOUSE_BUTTON_RIGHT)) else if (Input::IsMouseButtonPressed(MouseButton::Right))
MouseZoom(delta.y); MouseZoom(delta.y);
} }

View File

@ -0,0 +1,109 @@
//
// Created by sfd on 25-12-25.
//
#include "PhysicsSettingsWindow.h"
#include "imgui.h"
#include "Prism/Physics/PhysicsLayer.h"
namespace Prism
{
static int32_t s_SelectedLayer = -1;
static char s_NewLayerNameBuffer[50];
void PhysicsSettingsWindow::OnImGuiRender(bool* show)
{
if (!(*show))
return;
ImGui::Begin("Physics", show);
ImGui::PushID(0);
ImGui::Columns(2);
RenderLayerList();
ImGui::NextColumn();
RenderSelectedLayer();
ImGui::PopID();
ImGui::End();
}
void PhysicsSettingsWindow::RenderLayerList()
{
if (ImGui::Button("New Layer"))
{
ImGui::OpenPopup("NewLayerNamePopup");
}
if (ImGui::BeginPopup("NewLayerNamePopup"))
{
ImGui::InputText("##LayerNameID", s_NewLayerNameBuffer, 50);
if (ImGui::Button("Add"))
{
PhysicsLayerManager::AddLayer(std::string(s_NewLayerNameBuffer));
memset(s_NewLayerNameBuffer, 0, 50);
ImGui::CloseCurrentPopup();
}
ImGui::EndPopup();
}
uint32_t buttonId = 1;
for (const auto& layer : PhysicsLayerManager::GetLayers())
{
if (ImGui::Button(layer.Name.c_str()))
{
s_SelectedLayer = layer.LayerID;
}
if (layer.Name != "Default")
{
ImGui::SameLine();
ImGui::PushID(buttonId++);
if (ImGui::Button("X"))
{
PhysicsLayerManager::RemoveLayer(layer.LayerID);
}
ImGui::PopID();
}
}
}
void PhysicsSettingsWindow::RenderSelectedLayer()
{
if (s_SelectedLayer == -1)
return;
const PhysicsLayer& layerInfo = PhysicsLayerManager::GetLayer(s_SelectedLayer);
for (const auto& layer : PhysicsLayerManager::GetLayers())
{
if (layer.LayerID == s_SelectedLayer)
continue;
const PhysicsLayer& otherLayerInfo = PhysicsLayerManager::GetLayer(layer.LayerID);
bool shouldCollide;
if (layerInfo.CollidesWith == 0 || otherLayerInfo.CollidesWith == 0)
{
shouldCollide = false;
}
else
{
shouldCollide = layerInfo.CollidesWith & otherLayerInfo.BitValue;
}
ImGui::TextUnformatted(otherLayerInfo.Name.c_str());
ImGui::SameLine();
if (ImGui::Checkbox(("##" + otherLayerInfo.Name).c_str(), &shouldCollide))
{
PhysicsLayerManager::SetLayerCollision(s_SelectedLayer, layer.LayerID, shouldCollide);
}
}
}
}

View File

@ -0,0 +1,20 @@
//
// Created by sfd on 25-12-25.
//
#ifndef PHYSICSSETTINGSWINDOW_H
#define PHYSICSSETTINGSWINDOW_H
namespace Prism
{
class PRISM_API PhysicsSettingsWindow
{
public:
static void OnImGuiRender(bool* show);
static void RenderLayerList();
static void RenderSelectedLayer();
};
}
#endif //PHYSICSSETTINGSWINDOW_H

View File

@ -12,7 +12,8 @@
#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/Physics/PhysicsLayer.h"
#include "Prism/Physics/PhysicsWrappers.h"
#include "Prism/Renderer/Meshfactory.h" #include "Prism/Renderer/Meshfactory.h"
#include "Prism/Script/ScriptEngine.h" #include "Prism/Script/ScriptEngine.h"
@ -951,7 +952,10 @@ namespace Prism
// Rigidbody Type // Rigidbody Type
const char* rbTypeStrings[] = { "Static", "Dynamic"}; const char* rbTypeStrings[] = { "Static", "Dynamic"};
const char* currentType = rbTypeStrings[(int)rbc.BodyType]; const char* currentType = rbTypeStrings[(int)rbc.BodyType];
if (ImGui::BeginCombo("Type", currentType))
ImGui::TextUnformatted("Type");
ImGui::SameLine();
if (ImGui::BeginCombo("##TypeSelection", currentType))
{ {
for (int type = 0; type < 2; type++) for (int type = 0; type < 2; type++)
{ {
@ -967,6 +971,32 @@ namespace Prism
ImGui::EndCombo(); ImGui::EndCombo();
} }
// Layer has been removed, set to Default layer
if (!PhysicsLayerManager::IsLayerValid(rbc.Layer))
rbc.Layer = 0;
uint32_t currentLayer = rbc.Layer;
const PhysicsLayer& layerInfo = PhysicsLayerManager::GetLayer(currentLayer);
ImGui::TextUnformatted("Layer");
ImGui::SameLine();
if (ImGui::BeginCombo("##LayerSelection", layerInfo.Name.c_str()))
{
for (const auto& layer : PhysicsLayerManager::GetLayers())
{
const bool is_selected = (currentLayer == layer.LayerID);
if (ImGui::Selectable(layer.Name.c_str(), is_selected))
{
currentLayer = layer.LayerID;
rbc.Layer = layer.LayerID;
}
if (is_selected)
ImGui::SetItemDefaultFocus();
}
ImGui::EndCombo();
}
if (rbc.BodyType == RigidBodyComponent::Type::Dynamic) if (rbc.BodyType == RigidBodyComponent::Type::Dynamic)
{ {
BeginPropertyGrid(); BeginPropertyGrid();
@ -1071,7 +1101,7 @@ namespace Prism
if (!file.empty()) if (!file.empty())
{ {
mcc.CollisionMesh = Ref<Mesh>::Create(file); mcc.CollisionMesh = Ref<Mesh>::Create(file);
PxPhysicsWrappers::CreateConvexMesh(mcc); PhysicsWrappers::CreateConvexMesh(mcc);
} }
} }
ImGui::EndColumns(); ImGui::EndColumns();

View File

@ -12,16 +12,12 @@
#define PX_PHYSX_STATIC_LIB #define PX_PHYSX_STATIC_LIB
#include <PxPhysicsAPI.h> #include <PxPhysicsAPI.h>
#include "PxPhysicsWrappers.h" #include "PhysicsLayer.h"
#include "PhysicsWrappers.h"
namespace Prism namespace Prism
{ {
static physx::PxScene* s_Scene = nullptr;
static std::vector<Entity> s_SimulatedEntities;
static Entity* s_EntityStorageBuffer = nullptr;
static int s_EntityStorageBufferPosition = 0;
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::vec3 scale, translation, skew;
@ -32,20 +28,26 @@ namespace Prism
return { translation, orientation, scale }; return { translation, orientation, scale };
} }
static physx::PxScene* s_Scene;
static std::vector<Entity> s_SimulatedEntities;
static Entity* s_EntityStorageBuffer;
static int s_EntityStorageBufferPosition;
void Physics3D::Init() void Physics3D::Init()
{ {
PxPhysicsWrappers::Initialize(); PhysicsWrappers::Initialize();
PhysicsLayerManager::AddLayer("Default");
} }
void Physics3D::Shutdown() void Physics3D::Shutdown()
{ {
PxPhysicsWrappers::Shutdown(); PhysicsWrappers::Shutdown();
} }
void Physics3D::CreateScene(const SceneParams& params) void Physics3D::CreateScene(const SceneParams& params)
{ {
PM_CORE_ASSERT(s_Scene == nullptr, "Scene already has a Physics Scene!"); PM_CORE_ASSERT(s_Scene == nullptr, "Scene already has a Physics Scene!");
s_Scene = PxPhysicsWrappers::CreateScene(params); s_Scene = PhysicsWrappers::CreateScene(params);
} }
void Physics3D::CreateActor(Entity e, int entityCount) void Physics3D::CreateActor(Entity e, int entityCount)
@ -67,53 +69,48 @@ namespace Prism
if (s_EntityStorageBuffer == nullptr) if (s_EntityStorageBuffer == nullptr)
s_EntityStorageBuffer = new Entity[entityCount]; s_EntityStorageBuffer = new Entity[entityCount];
// Create Actor Body physx::PxRigidActor* actor = PhysicsWrappers::CreateActor(rigidbody, e.Transform());
physx::PxRigidActor* actor = PxPhysicsWrappers::CreateActor(rigidbody, e.Transform());
s_SimulatedEntities.push_back(e); s_SimulatedEntities.push_back(e);
Entity* entityStorage = &s_EntityStorageBuffer[s_EntityStorageBufferPosition++]; Entity* entityStorage = &s_EntityStorageBuffer[s_EntityStorageBufferPosition++];
*entityStorage = e; *entityStorage = e;
actor->userData = (void*)entityStorage; actor->userData = (void*)entityStorage;
rigidbody.RuntimeActor = actor; rigidbody.RuntimeActor = actor;
// Physics Material const physx::PxMaterial* material = PhysicsWrappers::CreateMaterial(e.GetComponent<PhysicsMaterialComponent>());
const physx::PxMaterial* material = PxPhysicsWrappers::CreateMaterial(e.GetComponent<PhysicsMaterialComponent>());
const auto& transform = e.Transform();
auto [translation, rotation, scale] = GetTransformDecomposition(transform);
auto [translation, rotationQuat, scale] = GetTransformDecomposition(e.Transform());
// Add all colliders // Add all colliders
if (e.HasComponent<BoxColliderComponent>()) if (e.HasComponent<BoxColliderComponent>())
{ {
const BoxColliderComponent& collider = e.GetComponent<BoxColliderComponent>(); const BoxColliderComponent& collider = e.GetComponent<BoxColliderComponent>();
PxPhysicsWrappers::AddBoxCollider(*actor, *material, collider, scale); PhysicsWrappers::AddBoxCollider(*actor, *material, collider, scale);
} }
if (e.HasComponent<SphereColliderComponent>()) if (e.HasComponent<SphereColliderComponent>())
{ {
const SphereColliderComponent& collider = e.GetComponent<SphereColliderComponent>(); const SphereColliderComponent& collider = e.GetComponent<SphereColliderComponent>();
PxPhysicsWrappers::AddSphereCollider(*actor, *material, collider, scale); PhysicsWrappers::AddSphereCollider(*actor, *material, collider, scale);
} }
if (e.HasComponent<CapsuleColliderComponent>()) if (e.HasComponent<CapsuleColliderComponent>())
{ {
const CapsuleColliderComponent& collider = e.GetComponent<CapsuleColliderComponent>(); const CapsuleColliderComponent& collider = e.GetComponent<CapsuleColliderComponent>();
PxPhysicsWrappers::AddCapsuleCollider(*actor, *material, collider, scale); PhysicsWrappers::AddCapsuleCollider(*actor, *material, collider, scale);
} }
if (e.HasComponent<MeshColliderComponent>()) if (e.HasComponent<MeshColliderComponent>())
{ {
MeshColliderComponent& collider = e.GetComponent<MeshColliderComponent>(); auto& collider = e.GetComponent<MeshColliderComponent>();
PxPhysicsWrappers::AddMeshCollider(*actor, *material, collider, scale); PhysicsWrappers::AddMeshCollider(*actor, *material, collider, scale);
} }
// Set collision filters if (!PhysicsLayerManager::IsLayerValid(rigidbody.Layer))
if (rigidbody.BodyType == RigidBodyComponent::Type::Static) rigidbody.Layer = 0;
{
PxPhysicsWrappers::SetCollisionFilters(*actor, (uint32_t)FilterGroup::Static, (uint32_t)FilterGroup::All); PhysicsWrappers::SetCollisionFilters(*actor, rigidbody.Layer);
}
else if (rigidbody.BodyType == RigidBodyComponent::Type::Dynamic)
{
PxPhysicsWrappers::SetCollisionFilters(*actor, (uint32_t)FilterGroup::Dynamic, (uint32_t)FilterGroup::All);
}
s_Scene->addActor(*actor); s_Scene->addActor(*actor);
} }
@ -127,7 +124,7 @@ namespace Prism
{ {
auto& transform = e.Transform(); auto& transform = e.Transform();
// TODO: Come up with a better solution for scale // TODO: Come up with a better solution for scale
auto [p, r, scale] = GetTransformDecomposition(transform); auto [position, rotation, scale] = GetTransformDecomposition(transform);
const auto& rb = e.GetComponent<RigidBodyComponent>(); const auto& rb = e.GetComponent<RigidBodyComponent>();
const auto actor = static_cast<physx::PxRigidActor*>(rb.RuntimeActor); const auto actor = static_cast<physx::PxRigidActor*>(rb.RuntimeActor);
@ -153,10 +150,15 @@ namespace Prism
s_Scene = nullptr; s_Scene = nullptr;
} }
void* Physics3D::GetPhysicsScene()
{
return s_Scene;
}
bool Physics3D::ConnectPVD() bool Physics3D::ConnectPVD()
{ {
PM_CORE_INFO("Trying to connect PVD"); PM_CORE_INFO("Trying to connect PVD");
const bool isconnect = PxPhysicsWrappers::ConnectPVD(); const bool isconnect = PhysicsWrappers::ConnectPVD();
if (isconnect) if (isconnect)
PM_CORE_INFO("PVD Connected"); PM_CORE_INFO("PVD Connected");
else else
@ -164,11 +166,11 @@ namespace Prism
return isconnect; return isconnect;
} }
bool Physics3D::IsPVDConnected() {return PxPhysicsWrappers::IsPVDConnected();} bool Physics3D::IsPVDConnected() {return PhysicsWrappers::IsPVDConnected();}
void Physics3D::DisconnectPVD() void Physics3D::DisconnectPVD()
{ {
PxPhysicsWrappers::DisconnectPVD(); PhysicsWrappers::DisconnectPVD();
} }

View File

@ -27,6 +27,14 @@ namespace Prism
All = Static | Dynamic | Kinematic All = Static | Dynamic | Kinematic
}; };
struct RaycastHit
{
uint64_t EntityID;
glm::vec3 Position;
glm::vec3 Normal;
float Distance;
};
struct SceneParams struct SceneParams
{ {
glm::vec3 Gravity = { 0.0F, -9.81F, 0.0F }; glm::vec3 Gravity = { 0.0F, -9.81F, 0.0F };
@ -45,6 +53,8 @@ namespace Prism
static void DestroyScene(); static void DestroyScene();
static void* GetPhysicsScene();
static bool ConnectPVD(); static bool ConnectPVD();
static bool IsPVDConnected(); static bool IsPVDConnected();
static void DisconnectPVD(); static void DisconnectPVD();

View File

@ -0,0 +1,168 @@
//
// Created by sfd on 25-12-25.
//
#include "PhysicsLayer.h"
namespace Prism
{
template<typename T, typename ConditionFunction>
static bool RemoveIfExists(std::vector<T>& vector, ConditionFunction condition)
{
for (std::vector<T>::iterator it = vector.begin(); it != vector.end(); ++it)
{
if (condition(*it))
{
vector.erase(it);
return true;
}
}
return false;
}
uint32_t PhysicsLayerManager::AddLayer(const std::string& name, bool setCollisions)
{
const uint32_t layerId = GetNextLayerID();
const PhysicsLayer layer = { layerId, name, static_cast<uint32_t>(BIT(layerId)) };
s_Layers.push_back(layer);
if (setCollisions)
{
for (const auto& layer2 : s_Layers)
{
SetLayerCollision(layer.LayerID, layer2.LayerID, true);
}
}
return layer.LayerID;
}
void PhysicsLayerManager::RemoveLayer(uint32_t layerId)
{
if (!IsLayerValid(layerId))
return;
const PhysicsLayer& layerInfo = GetLayer(layerId);
for (auto& otherLayer : s_Layers)
{
if (otherLayer.LayerID == layerId)
continue;
if (otherLayer.CollidesWith & layerInfo.BitValue)
{
otherLayer.CollidesWith &= ~layerInfo.BitValue;
}
}
RemoveIfExists<PhysicsLayer>(s_Layers, [&](const PhysicsLayer& layer) { return layer.LayerID == layerId; });
}
void PhysicsLayerManager::SetLayerCollision(uint32_t layerId, uint32_t otherLayer, bool collides)
{
if (ShouldCollide(layerId, otherLayer) && collides)
return;
PhysicsLayer& layerInfo = GetLayer(layerId);
PhysicsLayer& otherLayerInfo = GetLayer(otherLayer);
if (collides)
{
layerInfo.CollidesWith |= otherLayerInfo.BitValue;
otherLayerInfo.CollidesWith |= layerInfo.BitValue;
}
else
{
layerInfo.CollidesWith &= ~otherLayerInfo.BitValue;
otherLayerInfo.CollidesWith &= ~layerInfo.BitValue;
}
}
const std::vector<PhysicsLayer>& PhysicsLayerManager::GetLayerCollisions(uint32_t layerId)
{
const PhysicsLayer& layer = GetLayer(layerId);
std::vector<PhysicsLayer> layers;
for (const auto& otherLayer : s_Layers)
{
if (otherLayer.LayerID == layerId)
continue;
if (layer.CollidesWith & otherLayer.BitValue)
layers.push_back(otherLayer);
}
return layers;
}
PhysicsLayer& PhysicsLayerManager::GetLayer(uint32_t layerId)
{
for (auto& layer : s_Layers)
{
if (layer.LayerID == layerId)
{
return layer;
}
}
return s_NullLayer;
}
PhysicsLayer& PhysicsLayerManager::GetLayer(const std::string& layerName)
{
for (auto& layer : s_Layers)
{
if (layer.Name == layerName)
{
return layer;
}
}
return s_NullLayer;
}
bool PhysicsLayerManager::ShouldCollide(uint32_t layer1, uint32_t layer2)
{
return GetLayer(layer1).CollidesWith & GetLayer(layer2).BitValue;
}
bool PhysicsLayerManager::IsLayerValid(uint32_t layerId)
{
for (const auto& layer : s_Layers)
{
if (layer.LayerID == layerId)
return true;
}
return false;
}
void PhysicsLayerManager::ClearLayers()
{
s_Layers.clear();
}
uint32_t PhysicsLayerManager::GetNextLayerID()
{
int32_t lastId = -1;
for (const auto& layer : s_Layers)
{
if (lastId != -1)
{
if (layer.LayerID != lastId + 1)
{
return lastId + 1;
}
}
lastId = layer.LayerID;
}
return s_Layers.size();
}
std::vector<PhysicsLayer> PhysicsLayerManager::s_Layers;
PhysicsLayer PhysicsLayerManager::s_NullLayer = { 0, "NULL", 0, -1 };
}

View File

@ -0,0 +1,51 @@
//
// Created by sfd on 25-12-25.
//
#ifndef PHYSICSLAYER_H
#define PHYSICSLAYER_H
namespace Prism
{
struct PhysicsLayer
{
uint32_t LayerID;
std::string Name;
uint32_t BitValue;
int32_t CollidesWith = 0;
};
class PhysicsLayerManager
{
public:
static uint32_t AddLayer(const std::string& name, bool setCollisions = true);
static void RemoveLayer(uint32_t layerId);
static void SetLayerCollision(uint32_t layerId, uint32_t otherLayer, bool collides);
static const std::vector<PhysicsLayer>& GetLayerCollisions(uint32_t layerId);
static const std::vector<PhysicsLayer>& GetLayers() { return s_Layers; }
static PhysicsLayer& GetLayer(uint32_t layerId);
static PhysicsLayer& GetLayer(const std::string& layerName);
static uint32_t GetLayerCount() { return static_cast<uint32_t>(s_Layers.size()); }
static bool ShouldCollide(uint32_t layer1, uint32_t layer2);
static bool IsLayerValid(uint32_t layerId);
static void ClearLayers();
private:
static uint32_t GetNextLayerID();
private:
static std::vector<PhysicsLayer> s_Layers;
static PhysicsLayer s_NullLayer;
};
}
#endif //PHYSICSLAYER_H

View File

@ -25,23 +25,23 @@ namespace Prism
physx::PxVec3 ToPhysXVector(const glm::vec3& vector) physx::PxVec3 ToPhysXVector(const glm::vec3& vector)
{ {
return {vector.x, vector.y, vector.z}; return *(physx::PxVec3*)&vector;
} }
physx::PxVec4 ToPhysXVector(const glm::vec4& vector) physx::PxVec4 ToPhysXVector(const glm::vec4& vector)
{ {
return {vector.x, vector.y, vector.z, vector.w}; return *(physx::PxVec4*)&vector;
} }
physx::PxQuat ToPhysXQuat(const glm::quat& quat) physx::PxQuat ToPhysXQuat(const glm::quat& quat)
{ {
return {quat.x, quat.y, quat.z, quat.w}; return *(physx::PxQuat*)&quat;
} }
glm::mat4 FromPhysXTransform(const physx::PxTransform& transform) glm::mat4 FromPhysXTransform(const physx::PxTransform& transform)
{ {
glm::quat rotation = FromPhysXQuat(transform.q); const glm::quat rotation = FromPhysXQuat(transform.q);
glm::vec3 position = FromPhysXVector(transform.p); const glm::vec3 position = FromPhysXVector(transform.p);
return glm::translate(glm::mat4(1.0F), position) * glm::toMat4(rotation); return glm::translate(glm::mat4(1.0F), position) * glm::toMat4(rotation);
} }
@ -52,20 +52,20 @@ namespace Prism
glm::vec3 FromPhysXVector(const physx::PxVec3& vector) glm::vec3 FromPhysXVector(const physx::PxVec3& vector)
{ {
return {vector.x, vector.y, vector.z}; return *(glm::vec3*)&vector;
} }
glm::vec4 FromPhysXVector(const physx::PxVec4& vector) glm::vec4 FromPhysXVector(const physx::PxVec4& vector)
{ {
return {vector.x, vector.y, vector.z, vector.w}; return *(glm::vec4*)&vector;
} }
glm::quat FromPhysXQuat(const physx::PxQuat& quat) glm::quat FromPhysXQuat(const physx::PxQuat& quat)
{ {
return {quat.w, quat.x, quat.y, quat.z}; return *(glm::quat*)&quat;
} }
physx::PxFilterFlags HazelFilterShader(physx::PxFilterObjectAttributes attributes0, physx::PxFilterData filterData0, physx::PxFilterObjectAttributes attributes1, physx::PxFilterData filterData1, physx::PxPairFlags& pairFlags, const void* constantBlock, physx::PxU32 constantBlockSize) physx::PxFilterFlags PrismFilterShader(physx::PxFilterObjectAttributes attributes0, physx::PxFilterData filterData0, physx::PxFilterObjectAttributes attributes1, physx::PxFilterData filterData1, physx::PxPairFlags& pairFlags, const void* constantBlock, physx::PxU32 constantBlockSize)
{ {
if (physx::PxFilterObjectIsTrigger(attributes0) || physx::PxFilterObjectIsTrigger(attributes1)) if (physx::PxFilterObjectIsTrigger(attributes0) || physx::PxFilterObjectIsTrigger(attributes1))
{ {
@ -79,9 +79,10 @@ namespace Prism
{ {
pairFlags |= physx::PxPairFlag::eNOTIFY_TOUCH_FOUND; pairFlags |= physx::PxPairFlag::eNOTIFY_TOUCH_FOUND;
pairFlags |= physx::PxPairFlag::eNOTIFY_TOUCH_LOST; pairFlags |= physx::PxPairFlag::eNOTIFY_TOUCH_LOST;
return physx::PxFilterFlag::eDEFAULT;
} }
return physx::PxFilterFlag::eDEFAULT; return physx::PxFilterFlag::eSUPPRESS;
} }
void ContactListener::onConstraintBreak(physx::PxConstraintInfo* constraints, physx::PxU32 count) void ContactListener::onConstraintBreak(physx::PxConstraintInfo* constraints, physx::PxU32 count)
@ -92,14 +93,24 @@ namespace Prism
void ContactListener::onWake(physx::PxActor** actors, physx::PxU32 count) void ContactListener::onWake(physx::PxActor** actors, physx::PxU32 count)
{ {
PX_UNUSED(actors); for (uint32_t i = 0; i < count; i++)
PX_UNUSED(count); {
physx::PxActor& actor = *actors[i];
Entity& entity = *(Entity*)actor.userData;
PM_CORE_INFO("PhysX Actor waking up: ID: {0}, Name: {1}", static_cast<uint64_t>(entity.GetUUID()), entity.GetComponent<TagComponent>().Tag);
}
} }
void ContactListener::onSleep(physx::PxActor** actors, physx::PxU32 count) void ContactListener::onSleep(physx::PxActor** actors, physx::PxU32 count)
{ {
PX_UNUSED(actors); for (uint32_t i = 0; i < count; i++)
PX_UNUSED(count); {
physx::PxActor& actor = *actors[i];
Entity& entity = *(Entity*)actor.userData;
PM_CORE_INFO("PhysX Actor going to sleep: ID: {0}, Name: {1}", static_cast<uint64_t>(entity.GetUUID()), entity.GetComponent<TagComponent>().Tag);
}
} }
void ContactListener::onContact(const physx::PxContactPairHeader& pairHeader, const physx::PxContactPair* pairs, physx::PxU32 nbPairs) void ContactListener::onContact(const physx::PxContactPairHeader& pairHeader, const physx::PxContactPair* pairs, physx::PxU32 nbPairs)

View File

@ -25,7 +25,7 @@ namespace Prism
glm::vec4 FromPhysXVector(const physx::PxVec4& vector); glm::vec4 FromPhysXVector(const physx::PxVec4& vector);
glm::quat FromPhysXQuat(const physx::PxQuat& quat); glm::quat FromPhysXQuat(const physx::PxQuat& quat);
physx::PxFilterFlags HazelFilterShader(physx::PxFilterObjectAttributes attributes0, physx::PxFilterData filterData0, physx::PxFilterObjectAttributes attributes1, physx::PxFilterFlags PrismFilterShader(physx::PxFilterObjectAttributes attributes0, physx::PxFilterData filterData0, physx::PxFilterObjectAttributes attributes1,
physx::PxFilterData filterData1, physx::PxPairFlags& pairFlags, const void* constantBlock, physx::PxU32 constantBlockSize); physx::PxFilterData filterData1, physx::PxPairFlags& pairFlags, const void* constantBlock, physx::PxU32 constantBlockSize);
class ContactListener final : public physx::PxSimulationEventCallback class ContactListener final : public physx::PxSimulationEventCallback

View File

@ -2,41 +2,94 @@
// Created by sfd on 25-12-20. // Created by sfd on 25-12-20.
// //
#include "PxPhysicsWrappers.h" #include "PhysicsWrappers.h"
#include "Physics3D.h" #include "Physics3D.h"
#include <cooking/PxCooking.h> #include <cooking/PxCooking.h>
#define GLM_ENABLE_EXPERIMENTAL #define GLM_ENABLE_EXPERIMENTAL
#include <glm/gtx/rotate_vector.hpp> #include <glm/gtx/rotate_vector.hpp>
#define PHYSX_DEBUGGER 1 #include "PhysicsLayer.h"
#define PHYSX_DEBUGGER
namespace Prism namespace Prism
{ {
static physx::PxDefaultErrorCallback s_ErrorCallback; static PhysicsErrorCallback s_ErrorCallback;
static physx::PxDefaultAllocator s_Allocator; static physx::PxDefaultAllocator s_Allocator;
static physx::PxFoundation* s_Foundation; static physx::PxFoundation* s_Foundation = nullptr;
static physx::PxPhysics* s_Physics; static physx::PxPhysics* s_Physics = nullptr;
static physx::PxPvd* s_VisualDebugger; static physx::PxPvd* s_VisualDebugger = nullptr;
static physx::PxOverlapHit s_OverlapBuffer[OVERLAP_MAX_COLLIDERS];
static physx::PxSimulationFilterShader s_FilterShader = physx::PxDefaultSimulationFilterShader; static physx::PxSimulationFilterShader s_FilterShader = physx::PxDefaultSimulationFilterShader;
static ContactListener s_ContactListener; static ContactListener s_ContactListener;
physx::PxScene* PxPhysicsWrappers::CreateScene(const SceneParams& sceneParams) void PhysicsErrorCallback::reportError(physx::PxErrorCode::Enum code, const char* message, const char* file, int line)
{
const char* errorMessage = NULL;
switch (code)
{
case physx::PxErrorCode::eNO_ERROR: errorMessage = "No Error"; break;
case physx::PxErrorCode::eDEBUG_INFO: errorMessage = "Info"; break;
case physx::PxErrorCode::eDEBUG_WARNING: errorMessage = "Warning"; break;
case physx::PxErrorCode::eINVALID_PARAMETER: errorMessage = "Invalid Parameter"; break;
case physx::PxErrorCode::eINVALID_OPERATION: errorMessage = "Invalid Operation"; break;
case physx::PxErrorCode::eOUT_OF_MEMORY: errorMessage = "Out Of Memory"; break;
case physx::PxErrorCode::eINTERNAL_ERROR: errorMessage = "Internal Error"; break;
case physx::PxErrorCode::eABORT: errorMessage = "Abort"; break;
case physx::PxErrorCode::ePERF_WARNING: errorMessage = "Performance Warning"; break;
case physx::PxErrorCode::eMASK_ALL: errorMessage = "Unknown Error"; break;
}
switch (code)
{
case physx::PxErrorCode::eNO_ERROR:
case physx::PxErrorCode::eDEBUG_INFO:
PM_CORE_INFO("[PhysX]: {0}: {1} at {2} ({3})", errorMessage, message, file, line);
break;
case physx::PxErrorCode::eDEBUG_WARNING:
case physx::PxErrorCode::ePERF_WARNING:
PM_CORE_WARN("[PhysX]: {0}: {1} at {2} ({3})", errorMessage, message, file, line);
break;
case physx::PxErrorCode::eINVALID_PARAMETER:
case physx::PxErrorCode::eINVALID_OPERATION:
case physx::PxErrorCode::eOUT_OF_MEMORY:
case physx::PxErrorCode::eINTERNAL_ERROR:
PM_CORE_ERROR("[PhysX]: {0}: {1} at {2} ({3})", errorMessage, message, file, line);
break;
case physx::PxErrorCode::eABORT:
case physx::PxErrorCode::eMASK_ALL:
PM_CORE_FATAL("[PhysX]: {0}: {1} at {2} ({3})", errorMessage, message, file, line);
PM_CORE_ASSERT(false);
break;
}
}
physx::PxScene* PhysicsWrappers::CreateScene(const SceneParams& sceneParams)
{ {
physx::PxSceneDesc sceneDesc(s_Physics->getTolerancesScale()); physx::PxSceneDesc sceneDesc(s_Physics->getTolerancesScale());
sceneDesc.gravity = ToPhysXVector(sceneParams.Gravity); sceneDesc.gravity = ToPhysXVector(sceneParams.Gravity);
sceneDesc.cpuDispatcher = physx::PxDefaultCpuDispatcherCreate(1); sceneDesc.cpuDispatcher = physx::PxDefaultCpuDispatcherCreate(1);
sceneDesc.filterShader = HazelFilterShader; sceneDesc.filterShader = PrismFilterShader;
sceneDesc.simulationEventCallback = &s_ContactListener; sceneDesc.simulationEventCallback = &s_ContactListener;
sceneDesc.wakeCounterResetValue = 0.5f;
sceneDesc.bounceThresholdVelocity = 0.1f;
sceneDesc.frictionOffsetThreshold = 0.1f;
sceneDesc.frictionCorrelationDistance = 0.1f;
sceneDesc.flags |= physx::PxSceneFlag::eENABLE_ACTIVE_ACTORS;
PM_CORE_ASSERT(sceneDesc.isValid()); PM_CORE_ASSERT(sceneDesc.isValid());
return s_Physics->createScene(sceneDesc); return s_Physics->createScene(sceneDesc);
} }
physx::PxRigidActor* PxPhysicsWrappers::CreateActor(const RigidBodyComponent& rigidbody, const glm::mat4& transform) physx::PxRigidActor* PhysicsWrappers::CreateActor(const RigidBodyComponent& rigidbody, const glm::mat4& transform)
{ {
physx::PxRigidActor* actor = nullptr; physx::PxRigidActor* actor = nullptr;
@ -57,6 +110,14 @@ namespace Prism
dynamicActor->setRigidDynamicLockFlag(physx::PxRigidDynamicLockFlag::eLOCK_ANGULAR_Y, rigidbody.LockRotationY); dynamicActor->setRigidDynamicLockFlag(physx::PxRigidDynamicLockFlag::eLOCK_ANGULAR_Y, rigidbody.LockRotationY);
dynamicActor->setRigidDynamicLockFlag(physx::PxRigidDynamicLockFlag::eLOCK_ANGULAR_Z, rigidbody.LockRotationZ); dynamicActor->setRigidDynamicLockFlag(physx::PxRigidDynamicLockFlag::eLOCK_ANGULAR_Z, rigidbody.LockRotationZ);
dynamicActor->setSleepThreshold(0.1f);
dynamicActor->setAngularVelocity({1,1,1});
dynamicActor->setActorFlag(physx::PxActorFlag::eDISABLE_SIMULATION, false);
// using OnWake and OnSleep callback should enable eSEND_SLEEP_NOTIFIES
// https://nvidia-omniverse.github.io/PhysX/physx/5.6.1/_api_build/classPxSimulationEventCallback.html#_CPPv4N25PxSimulationEventCallback6onWakeEPP7PxActor5PxU32
dynamicActor->setActorFlag(physx::PxActorFlag::eSEND_SLEEP_NOTIFIES, true);
physx::PxRigidBodyExt::updateMassAndInertia(*dynamicActor, rigidbody.Mass); physx::PxRigidBodyExt::updateMassAndInertia(*dynamicActor, rigidbody.Mass);
actor = dynamicActor; actor = dynamicActor;
} }
@ -64,11 +125,16 @@ namespace Prism
return actor; return actor;
} }
void PxPhysicsWrappers::SetCollisionFilters(const physx::PxRigidActor& actor, const uint32_t actorGroup, const uint32_t filters) void PhysicsWrappers::SetCollisionFilters(const physx::PxRigidActor& actor, uint32_t physicsLayer)
{ {
const PhysicsLayer& layerInfo = PhysicsLayerManager::GetLayer(physicsLayer);
if (layerInfo.CollidesWith == 0)
return;
physx::PxFilterData filterData; physx::PxFilterData filterData;
filterData.word0 = actorGroup; filterData.word0 = layerInfo.BitValue;
filterData.word1 = filters; filterData.word1 = layerInfo.CollidesWith;
const physx::PxU32 numShapes = actor.getNbShapes(); const physx::PxU32 numShapes = actor.getNbShapes();
@ -81,7 +147,7 @@ namespace Prism
s_Allocator.deallocate(shapes); s_Allocator.deallocate(shapes);
} }
void PxPhysicsWrappers::AddBoxCollider(physx::PxRigidActor& actor, const physx::PxMaterial& material, const BoxColliderComponent& collider, const glm::vec3& scale) void PhysicsWrappers::AddBoxCollider(physx::PxRigidActor& actor, const physx::PxMaterial& material, const BoxColliderComponent& collider, const glm::vec3& scale)
{ {
glm::vec3 colliderSize = collider.Size; glm::vec3 colliderSize = collider.Size;
@ -98,7 +164,7 @@ namespace Prism
shape->setLocalPose(ToPhysXTransform(glm::translate(glm::mat4(1.0F), collider.Offset))); shape->setLocalPose(ToPhysXTransform(glm::translate(glm::mat4(1.0F), collider.Offset)));
} }
void PxPhysicsWrappers::AddSphereCollider(physx::PxRigidActor& actor, const physx::PxMaterial& material, const SphereColliderComponent& collider, const glm::vec3& scale) void PhysicsWrappers::AddSphereCollider(physx::PxRigidActor& actor, const physx::PxMaterial& material, const SphereColliderComponent& collider, const glm::vec3& scale)
{ {
float colliderRadius = collider.Radius; float colliderRadius = collider.Radius;
@ -111,16 +177,16 @@ namespace Prism
shape->setFlag(physx::PxShapeFlag::eTRIGGER_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) void PhysicsWrappers::AddCapsuleCollider(physx::PxRigidActor& actor, const physx::PxMaterial& material,const CapsuleColliderComponent& collider, const glm::vec3& scale)
{ {
float colliderRadius = collider.Radius; float colliderRadius = collider.Radius;
float colliderHeight = collider.Height; float colliderHeight = collider.Height;
if (scale.x != 0.0F) colliderRadius *= scale.x * 0.5f; if (scale.x != 0.0F) colliderRadius *= scale.x;
if (scale.y != 0.0F) colliderHeight *= scale.y; if (scale.y != 0.0F) colliderHeight *= scale.y ;
const auto capsuleGeometry = physx::PxCapsuleGeometry(colliderRadius, colliderHeight / 2.0F); const auto capsuleGeometry = physx::PxCapsuleGeometry(colliderRadius, colliderHeight * 0.5f);
physx::PxShape* shape = physx::PxRigidActorExt::createExclusiveShape(actor, capsuleGeometry, material); physx::PxShape* shape = physx::PxRigidActorExt::createExclusiveShape(actor, capsuleGeometry, material);
shape->setFlag(physx::PxShapeFlag::eSIMULATION_SHAPE, !collider.IsTrigger); shape->setFlag(physx::PxShapeFlag::eSIMULATION_SHAPE, !collider.IsTrigger);
@ -130,21 +196,16 @@ namespace Prism
} }
void PxPhysicsWrappers::AddMeshCollider(physx::PxRigidActor& actor, const physx::PxMaterial& material,MeshColliderComponent& collider, const glm::vec3& scale) void PhysicsWrappers::AddMeshCollider(physx::PxRigidActor& actor, const physx::PxMaterial& material,MeshColliderComponent& collider, const glm::vec3& scale)
{ {
// TODO: Possibly take a look at https://github.com/kmammou/v-hacd for computing convex meshes from triangle meshes... physx::PxConvexMeshGeometry convexGeometry = physx::PxConvexMeshGeometry(CreateConvexMesh(collider));
physx::PxConvexMeshGeometry triangleGeometry = physx::PxConvexMeshGeometry(CreateConvexMesh(collider)); convexGeometry.meshFlags = physx::PxConvexMeshGeometryFlag::eTIGHT_BOUNDS;
triangleGeometry.meshFlags = physx::PxConvexMeshGeometryFlag::eTIGHT_BOUNDS; physx::PxShape* shape = physx::PxRigidActorExt::createExclusiveShape(actor, convexGeometry, material);
physx::PxShape* shape = physx::PxRigidActorExt::createExclusiveShape(actor, triangleGeometry, material);
shape->setFlag(physx::PxShapeFlag::eSIMULATION_SHAPE, !collider.IsTrigger); shape->setFlag(physx::PxShapeFlag::eSIMULATION_SHAPE, !collider.IsTrigger);
shape->setFlag(physx::PxShapeFlag::eTRIGGER_SHAPE, collider.IsTrigger); shape->setFlag(physx::PxShapeFlag::eTRIGGER_SHAPE, collider.IsTrigger);
// TODO: temp solve
// physx::PxQuat rotation(physx::PxPi / 2.0f, physx::PxVec3(1.0f, 0.0f, 0.0f));
// shape->setLocalPose(physx::PxTransform(physx::PxVec3(0.0f), rotation));
} }
physx::PxConvexMesh* PxPhysicsWrappers::CreateConvexMesh(MeshColliderComponent& collider) physx::PxConvexMesh* PhysicsWrappers::CreateConvexMesh(MeshColliderComponent& collider)
{ {
const auto& vertices = collider.CollisionMesh->GetStaticVertices(); const auto& vertices = collider.CollisionMesh->GetStaticVertices();
@ -177,7 +238,7 @@ namespace Prism
for (uint32_t i = 0; i < nbPolygons; i++) for (uint32_t i = 0; i < nbPolygons; i++)
{ {
physx::PxHullPolygon polygon; physx::PxHullPolygon polygon{};
mesh->getPolygonData(i, polygon); mesh->getPolygonData(i, polygon);
nbVertices += polygon.mNbVerts; nbVertices += polygon.mNbVerts;
nbFaces += (polygon.mNbVerts - 2) * 3; nbFaces += (polygon.mNbVerts - 2) * 3;
@ -193,7 +254,7 @@ namespace Prism
uint32_t indexCounter = 0; uint32_t indexCounter = 0;
for (uint32_t i = 0; i < nbPolygons; i++) for (uint32_t i = 0; i < nbPolygons; i++)
{ {
physx::PxHullPolygon polygon; physx::PxHullPolygon polygon{};
mesh->getPolygonData(i, polygon); mesh->getPolygonData(i, polygon);
const uint32_t vI0 = vertCounter; const uint32_t vI0 = vertCounter;
@ -221,19 +282,102 @@ namespace Prism
return mesh; return mesh;
} }
physx::PxMaterial* PxPhysicsWrappers::CreateMaterial(const PhysicsMaterialComponent& material) physx::PxMaterial* PhysicsWrappers::CreateMaterial(const PhysicsMaterialComponent& material)
{ {
return s_Physics->createMaterial(material.StaticFriction, material.DynamicFriction, material.Bounciness); return s_Physics->createMaterial(material.StaticFriction, material.DynamicFriction, material.Bounciness);
} }
void PxPhysicsWrappers::Initialize() bool PhysicsWrappers::Raycast(const glm::vec3& origin, const glm::vec3& direction, float maxDistance, RaycastHit* hit)
{
const auto* scene = static_cast<physx::PxScene*>(Physics3D::GetPhysicsScene());
physx::PxRaycastBuffer hitInfo;
const bool result = scene->raycast(ToPhysXVector(origin), ToPhysXVector(glm::normalize(direction)), maxDistance, hitInfo);
if (result)
{
Entity& entity = *static_cast<Entity*>(hitInfo.block.actor->userData);
hit->EntityID = entity.GetUUID();
hit->Position = FromPhysXVector(hitInfo.block.position);
hit->Normal = FromPhysXVector(hitInfo.block.normal);
hit->Distance = hitInfo.block.distance;
}
return result;
}
bool PhysicsWrappers::OverlapBox(const glm::vec3& origin, const glm::vec3& halfSize, std::array<physx::PxOverlapHit, OVERLAP_MAX_COLLIDERS>& buffer, uint32_t* count)
{
const physx::PxScene* scene = static_cast<physx::PxScene*>(Physics3D::GetPhysicsScene());
memset(s_OverlapBuffer, 0, sizeof(s_OverlapBuffer));
physx::PxOverlapBuffer buf(s_OverlapBuffer, OVERLAP_MAX_COLLIDERS);
const auto geometry = physx::PxBoxGeometry(halfSize.x, halfSize.y, halfSize.z);
const physx::PxTransform pose = ToPhysXTransform(glm::translate(glm::mat4(1.0F), origin));
const bool result = scene->overlap(geometry, pose, buf);
if (result)
{
const uint32_t bodyCount = buf.nbTouches >= OVERLAP_MAX_COLLIDERS ? OVERLAP_MAX_COLLIDERS : buf.nbTouches;
memcpy(buffer.data(), buf.touches, bodyCount * sizeof(physx::PxOverlapHit));
*count = bodyCount;
}
return result;
}
bool PhysicsWrappers::OverlapSphere(const glm::vec3& origin, float radius, std::array<physx::PxOverlapHit, OVERLAP_MAX_COLLIDERS>& buffer, uint32_t* count)
{
const physx::PxScene* scene = static_cast<physx::PxScene*>(Physics3D::GetPhysicsScene());
memset(s_OverlapBuffer, 0, sizeof(s_OverlapBuffer));
physx::PxOverlapBuffer buf(s_OverlapBuffer, OVERLAP_MAX_COLLIDERS);
const auto geometry = physx::PxSphereGeometry(radius);
const physx::PxTransform pose = ToPhysXTransform(glm::translate(glm::mat4(1.0F), origin));
const bool result = scene->overlap(geometry, pose, buf);
if (result)
{
const uint32_t bodyCount = buf.nbTouches >= OVERLAP_MAX_COLLIDERS ? OVERLAP_MAX_COLLIDERS : buf.nbTouches;
memcpy(buffer.data(), buf.touches, bodyCount * sizeof(physx::PxOverlapHit));
*count = bodyCount;
}
return result;
}
bool PhysicsWrappers::OverlapCapsule(const glm::vec3& origin, float radius, float halfHeight, std::array<physx::PxOverlapHit, OVERLAP_MAX_COLLIDERS>& buffer, uint32_t* count)
{
const physx::PxScene* scene = static_cast<physx::PxScene*>(Physics3D::GetPhysicsScene());
memset(s_OverlapBuffer, 0, sizeof(s_OverlapBuffer));
physx::PxOverlapBuffer buf(s_OverlapBuffer, OVERLAP_MAX_COLLIDERS);
const auto geometry = physx::PxCapsuleGeometry(radius, halfHeight);
const physx::PxTransform pose = ToPhysXTransform(glm::translate(glm::mat4(1.0F), origin));
const bool result = scene->overlap(geometry, pose, buf);
if (result)
{
const uint32_t bodyCount = buf.nbTouches >= OVERLAP_MAX_COLLIDERS ? OVERLAP_MAX_COLLIDERS : buf.nbTouches;
memcpy(buffer.data(), buf.touches, bodyCount * sizeof(physx::PxOverlapHit));
*count = bodyCount;
}
return result;
}
void PhysicsWrappers::Initialize()
{ {
PM_CORE_ASSERT(!s_Foundation, "PXPhysicsWrappers::Initializer shouldn't be called more than once!"); PM_CORE_ASSERT(!s_Foundation, "PXPhysicsWrappers::Initializer shouldn't be called more than once!");
s_Foundation = PxCreateFoundation(PX_PHYSICS_VERSION, s_Allocator, s_ErrorCallback); s_Foundation = PxCreateFoundation(PX_PHYSICS_VERSION, s_Allocator, s_ErrorCallback);
PM_CORE_ASSERT(s_Foundation, "PxCreateFoundation Failed!"); PM_CORE_ASSERT(s_Foundation, "PxCreateFoundation Failed!");
#if PHYSX_DEBUGGER #ifdef PHYSX_DEBUGGER
s_VisualDebugger = PxCreatePvd(*s_Foundation); s_VisualDebugger = PxCreatePvd(*s_Foundation);
ConnectPVD(); ConnectPVD();
#endif #endif
@ -242,16 +386,16 @@ namespace Prism
PM_CORE_ASSERT(s_Physics, "PxCreatePhysics Failed!"); PM_CORE_ASSERT(s_Physics, "PxCreatePhysics Failed!");
} }
void PxPhysicsWrappers::Shutdown() void PhysicsWrappers::Shutdown()
{ {
s_Physics->release(); s_Physics->release();
s_Foundation->release(); s_Foundation->release();
} }
bool PxPhysicsWrappers::ConnectPVD() bool PhysicsWrappers::ConnectPVD()
{ {
bool isConnect = false; bool isConnect = false;
#if PHYSX_DEBUGGER #ifdef PHYSX_DEBUGGER
physx::PxPvdTransport* transport = physx::PxDefaultPvdSocketTransportCreate("localhost", 5425, 10); physx::PxPvdTransport* transport = physx::PxDefaultPvdSocketTransportCreate("localhost", 5425, 10);
if (s_VisualDebugger->isConnected()) if (s_VisualDebugger->isConnected())
{ {
@ -263,14 +407,14 @@ namespace Prism
return isConnect; return isConnect;
} }
bool PxPhysicsWrappers::IsPVDConnected() bool PhysicsWrappers::IsPVDConnected()
{ {
return s_VisualDebugger->isConnected(); return s_VisualDebugger->isConnected();
} }
void PxPhysicsWrappers::DisconnectPVD() void PhysicsWrappers::DisconnectPVD()
{ {
#if PHYSX_DEBUGGER #ifdef PHYSX_DEBUGGER
if (s_VisualDebugger->isConnected(false)) if (s_VisualDebugger->isConnected(false))
{ {
s_VisualDebugger->disconnect(); s_VisualDebugger->disconnect();

View File

@ -2,37 +2,56 @@
// Created by sfd on 25-12-20. // Created by sfd on 25-12-20.
// //
#ifndef PXPHYSICSWRAPPERS_H #ifndef PHYSICSWRAPPERS_H
#define PXPHYSICSWRAPPERS_H #define PHYSICSWRAPPERS_H
#include "PhysicsUtils.h" #include "PhysicsUtils.h"
#include "Prism/Scene/Components.h" #include "Prism/Scene/Components.h"
#define OVERLAP_MAX_COLLIDERS 10
namespace Prism namespace Prism
{ {
struct RaycastHit;
struct SceneParams; struct SceneParams;
class PxPhysicsWrappers class PhysicsErrorCallback final : public physx::PxErrorCallback
{
public:
void reportError(physx::PxErrorCode::Enum code, const char* message, const char* file, int line) override;
};
class PhysicsWrappers
{ {
public: public:
static physx::PxScene* CreateScene(const SceneParams& sceneParams); static physx::PxScene* CreateScene(const SceneParams& sceneParams);
static physx::PxRigidActor* CreateActor(const RigidBodyComponent& rigidbody, const glm::mat4& transform); static physx::PxRigidActor* CreateActor(const RigidBodyComponent& rigidbody, const glm::mat4& transform);
static void SetCollisionFilters(const physx::PxRigidActor& actor, uint32_t actorGroup, uint32_t filters); static void SetCollisionFilters(const physx::PxRigidActor& actor, uint32_t physicsLayer);
static void AddBoxCollider(physx::PxRigidActor& actor, const physx::PxMaterial& material, const BoxColliderComponent& collider, const glm::vec3& scale = glm::vec3(0.0f)); static void 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 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 AddCapsuleCollider(physx::PxRigidActor& actor, const physx::PxMaterial& material, const CapsuleColliderComponent& collider, const glm::vec3& scale = glm::vec3(0.0f));
static void AddMeshCollider(::physx::PxRigidActor& actor, const ::physx::PxMaterial& material, ::Prism::MeshColliderComponent& collider, const glm::vec3& scale = glm::vec3(0.0f)); static void 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::PxConvexMesh* CreateConvexMesh(MeshColliderComponent& collider);
static physx::PxMaterial* CreateMaterial(const PhysicsMaterialComponent& material); static physx::PxMaterial* CreateMaterial(const PhysicsMaterialComponent& material);
static bool Raycast(const glm::vec3& origin, const glm::vec3& direction, float maxDistance, RaycastHit* hit);
/*
static bool OverlapBox(const glm::vec3& origin, const glm::vec3& halfSize, std::vector<physx::PxOverlapHit>& buffer);
static bool OverlapSphere(const glm::vec3& origin, float radius, std::vector<physx::PxOverlapHit>& buffer);
*/
static bool OverlapBox(const glm::vec3& origin, const glm::vec3& halfSize, std::array<physx::PxOverlapHit, OVERLAP_MAX_COLLIDERS>& buffer, uint32_t* count);
static bool OverlapCapsule(const glm::vec3& origin, float radius, float halfHeight, std::array<physx::PxOverlapHit, OVERLAP_MAX_COLLIDERS>& buffer, uint32_t* count);
static bool OverlapSphere(const glm::vec3& origin, float radius, std::array<physx::PxOverlapHit, OVERLAP_MAX_COLLIDERS>& buffer, uint32_t* count);
private: private:
static void Initialize(); static void Initialize();
static void Shutdown(); static void Shutdown();
static bool ConnectPVD(); static bool ConnectPVD();
static bool IsPVDConnected(); static bool IsPVDConnected();
static void DisconnectPVD(); static void DisconnectPVD();
@ -43,4 +62,4 @@ namespace Prism
} }
#endif //PXPHYSICSWRAPPERS_H #endif //PHYSICSWRAPPERS_H

View File

@ -17,11 +17,12 @@ namespace Prism
const auto state = glfwGetKey(static_cast<GLFWwindow*>(window.GetNativeWindow()), static_cast<uint32_t>(keycode)); const auto state = glfwGetKey(static_cast<GLFWwindow*>(window.GetNativeWindow()), static_cast<uint32_t>(keycode));
return state == GLFW_PRESS || state == GLFW_REPEAT; return state == GLFW_PRESS || state == GLFW_REPEAT;
} }
bool Input::IsMouseButtonPressed(int button)
bool Input::IsMouseButtonPressed(MouseButton button)
{ {
const auto& window = dynamic_cast<WindowsWindow&>(Application::Get().GetWindow()); const auto& window = dynamic_cast<WindowsWindow&>(Application::Get().GetWindow());
const auto state = glfwGetMouseButton(static_cast<GLFWwindow*>(window.GetNativeWindow()), button); const auto state = glfwGetMouseButton(static_cast<GLFWwindow*>(window.GetNativeWindow()), static_cast<int>(button));
return state == GLFW_PRESS; return state == GLFW_PRESS;
} }

View File

@ -53,7 +53,7 @@ namespace Prism
std::vector<Vertex> vertices; std::vector<Vertex> vertices;
std::vector<Index> indices; std::vector<Index> indices;
constexpr float latitudeBands = 30; constexpr uint32_t latitudeBands = 30;
constexpr float longitudeBands = 30; constexpr float longitudeBands = 30;
for (float latitude = 0.0f; latitude <= latitudeBands; latitude++) for (float latitude = 0.0f; latitude <= latitudeBands; latitude++)
@ -77,10 +77,10 @@ namespace Prism
for (uint32_t latitude = 0; latitude < latitudeBands; latitude++) for (uint32_t latitude = 0; latitude < latitudeBands; latitude++)
{ {
for (uint32_t longitude = 0; longitude < longitudeBands; longitude++) for (uint32_t longitude = 0; longitude < static_cast<uint32_t>(longitudeBands); longitude++)
{ {
const uint32_t first = (latitude * (longitudeBands + 1)) + longitude; const uint32_t first = (latitude * (static_cast<uint32_t>(longitudeBands) + 1)) + longitude;
const uint32_t second = first + longitudeBands + 1; const uint32_t second = first + static_cast<uint32_t>(longitudeBands) + 1;
indices.push_back({ first, second, first + 1 }); indices.push_back({ first, second, first + 1 });
indices.push_back({ second, second + 1, first + 1 }); indices.push_back({ second, second + 1, first + 1 });
@ -120,11 +120,11 @@ namespace Prism
calcV += 180.0f / (float)segments; calcV += 180.0f / (float)segments;
} }
float yOffset = (height - (radius * 2.0f)) * 0.5f; float yOffset = height * 0.5f;
if (yOffset < 0.0f) if (yOffset < 0.0f)
yOffset = 0.0f; yOffset = 0.0f;
int top = glm::ceil(pointCount * 0.5f); int top = static_cast<int32_t>(glm::ceil(pointCount * 0.5f));
for (int y = 0; y < top; y++) for (int y = 0; y < top; y++)
{ {
@ -136,7 +136,7 @@ namespace Prism
} }
} }
int bottom = glm::floor(pointCount * 0.5f); int bottom = static_cast<int32_t>(glm::floor(pointCount * 0.5f));
for (int y = bottom; y < pointCount; y++) for (int y = bottom; y < pointCount; y++)
{ {

View File

@ -156,6 +156,7 @@ namespace Prism
Type BodyType; Type BodyType;
float Mass = 1.0f; float Mass = 1.0f;
bool IsKinematic = false; bool IsKinematic = false;
uint32_t Layer = 0;
bool LockPositionX = false; bool LockPositionX = false;
bool LockPositionY = false; bool LockPositionY = false;

View File

@ -49,6 +49,7 @@ namespace Prism
m_Scene->m_Registry.remove<T>(m_EntityHandle); m_Scene->m_Registry.remove<T>(m_EntityHandle);
} }
const std::string& Tag() const { return m_Scene->m_Registry.get<TagComponent>(m_EntityHandle).Tag; }
glm::mat4& Transform() { return m_Scene->m_Registry.get<TransformComponent>(m_EntityHandle); } glm::mat4& Transform() { return m_Scene->m_Registry.get<TransformComponent>(m_EntityHandle); }
const glm::mat4& Transform() const { return m_Scene->m_Registry.get<TransformComponent>(m_EntityHandle); } const glm::mat4& Transform() const { return m_Scene->m_Registry.get<TransformComponent>(m_EntityHandle); }

View File

@ -19,7 +19,8 @@
#include <fstream> #include <fstream>
#include "Prism/Physics/PxPhysicsWrappers.h" #include "Prism/Physics/PhysicsLayer.h"
#include "Prism/Physics/PhysicsWrappers.h"
#include "Prism/Renderer/Meshfactory.h" #include "Prism/Renderer/Meshfactory.h"
namespace YAML namespace YAML
@ -340,6 +341,7 @@ namespace Prism
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 << "IsKinematic" << YAML::Value << rigidbodyComponent.IsKinematic;
out << YAML::Key << "Layer" << YAML::Value << rigidbodyComponent.Layer;
out << YAML::Key << "Constraints"; out << YAML::Key << "Constraints";
out << YAML::BeginMap; // Constraints out << YAML::BeginMap; // Constraints
@ -456,6 +458,29 @@ namespace Prism
SerializeEntity(out, entity); SerializeEntity(out, entity);
}); });
out << YAML::EndSeq; out << YAML::EndSeq;
out << YAML::Key << "PhysicsLayers";
out << YAML::Value << YAML::BeginSeq;
for (uint32_t i = 0; i < PhysicsLayerManager::GetLayerCount(); i++)
{
const PhysicsLayer& layer = PhysicsLayerManager::GetLayer(i);
out << YAML::BeginMap;
out << YAML::Key << "Name" << YAML::Value << layer.Name;
out << YAML::Key << "CollidesWith" << YAML::Value;
out << YAML::BeginSeq;
for (const auto& collidingLayer : PhysicsLayerManager::GetLayerCollisions(layer.LayerID))
{
out << YAML::BeginMap;
out << YAML::Key << "Name" << YAML::Value << collidingLayer.Name;
out << YAML::EndMap;
}
out << YAML::EndSeq;
out << YAML::EndMap;
}
out << YAML::EndSeq;
out << YAML::EndMap; out << YAML::EndMap;
std::ofstream fout(filepath); std::ofstream fout(filepath);
@ -661,6 +686,7 @@ namespace Prism
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.IsKinematic = rigidBodyComponent["IsKinematic"] ? rigidBodyComponent["IsKinematic"].as<bool>() : false;
component.Layer = rigidBodyComponent["Layer"] ? rigidBodyComponent["Layer"].as<uint32_t>() : 0;
component.LockPositionX = rigidBodyComponent["Constraints"]["LockPositionX"].as<bool>(); component.LockPositionX = rigidBodyComponent["Constraints"]["LockPositionX"].as<bool>();
component.LockPositionY = rigidBodyComponent["Constraints"]["LockPositionY"].as<bool>(); component.LockPositionY = rigidBodyComponent["Constraints"]["LockPositionY"].as<bool>();
@ -710,12 +736,37 @@ namespace Prism
auto meshPath = meshColliderComponent["AssetPath"].as<std::string>(); auto meshPath = meshColliderComponent["AssetPath"].as<std::string>();
auto& component = 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; component.IsTrigger = meshColliderComponent["IsTrigger"] ? meshColliderComponent["IsTrigger"].as<bool>() : false;
PxPhysicsWrappers::CreateConvexMesh(component); PhysicsWrappers::CreateConvexMesh(component);
PM_CORE_INFO(" Mesh Collider Asset Path: {0}", meshPath); PM_CORE_INFO(" Mesh Collider Asset Path: {0}", meshPath);
} }
} }
} }
if (auto physicsLayers = data["PhysicsLayers"])
{
PhysicsLayerManager::ClearLayers();
for (auto layer : physicsLayers)
{
PhysicsLayerManager::AddLayer(layer["Name"].as<std::string>(), false);
}
for (auto layer : physicsLayers)
{
const PhysicsLayer& layerInfo = PhysicsLayerManager::GetLayer(layer["Name"].as<std::string>());
if (auto collidesWith = layer["CollidesWith"])
{
for (auto collisionLayer : collidesWith)
{
const auto& otherLayer = PhysicsLayerManager::GetLayer(collisionLayer["Name"].as<std::string>());
PhysicsLayerManager::SetLayerCollision(layerInfo.LayerID, otherLayer.LayerID, true);
}
}
}
}
return true; return true;
} }

View File

@ -18,7 +18,6 @@
#include <mono/metadata/object.h> #include <mono/metadata/object.h>
#include <mono/metadata/reflection.h> #include <mono/metadata/reflection.h>
#include <mono/metadata/mono-debug.h> #include <mono/metadata/mono-debug.h>
#include <mono/metadata/debug-helpers.h>
#include "imgui.h" #include "imgui.h"
@ -575,6 +574,85 @@ namespace Prism
} }
} }
MonoObject* ScriptEngine::Construct(const std::string& fullName, bool callConstructor, void** parameters)
{
std::string namespaceName;
std::string className;
std::string parameterList;
if (fullName.find('.') != std::string::npos)
{
namespaceName = fullName.substr(0, fullName.find_first_of('.'));
className = fullName.substr(fullName.find_first_of('.') + 1, (fullName.find_first_of(':') - fullName.find_first_of('.')) - 1);
}
if (fullName.find(':') != std::string::npos)
{
parameterList = fullName.substr(fullName.find_first_of(':'));
}
MonoClass* clazz = mono_class_from_name(s_CoreAssemblyImage, namespaceName.c_str(), className.c_str());
if (!clazz) {
PM_CORE_FATAL("Class not found: {0}.{1}", namespaceName, className);
return nullptr;
}
MonoObject* obj = mono_object_new(mono_domain_get(), clazz);
if (callConstructor)
{
MonoMethodDesc* desc = mono_method_desc_new(parameterList.c_str(), NULL);
MonoMethod* constructor = mono_method_desc_search_in_class(desc, clazz);
if (!constructor) {
PM_CORE_ERROR("Constructor not found: {0}", fullName);
void* iter = nullptr;
MonoMethod* method;
while ((method = mono_class_get_methods(clazz, &iter)) != nullptr) {
PM_CORE_DEBUG("Found method: {0}",mono_method_full_name(method, true));
}
return obj;
}
MonoObject* exception = nullptr;
mono_runtime_invoke(constructor, obj, parameters, &exception);
}
return obj;
}
static std::unordered_map<std::string, MonoClass*> s_Classes;
MonoClass* ScriptEngine::GetCoreClass(const std::string& fullName)
{
if (s_Classes.find(fullName) != s_Classes.end())
return s_Classes[fullName];
std::string namespaceName;
std::string className;
if (fullName.find('.') != std::string::npos)
{
namespaceName = fullName.substr(0, fullName.find_last_of('.'));
className = fullName.substr(fullName.find_last_of('.') + 1);
}
else
{
className = fullName;
}
MonoClass* monoClass = mono_class_from_name(s_CoreAssemblyImage, namespaceName.c_str(), className.c_str());
if (!monoClass)
std::cout << "mono_class_from_name failed" << std::endl;
s_Classes[fullName] = monoClass;
return monoClass;
}
bool ScriptEngine::IsEntityModuleValid(Entity entity) bool ScriptEngine::IsEntityModuleValid(Entity entity)
{ {
return entity.HasComponent<ScriptComponent>() && ModuleExists(entity.GetComponent<ScriptComponent>().ModuleName); return entity.HasComponent<ScriptComponent>() && ModuleExists(entity.GetComponent<ScriptComponent>().ModuleName);

View File

@ -10,6 +10,7 @@
extern "C" { extern "C" {
typedef struct _MonoObject MonoObject; typedef struct _MonoObject MonoObject;
typedef struct _MonoClassField MonoClassField; typedef struct _MonoClassField MonoClassField;
typedef struct _MonoClass MonoClass;
} }
namespace Prism namespace Prism
@ -126,6 +127,9 @@ namespace Prism
static void OnTriggerBegin(Entity entityID); static void OnTriggerBegin(Entity entityID);
static void OnTriggerEnd(Entity entityID); static void OnTriggerEnd(Entity entityID);
static MonoObject* Construct(const std::string& fullName, bool callConstructor = true, void** parameters = nullptr);
static MonoClass* GetCoreClass(const std::string& fullName);
static bool IsEntityModuleValid(Entity entity); static bool IsEntityModuleValid(Entity entity);
static void OnScriptComponentDestroyed(const UUID &sceneID, const UUID &entityID); static void OnScriptComponentDestroyed(const UUID &sceneID, const UUID &entityID);

View File

@ -4,7 +4,7 @@
#include "ScriptEngineRegistry.h" #include "ScriptEngineRegistry.h"
#include "ScriptWarppers.h" #include "ScriptWrappers.h"
#include "Prism/Scene/Entity.h" #include "Prism/Scene/Entity.h"
#include "mono/metadata/reflection.h" #include "mono/metadata/reflection.h"
@ -51,6 +51,15 @@ namespace Prism
mono_add_internal_call("Prism.Noise::PerlinNoise_Native", (const void*)Prism::Script::Prism_Noise_PerlinNoise); mono_add_internal_call("Prism.Noise::PerlinNoise_Native", (const void*)Prism::Script::Prism_Noise_PerlinNoise);
mono_add_internal_call("Prism.Physics::Raycast_Native", (const void*)Prism::Script::Prism_Physics_Raycast);
mono_add_internal_call("Prism.Physics::OverlapBox_Native", (const void*)Prism::Script::Prism_Physics_OverlapBox);
mono_add_internal_call("Prism.Physics::OverlapCapsule_Native", (const void*)Prism::Script::Prism_Physics_OverlapCapsule);
mono_add_internal_call("Prism.Physics::OverlapSphere_Native", (const void*)Prism::Script::Prism_Physics_OverlapSphere);
mono_add_internal_call("Prism.Physics::OverlapBoxNonAlloc_Native", (const void*)Prism::Script::Prism_Physics_OverlapBoxNonAlloc);
mono_add_internal_call("Prism.Physics::OverlapCapsuleNonAlloc_Native", (const void*)Prism::Script::Prism_Physics_OverlapCapsuleNonAlloc);
mono_add_internal_call("Prism.Physics::OverlapSphereNonAlloc_Native", (const void*)Prism::Script::Prism_Physics_OverlapSphereNonAlloc);
mono_add_internal_call("Prism.Entity::GetTransform_Native",(const void*)Prism::Script::Prism_Entity_GetTransform); mono_add_internal_call("Prism.Entity::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::GetRelativeDirection_Native", (const void*)Prism::Script::Prism_TransformComponent_GetRelativeDirection);
@ -77,6 +86,7 @@ namespace Prism
// Input // 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::IsMouseButtonPressed_Native", (const void*)Prism::Script::Prism_Input_IsMouseButtonPressed);
mono_add_internal_call("Prism.Input::GetMousePosition_Native", (const void*)Prism::Script::Prism_Input_GetMousePosition); mono_add_internal_call("Prism.Input::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::SetCursorMode_Native", (const void*)Prism::Script::Prism_Input_SetCursorMode);
mono_add_internal_call("Prism.Input::GetCursorMode_Native", (const void*)Prism::Script::Prism_Input_GetCursorMode); mono_add_internal_call("Prism.Input::GetCursorMode_Native", (const void*)Prism::Script::Prism_Input_GetCursorMode);
@ -97,6 +107,9 @@ namespace Prism
mono_add_internal_call("Prism.RigidBodyComponent::GetLinearVelocity_Native", (const void*)Prism::Script::Prism_RigidBodyComponent_GetLinearVelocity); mono_add_internal_call("Prism.RigidBodyComponent::GetLinearVelocity_Native", (const void*)Prism::Script::Prism_RigidBodyComponent_GetLinearVelocity);
mono_add_internal_call("Prism.RigidBodyComponent::SetLinearVelocity_Native", (const void*)Prism::Script::Prism_RigidBodyComponent_SetLinearVelocity); mono_add_internal_call("Prism.RigidBodyComponent::SetLinearVelocity_Native", (const void*)Prism::Script::Prism_RigidBodyComponent_SetLinearVelocity);
mono_add_internal_call("Prism.RigidBodyComponent::Rotate_Native", (const void*)Prism::Script::Prism_RigidBodyComponent_Rotate); mono_add_internal_call("Prism.RigidBodyComponent::Rotate_Native", (const void*)Prism::Script::Prism_RigidBodyComponent_Rotate);
mono_add_internal_call("Prism.RigidBodyComponent::GetLayer_Native", (const void*)Prism::Script::Prism_RigidBodyComponent_GetLayer);
mono_add_internal_call("Prism.RigidBodyComponent::GetMass_Native", (const void*)Prism::Script::Prism_RigidBodyComponent_GetMass);
mono_add_internal_call("Prism.RigidBodyComponent::SetMass_Native", (const void*)Prism::Script::Prism_RigidBodyComponent_SetMass);
// Material // 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);

View File

@ -2,7 +2,7 @@
// Created by sfd on 25-12-6. // Created by sfd on 25-12-6.
// //
#include "ScriptWarppers.h" #include "ScriptWrappers.h"
#include "ScriptEngine.h" #include "ScriptEngine.h"
#include "box2d/box2d.h" #include "box2d/box2d.h"
@ -22,6 +22,8 @@
#include "PxRigidDynamic.h" #include "PxRigidDynamic.h"
#include "Prism/Physics/Physics3D.h" #include "Prism/Physics/Physics3D.h"
#include "Prism/Physics/PhysicsUtils.h" #include "Prism/Physics/PhysicsUtils.h"
#include "Prism/Physics/PhysicsWrappers.h"
#include <mono/metadata/appdomain.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;
@ -71,6 +73,11 @@ namespace Prism { namespace Script {
return Input::IsKeyPressed(key); return Input::IsKeyPressed(key);
} }
bool Prism_Input_IsMouseButtonPressed(const MouseButton button)
{
return Input::IsMouseButtonPressed(button);
}
void Prism_Input_GetMousePosition(glm::vec2* outPosition) void Prism_Input_GetMousePosition(glm::vec2* outPosition)
{ {
auto [x, y] = Input::GetMousePosition(); auto [x, y] = Input::GetMousePosition();
@ -87,10 +94,189 @@ namespace Prism { namespace Script {
return Input::GetCursorMode(); return Input::GetCursorMode();
} }
//////////////////////////////////////////////////////////////// bool Prism_Physics_Raycast(const glm::vec3* origin, const glm::vec3* direction, const float maxDistance, RaycastHit* hit)
{
return PhysicsWrappers::Raycast(*origin, *direction, maxDistance, hit);
}
// Helper function for the Overlap functions below
static void AddCollidersToArray(MonoArray* array, const std::array<physx::PxOverlapHit, OVERLAP_MAX_COLLIDERS>& hits, const uint32_t count)
{
uint32_t arrayIndex = 0;
for (uint32_t i = 0; i < count; i++)
{
Entity& entity = *static_cast<Entity*>(hits[i].actor->userData);
if (entity.HasComponent<BoxColliderComponent>())
{
auto& boxCollider = entity.GetComponent<BoxColliderComponent>();
UUID uuid = entity.GetUUID();
void* data[] = {
&uuid,
&boxCollider.IsTrigger,
&boxCollider.Size,
&boxCollider.Offset
};
MonoObject* obj = ScriptEngine::Construct("Prism.BoxCollider:.ctor(ulong,bool,Vec3,Vec3)", true, data);
mono_array_set(array, MonoObject*, arrayIndex++, obj);
}
if (entity.HasComponent<SphereColliderComponent>())
{
auto& sphereCollider = entity.GetComponent<SphereColliderComponent>();
UUID uuid = entity.GetUUID();
void* data[] = {
&uuid,
&sphereCollider.IsTrigger,
&sphereCollider.Radius
};
MonoObject* obj = ScriptEngine::Construct("Prism.SphereCollider:.ctor(ulong,bool,single)", true, data);
mono_array_set(array, MonoObject*, arrayIndex++, obj);
}
if (entity.HasComponent<CapsuleColliderComponent>())
{
auto& capsuleCollider = entity.GetComponent<CapsuleColliderComponent>();
UUID uuid = entity.GetUUID();
void* data[] = {
&uuid,
&capsuleCollider.IsTrigger,
&capsuleCollider.Radius,
&capsuleCollider.Height
};
MonoObject* obj = ScriptEngine::Construct("Prism.CapsuleCollider:.ctor(ulong,bool,single,single)", true, data);
mono_array_set(array, MonoObject*, arrayIndex++, obj);
}
if (entity.HasComponent<MeshColliderComponent>())
{
auto& meshCollider = entity.GetComponent<MeshColliderComponent>();
auto mesh = new Ref<Mesh>(meshCollider.CollisionMesh);
UUID uuid = entity.GetUUID();
void* data[] = {
&uuid,
&meshCollider.IsTrigger,
&mesh
};
MonoObject* obj = ScriptEngine::Construct("Prism.MeshCollider:.ctor(ulong,bool,intptr)", true, data);
mono_array_set(array, MonoObject*, arrayIndex++, obj);
}
}
}
static std::array<physx::PxOverlapHit, OVERLAP_MAX_COLLIDERS> s_OverlapBuffer;
MonoArray* Prism_Physics_OverlapBox(const glm::vec3* origin, const glm::vec3* halfSize)
{
MonoArray* outColliders = nullptr;
memset(s_OverlapBuffer.data(), 0, OVERLAP_MAX_COLLIDERS * sizeof(physx::PxOverlapHit));
uint32_t count;
if (PhysicsWrappers::OverlapBox(*origin, *halfSize, s_OverlapBuffer, &count))
{
outColliders = mono_array_new(mono_domain_get(), ScriptEngine::GetCoreClass("Prism.Collider"), count);
AddCollidersToArray(outColliders, s_OverlapBuffer, count);
}
return outColliders;
}
MonoArray* Prism_Physics_OverlapCapsule(const glm::vec3* origin, const float radius, const float halfHeight)
{
MonoArray* outColliders = nullptr;
memset(s_OverlapBuffer.data(), 0, OVERLAP_MAX_COLLIDERS * sizeof(physx::PxOverlapHit));
uint32_t count;
if (PhysicsWrappers::OverlapCapsule(*origin, radius, halfHeight, s_OverlapBuffer, &count))
{
outColliders = mono_array_new(mono_domain_get(), ScriptEngine::GetCoreClass("Prism.Collider"), count);
AddCollidersToArray(outColliders, s_OverlapBuffer, count);
}
return outColliders;
}
MonoArray* Prism_Physics_OverlapSphere(const glm::vec3* origin, const float radius)
{
MonoArray* outColliders = nullptr;
memset(s_OverlapBuffer.data(), 0, OVERLAP_MAX_COLLIDERS * sizeof(physx::PxOverlapHit));
uint32_t count;
if (PhysicsWrappers::OverlapSphere(*origin, radius, s_OverlapBuffer, &count))
{
outColliders = mono_array_new(mono_domain_get(), ScriptEngine::GetCoreClass("Prism.Collider"), count);
AddCollidersToArray(outColliders, s_OverlapBuffer, count);
}
return outColliders;
}
int32_t Prism_Physics_OverlapBoxNonAlloc(const glm::vec3* origin, const glm::vec3* halfSize, MonoArray* outColliders)
{
memset(s_OverlapBuffer.data(), 0, OVERLAP_MAX_COLLIDERS * sizeof(physx::PxOverlapHit));
const uint64_t arrayLength = mono_array_length(outColliders);
uint32_t count = 0;
if (PhysicsWrappers::OverlapBox(*origin, *halfSize, s_OverlapBuffer, &count))
{
if (count > arrayLength)
count = static_cast<uint32_t>(arrayLength);
AddCollidersToArray(outColliders, s_OverlapBuffer, count);
}
return static_cast<int32_t>(count);
}
int32_t Prism_Physics_OverlapCapsuleNonAlloc(const glm::vec3* origin, const float radius, const float halfHeight, MonoArray* outColliders)
{
memset(s_OverlapBuffer.data(), 0, OVERLAP_MAX_COLLIDERS * sizeof(physx::PxOverlapHit));
const uint64_t arrayLength = mono_array_length(outColliders);
uint32_t count = 0;
if (PhysicsWrappers::OverlapCapsule(*origin, radius, halfHeight, s_OverlapBuffer, &count))
{
if (count > arrayLength)
count = static_cast<uint32_t>(arrayLength);
AddCollidersToArray(outColliders, s_OverlapBuffer, count);
}
return static_cast<int32_t>(count);
}
int32_t Prism_Physics_OverlapSphereNonAlloc(const glm::vec3* origin, const float radius, MonoArray* outColliders)
{
memset(s_OverlapBuffer.data(), 0, OVERLAP_MAX_COLLIDERS * sizeof(physx::PxOverlapHit));
const uint64_t arrayLength = mono_array_length(outColliders);
uint32_t count;
if (PhysicsWrappers::OverlapSphere(*origin, radius, s_OverlapBuffer, &count))
{
if (count > arrayLength)
count = static_cast<uint32_t>(arrayLength);
AddCollidersToArray(outColliders, s_OverlapBuffer, count);
}
return static_cast<int32_t>(count);
}
//////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////
// Entity ////////////////////////////////////////////////////// // Entity //
//////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////
void Prism_Entity_GetTransform(const uint64_t entityID, glm::mat4* outTransform) void Prism_Entity_GetTransform(const uint64_t entityID, glm::mat4* outTransform)
@ -117,53 +303,6 @@ namespace Prism { namespace Script {
memcpy(glm::value_ptr(transformComponent.Transform), inTransform, sizeof(glm::mat4)); memcpy(glm::value_ptr(transformComponent.Transform), inTransform, sizeof(glm::mat4));
} }
/*
void Prism_Entity_GetForwardDirection(const uint64_t entityID, glm::vec3* outForward)
{
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);
*outForward = glm::rotate(glm::inverse(glm::normalize(rotation)), glm::vec3(0, 0, -1));
}
void Prism_Entity_GetRightDirection(const uint64_t entityID, glm::vec3* outRight)
{
Ref<Scene> 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);
*outRight = glm::rotate(glm::inverse(glm::normalize(rotation)), glm::vec3(1, 0, 0));
}
void Prism_Entity_GetUpDirection(const uint64_t entityID, glm::vec3* outUp)
{
Ref<Scene> 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);
*outUp = glm::rotate(glm::inverse(glm::normalize(rotation)), glm::vec3(0, 1, 0));
}
*/
void Prism_Entity_CreateComponent(const uint64_t entityID, void* type) void Prism_Entity_CreateComponent(const uint64_t entityID, void* type)
{ {
Ref<Scene> scene = ScriptEngine::GetCurrentSceneContext(); Ref<Scene> scene = ScriptEngine::GetCurrentSceneContext();
@ -212,7 +351,7 @@ namespace Prism { namespace Script {
const auto& transformComponent = entity.GetComponent<TransformComponent>(); const auto& transformComponent = entity.GetComponent<TransformComponent>();
auto [position, rotation, scale] = GetTransformDecomposition(transformComponent.Transform); auto [position, rotation, scale] = GetTransformDecomposition(transformComponent.Transform);
*outDirection = glm::rotate(glm::normalize(rotation), *inAbsoluteDirection); *outDirection = glm::rotate(rotation, *inAbsoluteDirection);
} }
void Prism_TransformComponent_GetRotation(const uint64_t entityID, glm::vec3* outRotation) void Prism_TransformComponent_GetRotation(const uint64_t entityID, glm::vec3* outRotation)
@ -438,27 +577,77 @@ namespace Prism { namespace Script {
dynamicActor->setGlobalPose(transform); dynamicActor->setGlobalPose(transform);
} }
uint32_t Prism_RigidBodyComponent_GetLayer(const uint64_t entityID)
{
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>();
return component.Layer;
}
float Prism_RigidBodyComponent_GetMass(const uint64_t entityID)
{
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);
const physx::PxRigidDynamic* dynamicActor = actor->is<physx::PxRigidDynamic>();
PM_CORE_ASSERT(dynamicActor);
return dynamicActor->getMass();
}
void Prism_RigidBodyComponent_SetMass(const uint64_t entityID, const float mass)
{
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>());
auto& component = entity.GetComponent<RigidBodyComponent>();
auto* actor = static_cast<physx::PxRigidActor*>(component.RuntimeActor);
auto* dynamicActor = actor->is<physx::PxRigidDynamic>();
PM_CORE_ASSERT(dynamicActor);
component.Mass = mass;
physx::PxRigidBodyExt::updateMassAndInertia(*dynamicActor, mass);
}
Ref<Mesh>* Prism_Mesh_Constructor(MonoString* filepath) Ref<Mesh>* Prism_Mesh_Constructor(MonoString* filepath)
{ {
return new Ref<Mesh>(new Mesh(mono_string_to_utf8(filepath))); return new Ref<Mesh>(new Mesh(mono_string_to_utf8(filepath)));
} }
void Prism_Mesh_Destructor(Ref<Mesh>* _this) void Prism_Mesh_Destructor(const Ref<Mesh>* _this)
{ {
const Ref<Mesh>* instance = (Ref<Mesh>*)_this; const Ref<Mesh>* instance = _this;
delete _this; delete _this;
} }
Ref<Material>* Prism_Mesh_GetMaterial(Ref<Mesh>* inMesh) Ref<Material>* Prism_Mesh_GetMaterial(Ref<Mesh>* inMesh)
{ {
Ref<Mesh>& mesh = *(Ref<Mesh>*)inMesh; Ref<Mesh>& mesh = *inMesh;
return new Ref<Material>(mesh->GetMaterial()); return new Ref<Material>(mesh->GetMaterial());
} }
Ref<MaterialInstance>* Prism_Mesh_GetMaterialByIndex(Ref<Mesh>* inMesh, const int index) Ref<MaterialInstance>* Prism_Mesh_GetMaterialByIndex(Ref<Mesh>* inMesh, const int index)
{ {
Ref<Mesh>& mesh = *(Ref<Mesh>*)inMesh; Ref<Mesh>& mesh = *inMesh;
const auto& materials = mesh->GetMaterials(); const auto& materials = mesh->GetMaterials();
PM_CORE_ASSERT(index < materials.size()); PM_CORE_ASSERT(index < materials.size());
@ -467,7 +656,7 @@ namespace Prism { namespace Script {
int Prism_Mesh_GetMaterialCount(Ref<Mesh>* inMesh) int Prism_Mesh_GetMaterialCount(Ref<Mesh>* inMesh)
{ {
Ref<Mesh>& mesh = *(Ref<Mesh>*)inMesh; Ref<Mesh>& mesh = *inMesh;
const auto& materials = mesh->GetMaterials(); const auto& materials = mesh->GetMaterials();
return (int)materials.size(); return (int)materials.size();
} }
@ -494,7 +683,7 @@ namespace Prism { namespace Script {
PM_CORE_ASSERT(dataSize <= buffer.Size); PM_CORE_ASSERT(dataSize <= buffer.Size);
// Convert RGBA32F color to RGBA8 // Convert RGBA32F color to RGBA8
auto pixels = static_cast<uint8_t*>(buffer.Data); auto pixels = static_cast<uint8_t*>(buffer.Data);
uint32_t index = 0;
for (uint32_t i = 0; i < instance->GetWidth() * instance->GetHeight(); i++) for (uint32_t i = 0; i < instance->GetWidth() * instance->GetHeight(); i++)
{ {
const glm::vec4& value = mono_array_get(inData, glm::vec4, i); const glm::vec4& value = mono_array_get(inData, glm::vec4, i);
@ -514,13 +703,13 @@ namespace Prism { namespace Script {
void Prism_Material_SetFloat(Ref<Material>* _this, MonoString* uniform, const float value) void Prism_Material_SetFloat(Ref<Material>* _this, MonoString* uniform, const float value)
{ {
Ref<Material>& instance = *(Ref<Material>*)_this; Ref<Material>& instance = *_this;
instance->Set(mono_string_to_utf8(uniform), value); instance->Set(mono_string_to_utf8(uniform), value);
} }
void Prism_Material_SetTexture(Ref<Material>* _this, MonoString* uniform, const Ref<Texture2D>* texture) void Prism_Material_SetTexture(Ref<Material>* _this, MonoString* uniform, const Ref<Texture2D>* texture)
{ {
Ref<Material>& instance = *(Ref<Material>*)_this; Ref<Material>& instance = *_this;
instance->Set(mono_string_to_utf8(uniform), *texture); instance->Set(mono_string_to_utf8(uniform), *texture);
} }
@ -531,25 +720,25 @@ namespace Prism { namespace Script {
void Prism_MaterialInstance_SetFloat(Ref<MaterialInstance>* _this, MonoString* uniform, const float value) void Prism_MaterialInstance_SetFloat(Ref<MaterialInstance>* _this, MonoString* uniform, const float value)
{ {
Ref<MaterialInstance>& instance = *(Ref<MaterialInstance>*)_this; Ref<MaterialInstance>& instance = *_this;
instance->Set(mono_string_to_utf8(uniform), value); instance->Set(mono_string_to_utf8(uniform), value);
} }
void Prism_MaterialInstance_SetVector3(Ref<MaterialInstance>* _this, MonoString* uniform, const glm::vec3* value) void Prism_MaterialInstance_SetVector3(Ref<MaterialInstance>* _this, MonoString* uniform, const glm::vec3* value)
{ {
Ref<MaterialInstance>& instance = *(Ref<MaterialInstance>*)_this; Ref<MaterialInstance>& instance = *_this;
instance->Set(mono_string_to_utf8(uniform), *value); instance->Set(mono_string_to_utf8(uniform), *value);
} }
void Prism_MaterialInstance_SetVector4(Ref<MaterialInstance> *_this, MonoString *uniform, const glm::vec4 *value) void Prism_MaterialInstance_SetVector4(Ref<MaterialInstance> *_this, MonoString *uniform, const glm::vec4 *value)
{ {
Ref<MaterialInstance>& instance = *(Ref<MaterialInstance>*)_this; Ref<MaterialInstance>& instance = *_this;
instance->Set(mono_string_to_utf8(uniform), *value); instance->Set(mono_string_to_utf8(uniform), *value);
} }
void Prism_MaterialInstance_SetTexture(Ref<MaterialInstance>* _this, MonoString* uniform, const Ref<Texture2D>* texture) void Prism_MaterialInstance_SetTexture(Ref<MaterialInstance>* _this, MonoString* uniform, const Ref<Texture2D>* texture)
{ {
Ref<MaterialInstance>& instance = *(Ref<MaterialInstance>*)_this; Ref<MaterialInstance>& instance = *_this;
instance->Set(mono_string_to_utf8(uniform), *texture); instance->Set(mono_string_to_utf8(uniform), *texture);
} }

View File

@ -2,8 +2,8 @@
// Created by sfd on 25-12-6. // Created by sfd on 25-12-6.
// //
#ifndef SCRIPTWARPPERS_H #ifndef SCRIPTWRAPPERS_H
#define SCRIPTWARPPERS_H #define SCRIPTWRAPPERS_H
#include "Prism/Core/Input.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"
@ -24,21 +24,26 @@ namespace Prism { namespace Script {
// Input // Input
bool Prism_Input_IsKeyPressed(KeyCode key); bool Prism_Input_IsKeyPressed(KeyCode key);
bool Prism_Input_IsMouseButtonPressed(MouseButton button);
void Prism_Input_GetMousePosition(glm::vec2* outPosition); void Prism_Input_GetMousePosition(glm::vec2* outPosition);
void Prism_Input_SetCursorMode(CursorMode mode); void Prism_Input_SetCursorMode(CursorMode mode);
CursorMode Prism_Input_GetCursorMode(); CursorMode Prism_Input_GetCursorMode();
// Physics
bool Prism_Physics_Raycast(const glm::vec3* origin, const glm::vec3* direction, float maxDistance, RaycastHit* hit);
MonoArray* Prism_Physics_OverlapBox(const glm::vec3* origin, const glm::vec3* halfSize);
MonoArray* Prism_Physics_OverlapCapsule(const glm::vec3* origin, float radius, float halfHeight);
MonoArray* Prism_Physics_OverlapSphere(const glm::vec3* origin, float radius);
int32_t Prism_Physics_OverlapBoxNonAlloc(const glm::vec3* origin, const glm::vec3* halfSize, MonoArray* outColliders);
int32_t Prism_Physics_OverlapCapsuleNonAlloc(const glm::vec3* origin, float radius, float halfHeight, MonoArray* outColliders);
int32_t Prism_Physics_OverlapSphereNonAlloc(const glm::vec3* origin, float radius, MonoArray* outColliders);
// Entity // Entity
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_GetTransform(uint64_t entityID, glm::mat4* outTransform);
void Prism_Entity_SetTransform(uint64_t entityID, const glm::mat4* inTransform); void Prism_Entity_SetTransform(uint64_t entityID, const glm::mat4* inTransform);
/*
void Prism_Entity_GetForwardDirection(uint64_t entityID, glm::vec3* outForward);
void Prism_Entity_GetRightDirection(uint64_t entityID, glm::vec3* outRight);
void Prism_Entity_GetUpDirection(uint64_t entityID, glm::vec3* outUp);
*/
void Prism_TransformComponent_GetRelativeDirection(uint64_t entityID, glm::vec3* outDirection, const glm::vec3* inAbsoluteDirection); void Prism_TransformComponent_GetRelativeDirection(uint64_t entityID, glm::vec3* outDirection, const glm::vec3* inAbsoluteDirection);
void Prism_TransformComponent_GetRotation(uint64_t entityID,glm::vec3* outRotation); void Prism_TransformComponent_GetRotation(uint64_t entityID,glm::vec3* outRotation);
@ -55,6 +60,9 @@ namespace Prism { namespace Script {
void Prism_RigidBodyComponent_GetLinearVelocity(uint64_t entityID, glm::vec3* outVelocity); void Prism_RigidBodyComponent_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); void Prism_RigidBodyComponent_Rotate(uint64_t entityID, glm::vec3* rotation);
uint32_t Prism_RigidBodyComponent_GetLayer(uint64_t entityID);
float Prism_RigidBodyComponent_GetMass(uint64_t entityID);
void Prism_RigidBodyComponent_SetMass(uint64_t entityID, float mass);
// Renderer // Renderer
// Texture2D // Texture2D
@ -75,7 +83,7 @@ namespace Prism { namespace Script {
// Mesh // Mesh
Ref<Mesh>* Prism_Mesh_Constructor(MonoString* filepath); Ref<Mesh>* Prism_Mesh_Constructor(MonoString* filepath);
void Prism_Mesh_Destructor(Ref<Mesh>* _this); void Prism_Mesh_Destructor(const Ref<Mesh>* _this);
Ref<Material>* Prism_Mesh_GetMaterial(Ref<Mesh>* inMesh); Ref<Material>* Prism_Mesh_GetMaterial(Ref<Mesh>* inMesh);
Ref<MaterialInstance>* Prism_Mesh_GetMaterialByIndex(Ref<Mesh>* inMesh, int index); Ref<MaterialInstance>* Prism_Mesh_GetMaterialByIndex(Ref<Mesh>* inMesh, int index);
int Prism_Mesh_GetMaterialCount(Ref<Mesh>* inMesh); int Prism_Mesh_GetMaterialCount(Ref<Mesh>* inMesh);
@ -87,4 +95,4 @@ namespace Prism { namespace Script {
} } } }
#endif //SCRIPTWARPPERS_H #endif //SCRIPTWRAPPERS_H