add PhysX SDK and some tweaks

This commit is contained in:
2025-12-17 12:39:20 +08:00
parent 57ca6c30f5
commit 00d3993a77
26 changed files with 1594 additions and 132 deletions

3
.gitmodules vendored
View File

@ -26,3 +26,6 @@
[submodule "Prism/vendor/Box2D"]
path = Prism/vendor/Box2D
url = https://github.com/erincatto/box2d.git
[submodule "Prism/vendor/PhysX"]
path = Prism/vendor/PhysX
url = https://github.com/NVIDIA-Omniverse/PhysX.git

View File

@ -182,6 +182,7 @@ namespace Prism
void EditorLayer::OnDetach()
{
m_EditorScene->OnShutdown();
}
void EditorLayer::OnUpdate(const TimeStep deltaTime)
@ -953,7 +954,12 @@ namespace Prism
SelectedSubmesh selection;
if (entity.HasComponent<MeshComponent>())
{
selection.Mesh = &entity.GetComponent<MeshComponent>().Mesh->GetSubmeshes()[0];
auto& meshComp = entity.GetComponent<MeshComponent>();
if (meshComp.Mesh)
{
selection.Mesh = &meshComp.Mesh->GetSubmeshes()[0];
}
}
selection.Entity = entity;
m_SelectionContext.clear();

View File

@ -0,0 +1,95 @@
Scene: Scene Name
Environment:
AssetPath: assets/env/pink_sunrise_4k.hdr
Light:
Direction: [-0.787, -0.73299998, 1]
Radiance: [1, 1, 1]
Multiplier: 0.514999986
Entities:
- Entity: 10169503531257462571
TagComponent:
Tag: Box
TransformComponent:
Position: [0, 1.5, 0]
Rotation: [1, 0, 0, 0]
Scale: [2, 2, 2]
MeshComponent:
AssetPath: assets/meshes/Cube1m.fbx
RigidBodyComponent:
BodyType: 1
Mass: 0.5
PhysicsMaterialComponent:
StaticFriction: 1
DynamicFriction: 1
Bounciness: 0
BoxColliderComponent:
Offset: [0, 0, 0]
Size: [2, 2, 2]
- Entity: 14057422478420564497
TagComponent:
Tag: Player
TransformComponent:
Position: [-19.43363, 4.50874043, -1.96695328e-06]
Rotation: [1, 0, 0, 0]
Scale: [1, 1, 1]
ScriptComponent:
ModuleName: Example.PlayerSphere
StoredFields:
- Name: HorizontalForce
Type: 1
Data: 10
- Name: MaxSpeed
Type: 6
Data: [10, 10, 10]
- Name: JumpForce
Type: 1
Data: 200
MeshComponent:
AssetPath: assets/meshes/Sphere1m.fbx
RigidBodyComponent:
BodyType: 1
Mass: 1
PhysicsMaterialComponent:
StaticFriction: 1
DynamicFriction: 1
Bounciness: 0
SphereColliderComponent:
Radius: 0.5
- Entity: 5178862374589434728
TagComponent:
Tag: Camera
TransformComponent:
Position: [-21.7406311, 9.70659542, 15]
Rotation: [0.999910355, -0.0133911213, 0, 0]
Scale: [1, 1, 1]
ScriptComponent:
ModuleName: Example.BasicController
StoredFields:
- Name: Speed
Type: 1
Data: 12
- Name: DistanceFromPlayer
Type: 1
Data: 15
CameraComponent:
Camera: some camera data...
Primary: true
- Entity: 18306113171518048249
TagComponent:
Tag: Box
TransformComponent:
Position: [0, 0, 0]
Rotation: [1, 0, 0, 0]
Scale: [50, 1, 50]
MeshComponent:
AssetPath: assets/meshes/Cube1m.fbx
RigidBodyComponent:
BodyType: 0
Mass: 1
PhysicsMaterialComponent:
StaticFriction: 1
DynamicFriction: 1
Bounciness: 0
BoxColliderComponent:
Offset: [0, 0, 0]
Size: [50, 1, 50]

View File

@ -5,6 +5,7 @@ namespace Example
public class BasicController : Entity
{
public float Speed;
public float DistanceFromPlayer = 20.0F;
private Entity m_PlayerEntity;
@ -17,8 +18,10 @@ namespace Example
{
Mat4 transform = GetTransform();
Vec3 playerTranstation = m_PlayerEntity.GetTransform().Translation;
Vec3 translation = transform.Translation;
translation.XY = m_PlayerEntity.GetTransform().Translation.XY;
translation.XY = playerTranstation.XY;
translation.Z = playerTranstation.Z + DistanceFromPlayer;
translation.Y = Math.Max(translation.Y, 4.5f);
transform.Translation = translation;
SetTransform(transform);

View File

@ -0,0 +1,92 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Prism;
namespace Example
{
class PlayerSphere : Entity
{
public float HorizontalForce = 10.0f;
public float JumpForce = 10.0f;
private RigidBodyComponent m_PhysicsBody;
private MaterialInstance m_MeshMaterial;
public int m_CollisionCounter = 0;
public Vec3 MaxSpeed = new Vec3();
private bool Colliding => m_CollisionCounter > 0;
void OnCreate()
{
m_PhysicsBody = GetComponent<RigidBodyComponent>();
MeshComponent meshComponent = GetComponent<MeshComponent>();
m_MeshMaterial = meshComponent.Mesh.GetMaterial(0);
m_MeshMaterial.Set("u_Metalness", 0.0f);
AddCollisionBeginCallback(OnPlayerCollisionBegin);
AddCollisionEndCallback(OnPlayerCollisionEnd);
}
void OnPlayerCollisionBegin(float value)
{
m_CollisionCounter++;
}
void OnPlayerCollisionEnd(float value)
{
m_CollisionCounter--;
}
void OnUpdate(float ts)
{
float movementForce = HorizontalForce;
if (!Colliding)
{
movementForce *= 0.4f;
}
Vec3 forward = GetForwardDirection();
Vec3 right = GetRightDirection();
Vec3 up = GetUpDirection();
if (Input.IsKeyPressed(KeyCode.W))
m_PhysicsBody.AddForce(forward * movementForce);
else if (Input.IsKeyPressed(KeyCode.S))
m_PhysicsBody.AddForce(forward * -movementForce);
if (Input.IsKeyPressed(KeyCode.D))
m_PhysicsBody.AddForce(right * movementForce);
else if (Input.IsKeyPressed(KeyCode.A))
m_PhysicsBody.AddForce(right * -movementForce);
if (Colliding && Input.IsKeyPressed(KeyCode.Space))
m_PhysicsBody.AddForce(up * JumpForce);
if (Colliding)
m_MeshMaterial.Set("u_AlbedoColor", new Vec3(1.0f, 0.0f, 0.0f));
else
m_MeshMaterial.Set("u_AlbedoColor", new Vec3(0.8f, 0.8f, 0.8f));
Vec3 linearVelocity = m_PhysicsBody.GetLinearVelocity();
linearVelocity.Clamp(new Vec3(-MaxSpeed.X, -1000, -MaxSpeed.Z), MaxSpeed);
m_PhysicsBody.SetLinearVelocity(linearVelocity);
if (Input.IsKeyPressed(KeyCode.R))
{
Mat4 transform = GetTransform();
transform.Translation = new Vec3(0.0f);
SetTransform(transform);
}
}
}
}

View File

@ -13,6 +13,8 @@ namespace Prism
private List<Action<float>> m_Collision2DBeginCallbacks = new List<Action<float>>();
private List<Action<float>> m_Collision2DEndCallbacks = new List<Action<float>>();
private Action<float> m_CollisionBeginCallbacks;
private Action<float> m_CollisionEndCallbacks;
protected Entity() { ID = 0; }
@ -63,6 +65,24 @@ namespace Prism
SetTransform_Native(ID, ref transform);
}
public Vec3 GetForwardDirection()
{
GetForwardDirection_Native(ID, out Vec3 forward);
return forward;
}
public Vec3 GetRightDirection()
{
GetRightDirection_Native(ID, out Vec3 right);
return right;
}
public Vec3 GetUpDirection()
{
GetUpDirection_Native(ID, out Vec3 up);
return up;
}
public void AddCollision2DBeginCallback(Action<float> callback)
{
m_Collision2DBeginCallbacks.Add(callback);
@ -73,6 +93,28 @@ namespace Prism
m_Collision2DEndCallbacks.Add(callback);
}
public void AddCollisionBeginCallback(Action<float> callback)
{
m_CollisionBeginCallbacks += callback;
}
public void AddCollisionEndCallback(Action<float> callback)
{
m_CollisionEndCallbacks += callback;
}
private void OnCollisionBegin(float data)
{
if (m_CollisionBeginCallbacks != null)
m_CollisionBeginCallbacks.Invoke(data);
}
private void OnCollisionEnd(float data)
{
if (m_CollisionEndCallbacks != null)
m_CollisionEndCallbacks.Invoke(data);
}
private void OnCollision2DBegin(float data)
{
foreach (var callback in m_Collision2DBeginCallbacks)
@ -96,5 +138,11 @@ namespace Prism
[MethodImpl(MethodImplOptions.InternalCall)]
private static extern ulong FindEntityByTag_Native(string tag);
[MethodImpl(MethodImplOptions.InternalCall)]
private static extern void GetForwardDirection_Native(ulong entityID, out Vec3 forward);
[MethodImpl(MethodImplOptions.InternalCall)]
private static extern void GetRightDirection_Native(ulong entityID, out Vec3 right);
[MethodImpl(MethodImplOptions.InternalCall)]
private static extern void GetUpDirection_Native(ulong entityID, out Vec3 up);
}
}

View File

@ -0,0 +1,15 @@
namespace Prism
{
public static class Mathf
{
public static float Clamp(float value, float min, float max)
{
if (value < min)
return min;
if (value > max)
return max;
return value;
}
}
}

View File

@ -33,6 +33,23 @@ namespace Prism
Z = vec.Z;
}
public void Clamp(Vec3 min, Vec3 max)
{
X = Mathf.Clamp(X, min.X, max.X);
Y = Mathf.Clamp(Y, min.Y, max.Y);
Z = Mathf.Clamp(Z, min.Z, max.Z);
}
public static Vec3 operator *(Vec3 left, float scalar)
{
return new Vec3(left.X * scalar, left.Y * scalar, left.Z * scalar);
}
public static Vec3 operator *(float scalar, Vec3 right)
{
return new Vec3(scalar * right.X, scalar * right.Y, scalar * right.Z);
}
public Vec2 XY {
get { return new Vec2(X, Y); }
set { X = value.X; Y = value.Y; }

View File

@ -123,4 +123,56 @@ namespace Prism
public class BoxCollider2DComponent : Component
{
}
public class BoxColliderComponent : Component
{
}
public class SphereColliderComponent : Component
{
}
public class RigidBodyComponent : Component
{
public enum ForceMode
{
Force = 0,
Impulse,
VelocityChange,
Acceleration
}
public void AddForce(Vec3 force, ForceMode forceMode = ForceMode.Force)
{
AddForce_Native(Entity.ID, ref force, forceMode);
}
public void AddTorque(Vec3 torque, ForceMode forceMode = ForceMode.Force)
{
AddTorque_Native(Entity.ID, ref torque, forceMode);
}
public Vec3 GetLinearVelocity()
{
GetLinearVelocity_Native(Entity.ID, out Vec3 velocity);
return velocity;
}
public void SetLinearVelocity(Vec3 velocity)
{
SetLinearVelocity_Native(Entity.ID, ref velocity);
}
// TODO: Add SetMaxLinearVelocity() as well
[MethodImpl(MethodImplOptions.InternalCall)]
internal static extern void AddForce_Native(ulong entityID, ref Vec3 force, ForceMode forceMode);
[MethodImpl(MethodImplOptions.InternalCall)]
internal static extern void AddTorque_Native(ulong entityID, ref Vec3 torque, ForceMode forceMode);
[MethodImpl(MethodImplOptions.InternalCall)]
internal static extern void GetLinearVelocity_Native(ulong entityID, out Vec3 velocity);
[MethodImpl(MethodImplOptions.InternalCall)]
internal static extern void SetLinearVelocity_Native(ulong entityID, ref Vec3 velocity);
}
}

View File

@ -45,6 +45,36 @@ file(GLOB IMGUIZMO_SOURCE ${IMGUIZMO_DIR}/*.cpp)
list(APPEND SRC_SOURCE ${IMGUIZMO_SOURCE})
# ------------- NVIDIA PhysX -------------
# PhysX/physx/buildtools/presets/*.xml
# PX_GENERATE_STATIC_LIBRARIES=True
# NV_USE_STATIC_WINCRT=False
set(PHYSX_BUILD_TYPE "checked" CACHE STRING "The build type of PhysX")
set_property(CACHE PHYSX_BUILD_TYPE PROPERTY STRINGS debug checked profile release)
if(NOT CMAKE_BUILD_TYPE)
if(PHYSX_BUILD_TYPE STREQUAL "debug" OR PHYSX_BUILD_TYPE STREQUAL "checked")
set(CMAKE_BUILD_TYPE "Debug")
endif()
endif()
if(CMAKE_BUILD_TYPE STREQUAL "Release")
set(PHYSX_BUILD_TYPE "release")
elseif (CMAKE_BUILD_TYPE STREQUAL "Debug")
set(PHYSX_BUILD_TYPE "debug")
endif ()
include_directories(vendor/PhysX/physx/include)
link_directories("vendor/PhysX/physx/bin/win.x86_64.vc143.md/${PHYSX_BUILD_TYPE}") # This is the path where PhysX libraries are installed
if(CMAKE_BUILD_TYPE STREQUAL "Debug")
message("Building snippet in debug with PhysX ${PHYSX_BUILD_TYPE} configuration")
add_compile_definitions(_DEBUG)
else()
message("Building snippet in release configuration with PhysX ${PHYSX_BUILD_TYPE} configuration")
add_compile_definitions(NDEBUG)
endif()
# ------------- link libraries -------------
set(LINK_LIBRARIES_PRIVATE
@ -55,6 +85,13 @@ set(LINK_LIBRARIES_PRIVATE
tinyFileDialogs
FastNoise
yaml-cpp
PhysXExtensions_static_64
PhysX_static_64
PhysXPvdSDK_static_64
PhysXCommon_static_64
PhysXFoundation_static_64
PhysXCooking_static_64
)
set(LINK_LIBRARIES_PUBLIC
@ -84,10 +121,11 @@ set(TARGET_INCLUDE_DIR
# ------------- debug Defines -------------
set(DEBUG_DEFINITIONS
$<$<CONFIG:Debug>:PM_ENABLE_ASSERTS>
$<$<CONFIG:RelWithDebInfo>:PM_ENABLE_ASSERTS>
)
# static library
# static library
set(STATIC_LIBRARY ${PROJECT_NAME}-static)
add_library(${STATIC_LIBRARY} STATIC ${SRC_SOURCE})

View File

@ -11,6 +11,7 @@
#include "Prism/Renderer/FrameBuffer.h"
#include "tinyfiledialogs.h"
#include "Prism/Physics/Physics3D.h"
#include "Prism/Script/ScriptEngine.h"
namespace Prism
@ -35,6 +36,7 @@ namespace Prism
PushOverlay(m_ImGuiLayer);
ScriptEngine::Init("assets/scripts/ExampleApp.dll");
Physics3D::Init();
Renderer::Init();
Renderer::WaitAndRender();
@ -42,6 +44,10 @@ namespace Prism
Application::~Application()
{
for (Layer* layer : m_LayerStack)
layer->OnDetach();
Physics3D::Shutdown();
ScriptEngine::Shutdown();
}

View File

@ -14,7 +14,7 @@ namespace Prism
float Noise::PerlinNoise(float x, float y)
{
s_FastNoise.SetNoiseType(FastNoise::Perlin);
float result = s_FastNoise.GetNoise(x, y); // This returns a value between -1 and 1
const float result = s_FastNoise.GetNoise(x, y); // This returns a value between -1 and 1
return result;
}
}

View File

@ -135,6 +135,48 @@ namespace Prism
ImGui::CloseCurrentPopup();
}
}
if (!m_SelectionContext.HasComponent<RigidBodyComponent>())
{
if (ImGui::Button("Rigidbody"))
{
m_SelectionContext.AddComponent<RigidBodyComponent>();
ImGui::CloseCurrentPopup();
}
}
if (!m_SelectionContext.HasComponent<PhysicsMaterialComponent>())
{
if (ImGui::Button("Physics Material"))
{
m_SelectionContext.AddComponent<PhysicsMaterialComponent>();
ImGui::CloseCurrentPopup();
}
}
if (!m_SelectionContext.HasComponent<BoxColliderComponent>())
{
if (ImGui::Button("Box Collider"))
{
m_SelectionContext.AddComponent<BoxColliderComponent>();
ImGui::CloseCurrentPopup();
}
}
if (!m_SelectionContext.HasComponent<SphereColliderComponent>())
{
if (ImGui::Button("Sphere Collider"))
{
m_SelectionContext.AddComponent<SphereColliderComponent>();
ImGui::CloseCurrentPopup();
}
}
if (!m_SelectionContext.HasComponent<MeshColliderComponent>())
{
if (ImGui::Button("Mesh Collider"))
{
m_SelectionContext.AddComponent<MeshColliderComponent>();
ImGui::CloseCurrentPopup();
}
}
ImGui::EndPopup();
}
}
@ -858,6 +900,101 @@ namespace Prism
EndPropertyGrid();
});
DrawComponent<RigidBodyComponent>("Rigidbody", entity, [](RigidBodyComponent& rbc)
{
// Rigidbody Type
const char* rbTypeStrings[] = { "Static", "Dynamic", "Kinematic" };
const char* currentType = rbTypeStrings[(int)rbc.BodyType];
if (ImGui::BeginCombo("Type", currentType))
{
for (int type = 0; type < 3; type++)
{
bool is_selected = (currentType == rbTypeStrings[type]);
if (ImGui::Selectable(rbTypeStrings[type], is_selected))
{
currentType = rbTypeStrings[type];
rbc.BodyType = (RigidBodyComponent::Type)type;
}
if (is_selected)
ImGui::SetItemDefaultFocus();
}
ImGui::EndCombo();
}
if (rbc.BodyType == RigidBodyComponent::Type::Dynamic)
{
BeginPropertyGrid();
Property("Mass", rbc.Mass);
if (ImGui::TreeNode("RigidBodyConstraints", "Constraints"))
{
Property("Position: X", rbc.LockPositionX);
Property("Position: Y", rbc.LockPositionY);
Property("Position: Z", rbc.LockPositionZ);
Property("Rotation: X", rbc.LockRotationX);
Property("Rotation: Y", rbc.LockRotationY);
Property("Rotation: Z", rbc.LockRotationZ);
ImGui::TreePop();
}
EndPropertyGrid();
}
});
DrawComponent<PhysicsMaterialComponent>("Physics Material", entity, [](PhysicsMaterialComponent& pmc)
{
BeginPropertyGrid();
Property("Static Friction", pmc.StaticFriction);
Property("Dynamic Friction", pmc.DynamicFriction);
Property("Bounciness", pmc.Bounciness);
EndPropertyGrid();
});
DrawComponent<BoxColliderComponent>("Box Collider", entity, [](BoxColliderComponent& bcc)
{
BeginPropertyGrid();
Property("Size", bcc.Size);
//Property("Offset", bcc.Offset);
EndPropertyGrid();
});
DrawComponent<SphereColliderComponent>("Sphere Collider", entity, [](SphereColliderComponent& scc)
{
BeginPropertyGrid();
Property("Radius", scc.Radius);
EndPropertyGrid();
});
DrawComponent<MeshColliderComponent>("Mesh Collider", entity, [](MeshColliderComponent& mc)
{
ImGui::Columns(3);
ImGui::SetColumnWidth(0, 100);
ImGui::SetColumnWidth(1, 300);
ImGui::SetColumnWidth(2, 40);
ImGui::Text("File Path");
ImGui::NextColumn();
ImGui::PushItemWidth(-1);
if (mc.CollisionMesh)
ImGui::InputText("##meshfilepath", (char*)mc.CollisionMesh->GetFilePath().c_str(), 256, ImGuiInputTextFlags_ReadOnly);
else
ImGui::InputText("##meshfilepath", (char*)"Null", 256, ImGuiInputTextFlags_ReadOnly);
ImGui::PopItemWidth();
ImGui::NextColumn();
if (ImGui::Button("...##openmesh"))
{
std::string file = Application::Get().OpenFile();
if (!file.empty())
mc.CollisionMesh = Ref<Mesh>::Create(file);
}
});
}

View File

@ -0,0 +1,203 @@
//
// Created by sfd on 25-12-16.
//
#include "Physics3D.h"
#define GLM_ENABLE_EXPERIMENTAL
#include <glm/gtx/quaternion.hpp>
#include <glm/gtx/matrix_decompose.hpp>
#include <glm/gtc/type_ptr.hpp>
#include <cooking/PxCooking.h>
namespace Prism
{
// TODO: Kinematic Actors
// TODO: Rotation/Position Locking
// TODO: Collision "layers"
// TODO: Expose more of the API to scripts
// TODO: Connect/Disconnect PVD
// TODO: Collider Shape Rendering
// TODO: Relative Transformations for scripts
static physx::PxSimulationFilterShader s_DefaultFilterShader = physx::PxDefaultSimulationFilterShader;
static std::tuple<glm::vec3, glm::quat, glm::vec3> GetTransformDecomposition(const glm::mat4& transform)
{
glm::vec3 scale, translation, skew;
glm::vec4 perspective;
glm::quat orientation;
glm::decompose(transform, scale, orientation, translation, skew, perspective);
return { translation, orientation, scale };
}
static physx::PxFilterFlags PrismFilterShader(physx::PxFilterObjectAttributes attributes0, physx::PxFilterData filterData0, physx::PxFilterObjectAttributes attributes1, physx::PxFilterData filterData1, physx::PxPairFlags& pairFlags, const void* constantBlock, physx::PxU32 constantBlockSize)
{
if (physx::PxFilterObjectIsTrigger(attributes0) || physx::PxFilterObjectIsTrigger(attributes1))
{
pairFlags = physx::PxPairFlag::eTRIGGER_DEFAULT;
return physx::PxFilterFlag::eDEFAULT;
}
pairFlags = physx::PxPairFlag::eCONTACT_DEFAULT;
if ((filterData0.word0 & filterData1.word1) || (filterData1.word0 & filterData0.word1))
{
pairFlags |= physx::PxPairFlag::eNOTIFY_TOUCH_FOUND;
pairFlags |= physx::PxPairFlag::eNOTIFY_TOUCH_LOST;
}
return physx::PxFilterFlag::eDEFAULT;
}
void Physics3D::Init()
{
PM_CORE_ASSERT(!s_PXFoundation, "PhysXManager::Init shouldn't be called more than once!");
s_PXFoundation = PxCreateFoundation(PX_PHYSICS_VERSION, s_PXAllocator, s_PXErrorCallback);
PM_CORE_ASSERT(s_PXFoundation, "PxCreateFoundation Failed!");
PM_CORE_INFO("Try to connect PVD...");
s_PXPvd = PxCreatePvd(*s_PXFoundation);
physx::PxPvdTransport* transport = physx::PxDefaultPvdSocketTransportCreate("localhost", 5425, 100000000);
const bool isConnect = s_PXPvd->connect(*transport, physx::PxPvdInstrumentationFlag::eALL);
if (isConnect)
{
PM_CORE_INFO("PVD connect success");
}else
{
PM_CORE_ERROR("PVD connect failed");
}
s_PXPhysicsFactory = PxCreatePhysics(PX_PHYSICS_VERSION, *s_PXFoundation, physx::PxTolerancesScale(), true, isConnect ? s_PXPvd : nullptr);
PM_CORE_ASSERT(s_PXPhysicsFactory, "PxCreatePhysics Failed!");
}
void Physics3D::Shutdown()
{
s_PXPhysicsFactory->release();
s_PXFoundation->release();
}
physx::PxSceneDesc Physics3D::CreateSceneDesc()
{
physx::PxSceneDesc sceneDesc(s_PXPhysicsFactory->getTolerancesScale());
if (!sceneDesc.cpuDispatcher)
{
physx::PxDefaultCpuDispatcher* mCpuDispatcher = physx::PxDefaultCpuDispatcherCreate(4);
PM_CORE_ASSERT(mCpuDispatcher);
sceneDesc.cpuDispatcher = mCpuDispatcher;
}
if (!sceneDesc.filterShader)
sceneDesc.filterShader = PrismFilterShader;
return sceneDesc;
}
physx::PxScene* Physics3D::CreateScene(const physx::PxSceneDesc& sceneDesc)
{
return s_PXPhysicsFactory->createScene(sceneDesc);
}
physx::PxRigidActor* Physics3D::CreateAndAddActor(physx::PxScene* scene, const RigidBodyComponent& rigidbody, const glm::mat4& transform)
{
physx::PxRigidActor* actor = nullptr;
if (rigidbody.BodyType == RigidBodyComponent::Type::Static)
{
actor = s_PXPhysicsFactory->createRigidStatic(CreatePose(transform));
}
else if (rigidbody.BodyType == RigidBodyComponent::Type::Dynamic)
{
physx::PxRigidDynamic* dynamicActor = s_PXPhysicsFactory->createRigidDynamic(CreatePose(transform));
physx::PxRigidBodyExt::updateMassAndInertia(*dynamicActor, rigidbody.Mass);
dynamicActor->setRigidDynamicLockFlag(physx::PxRigidDynamicLockFlag::eLOCK_LINEAR_X, rigidbody.LockPositionX);
dynamicActor->setRigidDynamicLockFlag(physx::PxRigidDynamicLockFlag::eLOCK_LINEAR_Y, rigidbody.LockPositionY);
dynamicActor->setRigidDynamicLockFlag(physx::PxRigidDynamicLockFlag::eLOCK_LINEAR_Z, rigidbody.LockPositionZ);
dynamicActor->setRigidDynamicLockFlag(physx::PxRigidDynamicLockFlag::eLOCK_ANGULAR_X, rigidbody.LockRotationX);
dynamicActor->setRigidDynamicLockFlag(physx::PxRigidDynamicLockFlag::eLOCK_ANGULAR_Y, rigidbody.LockRotationY);
dynamicActor->setRigidDynamicLockFlag(physx::PxRigidDynamicLockFlag::eLOCK_ANGULAR_Z, rigidbody.LockRotationZ);
actor = dynamicActor;
}
actor->setActorFlag(physx::PxActorFlag::eVISUALIZATION, true);
scene->addActor(*actor);
return actor;
}
physx::PxMaterial* Physics3D::CreateMaterial(float staticFriction, float dynamicFriction, float restitution)
{
return s_PXPhysicsFactory->createMaterial(staticFriction, dynamicFriction, restitution);
}
physx::PxConvexMesh* Physics3D::CreateMeshCollider(const Ref<Mesh>& mesh)
{
const auto& vertices = mesh->GetStaticVertices();
const auto& indices = mesh->GetIndices();
const physx::PxCookingParams cookingParams(s_PXPhysicsFactory->getTolerancesScale());
physx::PxConvexMeshDesc convexDesc;
convexDesc.points.count = (physx::PxU32)vertices.size();
convexDesc.points.stride = sizeof(Vertex);
convexDesc.points.data = vertices.data();
convexDesc.flags = physx::PxConvexFlag::eCOMPUTE_CONVEX;
const physx::PxDefaultMemoryOutputStream buf;
physx::PxConvexMeshCookingResult::Enum result;
physx::PxConvexMesh* convexMesh = PxCreateConvexMesh(
cookingParams, // 第一步准备的烹饪参数
convexDesc, // 第二步准备的网格描述
*PxGetStandaloneInsertionCallback(), // 便捷的回调函数用于将资源插入物理SDK
&result // [可选] 获取烹饪结果详情
);
if (!convexMesh) {
PM_CORE_ERROR("Failed to create convex mesh. Cooking result code: {}", static_cast<int>(result));
return nullptr;
}
return convexMesh;
}
physx::PxTransform Physics3D::CreatePose(const glm::mat4& transform)
{
auto [translation, rotationQuat, scale] = GetTransformDecomposition(transform);
const glm::vec3 rotation = glm::eulerAngles(rotationQuat);
physx::PxTransform physxTransform(physx::PxVec3(translation.x, translation.y, translation.z));
physxTransform.rotate(physx::PxVec3(rotation.x, rotation.y, rotation.z));
return physxTransform;
}
void Physics3D::SetCollisionFilters(physx::PxRigidActor* actor, uint32_t filterGroup, uint32_t filterMask)
{
physx::PxFilterData filterData;
filterData.word0 = filterGroup; // word0 = own ID
filterData.word1 = filterMask; // word1 = ID mask to filter pairs that trigger a
// contact callback;
const physx::PxU32 numShapes = actor->getNbShapes();
physx::PxShape** shapes = (physx::PxShape**)s_PXAllocator.allocate(sizeof(physx::PxShape*) * numShapes, "", "", 0);
actor->getShapes(shapes, numShapes);
for (physx::PxU32 i = 0; i < numShapes; i++)
{
physx::PxShape* shape = shapes[i];
shape->setFlag(physx::PxShapeFlag::eVISUALIZATION, true);
shape->setSimulationFilterData(filterData);
}
s_PXAllocator.deallocate(shapes);
}
physx::PxDefaultErrorCallback Physics3D::s_PXErrorCallback;
physx::PxDefaultAllocator Physics3D::s_PXAllocator;
physx::PxFoundation* Physics3D::s_PXFoundation;
physx::PxPhysics* Physics3D::s_PXPhysicsFactory;
physx::PxPvd* Physics3D::s_PXPvd;
}

View File

@ -0,0 +1,56 @@
//
// Created by sfd on 25-12-16.
//
#ifndef PHYSXMANAGER_H
#define PHYSXMANAGER_H
#define PX_PHYSX_STATIC_LIB
#include <PxPhysicsAPI.h>
#include "glm/glm.hpp"
#include "Prism/Scene/Components.h"
namespace Prism
{
enum class ForceMode : uint16_t
{
Force = 0,
Impulse,
VelocityChange,
Acceleration
};
enum class FilterGroup : uint32_t
{
Static = BIT(0),
Dynamic = BIT(1),
Kinematic = BIT(2),
All = Static | Dynamic | Kinematic
};
class PRISM_API Physics3D
{
public:
static void Init();
static void Shutdown();
static physx::PxSceneDesc CreateSceneDesc();
static physx::PxScene* CreateScene(const physx::PxSceneDesc& sceneDesc);
static physx::PxRigidActor* CreateAndAddActor(physx::PxScene* scene, const RigidBodyComponent& rigidbody, const glm::mat4& transform);
static physx::PxMaterial* CreateMaterial(float staticFriction, float dynamicFriction, float restitution);
static physx::PxConvexMesh* CreateMeshCollider(const Ref<Mesh>& mesh);
static physx::PxTransform CreatePose(const glm::mat4& transform);
static void SetCollisionFilters(physx::PxRigidActor* actor, uint32_t filterGroup, uint32_t filterMask);
// private:
static physx::PxDefaultErrorCallback s_PXErrorCallback;
static physx::PxDefaultAllocator s_PXAllocator;
static physx::PxFoundation* s_PXFoundation;
static physx::PxPhysics* s_PXPhysicsFactory;
static physx::PxPvd* s_PXPvd;
};
}
#endif //PHYSXMANAGER_H

View File

@ -115,6 +115,9 @@ namespace Prism
std::vector<Submesh>& GetSubmeshes() { return m_Submeshes; }
const std::vector<Submesh>& GetSubmeshes() const { return m_Submeshes; }
const std::vector<Vertex>& GetStaticVertices() const { return m_StaticVertices; }
const std::vector<Index>& GetIndices() const { return m_Indices; }
inline Ref<Shader> GetMeshShader() { return m_MeshShader; }
inline Ref<Material> GetMaterial() { return m_BaseMaterial; }
std::vector<Ref<MaterialInstance>>& GetMaterials() { return m_Materials; }

View File

@ -137,6 +137,81 @@ namespace Prism
CircleCollider2DComponent() = default;
CircleCollider2DComponent(const CircleCollider2DComponent& other) = default;
};
struct SphereColliderComponent
{
float Radius = 1.0f;
// TODO: Physics Material
SphereColliderComponent() = default;
SphereColliderComponent(const SphereColliderComponent& other) = default;
};
struct RigidBodyComponent
{
enum class Type { Static, Dynamic, Kinematic };
Type BodyType;
float Mass = 1.0f;
bool LockPositionX = false;
bool LockPositionY = false;
bool LockPositionZ = false;
bool LockRotationX = false;
bool LockRotationY = false;
bool LockRotationZ = false;
void* RuntimeActor = nullptr;
RigidBodyComponent() = default;
RigidBodyComponent(const RigidBodyComponent& other) = default;
};
// TODO: This will eventually be a resource, but that requires object referencing through the editor
struct PhysicsMaterialComponent
{
float StaticFriction = 1.0f;
float DynamicFriction = 1.0f;
float Bounciness = 1.0f;
PhysicsMaterialComponent() = default;
PhysicsMaterialComponent(const PhysicsMaterialComponent& other) = default;
};
struct BoxColliderComponent
{
glm::vec3 Size = { 1.0f, 1.0f, 1.0f };
glm::vec3 Offset = { 0.0f, 0.0f, 0.0f };
BoxColliderComponent() = default;
BoxColliderComponent(const BoxColliderComponent& other) = default;
};
struct CapsuleColliderComponent
{
float Radius = 0.5f;
float Height = 1.0f;
CapsuleColliderComponent() = default;
CapsuleColliderComponent(const CapsuleColliderComponent& other) = default;
};
struct MeshColliderComponent
{
Ref<Prism::Mesh> CollisionMesh;
MeshColliderComponent() = default;
MeshColliderComponent(const MeshColliderComponent& other) = default;
MeshColliderComponent(const Ref<Prism::Mesh>& mesh)
: CollisionMesh(mesh)
{
}
operator Ref<Prism::Mesh>() { return CollisionMesh; }
};
}

View File

@ -14,15 +14,18 @@
#include <glm/gtx/quaternion.hpp>
#include <glm/gtx/matrix_decompose.hpp>
#include "Prism/Physics/Physics3D.h"
namespace Prism
{
// TODO: THIS SHOULD MOVE TO PHYSICS FILE!
std::unordered_map<UUID, Scene*> s_ActiveScenes;
static physx::PxDefaultErrorCallback s_PXErrorCallback;
static physx::PxDefaultAllocator s_PXAllocator;
static physx::PxFoundation* s_PXFoundation;
static uint32_t s_SceneIDCounter = 0;
struct SceneComponent
@ -42,6 +45,13 @@ namespace Prism
}
};
struct PhysXSceneComponent
{
// NOTE: PhysX does some internal ref counting, and thus doesn't allow unique_ptr
physx::PxScene* World;
};
void ProcessContactEvents(const b2WorldId worldId) {
const b2ContactEvents contactEvents = b2World_GetContactEvents(worldId);
@ -75,6 +85,65 @@ namespace Prism
}
}
class PhysXContactListener : public physx::PxSimulationEventCallback
{
public:
virtual void onConstraintBreak(physx::PxConstraintInfo* constraints, physx::PxU32 count) override
{
PX_UNUSED(constraints);
PX_UNUSED(count);
}
virtual void onWake(physx::PxActor** actors, physx::PxU32 count) override
{
PX_UNUSED(actors);
PX_UNUSED(count);
}
virtual void onSleep(physx::PxActor** actors, physx::PxU32 count) override
{
PX_UNUSED(actors);
PX_UNUSED(count);
}
virtual void onContact(const physx::PxContactPairHeader& pairHeader, const physx::PxContactPair* pairs, physx::PxU32 nbPairs) override
{
Entity& a = *(Entity*)pairHeader.actors[0]->userData;
Entity& b = *(Entity*)pairHeader.actors[1]->userData;
if (pairs->flags == physx::PxContactPairFlag::eACTOR_PAIR_HAS_FIRST_TOUCH)
{
if (a.HasComponent<ScriptComponent>() && ScriptEngine::ModuleExists(a.GetComponent<ScriptComponent>().ModuleName))
ScriptEngine::OnCollisionBegin(a);
if (b.HasComponent<ScriptComponent>() && ScriptEngine::ModuleExists(b.GetComponent<ScriptComponent>().ModuleName))
ScriptEngine::OnCollisionBegin(b);
}
else if (pairs->flags == physx::PxContactPairFlag::eACTOR_PAIR_LOST_TOUCH)
{
if (a.HasComponent<ScriptComponent>() && ScriptEngine::ModuleExists(a.GetComponent<ScriptComponent>().ModuleName))
ScriptEngine::OnCollisionEnd(a);
if (b.HasComponent<ScriptComponent>() && ScriptEngine::ModuleExists(b.GetComponent<ScriptComponent>().ModuleName))
ScriptEngine::OnCollisionEnd(b);
}
}
virtual void onTrigger(physx::PxTriggerPair* pairs, physx::PxU32 count) override
{
PX_UNUSED(pairs);
PX_UNUSED(count);
}
virtual void onAdvance(const physx::PxRigidBody* const* bodyBuffer, const physx::PxTransform* poseBuffer, const physx::PxU32 count) override
{
PX_UNUSED(bodyBuffer);
PX_UNUSED(poseBuffer);
PX_UNUSED(count);
}
};
static PhysXContactListener s_PhysXContactListener;
void OnTransformConstruct(entt::registry& registry, entt::entity entity)
@ -134,6 +203,26 @@ namespace Prism
s_ActiveScenes[m_SceneID] = this;
physx::PxSceneDesc sceneDesc = Physics3D::CreateSceneDesc();
sceneDesc.gravity = physx::PxVec3(0.0f, -9.8f, 0.0f);
sceneDesc.simulationEventCallback = &s_PhysXContactListener;
const PhysXSceneComponent& physxWorld = m_Registry.emplace<PhysXSceneComponent>(m_SceneEntity, Physics3D::CreateScene(sceneDesc));
physx::PxPvdSceneClient* pvdClient = physxWorld.World->getScenePvdClient();
if(pvdClient)
{
pvdClient->setScenePvdFlag(physx::PxPvdSceneFlag::eTRANSMIT_CONSTRAINTS, true);
pvdClient->setScenePvdFlag(physx::PxPvdSceneFlag::eTRANSMIT_CONTACTS, true);
pvdClient->setScenePvdFlag(physx::PxPvdSceneFlag::eTRANSMIT_SCENEQUERIES, true);
}else
{
PM_CORE_WARN("you are using pvd to debug: ");
PM_CORE_WARN("PvdSceneClient is null is pvd running or you are using release/profile PhysX?");
PM_CORE_WARN("to using Pvd, should using debug/checked version to build!");
}
PM_CORE_ASSERT(physxWorld.World);
Init();
}
@ -147,11 +236,20 @@ namespace Prism
void Scene::Init()
{
auto skyboxShader = Shader::Create("assets/shaders/Skybox.glsl");
const auto skyboxShader = Shader::Create("assets/shaders/Skybox.glsl");
m_SkyboxMaterial = MaterialInstance::Create(Material::Create(skyboxShader));
m_SkyboxMaterial->SetFlag(MaterialFlag::DepthTest, false);
}
void Scene::OnShutdown()
{
auto b2WorldView = m_Registry.view<Box2DWorldComponent>();
b2DestroyWorld(m_Registry.get<Box2DWorldComponent>(m_SceneEntity).World);
auto physxView = m_Registry.view<PhysXSceneComponent>();
m_Registry.get<PhysXSceneComponent>(m_SceneEntity).World->release();
}
void Scene::OnUpdate(TimeStep ts)
{
// Update all entities
@ -175,16 +273,8 @@ namespace Prism
// box2DWorld->Step(ts, velocityIterations, positionIterations);
b2World_Step(box2DWorld, ts, positionIterations);
{
ProcessContactEvents(box2DWorld);
/*
const b2ContactEvents contactEvents = b2World_GetContactEvents(box2DWorld);
if (contactEvents.beginCount > 0)
PM_CORE_WARN("collision box counts in begin: {}", contactEvents.beginCount);
if (contactEvents.endCount > 0)
PM_CORE_WARN("collision box counts in end: {}", contactEvents.endCount);
*/
}
// Process Contact Envents box2d version 3.0^ should impl contact event after b2World_Step
ProcessContactEvents(box2DWorld);
{
const auto view = m_Registry.view<RigidBody2DComponent>();
@ -206,6 +296,65 @@ namespace Prism
}
}
// PhysX Physics
auto physxView = m_Registry.view<PhysXSceneComponent>();
physx::PxScene* physxScene = m_Registry.get<PhysXSceneComponent>(physxView.front()).World;
constexpr float stepSize = 0.016666660f;
physxScene->simulate(stepSize);
physxScene->fetchResults(true);
{
auto view = m_Registry.view<RigidBodyComponent>();
for (auto entity : view)
{
Entity e = { entity, this };
auto& transform = e.Transform();
RigidBodyComponent& rb = e.GetComponent<RigidBodyComponent>();
physx::PxRigidActor* actor = static_cast<physx::PxRigidActor*>(rb.RuntimeActor);
const auto& position = actor->getGlobalPose().p;
const physx::PxQuat& physicsBodyRotation = actor->getGlobalPose().q;
auto [translation, rotationQuat, scale] = GetTransformDecomposition(transform);
if (rb.BodyType == RigidBodyComponent::Type::Dynamic)
{
/*
// If the rigidbody is dynamic, the position of the entity is determined by the rigidbody
// TODO: Get rotation from RigidActor
float xAngle, yAngle, zAngle;
physx::PxVec3 axis;
physicsBodyRotation.toRadiansAndUnitAxis(xAngle, axis);
physicsBodyRotation.toRadiansAndUnitAxis(yAngle, axis);
physicsBodyRotation.toRadiansAndUnitAxis(zAngle, axis);
transform = glm::translate(glm::mat4(1.0f), { position.x, position.y, position.z }) *
glm::toMat4(glm::quat({ xAngle, yAngle, zAngle })) *
glm::scale(glm::mat4(1.0f), scale);
*/
// 获取物理引擎的位置和旋转
physx::PxTransform globalPose = actor->getGlobalPose();
const physx::PxVec3& pos = globalPose.p;
const physx::PxQuat& physicsQuat = globalPose.q;
glm::quat glmQuat{physicsQuat.w, physicsQuat.x, physicsQuat.y, physicsQuat.z};
// 使用转换后的四元数创建变换矩阵
transform = glm::translate(glm::mat4(1.0f),
glm::vec3(pos.x, pos.y, pos.z)) *
glm::toMat4(glmQuat) *
glm::scale(glm::mat4(1.0f), scale);
}
else if (rb.BodyType == RigidBodyComponent::Type::Static)
{
// If the rigidbody is static, make sure the actor is at the entitys position
actor->setGlobalPose(Physics3D::CreatePose(transform));
}
}
}
}
void Scene::OnRenderRuntime(TimeStep ts)
@ -328,7 +477,7 @@ namespace Prism
auto& world = m_Registry.get<Box2DWorldComponent>(sceneView.front()).World;
{
auto view = m_Registry.view<RigidBody2DComponent>();
m_PhysicsBodyEntityBuffer = new Entity[view.size()];
m_Physics2DBodyEntityBuffer = new Entity[view.size()];
uint32_t physicsBodyEntityBufferIndex = 0;
for (auto entity : view)
{
@ -353,7 +502,7 @@ namespace Prism
// box2D fixRotation renamed to motionlocks
bodyDef.motionLocks = b2MotionLocks{false, false, rigidBody2D.FixedRotation};
Entity* entityStorage = &m_PhysicsBodyEntityBuffer[physicsBodyEntityBufferIndex++];
Entity* entityStorage = &m_Physics2DBodyEntityBuffer[physicsBodyEntityBufferIndex++];
*entityStorage = e;
bodyDef.userData = entityStorage;
@ -420,12 +569,161 @@ namespace Prism
}
auto physxView = m_Registry.view<PhysXSceneComponent>();
physx::PxScene* physxWorld = m_Registry.get<PhysXSceneComponent>(physxView.front()).World;
{
auto view = m_Registry.view<RigidBodyComponent>();
m_Physics3DBodyEntityBuffer = new Entity[view.size()];
uint32_t physicsBodyEntityBufferIndex = 0;
for (auto entity : view)
{
Entity e = { entity, this };
UUID entityID = e.GetComponent<IDComponent>().ID;
auto& transform = e.Transform();
auto& rigidbody = m_Registry.get<RigidBodyComponent>(entity);
physx::PxRigidActor* actor = Physics3D::CreateAndAddActor(physxWorld, rigidbody, transform);
PM_CORE_ASSERT(actor);
Entity* entityStorage = &m_Physics3DBodyEntityBuffer[physicsBodyEntityBufferIndex++];
*entityStorage = e;
actor->userData = (void*)entityStorage;
rigidbody.RuntimeActor = actor;
}
}
{
auto view = m_Registry.view<BoxColliderComponent>();
for (auto entity : view)
{
Entity e = { entity, this };
auto& transform = e.Transform();
auto& boxCollider = m_Registry.get<BoxColliderComponent>(entity);
if (e.HasComponent<RigidBodyComponent>())
{
auto& rigidBody = e.GetComponent<RigidBodyComponent>();
auto& physicsMaterial = e.GetComponent<PhysicsMaterialComponent>();
PM_CORE_ASSERT(rigidBody.RuntimeActor);
physx::PxRigidActor* actor = static_cast<physx::PxRigidActor*>(rigidBody.RuntimeActor);
physx::PxBoxGeometry boxGeometry = physx::PxBoxGeometry(boxCollider.Size.x / 2.0F, boxCollider.Size.y / 2.0F, boxCollider.Size.z / 2.0F);
physx::PxMaterial* material = Physics3D::CreateMaterial(physicsMaterial.StaticFriction, physicsMaterial.DynamicFriction, physicsMaterial.Bounciness);
physx::PxShape* shape = physx::PxRigidActorExt::createExclusiveShape(*actor, boxGeometry, *material);
shape->setLocalPose(Physics3D::CreatePose(glm::translate(glm::mat4(1.0F), boxCollider.Offset)));
}
}
}
{
auto view = m_Registry.view<SphereColliderComponent>();
for (auto entity : view)
{
Entity e = { entity, this };
auto& transform = e.Transform();
auto& sphereCollider = m_Registry.get<SphereColliderComponent>(entity);
if (e.HasComponent<RigidBodyComponent>())
{
auto& rigidBody = e.GetComponent<RigidBodyComponent>();
auto& physicsMaterial = e.GetComponent<PhysicsMaterialComponent>();
PM_CORE_ASSERT(rigidBody.RuntimeActor);
physx::PxRigidActor* actor = static_cast<physx::PxRigidActor*>(rigidBody.RuntimeActor);
physx::PxSphereGeometry sphereGeometry = physx::PxSphereGeometry(sphereCollider.Radius);
physx::PxMaterial* material = Physics3D::CreateMaterial(physicsMaterial.StaticFriction, physicsMaterial.DynamicFriction, physicsMaterial.Bounciness);
physx::PxRigidActorExt::createExclusiveShape(*actor, sphereGeometry, *material);
physx::PxRigidDynamic* rigidBodyActor = actor->is<physx::PxRigidDynamic>();
if (rigidBodyActor)
{
rigidBodyActor->setRigidDynamicLockFlag(physx::PxRigidDynamicLockFlag::eLOCK_ANGULAR_X, true);
rigidBodyActor->setRigidDynamicLockFlag(physx::PxRigidDynamicLockFlag::eLOCK_ANGULAR_Y, true);
rigidBodyActor->setRigidDynamicLockFlag(physx::PxRigidDynamicLockFlag::eLOCK_ANGULAR_Z, true);
}
}
}
}
{
auto view = m_Registry.view<CapsuleColliderComponent>();
for (auto entity : view)
{
Entity e = { entity, this };
auto& transform = e.Transform();
auto& capsuleCollider = m_Registry.get<CapsuleColliderComponent>(entity);
if (e.HasComponent<RigidBodyComponent>())
{
auto& rigidBody = e.GetComponent<RigidBodyComponent>();
auto& physicsMaterial = e.GetComponent<PhysicsMaterialComponent>();
PM_CORE_ASSERT(rigidBody.RuntimeActor);
physx::PxRigidActor* actor = static_cast<physx::PxRigidActor*>(rigidBody.RuntimeActor);
physx::PxCapsuleGeometry capsuleGeometry = physx::PxCapsuleGeometry(capsuleCollider.Radius, capsuleCollider.Height / 2.0F);
physx::PxMaterial* material = Physics3D::CreateMaterial(physicsMaterial.StaticFriction, physicsMaterial.DynamicFriction, physicsMaterial.Bounciness);
physx::PxShape* shape = physx::PxRigidActorExt::createExclusiveShape(*actor, capsuleGeometry, *material);
// Make sure that the capsule is facing up (+Y)
shape->setLocalPose(physx::PxTransform(physx::PxQuat(physx::PxHalfPi, physx::PxVec3(0, 0, 1))));
}
}
}
{
auto meshView = m_Registry.view<MeshColliderComponent>();
for (auto entity : meshView)
{
Entity e = { entity, this };
auto& transform = e.Transform();
auto& meshCollider = m_Registry.get<MeshColliderComponent>(entity);
if (e.HasComponent<RigidBodyComponent>())
{
auto& rigidBody = e.GetComponent<RigidBodyComponent>();
auto& physicsMaterial = e.GetComponent<PhysicsMaterialComponent>();
PM_CORE_ASSERT(rigidBody.RuntimeActor);
physx::PxRigidActor* actor = static_cast<physx::PxRigidActor*>(rigidBody.RuntimeActor);
physx::PxConvexMesh* triangleMesh = Physics3D::CreateMeshCollider(meshCollider);
PM_CORE_ASSERT(triangleMesh);
physx::PxConvexMeshGeometry triangleGeometry = physx::PxConvexMeshGeometry(triangleMesh);
physx::PxMaterial* material = Physics3D::CreateMaterial(physicsMaterial.StaticFriction, physicsMaterial.DynamicFriction, physicsMaterial.Bounciness);
physx::PxRigidActorExt::createExclusiveShape(*actor, triangleGeometry, *material);
}
}
// Setup Collision Filters
auto rbView = m_Registry.view<RigidBodyComponent>();
for (auto entity : rbView)
{
Entity e = { entity, this };
auto& rigidBody = e.GetComponent<RigidBodyComponent>();
PM_CORE_ASSERT(rigidBody.RuntimeActor);
physx::PxRigidActor* actor = static_cast<physx::PxRigidActor*>(rigidBody.RuntimeActor);
if (rigidBody.BodyType == RigidBodyComponent::Type::Static)
Physics3D::SetCollisionFilters(actor, (uint32_t)FilterGroup::Static, (uint32_t)FilterGroup::All);
else if (rigidBody.BodyType == RigidBodyComponent::Type::Dynamic)
Physics3D::SetCollisionFilters(actor, (uint32_t)FilterGroup::Dynamic, (uint32_t)FilterGroup::All);
}
}
m_IsPlaying = true;
}
void Scene::OnRuntimeStop()
{
delete[] m_PhysicsBodyEntityBuffer;
auto physxView = m_Registry.view<PhysXSceneComponent>();
m_Registry.get<PhysXSceneComponent>(m_SceneEntity).World->release();
delete[] m_Physics3DBodyEntityBuffer;
delete[] m_Physics2DBodyEntityBuffer;
m_IsPlaying = false;
}
@ -534,6 +832,11 @@ namespace Prism
CopyComponentIfExists<RigidBody2DComponent>(newEntity.m_EntityHandle, entity.m_EntityHandle, m_Registry);
CopyComponentIfExists<BoxCollider2DComponent>(newEntity.m_EntityHandle, entity.m_EntityHandle, m_Registry);
CopyComponentIfExists<CircleCollider2DComponent>(newEntity.m_EntityHandle, entity.m_EntityHandle, m_Registry);
CopyComponentIfExists<RigidBodyComponent>(newEntity.m_EntityHandle, entity.m_EntityHandle, m_Registry);
CopyComponentIfExists<PhysicsMaterialComponent>(newEntity.m_EntityHandle, entity.m_EntityHandle, m_Registry);
CopyComponentIfExists<BoxColliderComponent>(newEntity.m_EntityHandle, entity.m_EntityHandle, m_Registry);
CopyComponentIfExists<SphereColliderComponent>(newEntity.m_EntityHandle, entity.m_EntityHandle, m_Registry);
CopyComponentIfExists<MeshColliderComponent>(newEntity.m_EntityHandle, entity.m_EntityHandle, m_Registry);
}
Entity Scene::FindEntityByTag(const std::string &tag) {
@ -577,6 +880,11 @@ namespace Prism
CopyComponent<RigidBody2DComponent>(target->m_Registry, m_Registry, enttMap);
CopyComponent<BoxCollider2DComponent>(target->m_Registry, m_Registry, enttMap);
CopyComponent<CircleCollider2DComponent>(target->m_Registry, m_Registry, enttMap);
CopyComponent<RigidBodyComponent>(target->m_Registry, m_Registry, enttMap);
CopyComponent<PhysicsMaterialComponent>(target->m_Registry, m_Registry, enttMap);
CopyComponent<BoxColliderComponent>(target->m_Registry, m_Registry, enttMap);
CopyComponent<SphereColliderComponent>(target->m_Registry, m_Registry, enttMap);
CopyComponent<MeshColliderComponent>(target->m_Registry, m_Registry, enttMap);
const auto& entityInstanceMap = ScriptEngine::GetEntityInstanceMap();
if (entityInstanceMap.find(target->GetUUID()) != entityInstanceMap.end())

View File

@ -44,6 +44,7 @@ namespace Prism
~Scene();
void Init();
void OnShutdown();
void OnUpdate(TimeStep ts);
void OnRenderRuntime(TimeStep ts);
@ -109,7 +110,8 @@ namespace Prism
EntityMap m_EntityIDMap;
entt::entity m_SelectedEntity;
Entity* m_PhysicsBodyEntityBuffer = nullptr;
Entity* m_Physics2DBodyEntityBuffer = nullptr;
Entity* m_Physics3DBodyEntityBuffer = nullptr;
Light m_Light;
float m_LightMultiplier = 0.3f;

View File

@ -329,6 +329,77 @@ namespace Prism
out << YAML::EndMap; // CircleCollider2DComponent
}
if (entity.HasComponent<RigidBodyComponent>())
{
out << YAML::Key << "RigidBodyComponent";
out << YAML::BeginMap; // RigidBodyComponent
auto& rigidbodyComponent = entity.GetComponent<RigidBodyComponent>();
out << YAML::Key << "BodyType" << YAML::Value << (int)rigidbodyComponent.BodyType;
out << YAML::Key << "Mass" << YAML::Value << rigidbodyComponent.Mass;
out << YAML::Key << "Constraints";
out << YAML::BeginMap; // Constraints
out << YAML::Key << "LockPositionX" << YAML::Value << rigidbodyComponent.LockPositionX;
out << YAML::Key << "LockPositionY" << YAML::Value << rigidbodyComponent.LockPositionY;
out << YAML::Key << "LockPositionZ" << YAML::Value << rigidbodyComponent.LockPositionZ;
out << YAML::Key << "LockRotationX" << YAML::Value << rigidbodyComponent.LockRotationX;
out << YAML::Key << "LockRotationY" << YAML::Value << rigidbodyComponent.LockRotationY;
out << YAML::Key << "LockRotationZ" << YAML::Value << rigidbodyComponent.LockRotationZ;
out << YAML::EndMap;
out << YAML::EndMap; // RigidBodyComponent
}
if (entity.HasComponent<PhysicsMaterialComponent>())
{
out << YAML::Key << "PhysicsMaterialComponent";
out << YAML::BeginMap; // PhysicsMaterialComponent
auto& physicsMaterial = entity.GetComponent<PhysicsMaterialComponent>();
out << YAML::Key << "StaticFriction" << YAML::Value << physicsMaterial.StaticFriction;
out << YAML::Key << "DynamicFriction" << YAML::Value << physicsMaterial.DynamicFriction;
out << YAML::Key << "Bounciness" << YAML::Value << physicsMaterial.Bounciness;
out << YAML::EndMap;
}
if (entity.HasComponent<BoxColliderComponent>())
{
out << YAML::Key << "BoxColliderComponent";
out << YAML::BeginMap; // BoxColliderComponent
auto& boxColliderComponent = entity.GetComponent<BoxColliderComponent>();
out << YAML::Key << "Offset" << YAML::Value << boxColliderComponent.Offset;
out << YAML::Key << "Size" << YAML::Value << boxColliderComponent.Size;
out << YAML::EndMap; // BoxColliderComponent
}
if (entity.HasComponent<SphereColliderComponent>())
{
out << YAML::Key << "SphereColliderComponent";
out << YAML::BeginMap; // SphereColliderComponent
auto& sphereColliderComponent = entity.GetComponent<SphereColliderComponent>();
out << YAML::Key << "Radius" << YAML::Value << sphereColliderComponent.Radius;
out << YAML::EndMap; // SphereColliderComponent
}
if (entity.HasComponent<MeshColliderComponent>())
{
out << YAML::Key << "MeshColliderComponent";
out << YAML::BeginMap; // MeshColliderComponent
auto mesh = entity.GetComponent<MeshColliderComponent>().CollisionMesh;
out << YAML::Key << "AssetPath" << YAML::Value << mesh->GetFilePath();
out << YAML::EndMap; // MeshColliderComponent
}
out << YAML::EndMap; // Entity
}
@ -562,6 +633,49 @@ namespace Prism
component.Density = circleCollider2DComponent["Density"] ? circleCollider2DComponent["Density"].as<float>() : 1.0f;
component.Friction = circleCollider2DComponent["Friction"] ? circleCollider2DComponent["Friction"].as<float>() : 1.0f;
}
if (auto rigidBodyComponent = entity["RigidBodyComponent"])
{
auto& component = deserializedEntity.AddComponent<RigidBodyComponent>();
component.BodyType = (RigidBodyComponent::Type)rigidBodyComponent["BodyType"].as<int>();
component.Mass = rigidBodyComponent["Mass"].as<float>();
component.LockPositionX = rigidBodyComponent["LockPositionX"] ? rigidBodyComponent["LockPositionX"].as<bool>() : false;
component.LockPositionY = rigidBodyComponent["LockPositionY"] ? rigidBodyComponent["LockPositionY"].as<bool>() : false;
component.LockPositionZ = rigidBodyComponent["LockPositionZ"] ? rigidBodyComponent["LockPositionZ"].as<bool>() : false;
component.LockRotationX = rigidBodyComponent["LockRotationX"] ? rigidBodyComponent["LockRotationX"].as<bool>() : false;
component.LockRotationY = rigidBodyComponent["LockRotationY"] ? rigidBodyComponent["LockRotationY"].as<bool>() : false;
component.LockRotationZ = rigidBodyComponent["LockRotationZ"] ? rigidBodyComponent["LockRotationZ"].as<bool>() : false;
}
if (auto physicsMaterialComponent = entity["PhysicsMaterialComponent"])
{
auto& component = deserializedEntity.AddComponent<PhysicsMaterialComponent>();
component.StaticFriction = physicsMaterialComponent["StaticFriction"].as<float>();
component.DynamicFriction = physicsMaterialComponent["DynamicFriction"].as<float>();
component.Bounciness = physicsMaterialComponent["Bounciness"].as<float>();
}
if (auto boxColliderComponent = entity["BoxColliderComponent"])
{
auto& component = deserializedEntity.AddComponent<BoxColliderComponent>();
component.Offset = boxColliderComponent["Offset"].as<glm::vec3>();
component.Size = boxColliderComponent["Size"].as<glm::vec3>();
}
if (auto sphereColliderComponent = entity["SphereColliderComponent"])
{
auto& component = deserializedEntity.AddComponent<SphereColliderComponent>();
component.Radius = sphereColliderComponent["Radius"].as<float>();
}
if (auto meshColliderComponent = entity["MeshColliderComponent"])
{
auto meshPath = meshColliderComponent["AssetPath"].as<std::string>();
deserializedEntity.AddComponent<MeshColliderComponent>(Ref<Mesh>::Create(meshPath));
PM_CORE_INFO(" Mesh Collider Asset Path: {0}", meshPath);
}
}
}
return true;

View File

@ -20,6 +20,8 @@
#include "imgui.h"
#define ENABLE_MONO_DEBUG
namespace Prism
{
static MonoDomain* s_MonoDomain = nullptr;
@ -48,6 +50,8 @@ namespace Prism
MonoMethod* OnUpdateMethod = nullptr;
// Physics
MonoMethod* OnCollisionBeginMethod = nullptr;
MonoMethod* OnCollisionEndMethod = nullptr;
MonoMethod* OnCollision2DBeginMethod = nullptr;
MonoMethod* OnCollision2DEndMethod = nullptr;
@ -59,6 +63,9 @@ namespace Prism
// Physics (Entity class)
OnCollision2DBeginMethod = GetMethod(s_CoreAssemblyImage, "Prism.Entity:OnCollision2DBegin(single)");
OnCollision2DEndMethod = GetMethod(s_CoreAssemblyImage, "Prism.Entity:OnCollision2DEnd(single)");
OnCollisionBeginMethod = GetMethod(s_CoreAssemblyImage, "Prism.Entity:OnCollisionBegin(single)");
OnCollisionEndMethod = GetMethod(s_CoreAssemblyImage, "Prism.Entity:OnCollisionEnd(single)");
}
};
@ -423,6 +430,7 @@ namespace Prism
auto& dstModuleFieldMap = dstEntityMap[entityID].ModuleFieldMap;
for (auto& [fieldName, field] : srcFieldMap)
{
volatile auto name = fieldName;
PM_CORE_ASSERT(dstModuleFieldMap.find(moduleName) != dstModuleFieldMap.end());
auto& fieldMap = dstModuleFieldMap.at(moduleName);
PM_CORE_ASSERT(fieldMap.find(fieldName) != fieldMap.end());
@ -488,6 +496,38 @@ namespace Prism
}
void ScriptEngine::OnCollisionBegin(Entity entity)
{
OnCollisionBegin(entity.m_Scene->GetUUID(), entity.GetComponent<IDComponent>().ID);
}
void ScriptEngine::OnCollisionBegin(const UUID& sceneID, const UUID& entityID)
{
EntityInstance& entityInstance = GetEntityInstanceData(sceneID, entityID).Instance;
if (entityInstance.ScriptClass->OnCollisionBeginMethod)
{
float value = 5.0f;
void* args[] = { &value };
CallMethod(entityInstance.GetInstance(), entityInstance.ScriptClass->OnCollisionBeginMethod, args);
}
}
void ScriptEngine::OnCollisionEnd(Entity entity)
{
OnCollisionEnd(entity.m_Scene->GetUUID(), entity.GetComponent<IDComponent>().ID);
}
void ScriptEngine::OnCollisionEnd(const UUID& sceneID, const UUID& entityID)
{
EntityInstance& entityInstance = GetEntityInstanceData(sceneID, entityID).Instance;
if (entityInstance.ScriptClass->OnCollisionEndMethod)
{
float value = 5.0f;
void* args[] = { &value };
CallMethod(entityInstance.GetInstance(), entityInstance.ScriptClass->OnCollisionEndMethod, args);
}
}
void ScriptEngine::OnScriptComponentDestroyed(const UUID &sceneID, const UUID &entityID)
{
PM_CORE_ASSERT(s_EntityInstanceMap.find(sceneID) != s_EntityInstanceMap.end());

View File

@ -123,6 +123,11 @@ namespace Prism
static void OnCollision2DEnd(Entity entity);
static void OnCollision2DEnd(const UUID &sceneID, const UUID &entityID);
static void OnCollisionBegin(Entity entity);
static void OnCollisionBegin(const UUID& sceneID, const UUID& entityID);
static void OnCollisionEnd(Entity entity);
static void OnCollisionEnd(const UUID& sceneID, const UUID& entityID);
static void OnScriptComponentDestroyed(const UUID &sceneID, const UUID &entityID);
static bool ModuleExists(const std::string& moduleName);

View File

@ -26,7 +26,7 @@ namespace Prism
s_HasComponentFuncs[type] = [](Entity& entity) { return entity.HasComponent<Type>(); };\
s_CreateComponentFuncs[type] = [](Entity& entity) { entity.AddComponent<Type>(); };\
} else {\
PM_CORE_ERROR("No C# component class found for " #Type "!");\
PM_CORE_ERROR("No C# component class found for {0}", #Type);\
}\
}
@ -40,6 +40,9 @@ namespace Prism
Component_RegisterType(SpriteRendererComponent);
Component_RegisterType(RigidBody2DComponent);
Component_RegisterType(BoxCollider2DComponent);
Component_RegisterType(RigidBodyComponent);
Component_RegisterType(BoxColliderComponent);
Component_RegisterType(SphereColliderComponent);
}
void ScriptEngineRegistry::RegisterAll()
@ -50,6 +53,10 @@ namespace Prism
mono_add_internal_call("Prism.Entity::GetTransform_Native",(const void*)Prism::Script::Prism_Entity_GetTransform);
mono_add_internal_call("Prism.Entity::SetTransform_Native",(const void*)Prism::Script::Prism_Entity_SetTransform);
mono_add_internal_call("Prism.Entity::GetForwardDirection_Native", Prism::Script::Prism_Entity_GetForwardDirection);
mono_add_internal_call("Prism.Entity::GetRightDirection_Native", Prism::Script::Prism_Entity_GetRightDirection);
mono_add_internal_call("Prism.Entity::GetUpDirection_Native", Prism::Script::Prism_Entity_GetUpDirection);
mono_add_internal_call("Prism.Entity::CreateComponent_Native",(const void*)Prism::Script::Prism_Entity_CreateComponent);
mono_add_internal_call("Prism.Entity::HasComponent_Native",(const void*)Prism::Script::Prism_Entity_HasComponent);
mono_add_internal_call("Prism.Entity::FindEntityByTag_Native", (const void*)Prism::Script::Prism_Entity_FindEntityByTag);
@ -67,6 +74,11 @@ namespace Prism
mono_add_internal_call("Prism.Texture2D::Destructor_Native", (const void*)Prism::Script::Prism_Texture2D_Destructor);
mono_add_internal_call("Prism.Texture2D::SetData_Native", (const void*)Prism::Script::Prism_Texture2D_SetData);
mono_add_internal_call("Prism.RigidBodyComponent::AddForce_Native", Prism::Script::Prism_RigidBodyComponent_AddForce);
mono_add_internal_call("Prism.RigidBodyComponent::AddTorque_Native", Prism::Script::Prism_RigidBodyComponent_AddTorque);
mono_add_internal_call("Prism.RigidBodyComponent::GetLinearVelocity_Native", Prism::Script::Prism_RigidBodyComponent_GetLinearVelocity);
mono_add_internal_call("Prism.RigidBodyComponent::SetLinearVelocity_Native", Prism::Script::Prism_RigidBodyComponent_SetLinearVelocity);
mono_add_internal_call("Prism.Material::Destructor_Native", (const void*)Prism::Script::Prism_Material_Destructor);
mono_add_internal_call("Prism.Material::SetFloat_Native", (const void*)Prism::Script::Prism_Material_SetFloat);
mono_add_internal_call("Prism.Material::SetTexture_Native", (const void*)Prism::Script::Prism_Material_SetTexture);

View File

@ -14,6 +14,13 @@
#include "Prism/Scene/Entity.h"
#include "Prism/Scene/Scene.h"
#define GLM_ENABLE_EXPERIMENTAL
#include <glm/gtx/quaternion.hpp>
#include <glm/gtx/matrix_decompose.hpp>
#include "PxRigidActor.h"
#include "PxRigidDynamic.h"
#include "Prism/Physics/Physics3D.h"
namespace Prism {
extern std::unordered_map<MonoType*, std::function<bool(Entity&)>> s_HasComponentFuncs;
@ -31,13 +38,23 @@ namespace Prism { namespace Script {
SpriteRenderer = 4
};
static std::tuple<glm::vec3, glm::quat, glm::vec3> GetTransformDecomposition(const glm::mat4& transform)
{
glm::vec3 scale, translation, skew;
glm::vec4 perspective;
glm::quat orientation;
glm::decompose(transform, scale, orientation, translation, skew, perspective);
return { translation, orientation, scale };
}
////////////////////////////////////////////////////////////////
// Math ////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////
float Prism_Noise_PerlinNoise(float x, float y)
float Prism_Noise_PerlinNoise(const float x, const float y)
{
return Noise::PerlinNoise(x, y);
}
@ -48,7 +65,7 @@ namespace Prism { namespace Script {
// Input ///////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////
bool Prism_Input_IsKeyPressed(KeyCode key)
bool Prism_Input_IsKeyPressed(const KeyCode key)
{
return Input::IsKeyPressed(key);
}
@ -59,7 +76,7 @@ namespace Prism { namespace Script {
// Entity //////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////
void Prism_Entity_GetTransform(uint64_t entityID, glm::mat4* outTransform)
void Prism_Entity_GetTransform(const uint64_t entityID, glm::mat4* outTransform)
{
Ref<Scene> scene = ScriptEngine::GetCurrentSceneContext();
PM_CORE_ASSERT(scene, "No active scene!");
@ -71,7 +88,7 @@ namespace Prism { namespace Script {
memcpy(outTransform, glm::value_ptr(transformComponent.Transform), sizeof(glm::mat4));
}
void Prism_Entity_SetTransform(uint64_t entityID, glm::mat4* inTransform)
void Prism_Entity_SetTransform(const uint64_t entityID, const glm::mat4* inTransform)
{
Ref<Scene> scene = ScriptEngine::GetCurrentSceneContext();
PM_CORE_ASSERT(scene, "No active scene!");
@ -82,8 +99,7 @@ namespace Prism { namespace Script {
auto& transformComponent = entity.GetComponent<TransformComponent>();
memcpy(glm::value_ptr(transformComponent.Transform), inTransform, sizeof(glm::mat4));
}
void Prism_Entity_CreateComponent(uint64_t entityID, void* type)
void Prism_Entity_GetForwardDirection(const uint64_t entityID, glm::vec3* outForward)
{
Ref<Scene> scene = ScriptEngine::GetCurrentSceneContext();
PM_CORE_ASSERT(scene, "No active scene!");
@ -91,20 +107,65 @@ namespace Prism { namespace Script {
PM_CORE_ASSERT(entityMap.find(entityID) != entityMap.end(), "Invalid entity ID or entity doesn't exist in scene!");
Entity entity = entityMap.at(entityID);
MonoType* monoType = mono_reflection_type_get_type((MonoReflectionType*)type);
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)
{
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);
MonoType* monoType = mono_reflection_type_get_type(static_cast<MonoReflectionType*>(type));
s_CreateComponentFuncs[monoType](entity);
}
bool Prism_Entity_HasComponent(uint64_t entityID, void* type)
bool Prism_Entity_HasComponent(const uint64_t entityID, void* type)
{
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);
MonoType* monoType = mono_reflection_type_get_type((MonoReflectionType*)type);
bool result = s_HasComponentFuncs[monoType](entity);
Entity entity = entityMap.at(entityID);
MonoType* monoType = mono_reflection_type_get_type(static_cast<MonoReflectionType*>(type));
const bool result = s_HasComponentFuncs[monoType](entity);
return result;
}
@ -120,7 +181,7 @@ namespace Prism { namespace Script {
return 0;
}
void* Prism_MeshComponent_GetMesh(uint64_t entityID)
void* Prism_MeshComponent_GetMesh(const uint64_t entityID)
{
Ref<Scene> scene = ScriptEngine::GetCurrentSceneContext();
PM_CORE_ASSERT(scene, "No active scene!");
@ -132,7 +193,7 @@ namespace Prism { namespace Script {
return new Ref<Mesh>(meshComponent.Mesh);
}
void Prism_MeshComponent_SetMesh(uint64_t entityID, Ref<Mesh>* inMesh)
void Prism_MeshComponent_SetMesh(const uint64_t entityID, const Ref<Mesh>* inMesh)
{
Ref<Scene> scene = ScriptEngine::GetCurrentSceneContext();
PM_CORE_ASSERT(scene, "No active scene!");
@ -144,70 +205,7 @@ namespace Prism { namespace Script {
meshComponent.Mesh = inMesh ? *inMesh : nullptr;
}
void Prism_RigidBody2DComponent_ApplyLinearImpulse(uint64_t entityID, glm::vec2 *impulse, glm::vec2 *offset, bool wake)
{
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<RigidBody2DComponent>());
auto& component = entity.GetComponent<RigidBody2DComponent>();
b2BodyId body = component.RuntimeBodyID;
b2Body_ApplyLinearImpulse(body, *(const b2Vec2*)impulse, b2Body_GetWorldCenterOfMass(body) + *(const b2Vec2*)offset, wake);
}
void Prism_RigidBody2DComponent_GetLinearVelocity(uint64_t entityID, glm::vec2 *outVelocity)
{
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<RigidBody2DComponent>());
auto& component = entity.GetComponent<RigidBody2DComponent>();
b2Vec2 velocity = b2Body_GetLinearVelocity(component.RuntimeBodyID);
PM_CORE_ASSERT(outVelocity);
*outVelocity = { velocity.x, velocity.y };
}
void Prism_RigidBody2DComponent_SetLinearVelocity(uint64_t entityID, glm::vec2 *velocity)
{
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<RigidBody2DComponent>());
auto& component = entity.GetComponent<RigidBody2DComponent>();
PM_CORE_ASSERT(velocity);
b2Body_SetLinearVelocity(component.RuntimeBodyID, {velocity->x, velocity->y});
}
void Hazel_RigidBody2DComponent_GetLinearVelocity(uint64_t entityID, glm::vec2* outVelocity)
{
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<RigidBody2DComponent>());
auto& component = entity.GetComponent<RigidBody2DComponent>();
const auto& velocity = b2Body_GetLinearVelocity(component.RuntimeBodyID);
PM_CORE_ASSERT(outVelocity);
*outVelocity = { velocity.x, velocity.y };
}
void Hazel_RigidBody2DComponent_SetLinearVelocity(uint64_t entityID, glm::vec2* velocity)
void Prism_RigidBody2DComponent_ApplyLinearImpulse(const uint64_t entityID, const glm::vec2 *impulse, const glm::vec2 *offset, const bool wake)
{
Ref<Scene> scene = ScriptEngine::GetCurrentSceneContext();
PM_CORE_ASSERT(scene, "No active scene!");
@ -217,10 +215,133 @@ namespace Prism { namespace Script {
Entity entity = entityMap.at(entityID);
PM_CORE_ASSERT(entity.HasComponent<RigidBody2DComponent>());
const auto& component = entity.GetComponent<RigidBody2DComponent>();
const b2BodyId body = component.RuntimeBodyID;
b2Body_ApplyLinearImpulse(body, *(const b2Vec2*)impulse, b2Body_GetWorldCenterOfMass(body) + *(const b2Vec2*)offset, wake);
}
void Prism_RigidBody2DComponent_GetLinearVelocity(const uint64_t entityID, glm::vec2 *outVelocity)
{
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<RigidBody2DComponent>());
const auto& component = entity.GetComponent<RigidBody2DComponent>();
b2Vec2 velocity = b2Body_GetLinearVelocity(component.RuntimeBodyID);
PM_CORE_ASSERT(outVelocity);
*outVelocity = { velocity.x, velocity.y };
}
void Prism_RigidBody2DComponent_SetLinearVelocity(const uint64_t entityID, const glm::vec2 *velocity)
{
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<RigidBody2DComponent>());
const auto& component = entity.GetComponent<RigidBody2DComponent>();
PM_CORE_ASSERT(velocity);
b2Body_SetLinearVelocity(component.RuntimeBodyID, {velocity->x, velocity->y});
}
void Prism_RigidBodyComponent_AddForce(const uint64_t entityID, glm::vec3* force, ForceMode forceMode)
{
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>();
physx::PxRigidActor* actor = (physx::PxRigidActor*)component.RuntimeActor;
physx::PxRigidDynamic* dynamicActor = actor->is<physx::PxRigidDynamic>();
// We don't want to assert since scripts might want to be able to switch
// between a static and dynamic actor at runtime
if (!dynamicActor)
return;
PM_CORE_ASSERT(force);
dynamicActor->addForce({ force->x, force->y, force->z }, (physx::PxForceMode::Enum)forceMode);
}
void Prism_RigidBodyComponent_AddTorque(const uint64_t entityID, glm::vec3* torque, ForceMode forceMode)
{
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>();
physx::PxRigidActor* actor = (physx::PxRigidActor*)component.RuntimeActor;
physx::PxRigidDynamic* dynamicActor = actor->is<physx::PxRigidDynamic>();
// We don't want to assert since scripts might want to be able to switch
// between a static and dynamic actor at runtime
if (!dynamicActor)
return;
PM_CORE_ASSERT(torque);
dynamicActor->addTorque({ torque->x, torque->y, torque->z }, (physx::PxForceMode::Enum)forceMode);
}
void Prism_RigidBodyComponent_GetLinearVelocity(const uint64_t entityID, glm::vec3* outVelocity)
{
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>();
physx::PxRigidActor* actor = (physx::PxRigidActor*)component.RuntimeActor;
const physx::PxRigidDynamic* dynamicActor = actor->is<physx::PxRigidDynamic>();
// We don't want to assert since scripts might want to be able to switch
// between a static and dynamic actor at runtime
if (!dynamicActor)
return;
PM_CORE_ASSERT(outVelocity);
physx::PxVec3 velocity = dynamicActor->getLinearVelocity();
*outVelocity = { velocity.x, velocity.y, velocity.z };
}
void Prism_RigidBodyComponent_SetLinearVelocity(const uint64_t entityID, glm::vec3* velocity)
{
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>();
physx::PxRigidActor* actor = (physx::PxRigidActor*)component.RuntimeActor;
physx::PxRigidDynamic* dynamicActor = actor->is<physx::PxRigidDynamic>();
// We don't want to assert since scripts might want to be able to switch
// between a static and dynamic actor at runtime
if (!dynamicActor)
return;
PM_CORE_ASSERT(velocity);
dynamicActor->setLinearVelocity({ velocity->x, velocity->y, velocity->z });
}
Ref<Mesh>* Prism_Mesh_Constructor(MonoString* filepath)
{
@ -239,7 +360,7 @@ namespace Prism { namespace Script {
return new Ref<Material>(mesh->GetMaterial());
}
Ref<MaterialInstance>* Prism_Mesh_GetMaterialByIndex(Ref<Mesh>* inMesh, int index)
Ref<MaterialInstance>* Prism_Mesh_GetMaterialByIndex(Ref<Mesh>* inMesh, const int index)
{
Ref<Mesh>& mesh = *(Ref<Mesh>*)inMesh;
const auto& materials = mesh->GetMaterials();
@ -255,13 +376,13 @@ namespace Prism { namespace Script {
return (int)materials.size();
}
void* Prism_Texture2D_Constructor(uint32_t width, uint32_t height)
void* Prism_Texture2D_Constructor(const uint32_t width, const uint32_t height)
{
auto result = Texture2D::Create(TextureFormat::RGBA, width, height);
const auto result = Texture2D::Create(TextureFormat::RGBA, width, height);
return new Ref<Texture2D>(result);
}
void Prism_Texture2D_Destructor(Ref<Texture2D>* _this)
void Prism_Texture2D_Destructor(const Ref<Texture2D>* _this)
{
delete _this;
}
@ -270,67 +391,67 @@ namespace Prism { namespace Script {
{
Ref<Texture2D>& instance = *_this;
uint32_t dataSize = count * sizeof(glm::vec4) / 4;
const uint32_t dataSize = count * sizeof(glm::vec4) / 4;
instance->Lock();
Buffer buffer = instance->GetWriteableBuffer();
const Buffer buffer = instance->GetWriteableBuffer();
PM_CORE_ASSERT(dataSize <= buffer.Size);
// Convert RGBA32F color to RGBA8
uint8_t* pixels = (uint8_t*)buffer.Data;
uint32_t index = 0;
auto pixels = static_cast<uint8_t*>(buffer.Data);
uint32_t index = 0;
for (uint32_t i = 0; i < instance->GetWidth() * instance->GetHeight(); i++)
{
glm::vec4& value = mono_array_get(inData, glm::vec4, i);
*pixels++ = (uint32_t)(value.x * 255.0f);
*pixels++ = (uint32_t)(value.y * 255.0f);
*pixels++ = (uint32_t)(value.z * 255.0f);
*pixels++ = (uint32_t)(value.w * 255.0f);
const glm::vec4& value = mono_array_get(inData, glm::vec4, i);
*pixels++ = static_cast<uint32_t>(value.x * 255.0f);
*pixels++ = static_cast<uint32_t>(value.y * 255.0f);
*pixels++ = static_cast<uint32_t>(value.z * 255.0f);
*pixels++ = static_cast<uint32_t>(value.w * 255.0f);
}
instance->Unlock();
}
void Prism_Material_Destructor(Ref<Material>* _this)
void Prism_Material_Destructor(const Ref<Material>* _this)
{
delete _this;
}
void Prism_Material_SetFloat(Ref<Material>* _this, MonoString* uniform, float value)
void Prism_Material_SetFloat(Ref<Material>* _this, MonoString* uniform, const float value)
{
Ref<Material>& instance = *(Ref<Material>*)_this;
instance->Set(mono_string_to_utf8(uniform), value);
}
void Prism_Material_SetTexture(Ref<Material>* _this, MonoString* uniform, Ref<Texture2D>* texture)
void Prism_Material_SetTexture(Ref<Material>* _this, MonoString* uniform, const Ref<Texture2D>* texture)
{
Ref<Material>& instance = *(Ref<Material>*)_this;
instance->Set(mono_string_to_utf8(uniform), *texture);
}
void Prism_MaterialInstance_Destructor(Ref<MaterialInstance>* _this)
void Prism_MaterialInstance_Destructor(const Ref<MaterialInstance>* _this)
{
delete _this;
}
void Prism_MaterialInstance_SetFloat(Ref<MaterialInstance>* _this, MonoString* uniform, float value)
void Prism_MaterialInstance_SetFloat(Ref<MaterialInstance>* _this, MonoString* uniform, const float value)
{
Ref<MaterialInstance>& instance = *(Ref<MaterialInstance>*)_this;
instance->Set(mono_string_to_utf8(uniform), value);
}
void Prism_MaterialInstance_SetVector3(Ref<MaterialInstance>* _this, MonoString* uniform, glm::vec3* value)
void Prism_MaterialInstance_SetVector3(Ref<MaterialInstance>* _this, MonoString* uniform, const glm::vec3* value)
{
Ref<MaterialInstance>& instance = *(Ref<MaterialInstance>*)_this;
instance->Set(mono_string_to_utf8(uniform), *value);
}
void Prism_MaterialInstance_SetVector4(Ref<MaterialInstance> *_this, MonoString *uniform, glm::vec4 *value)
void Prism_MaterialInstance_SetVector4(Ref<MaterialInstance> *_this, MonoString *uniform, const glm::vec4 *value)
{
Ref<MaterialInstance>& instance = *(Ref<MaterialInstance>*)_this;
instance->Set(mono_string_to_utf8(uniform), *value);
}
void Prism_MaterialInstance_SetTexture(Ref<MaterialInstance>* _this, MonoString* uniform, Ref<Texture2D>* texture)
void Prism_MaterialInstance_SetTexture(Ref<MaterialInstance>* _this, MonoString* uniform, const Ref<Texture2D>* texture)
{
Ref<MaterialInstance>& instance = *(Ref<MaterialInstance>*)_this;
instance->Set(mono_string_to_utf8(uniform), *texture);

View File

@ -6,6 +6,7 @@
#define SCRIPTWARPPERS_H
#include "Prism/Core/KeyCodes.h"
#include "Prism/Core/Ref.h"
#include "Prism/Physics/Physics3D.h"
#include "Prism/Renderer/Material.h"
#include "Prism/Renderer/Mesh.h"
#include "Prism/Renderer/Texture.h"
@ -25,35 +26,44 @@ namespace Prism { namespace Script {
// Entity
void Prism_Entity_GetTransform(uint64_t entityID, glm::mat4* outTransform);
void Prism_Entity_SetTransform(uint64_t entityID, 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_Entity_CreateComponent(uint64_t entityID, void* type);
bool Prism_Entity_HasComponent(uint64_t entityID, void* type);
uint64_t Prism_Entity_FindEntityByTag(MonoString* tag);
void* Prism_MeshComponent_GetMesh(uint64_t entityID);
void Prism_MeshComponent_SetMesh(uint64_t entityID, Ref<Mesh>* inMesh);
void Prism_MeshComponent_SetMesh(uint64_t entityID, const Ref<Mesh>* inMesh);
// 2D Physic
void Prism_RigidBody2DComponent_ApplyLinearImpulse(uint64_t entityID, glm::vec2* impulse, glm::vec2* offset, bool wake);
void Prism_RigidBody2DComponent_ApplyLinearImpulse(uint64_t entityID, const glm::vec2* impulse, const glm::vec2* offset, bool wake);
void Prism_RigidBody2DComponent_GetLinearVelocity(uint64_t entityID, glm::vec2* outVelocity);
void Prism_RigidBody2DComponent_SetLinearVelocity(uint64_t entityID, glm::vec2* velocity);
void Prism_RigidBody2DComponent_SetLinearVelocity(uint64_t entityID, const glm::vec2* velocity);
void Prism_RigidBodyComponent_AddForce(uint64_t entityID, glm::vec3* force, ForceMode forceMode);
void Prism_RigidBodyComponent_AddTorque(uint64_t entityID, glm::vec3* torque, ForceMode forceMode);
void Prism_RigidBodyComponent_GetLinearVelocity(uint64_t entityID, glm::vec3* outVelocity);
void Prism_RigidBodyComponent_SetLinearVelocity(uint64_t entityID, glm::vec3* velocity);
// Renderer
// Texture2D
void* Prism_Texture2D_Constructor(uint32_t width, uint32_t height);
void Prism_Texture2D_Destructor(Ref<Texture2D>* _this);
void Prism_Texture2D_Destructor(const Ref<Texture2D>* _this);
void Prism_Texture2D_SetData(Ref<Texture2D>* _this, MonoArray* inData, int32_t count);
// Material
void Prism_Material_Destructor(Ref<Material>* _this);
void Prism_Material_Destructor(const Ref<Material>* _this);
void Prism_Material_SetFloat(Ref<Material>* _this, MonoString* uniform, float value);
void Prism_Material_SetTexture(Ref<Material>* _this, MonoString* uniform, Ref<Texture2D>* texture);
void Prism_Material_SetTexture(Ref<Material>* _this, MonoString* uniform, const Ref<Texture2D>* texture);
void Prism_MaterialInstance_Destructor(Ref<MaterialInstance>* _this);
void Prism_MaterialInstance_Destructor(const Ref<MaterialInstance>* _this);
void Prism_MaterialInstance_SetFloat(Ref<MaterialInstance>* _this, MonoString* uniform, float value);
void Prism_MaterialInstance_SetVector3(Ref<MaterialInstance>* _this, MonoString* uniform, glm::vec3* value);
void Prism_MaterialInstance_SetVector4(Ref<MaterialInstance>* _this, MonoString* uniform, glm::vec4* value);
void Prism_MaterialInstance_SetTexture(Ref<MaterialInstance>* _this, MonoString* uniform, Ref<Texture2D>* texture);
void Prism_MaterialInstance_SetVector3(Ref<MaterialInstance>* _this, MonoString* uniform, const glm::vec3* value);
void Prism_MaterialInstance_SetVector4(Ref<MaterialInstance>* _this, MonoString* uniform, const glm::vec4* value);
void Prism_MaterialInstance_SetTexture(Ref<MaterialInstance>* _this, MonoString* uniform, const Ref<Texture2D>* texture);
// Mesh
Ref<Mesh>* Prism_Mesh_Constructor(MonoString* filepath);

1
Prism/vendor/PhysX vendored Submodule

Submodule Prism/vendor/PhysX added at 09ff24f327