default mesh collider are generated by default mesh, add camera info serialization, using error info instead of assert to process missing filepath when deserializing scene, move cullface into internal renderer api, fixed dynamic vertex buffer bug

This commit is contained in:
2026-01-19 13:05:24 +08:00
parent 81b52abf0f
commit 323d646611
32 changed files with 646 additions and 307 deletions

View File

@ -171,7 +171,8 @@ namespace Prism
m_SceneHierarchyPanel->SetEntityDeletedCallback(std::bind(&EditorLayer::OnEntityDeleted, this, std::placeholders::_1)); m_SceneHierarchyPanel->SetEntityDeletedCallback(std::bind(&EditorLayer::OnEntityDeleted, this, std::placeholders::_1));
UpdateWindowTitle("untitled Scene"); UpdateWindowTitle("untitled Scene");
OpenScene("assets/scenes/FPSDemo.scene"); // OpenScene("assets/scenes/FPSDemo.scene");
NewScene();
} }
void EditorLayer::OnDetach() void EditorLayer::OnDetach()
@ -1128,15 +1129,15 @@ namespace Prism
void EditorLayer::SaveSceneAs() void EditorLayer::SaveSceneAs()
{ {
auto& app = Application::Get(); const auto& app = Application::Get();
std::string filepath = app.SaveFile("Prism Scene (*.hsc)\0*.hsc\0"); const 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); PM_CLIENT_INFO("Saving scene to: {0}", m_SceneFilePath);
SceneSerializer serializer(m_EditorScene); SceneSerializer serializer(m_EditorScene);
serializer.Serialize(filepath); serializer.Serialize(filepath);
std::filesystem::path path = filepath; const std::filesystem::path path = filepath;
UpdateWindowTitle(path.filename().string()); UpdateWindowTitle(path.filename().string());
m_SceneFilePath = filepath; m_SceneFilePath = filepath;
}else }else
@ -1174,13 +1175,14 @@ namespace Prism
m_SceneHierarchyPanel->SetContext(m_EditorScene); m_SceneHierarchyPanel->SetContext(m_EditorScene);
} }
float EditorLayer::GetSnapValue() float EditorLayer::GetSnapValue() const
{ {
switch (m_GizmoType) switch (m_GizmoType)
{ {
case ImGuizmo::OPERATION::TRANSLATE: return 0.5f; case ImGuizmo::OPERATION::TRANSLATE: return 0.5f;
case ImGuizmo::OPERATION::ROTATE: return 45.0f; case ImGuizmo::OPERATION::ROTATE: return 45.0f;
case ImGuizmo::OPERATION::SCALE: return 0.5f; case ImGuizmo::OPERATION::SCALE: return 0.5f;
default: break;
} }
return 0.0f; return 0.0f;
} }

View File

@ -53,7 +53,7 @@ namespace Prism
void OnScenePlay(); void OnScenePlay();
void OnSceneStop(); void OnSceneStop();
float GetSnapValue(); float GetSnapValue() const;
private: private:
Scope<SceneHierarchyPanel> m_SceneHierarchyPanel; Scope<SceneHierarchyPanel> m_SceneHierarchyPanel;

View File

@ -18,13 +18,13 @@ Entities:
StoredFields: StoredFields:
- Name: WalkingSpeed - Name: WalkingSpeed
Type: 1 Type: 1
Data: 20 Data: 4
- Name: RunSpeed - Name: RunSpeed
Type: 1 Type: 1
Data: 50 Data: 10
- Name: JumpForce - Name: JumpForce
Type: 1 Type: 1
Data: 50 Data: 1
- Name: MouseSensitivity - Name: MouseSensitivity
Type: 1 Type: 1
Data: 10 Data: 10
@ -147,7 +147,14 @@ Entities:
Rotation: [0, 0, 0] Rotation: [0, 0, 0]
Scale: [1, 1, 1] Scale: [1, 1, 1]
CameraComponent: CameraComponent:
Camera: some camera data... Camera:
ProjectionType: 0
PerspectiveFOV: 65
PerspectiveNear: 0.100000001
PerspectiveFar: 1000
OrthographicSize: 10
OrthographicNear: -1
OrthographicFar: 1
Primary: true Primary: true
- Entity: 18306113171518048249 - Entity: 18306113171518048249
TagComponent: TagComponent:
@ -186,7 +193,7 @@ Entities:
Rotation: [0, 0, 0] Rotation: [0, 0, 0]
Scale: [1, 1, 1] Scale: [1, 1, 1]
SkyLightComponent: SkyLightComponent:
EnvironmentAssetPath: assets\env\birchwood_4k.hdr EnvironmentAssetPath: assets/env/birchwood_4k.hdr
Intensity: 1 Intensity: 1
Angle: 0 Angle: 0
PhysicsLayers: PhysicsLayers:

View File

@ -109,7 +109,7 @@ namespace FPSExample
{ {
RaycastHit hitInfo; RaycastHit hitInfo;
if (Input.IsKeyPressed(KeyCode.H) && if (Input.IsKeyPressed(KeyCode.H) &&
Physics.Raycast(m_CameraTransform.Position + (m_CameraTransform.Transform.Forward), Physics.Raycast(m_CameraTransform.Translation + (m_CameraTransform.Transform.Forward),
m_CameraTransform.Transform.Forward, 20.0f, out hitInfo)) m_CameraTransform.Transform.Forward, 20.0f, out hitInfo))
{ {
FindEntityByID(hitInfo.EntityID).GetComponent<MeshComponent>().Mesh.GetMaterial(0).Set("u_AlbedoColor", new Vec3(1.0f ,0.0f, 0.0f)); FindEntityByID(hitInfo.EntityID).GetComponent<MeshComponent>().Mesh.GetMaterial(0).Set("u_AlbedoColor", new Vec3(1.0f ,0.0f, 0.0f));
@ -120,7 +120,7 @@ namespace FPSExample
// NOTE: The NonAlloc version of Overlap functions should be used when possible since it doesn't allocate a new array // 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. // whenever you call it. The normal versions allocates a brand new array every time.
int numColliders = Physics.OverlapBoxNonAlloc(m_Transform.Position, new Vec3(1.0f), colliders); int numColliders = Physics.OverlapBoxNonAlloc(m_Transform.Translation, new Vec3(1.0f), colliders);
Console.WriteLine("Colliders: {0}", numColliders); 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 // When using NonAlloc it's not safe to use a foreach loop since some of the colliders may not exist
@ -158,9 +158,9 @@ namespace FPSExample
} }
private void UpdateCameraTransform(){ private void UpdateCameraTransform(){
Vec3 position = m_Transform.Position + m_CameraTransform.Transform.Forward * CameraForwardOffset; Vec3 position = m_Transform.Translation + m_CameraTransform.Transform.Forward * CameraForwardOffset;
position.Y += m_Transform.Position.Y + CameraYOffset; position.Y += m_Transform.Translation.Y + CameraYOffset;
m_CameraTransform.Position = position; m_CameraTransform.Translation = position;
} }
} }
} }

View File

@ -5,18 +5,54 @@ namespace Prism
{ {
public class Entity public class Entity
{ {
private Action<float>? m_CollisionBeginCallbacks;
private Action<float>? m_CollisionEndCallbacks;
private Action<float>? m_Collision2DBeginCallbacks;
private Action<float>? m_Collision2DEndCallbacks;
private Action<float>? m_TriggerBeginCallbacks;
private Action<float>? m_TriggerEndCallbacks;
public ulong ID { get; private set; } public ulong ID { get; private set; }
~Entity() ~Entity()
{ {
} }
private Action<float>? m_CollisionBeginCallbacks; public Vec3 Translation
private Action<float>? m_CollisionEndCallbacks; {
private Action<float>? m_Collision2DBeginCallbacks; get
private Action<float>? m_Collision2DEndCallbacks; {
private Action<float>? m_TriggerBeginCallbacks; return GetComponent<TransformComponent>().Translation;
private Action<float>? m_TriggerEndCallbacks; }
set
{
GetComponent<TransformComponent>().Translation = value;
}
}
public Vec3 Rotation
{
get
{
return GetComponent<TransformComponent>().Rotation;
}
set
{
GetComponent<TransformComponent>().Rotation = value;
}
}
public Vec3 Scale
{
get
{
return GetComponent<TransformComponent>().Scale;
}
set
{
GetComponent<TransformComponent>().Scale = value;
}
}
protected Entity() { ID = 0; } protected Entity() { ID = 0; }

View File

@ -9,8 +9,8 @@ namespace Prism
public Vec3 Rotation; public Vec3 Rotation;
public Vec3 Scale; public Vec3 Scale;
public Vec3 Up; public Vec3 Up { get; }
public Vec3 Right; public Vec3 Right { get; }
public Vec3 Forward; public Vec3 Forward { get; }
} }
} }

View File

@ -8,6 +8,8 @@ namespace Prism
public float X; public float X;
public float Y; public float Y;
public static Vec2 Zero = new Vec2(0.0f, 0.0f);
public Vec2(float scalar) public Vec2(float scalar)
{ {
X = Y = scalar; X = Y = scalar;
@ -39,12 +41,34 @@ namespace Prism
return (float)Math.Sqrt(X * X + Y * Y); return (float)Math.Sqrt(X * X + Y * Y);
} }
public Vec2 SafeNormalized()
{
float length = Length();
if (length > float.Epsilon)
{
return new Vec2(X / length, Y / length);
}
else
{
return Zero;
}
}
public Vec2 Normalized() public Vec2 Normalized()
{ {
float length = Length(); float length = Length();
return new Vec2(X / length, Y / length); return new Vec2(X / length, Y / length);
} }
public void SafeNormalize()
{
float length = Length();
if (length > float.Epsilon)
{
X = X / length;
Y = Y / length;
}
}
public void Normalize() public void Normalize()
{ {
float length = Length(); float length = Length();

View File

@ -73,15 +73,25 @@ namespace Prism
public Vec3 Normalized() public Vec3 Normalized()
{ {
float length = Length(); float length = Length();
return new Vec3(X / length, Y / length, Z / length); if (length > float.Epsilon)
{
return new Vec3(X / length, Y / length, Z / length);
}
else
{
return Zero;
}
} }
public void Normalize() public void Normalize()
{ {
float length = Length(); float length = Length();
X = X / length; if (length > float.Epsilon)
Y = Y / length; {
Z = Z / length; X = X / length;
Y = Y / length;
Z = Z / length;
}
} }

View File

@ -33,21 +33,29 @@ namespace Prism
public class TransformComponent : Component public class TransformComponent : Component
{ {
private Transform m_Transform; public Transform Transform
public Transform Transform { get { return m_Transform; } }
public Vec3 Position
{ {
get get
{ {
GetTransform_Native(Entity.ID, out m_Transform); GetTransform_Native(Entity.ID, out Transform result);
return m_Transform.Position; return result;
} }
set set
{ {
m_Transform.Position = value; SetTransform_Native(Entity.ID, ref value);
SetTransform_Native(Entity.ID, ref m_Transform); }
}
public Vec3 Translation
{
get
{
GetTranslation_Native(Entity.ID, out Vec3 result);
return result;
}
set
{
SetTranslation_Native(Entity.ID, ref value);
} }
} }
@ -55,13 +63,12 @@ namespace Prism
{ {
get get
{ {
GetTransform_Native(Entity.ID, out m_Transform); GetRotation_Native(Entity.ID, out Vec3 result);
return m_Transform.Rotation; return result;
} }
set set
{ {
m_Transform.Rotation = value; SetRotation_Native(Entity.ID, ref value);
SetTransform_Native(Entity.ID, ref m_Transform);
} }
} }
@ -69,22 +76,38 @@ namespace Prism
{ {
get get
{ {
GetTransform_Native(Entity.ID, out m_Transform); GetScale_Native(Entity.ID, out Vec3 result);
return m_Transform.Scale; return result;
} }
set set
{ {
m_Transform.Scale = value; SetScale_Native(Entity.ID, ref value);
SetTransform_Native(Entity.ID, ref m_Transform);
} }
} }
[MethodImpl(MethodImplOptions.InternalCall)] [MethodImpl(MethodImplOptions.InternalCall)]
internal static extern void GetTransform_Native(ulong entityID, out Transform result); internal static extern void GetTransform_Native(ulong entityID, out Transform inTransform);
[MethodImpl(MethodImplOptions.InternalCall)] [MethodImpl(MethodImplOptions.InternalCall)]
internal static extern void SetTransform_Native(ulong entityID, ref Transform result); internal static extern void SetTransform_Native(ulong entityID, ref Transform outTransform);
[MethodImpl(MethodImplOptions.InternalCall)]
internal static extern void GetTranslation_Native(ulong entityID, out Vec3 outTranslation);
[MethodImpl(MethodImplOptions.InternalCall)]
internal static extern void SetTranslation_Native(ulong entityID, ref Vec3 inTranslation);
[MethodImpl(MethodImplOptions.InternalCall)]
internal static extern void GetRotation_Native(ulong entityID, out Vec3 outRotation);
[MethodImpl(MethodImplOptions.InternalCall)]
internal static extern void SetRotation_Native(ulong entityID, ref Vec3 inRotation);
[MethodImpl(MethodImplOptions.InternalCall)]
internal static extern void GetScale_Native(ulong entityID, out Vec3 outScale);
[MethodImpl(MethodImplOptions.InternalCall)]
internal static extern void SetScale_Native(ulong entityID, ref Vec3 inScale);
} }
public class MeshComponent : Component public class MeshComponent : Component

View File

@ -151,6 +151,20 @@ namespace Prism
} }
} }
template<class T, typename Function>
void SceneHierarchyPanel::AddComponentPopup(const char* componentName, Function function)
{
if (!m_SelectionContext.HasComponent<T>())
{
if (ImGui::Button(componentName))
{
T& component = m_SelectionContext.AddComponent<T>();
function(component);
ImGui::CloseCurrentPopup();
}
}
}
void SceneHierarchyPanel::OnImGuiRender() void SceneHierarchyPanel::OnImGuiRender()
{ {
ImGui::Begin("Scene Hierarchy"); ImGui::Begin("Scene Hierarchy");
@ -442,7 +456,15 @@ namespace Prism
AddComponentPopup<BoxColliderComponent>("BoxCollider"); AddComponentPopup<BoxColliderComponent>("BoxCollider");
AddComponentPopup<SphereColliderComponent>("SphereCollider"); AddComponentPopup<SphereColliderComponent>("SphereCollider");
AddComponentPopup<CapsuleColliderComponent>("CapsuleCollider"); AddComponentPopup<CapsuleColliderComponent>("CapsuleCollider");
AddComponentPopup<MeshColliderComponent>("MeshCollider");
AddComponentPopup<MeshColliderComponent>("MeshCollider", [&](MeshColliderComponent& component)
{
if (m_SelectionContext.HasComponent<MeshComponent>())
{
component.CollisionMesh = m_SelectionContext.GetComponent<MeshComponent>().Mesh;
PhysicsWrappers::CreateTriangleMesh(component);
}
});
ImGui::EndPopup(); ImGui::EndPopup();
@ -890,34 +912,37 @@ namespace Prism
UI::EndPropertyGrid(); UI::EndPropertyGrid();
}); });
DrawComponent<MeshColliderComponent>("Mesh Collider", entity, [](MeshColliderComponent& mcc) DrawComponent<MeshColliderComponent>("Mesh Collider", entity, [&](MeshColliderComponent& mcc)
{ {
ImGui::Columns(3); if (mcc.OverrideMesh)
ImGui::SetColumnWidth(0, 100);
ImGui::SetColumnWidth(1, 250);
ImGui::SetColumnWidth(2, 40);
ImGui::Text("File Path");
ImGui::NextColumn();
ImGui::PushItemWidth(-1);
if (mcc.CollisionMesh)
ImGui::InputText("##meshfilepath", (char*)mcc.CollisionMesh->GetFilePath().c_str(), 256, ImGuiInputTextFlags_ReadOnly);
else
ImGui::InputText("##meshfilepath", (char*)"Null", 256, ImGuiInputTextFlags_ReadOnly);
ImGui::PopItemWidth();
ImGui::NextColumn();
if (ImGui::Button("...##openmesh"))
{ {
std::string file = Application::Get().OpenFile(); ImGui::Columns(3);
if (!file.empty()) ImGui::SetColumnWidth(0, 100);
ImGui::SetColumnWidth(1, 250);
ImGui::SetColumnWidth(2, 40);
ImGui::Text("File Path");
ImGui::NextColumn();
ImGui::PushItemWidth(-1);
if (mcc.CollisionMesh)
ImGui::InputText("##meshfilepath", (char*)mcc.CollisionMesh->GetFilePath().c_str(), 256, ImGuiInputTextFlags_ReadOnly);
else
ImGui::InputText("##meshfilepath", (char*)"Null", 256, ImGuiInputTextFlags_ReadOnly);
ImGui::PopItemWidth();
ImGui::NextColumn();
if (ImGui::Button("...##openmesh"))
{ {
mcc.CollisionMesh = Ref<Mesh>::Create(file); std::string file = Application::Get().OpenFile();
if (mcc.IsConvex) if (!file.empty())
PhysicsWrappers::CreateConvexMesh(mcc); {
else mcc.CollisionMesh = Ref<Mesh>::Create(file);
PhysicsWrappers::CreateTriangleMesh(mcc); if (mcc.IsConvex)
PhysicsWrappers::CreateConvexMesh(mcc, entity.Transform().Scale);
else
PhysicsWrappers::CreateTriangleMesh(mcc, entity.Transform().Scale);
}
} }
ImGui::EndColumns();
} }
ImGui::EndColumns();
UI::BeginPropertyGrid(); UI::BeginPropertyGrid();
if (UI::Property("Is Convex", mcc.IsConvex)) if (UI::Property("Is Convex", mcc.IsConvex))
@ -932,6 +957,19 @@ namespace Prism
} }
UI::Property("Is Trigger", mcc.IsTrigger); UI::Property("Is Trigger", mcc.IsTrigger);
if (UI::Property("Override Mesh", mcc.OverrideMesh))
{
if (!mcc.OverrideMesh && entity.HasComponent<MeshComponent>())
{
mcc.CollisionMesh = entity.GetComponent<MeshComponent>().Mesh;
if (mcc.IsConvex)
PhysicsWrappers::CreateConvexMesh(mcc);
else
PhysicsWrappers::CreateTriangleMesh(mcc);
}
}
UI::EndPropertyGrid(); UI::EndPropertyGrid();
}); });

View File

@ -30,6 +30,9 @@ namespace Prism
template <class T> template <class T>
void AddComponentPopup(const char* componentName); void AddComponentPopup(const char* componentName);
template<class T, typename Function>
void AddComponentPopup(const char* componentName, Function function);
private: private:
Ref<Scene> m_Context; Ref<Scene> m_Context;
Entity m_SelectionContext; Entity m_SelectionContext;

View File

@ -210,11 +210,11 @@ namespace Prism
m_ActorInternal = actor; m_ActorInternal = actor;
} }
const physx::PxMaterial* physicsMat = physics.createMaterial(m_Material.StaticFriction, m_Material.DynamicFriction, m_Material.Bounciness); m_MaterialInternal = physics.createMaterial(m_Material.StaticFriction, m_Material.DynamicFriction, m_Material.Bounciness);
if (m_Entity.HasComponent<BoxColliderComponent>()) PhysicsWrappers::AddBoxCollider(*this, *physicsMat); if (m_Entity.HasComponent<BoxColliderComponent>()) PhysicsWrappers::AddBoxCollider(*this);
if (m_Entity.HasComponent<SphereColliderComponent>()) PhysicsWrappers::AddSphereCollider(*this, *physicsMat); if (m_Entity.HasComponent<SphereColliderComponent>()) PhysicsWrappers::AddSphereCollider(*this);
if (m_Entity.HasComponent<CapsuleColliderComponent>()) PhysicsWrappers::AddCapsuleCollider(*this, *physicsMat); if (m_Entity.HasComponent<CapsuleColliderComponent>()) PhysicsWrappers::AddCapsuleCollider(*this);
if (m_Entity.HasComponent<MeshColliderComponent>()) PhysicsWrappers::AddMeshCollider(*this, *physicsMat); if (m_Entity.HasComponent<MeshColliderComponent>()) PhysicsWrappers::AddMeshCollider(*this);
if (!PhysicsLayerManager::IsLayerValid(m_RigidBody.Layer)) if (!PhysicsLayerManager::IsLayerValid(m_RigidBody.Layer))
m_RigidBody.Layer = 0; m_RigidBody.Layer = 0;
@ -253,8 +253,14 @@ namespace Prism
} }
} }
void PhysicsActor::AddCollisionShape(physx::PxShape* shape) void PhysicsActor::AddCollisionShape(physx::PxShape* shape) const
{ {
const bool status = m_ActorInternal->attachShape(*shape);
shape->release();
if (!status)
shape = nullptr;
/*
const int shapeType = shape->getGeometry().getType(); const int shapeType = shape->getGeometry().getType();
if (m_Shapes.find(shapeType) == m_Shapes.end()) if (m_Shapes.find(shapeType) == m_Shapes.end())
@ -263,8 +269,10 @@ namespace Prism
} }
m_Shapes[shapeType].push_back(shape); m_Shapes[shapeType].push_back(shape);
*/
} }
/*
void PhysicsActor::RemoveCollisionsShapes(const int type) void PhysicsActor::RemoveCollisionsShapes(const int type)
{ {
if (m_Shapes.find(type) != m_Shapes.end()) if (m_Shapes.find(type) != m_Shapes.end())
@ -276,6 +284,7 @@ namespace Prism
m_Shapes.erase(type); m_Shapes.erase(type);
} }
} }
*/
void PhysicsActor::SetLayer(const uint32_t layer) const void PhysicsActor::SetLayer(const uint32_t layer) const
{ {

View File

@ -12,6 +12,7 @@ namespace physx
{ {
class PxRigidActor; class PxRigidActor;
class PxShape; class PxShape;
class PxMaterial;
} }
namespace Prism namespace Prism
@ -55,14 +56,15 @@ namespace Prism
void Update(float fixedTimestep) const; void Update(float fixedTimestep) const;
void SynchronizeTransform(); void SynchronizeTransform();
void AddCollisionShape(physx::PxShape* shape); void AddCollisionShape(physx::PxShape* shape) const;
void RemoveCollisionsShapes(int type);
private: private:
Entity m_Entity; Entity m_Entity;
RigidBodyComponent& m_RigidBody; RigidBodyComponent& m_RigidBody;
PhysicsMaterialComponent m_Material; PhysicsMaterialComponent m_Material;
physx::PxRigidActor* m_ActorInternal{}; physx::PxRigidActor* m_ActorInternal;
physx::PxMaterial* m_MaterialInternal;
friend class Physics3D; friend class Physics3D;
friend class PhysicsWrappers; friend class PhysicsWrappers;

View File

@ -24,6 +24,11 @@ namespace Prism
return physx::PxTransform{p, r}; return physx::PxTransform{p, r};
} }
physx::PxTransform ToPhysXTransform(const glm::vec3& translation, const glm::vec3& rotation)
{
return physx::PxTransform(ToPhysXVector(translation), ToPhysXQuat(glm::quat(rotation)));
}
physx::PxMat44 ToPhysXMatrix(const glm::mat4& matrix) physx::PxMat44 ToPhysXMatrix(const glm::mat4& matrix)
{ {
return *(physx::PxMat44*)&matrix; return *(physx::PxMat44*)&matrix;

View File

@ -16,6 +16,7 @@ namespace Prism
physx::PxTransform ToPhysXTransform(const TransformComponent& transform); physx::PxTransform ToPhysXTransform(const TransformComponent& transform);
physx::PxTransform ToPhysXTransform(const glm::mat4& matrix); physx::PxTransform ToPhysXTransform(const glm::mat4& matrix);
physx::PxTransform ToPhysXTransform(const glm::vec3& translation, const glm::vec3& rotation);
physx::PxMat44 ToPhysXMatrix(const glm::mat4& matrix); physx::PxMat44 ToPhysXMatrix(const glm::mat4& matrix);
physx::PxVec3 ToPhysXVector(const glm::vec3& vector); physx::PxVec3 ToPhysXVector(const glm::vec3& vector);
physx::PxVec4 ToPhysXVector(const glm::vec4& vector); physx::PxVec4 ToPhysXVector(const glm::vec4& vector);

View File

@ -9,6 +9,7 @@
#include <glm/gtx/rotate_vector.hpp> #include <glm/gtx/rotate_vector.hpp>
#include "PhysicsLayer.h" #include "PhysicsLayer.h"
#include "Prism/Core/Math/Math.h"
#include "Prism/Script/ScriptEngine.h" #include "Prism/Script/ScriptEngine.h"
#define PHYSX_DEBUGGER #define PHYSX_DEBUGGER
@ -177,9 +178,8 @@ namespace Prism
return s_Physics->createScene(sceneDesc); return s_Physics->createScene(sceneDesc);
} }
void PhysicsWrappers::AddBoxCollider(PhysicsActor& actor, const physx::PxMaterial& material) void PhysicsWrappers::AddBoxCollider(PhysicsActor& actor)
{ {
actor.RemoveCollisionsShapes(physx::PxGeometryType::eBOX);
const auto& collider = actor.m_Entity.GetComponent<BoxColliderComponent>(); const auto& collider = actor.m_Entity.GetComponent<BoxColliderComponent>();
const glm::vec3 scale = actor.m_Entity.Transform().Scale; const glm::vec3 scale = actor.m_Entity.Transform().Scale;
@ -191,20 +191,15 @@ namespace Prism
const auto boxGeometry = physx::PxBoxGeometry(colliderSize.x / 2.0f, colliderSize.y / 2.0f, colliderSize.z / 2.0f); const auto boxGeometry = physx::PxBoxGeometry(colliderSize.x / 2.0f, colliderSize.y / 2.0f, colliderSize.z / 2.0f);
physx::PxShape* shape = physx::PxRigidActorExt::createExclusiveShape(*actor.m_ActorInternal, boxGeometry, material); physx::PxShape* shape = physx::PxRigidActorExt::createExclusiveShape(*actor.m_ActorInternal, boxGeometry, *actor.m_MaterialInternal);
// physx::PxShape* shape = physx::PxRigidActorExt::createExclusiveShape(actor, boxGeometry, 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);
shape->setLocalPose(ToPhysXTransform(glm::translate(glm::mat4(1.0F), collider.Offset))); shape->setLocalPose(ToPhysXTransform(glm::translate(glm::mat4(1.0f), collider.Offset)));
actor.AddCollisionShape(shape);
} }
void PhysicsWrappers::AddSphereCollider(PhysicsActor& actor, const physx::PxMaterial& material) void PhysicsWrappers::AddSphereCollider(PhysicsActor& actor)
{ {
actor.RemoveCollisionsShapes(physx::PxGeometryType::eSPHERE);
const auto& collider = actor.m_Entity.GetComponent<SphereColliderComponent>(); const auto& collider = actor.m_Entity.GetComponent<SphereColliderComponent>();
const glm::vec3 scale = actor.m_Entity.Transform().Scale; const glm::vec3 scale = actor.m_Entity.Transform().Scale;
float colliderRadius = collider.Radius; float colliderRadius = collider.Radius;
@ -213,52 +208,43 @@ namespace Prism
const auto sphereGeometry = physx::PxSphereGeometry(colliderRadius); const auto sphereGeometry = physx::PxSphereGeometry(colliderRadius);
physx::PxShape* shape = physx::PxRigidActorExt::createExclusiveShape(*actor.m_ActorInternal, sphereGeometry, material); physx::PxShape* shape = physx::PxRigidActorExt::createExclusiveShape(*actor.m_ActorInternal, sphereGeometry, *actor.m_MaterialInternal);
// physx::PxShape* shape = physx::PxRigidActorExt::createExclusiveShape(actor, sphereGeometry, material); // physx::PxShape* shape = physx::PxRigidActorExt::createExclusiveShape(actor, sphereGeometry, 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);
actor.AddCollisionShape(shape);
} }
void PhysicsWrappers::AddCapsuleCollider(PhysicsActor& actor, const physx::PxMaterial& material) void PhysicsWrappers::AddCapsuleCollider(PhysicsActor& actor)
{ {
actor.RemoveCollisionsShapes(physx::PxGeometryType::eCAPSULE);
const auto& collider = actor.m_Entity.GetComponent<CapsuleColliderComponent>(); const auto& collider = actor.m_Entity.GetComponent<CapsuleColliderComponent>();
const glm::vec3 scale = actor.m_Entity.Transform().Scale; const glm::vec3 scale = actor.m_Entity.Transform().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; 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 * 0.5f); const auto capsuleGeometry = physx::PxCapsuleGeometry(colliderRadius, colliderHeight * 0.5f);
physx::PxShape* shape = physx::PxRigidActorExt::createExclusiveShape(*actor.m_ActorInternal, capsuleGeometry, material); physx::PxShape* shape = physx::PxRigidActorExt::createExclusiveShape(*actor.m_ActorInternal, capsuleGeometry, *actor.m_MaterialInternal);
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);
actor.AddCollisionShape(shape);
} }
void PhysicsWrappers::AddMeshCollider(PhysicsActor& actor, const physx::PxMaterial& material) void PhysicsWrappers::AddMeshCollider(PhysicsActor& actor)
{ {
auto& collider = actor.m_Entity.GetComponent<MeshColliderComponent>(); auto& collider = actor.m_Entity.GetComponent<MeshColliderComponent>();
glm::vec3 scale = actor.m_Entity.Transform().Scale; glm::vec3 scale = actor.m_Entity.Transform().Scale;
if (collider.IsConvex) if (collider.IsConvex)
{ {
actor.RemoveCollisionsShapes(physx::PxGeometryType::eTRIANGLEMESH); const std::vector<physx::PxShape*> shapes = CreateConvexMesh(collider, scale);
const std::vector<physx::PxConvexMesh*> meshes = CreateConvexMesh(collider, true); for (const auto shape : shapes)
for (const auto mesh : meshes)
{ {
physx::PxConvexMeshGeometry convexGeometry = physx::PxConvexMeshGeometry(mesh, physx::PxMeshScale(ToPhysXVector(scale))); physx::PxMaterial* materials[] = { actor.m_MaterialInternal };
convexGeometry.meshFlags = physx::PxConvexMeshGeometryFlag::eTIGHT_BOUNDS; shape->setMaterials(materials, 1);
physx::PxShape* shape = physx::PxRigidActorExt::createExclusiveShape(*actor.m_ActorInternal, convexGeometry, 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);
@ -267,14 +253,13 @@ namespace Prism
} }
else else
{ {
actor.RemoveCollisionsShapes(physx::PxGeometryType::eCONVEXMESH); const std::vector<physx::PxShape*> shapes = CreateTriangleMesh(collider, scale);
const std::vector<physx::PxTriangleMesh*> meshes = CreateTriangleMesh(collider); for (const auto shape : shapes)
for (const auto mesh : meshes)
{ {
physx::PxTriangleMeshGeometry convexGeometry = physx::PxTriangleMeshGeometry(mesh, physx::PxMeshScale(ToPhysXVector(scale))); physx::PxMaterial* materials[] = { actor.m_MaterialInternal };
physx::PxShape* shape = physx::PxRigidActorExt::createExclusiveShape(*actor.m_ActorInternal, convexGeometry, material); shape->setMaterials(materials, 1);
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);
@ -283,167 +268,143 @@ namespace Prism
} }
} }
std::vector<physx::PxTriangleMesh*> PhysicsWrappers::CreateTriangleMesh(MeshColliderComponent& collider) std::vector<physx::PxShape*> PhysicsWrappers::CreateTriangleMesh(MeshColliderComponent& collider, const glm::vec3& scale)
{ {
std::vector<physx::PxTriangleMesh*> meshes; std::vector<physx::PxShape*> shapes;
// 设置烹饪参数,可以根据需要调整 // 设置烹饪参数,可以根据需要调整
physx::PxCookingParams cookingParams(s_Physics->getTolerancesScale()); physx::PxCookingParams cookingParams(s_Physics->getTolerancesScale());
// 可以添加额外的烹饪参数设置,如: // 可以添加额外的烹饪参数设置,如:
// cookingParams.meshPreprocessParams = physx::PxMeshPreprocessingFlag::eWELD_VERTICES; // cookingParams.meshPreprocessParams = physx::PxMeshPreprocessingFlag::eWELD_VERTICES;
// cookingParams.meshWeldTolerance = 0.01f; // cookingParams.meshWeldTolerance = 0.01f;
// 获取顶点和索引数据 // 获取顶点和索引数据
const std::vector<Vertex>& vertices = collider.CollisionMesh->GetStaticVertices(); const std::vector<Vertex>& vertices = collider.CollisionMesh->GetStaticVertices();
const std::vector<Index>& indices = collider.CollisionMesh->GetIndices(); const std::vector<Index>& indices = collider.CollisionMesh->GetIndices();
// 提取顶点位置 // 清空旧的处理网格
std::vector<glm::vec3> vertexPositions; collider.ProcessedMeshes.clear();
if (vertices[0].Position != glm::vec3()) {
vertexPositions.reserve(vertices.size());
for (const auto& vertex : vertices) {
vertexPositions.push_back(vertex.Position);
}
}
// 清空旧的处理网格 // 处理每个子网格
collider.ProcessedMeshes.clear(); for (const auto& submesh : collider.CollisionMesh->GetSubmeshes())
{
// 准备三角形网格描述
physx::PxTriangleMeshDesc triangleDesc;
triangleDesc.points.count = submesh.VertexCount;
triangleDesc.points.data = &vertices[submesh.BaseVertex];
triangleDesc.points.stride = sizeof(Vertex);
// 处理每个子网格 triangleDesc.triangles.count = submesh.IndexCount / 3;
for (const auto& submesh : collider.CollisionMesh->GetSubmeshes()) triangleDesc.triangles.data = &indices[submesh.BaseIndex / 3];
{ triangleDesc.triangles.stride = sizeof(Index); // 假设Index包含三个值
// 准备三角形网格描述
physx::PxTriangleMeshDesc triangleDesc;
triangleDesc.points.count = submesh.VertexCount;
triangleDesc.points.stride = sizeof(glm::vec3);
// 使用顶点位置数组或原始顶点数据 // 如果需要,设置三角形标志
if (!vertexPositions.empty()) { // triangleDesc.flags = physx::PxMeshFlag::e16_BIT_INDICES; // 如果使用16位索引
triangleDesc.points.data = &vertexPositions[submesh.BaseVertex];
} else {
triangleDesc.points.stride = sizeof(Vertex);
triangleDesc.points.data = &vertices[submesh.BaseVertex];
}
triangleDesc.triangles.count = submesh.IndexCount / 3; // 创建三角形网格
triangleDesc.triangles.data = &indices[submesh.BaseIndex / 3]; physx::PxTriangleMeshCookingResult::Enum result;
triangleDesc.triangles.stride = sizeof(Index); // 假设Index包含三个值 physx::PxTriangleMesh* triangleMesh = PxCreateTriangleMesh(
cookingParams,
triangleDesc,
*PxGetStandaloneInsertionCallback(),
&result
);
// 如果需要,设置三角形标志
// triangleDesc.flags = physx::PxMeshFlag::e16_BIT_INDICES; // 如果使用16位索引
// 创建三角形网格 if (!triangleMesh) {
physx::PxTriangleMeshCookingResult::Enum result; PM_CORE_ERROR("Failed to create triangle mesh for submesh: {0}", submesh.MeshName);
physx::PxTriangleMesh* triangleMesh = PxCreateTriangleMesh( continue;
cookingParams, }
triangleDesc,
*PxGetStandaloneInsertionCallback(),
&result
);
if (!triangleMesh) { glm::vec3 submeshTranslation, submeshRotation, submeshScale;
PM_CORE_ERROR("Failed to create triangle mesh for submesh: {0}", submesh.MeshName); Math::DecomposeTransform(submesh.LocalTransform, submeshTranslation, submeshRotation, submeshScale);
continue;
}
meshes.push_back(triangleMesh); auto triangleGeometry = physx::PxTriangleMeshGeometry(triangleMesh, physx::PxMeshScale(ToPhysXVector(submeshScale * scale)));
physx::PxMaterial* material = s_Physics->createMaterial(0, 0, 0); // Dummy material, will be replaced at runtime.
physx::PxShape* shape = s_Physics->createShape(triangleGeometry, *material, true);
shape->setLocalPose(ToPhysXTransform(submeshTranslation, submeshRotation));
// 为可视化生成渲染网格 shapes.push_back(shape);
if (collider.ProcessedMeshes.empty())
{
const uint32_t nbVerts = triangleMesh->getNbVertices();
const physx::PxVec3* meshVertices = triangleMesh->getVertices();
const uint32_t nbTriangles = triangleMesh->getNbTriangles();
std::vector<Vertex> processedVertices; // 为可视化生成渲染网格
std::vector<Index> processedIndices; {
const uint32_t nbVerts = triangleMesh->getNbVertices();
const physx::PxVec3* meshVertices = triangleMesh->getVertices();
const uint32_t nbTriangles = triangleMesh->getNbTriangles();
// 获取顶点数据 std::vector<Vertex> processedVertices;
processedVertices.reserve(nbVerts); std::vector<Index> processedIndices;
for (uint32_t v = 0; v < nbVerts; v++)
{
Vertex vertex;
vertex.Position = FromPhysXVector(meshVertices[v]);
processedVertices.push_back(vertex);
}
// 获取三角形索引 processedVertices.reserve(nbVerts);
processedIndices.reserve(nbTriangles); for (uint32_t v = 0; v < nbVerts; v++)
{
Vertex vertex{};
vertex.Position = FromPhysXVector(meshVertices[v]);
processedVertices.push_back(vertex);
}
// 检查索引格式16位或32位 processedIndices.reserve(nbTriangles);
if (triangleMesh->getTriangleMeshFlags() & physx::PxTriangleMeshFlag::e16_BIT_INDICES)
{
const physx::PxU16* tris = static_cast<const physx::PxU16*>(triangleMesh->getTriangles());
for (uint32_t tri = 0; tri < nbTriangles; tri++)
{
Index index;
index.V1 = tris[3 * tri + 0];
index.V2 = tris[3 * tri + 1];
index.V3 = tris[3 * tri + 2];
processedIndices.push_back(index);
}
}
else
{
const physx::PxU32* tris = static_cast<const physx::PxU32*>(triangleMesh->getTriangles());
for (uint32_t tri = 0; tri < nbTriangles; tri++)
{
Index index;
index.V1 = static_cast<uint32_t>(tris[3 * tri + 0]);
index.V2 = static_cast<uint32_t>(tris[3 * tri + 1]);
index.V3 = static_cast<uint32_t>(tris[3 * tri + 2]);
processedIndices.push_back(index);
}
}
// 为当前子网格创建渲染网格 // 检查索引格式16位或32位
collider.ProcessedMeshes.push_back(Ref<Mesh>::Create(processedVertices, processedIndices)); if (triangleMesh->getTriangleMeshFlags() & physx::PxTriangleMeshFlag::e16_BIT_INDICES)
} {
} const auto* tris = static_cast<const physx::PxU16*>(triangleMesh->getTriangles());
for (uint32_t tri = 0; tri < nbTriangles; tri++)
{
Index index{};
index.V1 = tris[3 * tri + 0];
index.V2 = tris[3 * tri + 1];
index.V3 = tris[3 * tri + 2];
processedIndices.push_back(index);
}
}
else
{
const auto* tris = static_cast<const physx::PxU32*>(triangleMesh->getTriangles());
for (uint32_t tri = 0; tri < nbTriangles; tri++)
{
Index index{};
index.V1 = static_cast<uint32_t>(tris[3 * tri + 0]);
index.V2 = static_cast<uint32_t>(tris[3 * tri + 1]);
index.V3 = static_cast<uint32_t>(tris[3 * tri + 2]);
processedIndices.push_back(index);
}
}
return meshes; glm::mat4 scale = glm::scale(glm::mat4(1.0f), *(glm::vec3*)&triangleGeometry.scale.scale);
glm::mat4 transform = FromPhysXTransform(shape->getLocalPose()) * scale;
collider.ProcessedMeshes.push_back(Ref<Mesh>::Create(vertices, indices, transform));
// collider.ProcessedMeshes.push_back(Ref<Mesh>::Create(processedVertices, processedIndices, FromPhysXTransform(shape->getLocalPose())));
}
}
return shapes;
} }
std::vector<physx::PxConvexMesh*> PhysicsWrappers::CreateConvexMesh(MeshColliderComponent& collider, const bool rotatedX) std::vector<physx::PxShape*> PhysicsWrappers::CreateConvexMesh(MeshColliderComponent& collider, const glm::vec3& scale)
{ {
std::vector<physx::PxConvexMesh*> meshes; std::vector<physx::PxShape*> shapes;
physx::PxCookingParams cookingParams(s_Physics->getTolerancesScale()); physx::PxCookingParams cookingParams(s_Physics->getTolerancesScale());
cookingParams.planeTolerance = 0.0F; // cookingParams.planeTolerance = 0.001f; // because of float accuracy, this value should not be zero, using default value now (0.0007f)
cookingParams.meshPreprocessParams = physx::PxMeshPreprocessingFlags(physx::PxMeshPreprocessingFlag::eWELD_VERTICES); cookingParams.meshPreprocessParams = physx::PxMeshPreprocessingFlags(physx::PxMeshPreprocessingFlag::eWELD_VERTICES);
cookingParams.meshWeldTolerance = 0.01f; cookingParams.meshWeldTolerance = 0.01f;
const std::vector<Vertex>& vertices = collider.CollisionMesh->GetStaticVertices(); const std::vector<Vertex>& vertices = collider.CollisionMesh->GetStaticVertices();
const std::vector<Index>& indices = collider.CollisionMesh->GetIndices(); const std::vector<Index>& indices = collider.CollisionMesh->GetIndices();
// prepare vertices
std::vector<glm::vec3> position;
if (rotatedX)
{
for (auto& vertex : vertices)
position.push_back(glm::rotate(vertex.Position, glm::radians(90.0f), { -1.0f, 0.0f, 0.0f }));
}else
{
for (auto& vertex : vertices)
position.push_back(vertex.Position);
}
// clear old meshes // clear old meshes
collider.ProcessedMeshes.clear(); collider.ProcessedMeshes.clear();
// 处理每个子网格 // process all submesh
for (const auto& submesh : collider.CollisionMesh->GetSubmeshes()) for (const auto& submesh : collider.CollisionMesh->GetSubmeshes())
{ {
// 准备凸包描述
physx::PxConvexMeshDesc convexDesc; physx::PxConvexMeshDesc convexDesc;
convexDesc.points.count = submesh.VertexCount; convexDesc.points.count = submesh.VertexCount;
convexDesc.points.stride = sizeof(glm::vec3); convexDesc.points.data = &vertices[submesh.BaseVertex];
convexDesc.points.stride = sizeof(Vertex);
// 使用顶点位置数组或原始顶点数据
convexDesc.points.data = &position[submesh.BaseVertex];
convexDesc.indices.count = submesh.IndexCount / 3; convexDesc.indices.count = submesh.IndexCount / 3;
convexDesc.indices.data = &indices[submesh.BaseIndex / 3]; convexDesc.indices.data = &indices[submesh.BaseIndex / 3];
@ -467,10 +428,15 @@ namespace Prism
continue; continue;
} }
meshes.push_back(convexMesh); auto convexGeometry = physx::PxConvexMeshGeometry(convexMesh, physx::PxMeshScale(ToPhysXVector(scale)));
convexGeometry.meshFlags = physx::PxConvexMeshGeometryFlag::eTIGHT_BOUNDS;
physx::PxMaterial* material = s_Physics->createMaterial(0, 0, 0); // Dummy material, will be replaced at runtime.
physx::PxShape* shape = s_Physics->createShape(convexGeometry, *material, true);
shape->setLocalPose(ToPhysXTransform(submesh.Transform));
shapes.push_back(shape);
// 为可视化生成渲染网格 // 为可视化生成渲染网格
if (collider.ProcessedMeshes.empty())
{ {
const uint32_t nbPolygons = convexMesh->getNbPolygons(); const uint32_t nbPolygons = convexMesh->getNbPolygons();
const physx::PxVec3* convexVertices = convexMesh->getVertices(); const physx::PxVec3* convexVertices = convexMesh->getVertices();
@ -495,8 +461,6 @@ namespace Prism
vertex.Position = FromPhysXVector( vertex.Position = FromPhysXVector(
convexVertices[convexIndices[polygon.mIndexBase + vI]] convexVertices[convexIndices[polygon.mIndexBase + vI]]
); );
// 如果需要坐标系转换,可以在这里添加
// vertex.Position = glm::rotate(vertex.Position, glm::radians(90.0f), {1.0f, 0.0f, 0.0f});
collisionVertices.push_back(vertex); collisionVertices.push_back(vertex);
vertCounter++; vertCounter++;
@ -514,11 +478,11 @@ namespace Prism
} }
} }
collider.ProcessedMeshes.push_back(Ref<Mesh>::Create(collisionVertices, collisionIndices)); collider.ProcessedMeshes.push_back(Ref<Mesh>::Create(collisionVertices, collisionIndices, FromPhysXTransform(shape->getLocalPose())));
} }
} }
return meshes; return shapes;
#if 0 #if 0
const auto& vertices = collider.CollisionMesh->GetStaticVertices(); const auto& vertices = collider.CollisionMesh->GetStaticVertices();
@ -624,7 +588,7 @@ namespace Prism
physx::PxOverlapBuffer buf(s_OverlapBuffer, OVERLAP_MAX_COLLIDERS); physx::PxOverlapBuffer buf(s_OverlapBuffer, OVERLAP_MAX_COLLIDERS);
const auto geometry = physx::PxBoxGeometry(halfSize.x, halfSize.y, halfSize.z); const auto geometry = physx::PxBoxGeometry(halfSize.x, halfSize.y, halfSize.z);
const physx::PxTransform pose = ToPhysXTransform(glm::translate(glm::mat4(1.0F), origin)); const physx::PxTransform pose = ToPhysXTransform(glm::translate(glm::mat4(1.0f), origin));
const bool result = scene->overlap(geometry, pose, buf); const bool result = scene->overlap(geometry, pose, buf);
@ -645,7 +609,7 @@ namespace Prism
memset(s_OverlapBuffer, 0, sizeof(s_OverlapBuffer)); memset(s_OverlapBuffer, 0, sizeof(s_OverlapBuffer));
physx::PxOverlapBuffer buf(s_OverlapBuffer, OVERLAP_MAX_COLLIDERS); physx::PxOverlapBuffer buf(s_OverlapBuffer, OVERLAP_MAX_COLLIDERS);
const auto geometry = physx::PxSphereGeometry(radius); const auto geometry = physx::PxSphereGeometry(radius);
const physx::PxTransform pose = ToPhysXTransform(glm::translate(glm::mat4(1.0F), origin)); const physx::PxTransform pose = ToPhysXTransform(glm::translate(glm::mat4(1.0f), origin));
const bool result = scene->overlap(geometry, pose, buf); const bool result = scene->overlap(geometry, pose, buf);
@ -666,7 +630,7 @@ namespace Prism
memset(s_OverlapBuffer, 0, sizeof(s_OverlapBuffer)); memset(s_OverlapBuffer, 0, sizeof(s_OverlapBuffer));
physx::PxOverlapBuffer buf(s_OverlapBuffer, OVERLAP_MAX_COLLIDERS); physx::PxOverlapBuffer buf(s_OverlapBuffer, OVERLAP_MAX_COLLIDERS);
const auto geometry = physx::PxCapsuleGeometry(radius, halfHeight); const auto geometry = physx::PxCapsuleGeometry(radius, halfHeight);
const physx::PxTransform pose = ToPhysXTransform(glm::translate(glm::mat4(1.0F), origin)); const physx::PxTransform pose = ToPhysXTransform(glm::translate(glm::mat4(1.0f), origin));
const bool result = scene->overlap(geometry, pose, buf); const bool result = scene->overlap(geometry, pose, buf);

View File

@ -40,10 +40,10 @@ namespace Prism
// static physx::PxRigidActor* CreateActor(const RigidBodyComponent& rigidbody, const TransformComponent& transformComponent); // static physx::PxRigidActor* CreateActor(const RigidBodyComponent& rigidbody, const TransformComponent& transformComponent);
// static void SetCollisionFilters(const physx::PxRigidActor& actor, uint32_t physicsLayer); // static void SetCollisionFilters(const physx::PxRigidActor& actor, uint32_t physicsLayer);
static void AddBoxCollider(PhysicsActor& actor, const physx::PxMaterial& material); static void AddBoxCollider(PhysicsActor& actor);
static void AddSphereCollider(PhysicsActor& actor, const physx::PxMaterial& material); static void AddSphereCollider(PhysicsActor& actor);
static void AddCapsuleCollider(PhysicsActor& actor, const physx::PxMaterial& material); static void AddCapsuleCollider(PhysicsActor& actor);
static void AddMeshCollider(PhysicsActor& actor, const physx::PxMaterial& material); static void AddMeshCollider(PhysicsActor& actor);
// 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));
@ -51,8 +51,8 @@ namespace Prism
// 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 std::vector<physx::PxTriangleMesh*> CreateTriangleMesh(MeshColliderComponent& collider); static std::vector<physx::PxShape*> CreateTriangleMesh(MeshColliderComponent& collider, const glm::vec3& scale = glm::vec3(1.0f));
static std::vector<physx::PxConvexMesh*> CreateConvexMesh(MeshColliderComponent& collider, bool rotatedX = false); static std::vector<physx::PxShape*> CreateConvexMesh(MeshColliderComponent& collider, const glm::vec3& scale = glm::vec3(1.0f));
// static physx::PxMaterial* CreateMaterial(const PhysicsMaterialComponent& material); // static physx::PxMaterial* CreateMaterial(const PhysicsMaterialComponent& material);

View File

@ -156,7 +156,7 @@ namespace Prism
glClearColor(r, g, b, a); glClearColor(r, g, b, a);
} }
void RendererAPI::DrawIndexed(uint32_t count, PrimitiveType type, bool depthTest) void RendererAPI::DrawIndexed(uint32_t count, PrimitiveType type, bool depthTest, bool faceCulling)
{ {
if (!depthTest) if (!depthTest)
glDisable(GL_DEPTH_TEST); glDisable(GL_DEPTH_TEST);
@ -172,6 +172,11 @@ namespace Prism
break; break;
} }
if (faceCulling)
glEnable(GL_CULL_FACE);
else
glDisable(GL_CULL_FACE);
glDrawElements(glPrimitiveType, count, GL_UNSIGNED_INT, nullptr); glDrawElements(glPrimitiveType, count, GL_UNSIGNED_INT, nullptr);
if (!depthTest) if (!depthTest)

View File

@ -57,7 +57,7 @@ namespace Prism {
m_Size = size; m_Size = size;
Ref<OpenGLVertexBuffer> instance = this; Ref<OpenGLVertexBuffer> instance = this;
Renderer::Submit([instance, offset]() { Renderer::Submit([instance, offset]() {
glNamedBufferSubData(instance->m_RendererID, offset, instance->m_Size, instance->m_LocalData.Data); glNamedBufferSubData(instance->m_RendererID, offset, instance->m_LocalData.Size, instance->m_LocalData.Data);
}); });
} }

View File

@ -508,14 +508,14 @@ namespace Prism
m_Pipeline = Pipeline::Create(pipelineSpecification); m_Pipeline = Pipeline::Create(pipelineSpecification);
} }
Mesh::Mesh(const std::vector<Vertex>& vertices, const std::vector<Index>& indices) Mesh::Mesh(const std::vector<Vertex>& vertices, const std::vector<Index>& indices, const glm::mat4& transform)
: m_StaticVertices(vertices), m_Indices(indices), m_IsAnimated(false) : m_StaticVertices(vertices), m_Indices(indices), m_Scene(nullptr)
{ {
Submesh submesh; Submesh submesh;
submesh.BaseVertex = 0; submesh.BaseVertex = 0;
submesh.BaseIndex = 0; submesh.BaseIndex = 0;
submesh.IndexCount = static_cast<uint32_t>(indices.size()) * 3; submesh.IndexCount = static_cast<uint32_t>(indices.size()) * 3;
submesh.Transform = glm::mat4(1.0F); submesh.Transform = transform;
m_Submeshes.push_back(submesh); m_Submeshes.push_back(submesh);
m_VertexBuffer = VertexBuffer::Create(m_StaticVertices.data(), static_cast<uint32_t>(m_StaticVertices.size()) * sizeof(Vertex)); m_VertexBuffer = VertexBuffer::Create(m_StaticVertices.data(), static_cast<uint32_t>(m_StaticVertices.size()) * sizeof(Vertex));
@ -640,18 +640,20 @@ namespace Prism
void Mesh::TraverseNodes(const aiNode* node, const glm::mat4& parentTransform, uint32_t level) void Mesh::TraverseNodes(const aiNode* node, const glm::mat4& parentTransform, uint32_t level)
{ {
const glm::mat4 transform = parentTransform * Mat4FromAssimpMat4(node->mTransformation); const glm::mat4 localTransform = parentTransform * Mat4FromAssimpMat4(node->mTransformation);
glm::mat4 transform = parentTransform * localTransform;
for (uint32_t i = 0; i < node->mNumMeshes; i++) for (uint32_t i = 0; i < node->mNumMeshes; i++)
{ {
const uint32_t mesh = node->mMeshes[i]; const uint32_t mesh = node->mMeshes[i];
auto& submesh = m_Submeshes[mesh]; auto& submesh = m_Submeshes[mesh];
submesh.NodeName = node->mName.C_Str(); submesh.NodeName = node->mName.C_Str();
submesh.Transform = transform; submesh.Transform = transform;
submesh.LocalTransform = localTransform;
} }
for (uint32_t i = 0; i < node->mNumChildren; i++) for (uint32_t i = 0; i < node->mNumChildren; i++)
{ {
TraverseNodes(node->mChildren[i], transform, level + 1); TraverseNodes(node->mChildren[i], localTransform, level + 1);
} }
} }

View File

@ -97,6 +97,7 @@ namespace Prism
uint32_t VertexCount; uint32_t VertexCount;
glm::mat4 Transform; glm::mat4 Transform;
glm::mat4 LocalTransform;
AABB BoundingBox; AABB BoundingBox;
std::string NodeName, MeshName; std::string NodeName, MeshName;
@ -108,7 +109,7 @@ namespace Prism
Mesh(const std::string& filename); Mesh(const std::string& filename);
Mesh(const std::vector<Vertex>& vertices, const std::vector<Index>& indices); Mesh(const std::vector<Vertex>& vertices, const std::vector<Index>& indices, const glm::mat4& transform);
~Mesh(); ~Mesh();
void OnUpdate(TimeStep deltaTime); void OnUpdate(TimeStep deltaTime);

View File

@ -45,7 +45,7 @@ namespace Prism
{ 6, 7, 3 } { 6, 7, 3 }
}; };
return Ref<Mesh>::Create(vertices, indices); return Ref<Mesh>::Create(vertices, indices, glm::mat4(1.0f));
} }
Prism::Ref<Prism::Mesh> MeshFactory::CreateSphere(float radius) Prism::Ref<Prism::Mesh> MeshFactory::CreateSphere(float radius)
@ -87,7 +87,7 @@ namespace Prism
} }
} }
return Ref<Mesh>::Create(vertices, indices); return Ref<Mesh>::Create(vertices, indices, glm::mat4(1.0f));
} }
Ref<Mesh> MeshFactory::CreateCapsule(float radius, float height) Ref<Mesh> MeshFactory::CreateCapsule(float radius, float height)
@ -166,7 +166,7 @@ namespace Prism
} }
} }
return Ref<Mesh>::Create(vertices, indices); return Ref<Mesh>::Create(vertices, indices, glm::mat4(1.0f));
} }
} }

View File

@ -81,10 +81,10 @@ namespace Prism
{ {
} }
void Renderer::DrawIndexed(const uint32_t count, const PrimitiveType type, const bool depthTest) void Renderer::DrawIndexed(const uint32_t count, const PrimitiveType type, const bool depthTest, bool cullFace)
{ {
Submit([=]() { Submit([=]() {
RendererAPI::DrawIndexed(count, type, depthTest); RendererAPI::DrawIndexed(count, type, depthTest, cullFace);
}); });
} }
@ -147,16 +147,11 @@ namespace Prism
shader->SetMat4("u_Transform", transform); shader->SetMat4("u_Transform", transform);
} }
if (cullFace)
Submit([]() { glEnable(GL_CULL_FACE); });
else
Submit([]() { glDisable(GL_CULL_FACE); });
s_Data.m_FullscreenQuadVertexBuffer->Bind(); s_Data.m_FullscreenQuadVertexBuffer->Bind();
s_Data.m_FullscreenQuadPipeline->Bind(); s_Data.m_FullscreenQuadPipeline->Bind();
s_Data.m_FullscreenQuadIndexBuffer->Bind(); s_Data.m_FullscreenQuadIndexBuffer->Bind();
DrawIndexed(6, PrimitiveType::Triangles, depthTest); DrawIndexed(6, PrimitiveType::Triangles, depthTest, cullFace);
} }
void Renderer::SubmitFullscreenQuad(Ref<MaterialInstance> material) void Renderer::SubmitFullscreenQuad(Ref<MaterialInstance> material)
@ -170,16 +165,11 @@ namespace Prism
cullFace = !material->GetFlag(MaterialFlag::TwoSided); cullFace = !material->GetFlag(MaterialFlag::TwoSided);
} }
if (cullFace)
Submit([]() { glEnable(GL_CULL_FACE); });
else
Submit([]() { glDisable(GL_CULL_FACE); });
s_Data.m_FullscreenQuadVertexBuffer->Bind(); s_Data.m_FullscreenQuadVertexBuffer->Bind();
s_Data.m_FullscreenQuadPipeline->Bind(); s_Data.m_FullscreenQuadPipeline->Bind();
s_Data.m_FullscreenQuadIndexBuffer->Bind(); s_Data.m_FullscreenQuadIndexBuffer->Bind();
Renderer::DrawIndexed(6, PrimitiveType::Triangles, depthTest); Renderer::DrawIndexed(6, PrimitiveType::Triangles, depthTest, cullFace);
} }
void Renderer::SubmitMesh(Ref<Mesh>& mesh, const glm::mat4& transform, const Ref<MaterialInstance>& overrideMaterial) void Renderer::SubmitMesh(Ref<Mesh>& mesh, const glm::mat4& transform, const Ref<MaterialInstance>& overrideMaterial)

View File

@ -25,7 +25,7 @@ namespace Prism
static Ref<ShaderLibrary> GetShaderLibrary(); static Ref<ShaderLibrary> GetShaderLibrary();
static void DrawIndexed(uint32_t count, PrimitiveType type, bool depthTest = true); static void DrawIndexed(uint32_t count, PrimitiveType type, bool depthTest = true, bool faceCulling = true);
// For OpenGL // For OpenGL
static void SetLineThickness(float thickness); static void SetLineThickness(float thickness);

View File

@ -42,7 +42,7 @@ namespace Prism
static void Clear(float r, float g, float b, float a); static void Clear(float r, float g, float b, float a);
static void SetClearColor(float r, float g, float b, float a); static void SetClearColor(float r, float g, float b, float a);
static void DrawIndexed(uint32_t count,PrimitiveType type, bool depthTest = true); static void DrawIndexed(uint32_t count,PrimitiveType type, bool depthTest = true, bool faceCulling = true);
static void SetLineThickness(float thickness); static void SetLineThickness(float thickness);
static RendererAPIType Current() { return s_CurrentRendererAPI; } static RendererAPIType Current() { return s_CurrentRendererAPI; }

View File

@ -439,8 +439,8 @@ namespace Prism
// s_Data.SceneInfo.EnvironmentIrradianceMap->Bind(0); // s_Data.SceneInfo.EnvironmentIrradianceMap->Bind(0);
Renderer::SubmitFullscreenQuad(s_Data.SceneData.SkyboxMaterial); Renderer::SubmitFullscreenQuad(s_Data.SceneData.SkyboxMaterial);
const float aspectRatio = (float)s_Data.GeoPass->GetSpecification().TargetFramebuffer->GetWidth() / (float)s_Data.GeoPass->GetSpecification().TargetFramebuffer->GetHeight(); // const float aspectRatio = (float)s_Data.GeoPass->GetSpecification().TargetFramebuffer->GetWidth() / (float)s_Data.GeoPass->GetSpecification().TargetFramebuffer->GetHeight();
float frustumSize = 2.0f * sceneCamera.Near * glm::tan(sceneCamera.FOV * 0.5f) * aspectRatio; // float frustumSize = 2.0f * sceneCamera.Near * glm::tan(sceneCamera.FOV * 0.5f) * aspectRatio;
// Render entities // Render entities
for (auto& dc : s_Data.DrawList) for (auto& dc : s_Data.DrawList)
@ -858,6 +858,18 @@ namespace Prism
glm::mat4 lightViewMatrix = glm::lookAt(frustumCenter - lightDir * -minExtents.z, frustumCenter, glm::vec3(0.0f, 0.0f, 1.0f)); glm::mat4 lightViewMatrix = glm::lookAt(frustumCenter - lightDir * -minExtents.z, frustumCenter, glm::vec3(0.0f, 0.0f, 1.0f));
glm::mat4 lightOrthoMatrix = glm::ortho(minExtents.x, maxExtents.x, minExtents.y, maxExtents.y, 0.0f + s_Data.CascadeNearPlaneOffset, maxExtents.z - minExtents.z + s_Data.CascadeFarPlaneOffset); glm::mat4 lightOrthoMatrix = glm::ortho(minExtents.x, maxExtents.x, minExtents.y, maxExtents.y, 0.0f + s_Data.CascadeNearPlaneOffset, maxExtents.z - minExtents.z + s_Data.CascadeFarPlaneOffset);
// Offset to texel space to avoid shimmering (from https://stackoverflow.com/questions/33499053/cascaded-shadow-map-shimmering)
glm::mat4 shadowMatrix = lightOrthoMatrix * lightViewMatrix;
constexpr float ShadowMapResolution = 4096.0f;
glm::vec4 shadowOrigin = (shadowMatrix * glm::vec4(0.0f, 0.0f, 0.0f, 1.0f)) * ShadowMapResolution / 2.0f;
glm::vec4 roundedOrigin = glm::round(shadowOrigin);
glm::vec4 roundOffset = roundedOrigin - shadowOrigin;
roundOffset = roundOffset * 2.0f / ShadowMapResolution;
roundOffset.z = 0.0f;
roundOffset.w = 0.0f;
lightOrthoMatrix[3] += roundOffset;
// Store split distance and matrix in cascade // Store split distance and matrix in cascade
cascades[i].SplitDepth = (nearClip + splitDist * clipRange) * -1.0f; cascades[i].SplitDepth = (nearClip + splitDist * clipRange) * -1.0f;
cascades[i].ViewProj = lightOrthoMatrix * lightViewMatrix; cascades[i].ViewProj = lightOrthoMatrix * lightViewMatrix;

View File

@ -230,8 +230,8 @@ namespace Prism
Ref<Prism::Mesh> CollisionMesh; Ref<Prism::Mesh> CollisionMesh;
std::vector<Ref<Prism::Mesh>> ProcessedMeshes; std::vector<Ref<Prism::Mesh>> ProcessedMeshes;
bool IsConvex = false; bool IsConvex = false;
bool IsTrigger = false; bool IsTrigger = false;
bool OverrideMesh = false;
MeshColliderComponent() = default; MeshColliderComponent() = default;
MeshColliderComponent(const MeshColliderComponent& other) = default; MeshColliderComponent(const MeshColliderComponent& other) = default;

View File

@ -339,12 +339,10 @@ namespace Prism
meshComponent.Mesh->OnUpdate(ts); meshComponent.Mesh->OnUpdate(ts);
// TODO: Should we render (logically) // TODO: Should we render (logically)
SceneRenderer::SubmitMesh(meshComponent, transformComponent.GetTransform());
if (m_SelectedEntity == entity) if (m_SelectedEntity == entity)
{
SceneRenderer::SubmitSelectedMesh(meshComponent, transformComponent.GetTransform()); SceneRenderer::SubmitSelectedMesh(meshComponent, transformComponent.GetTransform());
} else
SceneRenderer::SubmitMesh(meshComponent, transformComponent.GetTransform());
} }
} }

View File

@ -4,6 +4,8 @@
#include "SceneSerializer.h" #include "SceneSerializer.h"
#include <filesystem>
#include "yaml-cpp/yaml.h" #include "yaml-cpp/yaml.h"
#include "Prism/Script/ScriptEngine.h" #include "Prism/Script/ScriptEngine.h"
@ -277,7 +279,17 @@ namespace Prism
out << YAML::BeginMap; // CameraComponent out << YAML::BeginMap; // CameraComponent
const auto& cameraComponent = entity.GetComponent<CameraComponent>(); const auto& cameraComponent = entity.GetComponent<CameraComponent>();
out << YAML::Key << "Camera" << YAML::Value << "some camera data..."; auto& camera = cameraComponent.Camera;
out << YAML::Key << "Camera" << YAML::Value;
out << YAML::BeginMap; // Camera
out << YAML::Key << "ProjectionType" << YAML::Value << static_cast<int>(camera.GetProjectionType());
out << YAML::Key << "PerspectiveFOV" << YAML::Value << camera.GetPerspectiveVerticalFOV();
out << YAML::Key << "PerspectiveNear" << YAML::Value << camera.GetPerspectiveNearClip();
out << YAML::Key << "PerspectiveFar" << YAML::Value << camera.GetPerspectiveFarClip();
out << YAML::Key << "OrthographicSize" << YAML::Value << camera.GetOrthographicSize();
out << YAML::Key << "OrthographicNear" << YAML::Value << camera.GetOrthographicNearClip();
out << YAML::Key << "OrthographicFar" << YAML::Value << camera.GetOrthographicFarClip();
out << YAML::EndMap; // Camera
out << YAML::Key << "Primary" << YAML::Value << cameraComponent.Primary; out << YAML::Key << "Primary" << YAML::Value << cameraComponent.Primary;
out << YAML::EndMap; // CameraComponent out << YAML::EndMap; // CameraComponent
@ -425,9 +437,13 @@ namespace Prism
out << YAML::BeginMap; // MeshColliderComponent out << YAML::BeginMap; // MeshColliderComponent
auto meshColliderComponent = entity.GetComponent<MeshColliderComponent>(); auto meshColliderComponent = entity.GetComponent<MeshColliderComponent>();
out << YAML::Key << "AssetPath" << YAML::Value << meshColliderComponent.CollisionMesh->GetFilePath();
if (meshColliderComponent.OverrideMesh)
out << YAML::Key << "AssetPath" << YAML::Value << meshColliderComponent.CollisionMesh->GetFilePath();
out << YAML::Key << "IsConvex" << YAML::Value << meshColliderComponent.IsConvex; out << YAML::Key << "IsConvex" << YAML::Value << meshColliderComponent.IsConvex;
out << YAML::Key << "IsTrigger" << YAML::Value << meshColliderComponent.IsTrigger; out << YAML::Key << "IsTrigger" << YAML::Value << meshColliderComponent.IsTrigger;
out << YAML::Key << "OverrideMesh" << YAML::Value << meshColliderComponent.OverrideMesh;
out << YAML::EndMap; // MeshColliderComponent out << YAML::EndMap; // MeshColliderComponent
} }
@ -505,12 +521,19 @@ namespace Prism
PM_CORE_ASSERT(false); PM_CORE_ASSERT(false);
} }
bool CheckPath(const std::string& path)
{
return std::filesystem::exists(path);
}
bool SceneSerializer::Deserialize(const std::string& filepath) bool SceneSerializer::Deserialize(const std::string& filepath)
{ {
std::ifstream stream(filepath); std::ifstream stream(filepath);
std::stringstream strStream; std::stringstream strStream;
strStream << stream.rdbuf(); strStream << stream.rdbuf();
std::vector<std::string> missingPaths;
YAML::Node data = YAML::Load(strStream.str()); YAML::Node data = YAML::Load(strStream.str());
if (!data["Scene"]) if (!data["Scene"])
return false; return false;
@ -557,7 +580,20 @@ namespace Prism
auto& transform = deserializedEntity.GetComponent<TransformComponent>(); auto& transform = deserializedEntity.GetComponent<TransformComponent>();
transform.Translation = transformComponent["Position"].as<glm::vec3>(); transform.Translation = transformComponent["Position"].as<glm::vec3>();
transform.Rotation = transformComponent["Rotation"].as<glm::vec3>(); // transform.Rotation = transformComponent["Rotation"].as<glm::vec3>();
const auto& rotationNode = transformComponent["Rotation"];
if (rotationNode.size() == 4)
{
auto rotation = transformComponent["Rotation"].as<glm::quat>();
transform.Rotation = glm::eulerAngles(rotation);
}
else
{
PM_CORE_ASSERT(rotationNode.size() == 3);
transform.Rotation = transformComponent["Rotation"].as<glm::vec3>();
}
transform.Scale = transformComponent["Scale"].as<glm::vec3>(); transform.Scale = transformComponent["Scale"].as<glm::vec3>();
PM_CORE_INFO("Entity Transform:"); PM_CORE_INFO("Entity Transform:");
@ -642,7 +678,15 @@ namespace Prism
const std::string meshPath = meshComponent["AssetPath"].as<std::string>(); const std::string meshPath = meshComponent["AssetPath"].as<std::string>();
// TEMP (because script creates mesh component...) // TEMP (because script creates mesh component...)
if (!deserializedEntity.HasComponent<MeshComponent>()) if (!deserializedEntity.HasComponent<MeshComponent>())
deserializedEntity.AddComponent<MeshComponent>(Ref<Mesh>::Create(meshPath)); {
Ref<Mesh> mesh;
if (!CheckPath(meshPath))
missingPaths.emplace_back(meshPath);
else
mesh = Ref<Mesh>::Create(meshPath);
deserializedEntity.AddComponent<MeshComponent>(mesh);
}
PM_CORE_INFO(" Mesh Asset Path: {0}", meshPath); PM_CORE_INFO(" Mesh Asset Path: {0}", meshPath);
} }
@ -661,7 +705,16 @@ namespace Prism
auto& component = deserializedEntity.AddComponent<SkyLightComponent>(); auto& component = deserializedEntity.AddComponent<SkyLightComponent>();
const std::string env = skyLightComponent["EnvironmentAssetPath"].as<std::string>(); const std::string env = skyLightComponent["EnvironmentAssetPath"].as<std::string>();
if (!env.empty()) if (!env.empty())
component.SceneEnvironment = Environment::Load(env); {
if (!CheckPath(env))
{
missingPaths.emplace_back(env);
}
else
{
component.SceneEnvironment = Environment::Load(env);
}
}
component.Intensity = skyLightComponent["Intensity"].as<float>(); component.Intensity = skyLightComponent["Intensity"].as<float>();
component.Angle = skyLightComponent["Angle"].as<float>(); component.Angle = skyLightComponent["Angle"].as<float>();
} }
@ -669,10 +722,25 @@ namespace Prism
if (auto cameraComponent = entity["CameraComponent"]) if (auto cameraComponent = entity["CameraComponent"])
{ {
auto& component = deserializedEntity.AddComponent<CameraComponent>(); auto& component = deserializedEntity.AddComponent<CameraComponent>();
component.Camera = SceneCamera(); const auto& cameraNode = cameraComponent["Camera"];
component.Primary = cameraComponent["Primary"].as<bool>();
PM_CORE_INFO(" Primary Camera: {0}", component.Primary); auto& camera = component.Camera;
if (cameraNode["ProjectionType"])
camera.SetProjectionType(static_cast<SceneCamera::ProjectionType>(cameraNode["ProjectionType"].as<int>()));
if (cameraNode["PerspectiveFOV"])
camera.SetPerspectiveVerticalFOV(cameraNode["PerspectiveFOV"].as<float>());
if (cameraNode["PerspectiveNear"])
camera.SetPerspectiveNearClip(cameraNode["PerspectiveNear"].as<float>());
if (cameraNode["PerspectiveFar"])
camera.SetPerspectiveFarClip(cameraNode["PerspectiveFar"].as<float>());
if (cameraNode["OrthographicSize"])
camera.SetOrthographicSize(cameraNode["OrthographicSize"].as<float>());
if (cameraNode["OrthographicNear"])
camera.SetOrthographicNearClip(cameraNode["OrthographicNear"].as<float>());
if (cameraNode["OrthographicFar"])
camera.SetOrthographicFarClip(cameraNode["OrthographicFar"].as<float>());
component.Primary = cameraComponent["Primary"].as<bool>();
} }
if (auto spriteRendererComponent = entity["SpriteRendererComponent"]) if (auto spriteRendererComponent = entity["SpriteRendererComponent"])
@ -767,16 +835,39 @@ namespace Prism
if (auto meshColliderComponent = entity["MeshColliderComponent"]) if (auto meshColliderComponent = entity["MeshColliderComponent"])
{ {
auto meshPath = meshColliderComponent["AssetPath"].as<std::string>(); Ref<Mesh> collisionMesh = deserializedEntity.HasComponent<MeshComponent>() ? deserializedEntity.GetComponent<MeshComponent>().Mesh : nullptr;
auto& component = deserializedEntity.AddComponent<MeshColliderComponent>(Ref<Mesh>::Create(meshPath)); bool overrideMesh = meshColliderComponent["OverrideMesh"] ? meshColliderComponent["OverrideMesh"].as<bool>() : false;
component.IsConvex = meshColliderComponent["IsConvex"] ? meshColliderComponent["IsConvex"].as<bool>() : false;
component.IsTrigger = meshColliderComponent["IsTrigger"] ? meshColliderComponent["IsTrigger"].as<bool>() : false;
if (component.IsConvex)
PhysicsWrappers::CreateConvexMesh(component);
else
PhysicsWrappers::CreateTriangleMesh(component);
PM_CORE_INFO(" Mesh Collider Asset Path: {0}", meshPath); if (overrideMesh)
{
auto meshPath = meshColliderComponent["AssetPath"].as<std::string>();
if (!CheckPath(meshPath))
{
missingPaths.emplace_back(meshPath);
}
else
{
collisionMesh = Ref<Mesh>::Create(meshPath);
}
collisionMesh = Ref<Mesh>::Create(meshPath);
}
if (collisionMesh)
{
auto& component = deserializedEntity.AddComponent<MeshColliderComponent>(collisionMesh);
component.IsConvex = meshColliderComponent["IsConvex"] ? meshColliderComponent["IsConvex"].as<bool>() : false;
component.IsTrigger = meshColliderComponent["IsTrigger"] ? meshColliderComponent["IsTrigger"].as<bool>() : false;
component.OverrideMesh = overrideMesh;
if (component.IsConvex)
PhysicsWrappers::CreateConvexMesh(component, deserializedEntity.Transform().Scale);
else
PhysicsWrappers::CreateTriangleMesh(component, deserializedEntity.Transform().Scale);
}
else
{
PM_CORE_WARN("MeshColliderComponent in use without valid mesh!");
}
} }
} }
} }
@ -805,6 +896,17 @@ namespace Prism
} }
} }
if (missingPaths.size())
{
PM_CORE_ERROR("The following files could not be loaded:");
for (auto& path : missingPaths)
{
PM_CORE_ERROR(" {0}", path);
}
return false;
}
return true; return true;
} }

View File

@ -68,6 +68,12 @@ namespace Prism
mono_add_internal_call("Prism.TransformComponent::GetTransform_Native", (const void*)Prism::Script::Prism_TransformComponent_GetTransform); mono_add_internal_call("Prism.TransformComponent::GetTransform_Native", (const void*)Prism::Script::Prism_TransformComponent_GetTransform);
mono_add_internal_call("Prism.TransformComponent::SetTransform_Native", (const void*)Prism::Script::Prism_TransformComponent_SetTransform); mono_add_internal_call("Prism.TransformComponent::SetTransform_Native", (const void*)Prism::Script::Prism_TransformComponent_SetTransform);
mono_add_internal_call("Prism.TransformComponent::GetTranslation_Native", (const void*)Prism::Script::Prism_TransformComponent_GetTranslation);
mono_add_internal_call("Prism.TransformComponent::SetTranslation_Native", (const void*)Prism::Script::Prism_TransformComponent_SetTranslation);
mono_add_internal_call("Prism.TransformComponent::GetRotation_Native", (const void*)Prism::Script::Prism_TransformComponent_GetRotation);
mono_add_internal_call("Prism.TransformComponent::SetRotation_Native", (const void*)Prism::Script::Prism_TransformComponent_SetRotation);
mono_add_internal_call("Prism.TransformComponent::GetScale_Native", (const void*)Prism::Script::Prism_TransformComponent_GetScale);
mono_add_internal_call("Prism.TransformComponent::SetScale_Native", (const void*)Prism::Script::Prism_TransformComponent_SetScale);
/* /*

View File

@ -311,7 +311,6 @@ namespace Prism { namespace Script {
uint64_t Prism_Entity_FindEntityByTag(MonoString* tag) uint64_t Prism_Entity_FindEntityByTag(MonoString* tag)
{ {
size_t a = sizeof(ScriptTransform);
Ref<Scene> scene = ScriptEngine::GetCurrentSceneContext(); Ref<Scene> scene = ScriptEngine::GetCurrentSceneContext();
PM_CORE_ASSERT(scene, "No active scene!"); PM_CORE_ASSERT(scene, "No active scene!");
@ -322,6 +321,7 @@ namespace Prism { namespace Script {
return 0; return 0;
} }
/* /*
void Prism_TransformComponent_GetRelativeDirection(const uint64_t entityID, glm::vec3* outDirection, const glm::vec3* inAbsoluteDirection) void Prism_TransformComponent_GetRelativeDirection(const uint64_t entityID, glm::vec3* outDirection, const glm::vec3* inAbsoluteDirection)
{ {
@ -376,13 +376,15 @@ namespace Prism { namespace Script {
PM_CORE_ASSERT(entityMap.find(entityID) != entityMap.end(), "Invalid entity ID or entity doesn't exist in scene!"); PM_CORE_ASSERT(entityMap.find(entityID) != entityMap.end(), "Invalid entity ID or entity doesn't exist in scene!");
Entity entity = entityMap.at(entityID); Entity entity = entityMap.at(entityID);
const auto& transform = entity.GetComponent<TransformComponent>();
const auto transform = entity.GetComponent<TransformComponent>();
const glm::quat rotation = glm::quat(transform.Rotation); const glm::quat rotation = glm::quat(transform.Rotation);
const glm::vec3 right = glm::normalize(glm::rotate(rotation, glm::vec3(1.0f, 0.0f, 0.0f))); const glm::vec3 right = glm::normalize(glm::rotate(rotation, glm::vec3(1.0f, 0.0f, 0.0f)));
const glm::vec3 up = glm::normalize(glm::rotate(rotation, glm::vec3(0.0f, 1.0f, 0.0f))); const glm::vec3 up = glm::normalize(glm::rotate(rotation, glm::vec3(0.0f, 1.0f, 0.0f)));
const glm::vec3 forward = glm::normalize(glm::rotate(rotation, glm::vec3(0.0f, 0.0f, -1.0f))); const glm::vec3 forward = glm::normalize(glm::rotate(rotation, glm::vec3(0.0f, 0.0f, -1.0f)));
*outTransform = { *outTransform = {
transform.Translation, glm::degrees(transform.Rotation), transform.Scale, transform.Translation, glm::degrees(transform.Rotation), transform.Scale,
up, right, forward up, right, forward
@ -397,13 +399,104 @@ namespace Prism { namespace Script {
PM_CORE_ASSERT(entityMap.find(entityID) != entityMap.end(), "Invalid entity ID or entity doesn't exist in scene!"); PM_CORE_ASSERT(entityMap.find(entityID) != entityMap.end(), "Invalid entity ID or entity doesn't exist in scene!");
Entity entity = entityMap.at(entityID); Entity entity = entityMap.at(entityID);
auto& transform = entity.GetComponent<TransformComponent>();
auto transform = entity.GetComponent<TransformComponent>();
transform.Translation = inTransform->Translation; transform.Translation = inTransform->Translation;
transform.Rotation = glm::radians(inTransform->Rotation); transform.Rotation = glm::radians(inTransform->Rotation);
transform.Scale = inTransform->Scale; transform.Scale = inTransform->Scale;
} }
/*
void Prism_TransformComponent_GetTransform(const uint64_t entityID, TransformComponent* outTransform)
{
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);
*outTransform = entity.GetComponent<TransformComponent>();
}
void Prism_TransformComponent_SetTransform(const uint64_t entityID, const TransformComponent* inTransform)
{
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);
entity.GetComponent<TransformComponent>() = *inTransform;
}
*/
void Prism_TransformComponent_GetTranslation(const uint64_t entityID, glm::vec3* outTranslation)
{
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);
*outTranslation = entity.GetComponent<TransformComponent>().Translation;
}
void Prism_TransformComponent_SetTranslation(const uint64_t entityID, const glm::vec3* inTranslation)
{
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);
entity.GetComponent<TransformComponent>().Translation = *inTranslation;
}
void Prism_TransformComponent_GetRotation(const uint64_t entityID, glm::vec3* outRotation)
{
Ref<Scene> scene = ScriptEngine::GetCurrentSceneContext();
PM_CORE_ASSERT(scene, "No active scene!");
const auto& entityMap = scene->GetEntityMap();
PM_CORE_ASSERT(entityMap.find(entityID) != entityMap.end(), "Invalid entity ID or entity doesn't exist in scene!");
Entity entity = entityMap.at(entityID);
*outRotation = glm::degrees(entity.GetComponent<TransformComponent>().Rotation);
}
void Prism_TransformComponent_SetRotation(const uint64_t entityID, const glm::vec3* inRotation)
{
Ref<Scene> scene = ScriptEngine::GetCurrentSceneContext();
PM_CORE_ASSERT(scene, "No active scene!");
const auto& entityMap = scene->GetEntityMap();
PM_CORE_ASSERT(entityMap.find(entityID) != entityMap.end(), "Invalid entity ID or entity doesn't exist in scene!");
Entity entity = entityMap.at(entityID);
entity.GetComponent<TransformComponent>().Rotation = glm::radians(*inRotation);
}
void Prism_TransformComponent_GetScale(uint64_t entityID, glm::vec3* outScale)
{
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);
*outScale = entity.GetComponent<TransformComponent>().Scale;
}
void Prism_TransformComponent_SetScale(const uint64_t entityID, const glm::vec3* inScale)
{
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);
entity.GetComponent<TransformComponent>().Scale = *inScale;
}
void* Prism_MeshComponent_GetMesh(const uint64_t entityID) void* Prism_MeshComponent_GetMesh(const uint64_t entityID)
{ {
Ref<Scene> scene = ScriptEngine::GetCurrentSceneContext(); Ref<Scene> scene = ScriptEngine::GetCurrentSceneContext();

View File

@ -59,6 +59,12 @@ namespace Prism { namespace Script {
*/ */
void Prism_TransformComponent_GetTransform(uint64_t entityID, ScriptTransform* outTransform); void Prism_TransformComponent_GetTransform(uint64_t entityID, ScriptTransform* outTransform);
void Prism_TransformComponent_SetTransform(uint64_t entityID, const ScriptTransform* inTransform); void Prism_TransformComponent_SetTransform(uint64_t entityID, const ScriptTransform* inTransform);
void Prism_TransformComponent_GetTranslation(uint64_t entityID, glm::vec3* outTranslation);
void Prism_TransformComponent_SetTranslation(uint64_t entityID, const glm::vec3* inTranslation);
void Prism_TransformComponent_GetRotation(uint64_t entityID, glm::vec3* outRotation);
void Prism_TransformComponent_SetRotation(uint64_t entityID, const glm::vec3* inRotation);
void Prism_TransformComponent_GetScale(uint64_t entityID, glm::vec3* outScale);
void Prism_TransformComponent_SetScale(uint64_t entityID, const glm::vec3* inScale);
// 2D Physic // 2D Physic
void Prism_RigidBody2DComponent_ApplyLinearImpulse(uint64_t entityID, const glm::vec2* impulse, const glm::vec2* offset, bool wake); void Prism_RigidBody2DComponent_ApplyLinearImpulse(uint64_t entityID, const glm::vec2* impulse, const glm::vec2* offset, bool wake);