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

View File

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

View File

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

View File

@ -109,7 +109,7 @@ namespace FPSExample
{
RaycastHit hitInfo;
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))
{
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
// 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);
// 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(){
Vec3 position = m_Transform.Position + m_CameraTransform.Transform.Forward * CameraForwardOffset;
position.Y += m_Transform.Position.Y + CameraYOffset;
m_CameraTransform.Position = position;
Vec3 position = m_Transform.Translation + m_CameraTransform.Transform.Forward * CameraForwardOffset;
position.Y += m_Transform.Translation.Y + CameraYOffset;
m_CameraTransform.Translation = position;
}
}
}

View File

@ -5,12 +5,6 @@ namespace Prism
{
public class Entity
{
public ulong ID { get; private set; }
~Entity()
{
}
private Action<float>? m_CollisionBeginCallbacks;
private Action<float>? m_CollisionEndCallbacks;
private Action<float>? m_Collision2DBeginCallbacks;
@ -18,6 +12,48 @@ namespace Prism
private Action<float>? m_TriggerBeginCallbacks;
private Action<float>? m_TriggerEndCallbacks;
public ulong ID { get; private set; }
~Entity()
{
}
public Vec3 Translation
{
get
{
return GetComponent<TransformComponent>().Translation;
}
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; }
internal Entity(ulong id)

View File

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

View File

@ -8,6 +8,8 @@ namespace Prism
public float X;
public float Y;
public static Vec2 Zero = new Vec2(0.0f, 0.0f);
public Vec2(float scalar)
{
X = Y = scalar;
@ -39,12 +41,34 @@ namespace Prism
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()
{
float length = 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()
{
float length = Length();

View File

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

View File

@ -33,21 +33,29 @@ namespace Prism
public class TransformComponent : Component
{
private Transform m_Transform;
public Transform Transform { get { return m_Transform; } }
public Vec3 Position
public Transform Transform
{
get
{
GetTransform_Native(Entity.ID, out m_Transform);
return m_Transform.Position;
GetTransform_Native(Entity.ID, out Transform result);
return result;
}
set
{
m_Transform.Position = value;
SetTransform_Native(Entity.ID, ref m_Transform);
SetTransform_Native(Entity.ID, ref value);
}
}
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
{
GetTransform_Native(Entity.ID, out m_Transform);
return m_Transform.Rotation;
GetRotation_Native(Entity.ID, out Vec3 result);
return result;
}
set
{
m_Transform.Rotation = value;
SetTransform_Native(Entity.ID, ref m_Transform);
SetRotation_Native(Entity.ID, ref value);
}
}
@ -69,22 +76,38 @@ namespace Prism
{
get
{
GetTransform_Native(Entity.ID, out m_Transform);
return m_Transform.Scale;
GetScale_Native(Entity.ID, out Vec3 result);
return result;
}
set
{
m_Transform.Scale = value;
SetTransform_Native(Entity.ID, ref m_Transform);
SetScale_Native(Entity.ID, ref value);
}
}
[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)]
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

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()
{
ImGui::Begin("Scene Hierarchy");
@ -442,7 +456,15 @@ namespace Prism
AddComponentPopup<BoxColliderComponent>("BoxCollider");
AddComponentPopup<SphereColliderComponent>("SphereCollider");
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();
@ -890,7 +912,9 @@ namespace Prism
UI::EndPropertyGrid();
});
DrawComponent<MeshColliderComponent>("Mesh Collider", entity, [](MeshColliderComponent& mcc)
DrawComponent<MeshColliderComponent>("Mesh Collider", entity, [&](MeshColliderComponent& mcc)
{
if (mcc.OverrideMesh)
{
ImGui::Columns(3);
ImGui::SetColumnWidth(0, 100);
@ -912,12 +936,13 @@ namespace Prism
{
mcc.CollisionMesh = Ref<Mesh>::Create(file);
if (mcc.IsConvex)
PhysicsWrappers::CreateConvexMesh(mcc);
PhysicsWrappers::CreateConvexMesh(mcc, entity.Transform().Scale);
else
PhysicsWrappers::CreateTriangleMesh(mcc);
PhysicsWrappers::CreateTriangleMesh(mcc, entity.Transform().Scale);
}
}
ImGui::EndColumns();
}
UI::BeginPropertyGrid();
if (UI::Property("Is Convex", mcc.IsConvex))
@ -932,6 +957,19 @@ namespace Prism
}
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();
});

View File

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

View File

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

View File

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

View File

@ -24,6 +24,11 @@ namespace Prism
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)
{
return *(physx::PxMat44*)&matrix;

View File

@ -16,6 +16,7 @@ namespace Prism
physx::PxTransform ToPhysXTransform(const TransformComponent& transform);
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::PxVec3 ToPhysXVector(const glm::vec3& vector);
physx::PxVec4 ToPhysXVector(const glm::vec4& vector);

View File

@ -9,6 +9,7 @@
#include <glm/gtx/rotate_vector.hpp>
#include "PhysicsLayer.h"
#include "Prism/Core/Math/Math.h"
#include "Prism/Script/ScriptEngine.h"
#define PHYSX_DEBUGGER
@ -177,9 +178,8 @@ namespace Prism
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 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);
physx::PxShape* shape = physx::PxRigidActorExt::createExclusiveShape(*actor.m_ActorInternal, boxGeometry, material);
// physx::PxShape* shape = physx::PxRigidActorExt::createExclusiveShape(actor, boxGeometry, material);
physx::PxShape* shape = physx::PxRigidActorExt::createExclusiveShape(*actor.m_ActorInternal, boxGeometry, *actor.m_MaterialInternal);
shape->setFlag(physx::PxShapeFlag::eSIMULATION_SHAPE, !collider.IsTrigger);
shape->setFlag(physx::PxShapeFlag::eTRIGGER_SHAPE, collider.IsTrigger);
shape->setLocalPose(ToPhysXTransform(glm::translate(glm::mat4(1.0F), collider.Offset)));
actor.AddCollisionShape(shape);
shape->setLocalPose(ToPhysXTransform(glm::translate(glm::mat4(1.0f), collider.Offset)));
}
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 glm::vec3 scale = actor.m_Entity.Transform().Scale;
float colliderRadius = collider.Radius;
@ -213,52 +208,43 @@ namespace Prism
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);
shape->setFlag(physx::PxShapeFlag::eSIMULATION_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 glm::vec3 scale = actor.m_Entity.Transform().Scale;
float colliderRadius = collider.Radius;
float colliderHeight = collider.Height;
if (scale.x != 0.0F) colliderRadius *= scale.x;
if (scale.y != 0.0F) colliderHeight *= scale.y ;
if (scale.x != 0.0f) colliderRadius *= scale.x;
if (scale.y != 0.0f) colliderHeight *= scale.y ;
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::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>();
glm::vec3 scale = actor.m_Entity.Transform().Scale;
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 mesh : meshes)
for (const auto shape : shapes)
{
physx::PxConvexMeshGeometry convexGeometry = physx::PxConvexMeshGeometry(mesh, physx::PxMeshScale(ToPhysXVector(scale)));
convexGeometry.meshFlags = physx::PxConvexMeshGeometryFlag::eTIGHT_BOUNDS;
physx::PxShape* shape = physx::PxRigidActorExt::createExclusiveShape(*actor.m_ActorInternal, convexGeometry, material);
physx::PxMaterial* materials[] = { actor.m_MaterialInternal };
shape->setMaterials(materials, 1);
shape->setFlag(physx::PxShapeFlag::eSIMULATION_SHAPE, !collider.IsTrigger);
shape->setFlag(physx::PxShapeFlag::eTRIGGER_SHAPE, collider.IsTrigger);
@ -267,14 +253,13 @@ namespace Prism
}
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 mesh : meshes)
for (const auto shape : shapes)
{
physx::PxTriangleMeshGeometry convexGeometry = physx::PxTriangleMeshGeometry(mesh, physx::PxMeshScale(ToPhysXVector(scale)));
physx::PxShape* shape = physx::PxRigidActorExt::createExclusiveShape(*actor.m_ActorInternal, convexGeometry, material);
physx::PxMaterial* materials[] = { actor.m_MaterialInternal };
shape->setMaterials(materials, 1);
shape->setFlag(physx::PxShapeFlag::eSIMULATION_SHAPE, !collider.IsTrigger);
shape->setFlag(physx::PxShapeFlag::eTRIGGER_SHAPE, collider.IsTrigger);
@ -283,9 +268,9 @@ 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());
@ -297,15 +282,6 @@ namespace Prism
const std::vector<Vertex>& vertices = collider.CollisionMesh->GetStaticVertices();
const std::vector<Index>& indices = collider.CollisionMesh->GetIndices();
// 提取顶点位置
std::vector<glm::vec3> vertexPositions;
if (vertices[0].Position != glm::vec3()) {
vertexPositions.reserve(vertices.size());
for (const auto& vertex : vertices) {
vertexPositions.push_back(vertex.Position);
}
}
// 清空旧的处理网格
collider.ProcessedMeshes.clear();
@ -315,15 +291,8 @@ namespace Prism
// 准备三角形网格描述
physx::PxTriangleMeshDesc triangleDesc;
triangleDesc.points.count = submesh.VertexCount;
triangleDesc.points.stride = sizeof(glm::vec3);
// 使用顶点位置数组或原始顶点数据
if (!vertexPositions.empty()) {
triangleDesc.points.data = &vertexPositions[submesh.BaseVertex];
} else {
triangleDesc.points.stride = sizeof(Vertex);
triangleDesc.points.data = &vertices[submesh.BaseVertex];
}
triangleDesc.points.stride = sizeof(Vertex);
triangleDesc.triangles.count = submesh.IndexCount / 3;
triangleDesc.triangles.data = &indices[submesh.BaseIndex / 3];
@ -341,15 +310,23 @@ namespace Prism
&result
);
if (!triangleMesh) {
PM_CORE_ERROR("Failed to create triangle mesh for submesh: {0}", submesh.MeshName);
continue;
}
meshes.push_back(triangleMesh);
glm::vec3 submeshTranslation, submeshRotation, submeshScale;
Math::DecomposeTransform(submesh.LocalTransform, submeshTranslation, submeshRotation, submeshScale);
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();
@ -358,25 +335,23 @@ namespace Prism
std::vector<Vertex> processedVertices;
std::vector<Index> processedIndices;
// 获取顶点数据
processedVertices.reserve(nbVerts);
for (uint32_t v = 0; v < nbVerts; v++)
{
Vertex vertex;
Vertex vertex{};
vertex.Position = FromPhysXVector(meshVertices[v]);
processedVertices.push_back(vertex);
}
// 获取三角形索引
processedIndices.reserve(nbTriangles);
// 检查索引格式16位或32位
if (triangleMesh->getTriangleMeshFlags() & physx::PxTriangleMeshFlag::e16_BIT_INDICES)
{
const physx::PxU16* tris = static_cast<const physx::PxU16*>(triangleMesh->getTriangles());
const auto* tris = static_cast<const physx::PxU16*>(triangleMesh->getTriangles());
for (uint32_t tri = 0; tri < nbTriangles; tri++)
{
Index index;
Index index{};
index.V1 = tris[3 * tri + 0];
index.V2 = tris[3 * tri + 1];
index.V3 = tris[3 * tri + 2];
@ -385,10 +360,10 @@ namespace Prism
}
else
{
const physx::PxU32* tris = static_cast<const physx::PxU32*>(triangleMesh->getTriangles());
const auto* tris = static_cast<const physx::PxU32*>(triangleMesh->getTriangles());
for (uint32_t tri = 0; tri < nbTriangles; tri++)
{
Index index;
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]);
@ -396,54 +371,40 @@ namespace Prism
}
}
// 为当前子网格创建渲染网格
collider.ProcessedMeshes.push_back(Ref<Mesh>::Create(processedVertices, processedIndices));
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 meshes;
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());
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.meshWeldTolerance = 0.01f;
const std::vector<Vertex>& vertices = collider.CollisionMesh->GetStaticVertices();
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
collider.ProcessedMeshes.clear();
// 处理每个子网格
// process all submesh
for (const auto& submesh : collider.CollisionMesh->GetSubmeshes())
{
// 准备凸包描述
physx::PxConvexMeshDesc convexDesc;
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.data = &indices[submesh.BaseIndex / 3];
@ -467,10 +428,15 @@ namespace Prism
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 physx::PxVec3* convexVertices = convexMesh->getVertices();
@ -495,8 +461,6 @@ namespace Prism
vertex.Position = FromPhysXVector(
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);
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
const auto& vertices = collider.CollisionMesh->GetStaticVertices();
@ -624,7 +588,7 @@ namespace Prism
physx::PxOverlapBuffer buf(s_OverlapBuffer, OVERLAP_MAX_COLLIDERS);
const auto geometry = physx::PxBoxGeometry(halfSize.x, halfSize.y, halfSize.z);
const physx::PxTransform pose = ToPhysXTransform(glm::translate(glm::mat4(1.0F), origin));
const physx::PxTransform pose = ToPhysXTransform(glm::translate(glm::mat4(1.0f), origin));
const bool result = scene->overlap(geometry, pose, buf);
@ -645,7 +609,7 @@ namespace Prism
memset(s_OverlapBuffer, 0, sizeof(s_OverlapBuffer));
physx::PxOverlapBuffer buf(s_OverlapBuffer, OVERLAP_MAX_COLLIDERS);
const auto geometry = physx::PxSphereGeometry(radius);
const physx::PxTransform pose = ToPhysXTransform(glm::translate(glm::mat4(1.0F), origin));
const physx::PxTransform pose = ToPhysXTransform(glm::translate(glm::mat4(1.0f), origin));
const bool result = scene->overlap(geometry, pose, buf);
@ -666,7 +630,7 @@ namespace Prism
memset(s_OverlapBuffer, 0, sizeof(s_OverlapBuffer));
physx::PxOverlapBuffer buf(s_OverlapBuffer, OVERLAP_MAX_COLLIDERS);
const auto geometry = physx::PxCapsuleGeometry(radius, halfHeight);
const physx::PxTransform pose = ToPhysXTransform(glm::translate(glm::mat4(1.0F), origin));
const physx::PxTransform pose = ToPhysXTransform(glm::translate(glm::mat4(1.0f), origin));
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 void SetCollisionFilters(const physx::PxRigidActor& actor, uint32_t physicsLayer);
static void AddBoxCollider(PhysicsActor& actor, const physx::PxMaterial& material);
static void AddSphereCollider(PhysicsActor& actor, const physx::PxMaterial& material);
static void AddCapsuleCollider(PhysicsActor& actor, const physx::PxMaterial& material);
static void AddMeshCollider(PhysicsActor& actor, const physx::PxMaterial& material);
static void AddBoxCollider(PhysicsActor& actor);
static void AddSphereCollider(PhysicsActor& actor);
static void AddCapsuleCollider(PhysicsActor& actor);
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 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 std::vector<physx::PxTriangleMesh*> CreateTriangleMesh(MeshColliderComponent& collider);
static std::vector<physx::PxConvexMesh*> CreateConvexMesh(MeshColliderComponent& collider, bool rotatedX = false);
static std::vector<physx::PxShape*> CreateTriangleMesh(MeshColliderComponent& collider, const glm::vec3& scale = glm::vec3(1.0f));
static std::vector<physx::PxShape*> CreateConvexMesh(MeshColliderComponent& collider, const glm::vec3& scale = glm::vec3(1.0f));
// static physx::PxMaterial* CreateMaterial(const PhysicsMaterialComponent& material);

View File

@ -156,7 +156,7 @@ namespace Prism
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)
glDisable(GL_DEPTH_TEST);
@ -172,6 +172,11 @@ namespace Prism
break;
}
if (faceCulling)
glEnable(GL_CULL_FACE);
else
glDisable(GL_CULL_FACE);
glDrawElements(glPrimitiveType, count, GL_UNSIGNED_INT, nullptr);
if (!depthTest)

View File

@ -57,7 +57,7 @@ namespace Prism {
m_Size = size;
Ref<OpenGLVertexBuffer> instance = this;
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);
}
Mesh::Mesh(const std::vector<Vertex>& vertices, const std::vector<Index>& indices)
: m_StaticVertices(vertices), m_Indices(indices), m_IsAnimated(false)
Mesh::Mesh(const std::vector<Vertex>& vertices, const std::vector<Index>& indices, const glm::mat4& transform)
: m_StaticVertices(vertices), m_Indices(indices), m_Scene(nullptr)
{
Submesh submesh;
submesh.BaseVertex = 0;
submesh.BaseIndex = 0;
submesh.IndexCount = static_cast<uint32_t>(indices.size()) * 3;
submesh.Transform = glm::mat4(1.0F);
submesh.Transform = transform;
m_Submeshes.push_back(submesh);
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)
{
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++)
{
const uint32_t mesh = node->mMeshes[i];
auto& submesh = m_Submeshes[mesh];
submesh.NodeName = node->mName.C_Str();
submesh.Transform = transform;
submesh.LocalTransform = localTransform;
}
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;
glm::mat4 Transform;
glm::mat4 LocalTransform;
AABB BoundingBox;
std::string NodeName, MeshName;
@ -108,7 +109,7 @@ namespace Prism
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();
void OnUpdate(TimeStep deltaTime);

View File

@ -45,7 +45,7 @@ namespace Prism
{ 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)
@ -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)
@ -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([=]() {
RendererAPI::DrawIndexed(count, type, depthTest);
RendererAPI::DrawIndexed(count, type, depthTest, cullFace);
});
}
@ -147,16 +147,11 @@ namespace Prism
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_FullscreenQuadPipeline->Bind();
s_Data.m_FullscreenQuadIndexBuffer->Bind();
DrawIndexed(6, PrimitiveType::Triangles, depthTest);
DrawIndexed(6, PrimitiveType::Triangles, depthTest, cullFace);
}
void Renderer::SubmitFullscreenQuad(Ref<MaterialInstance> material)
@ -170,16 +165,11 @@ namespace Prism
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_FullscreenQuadPipeline->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)

View File

@ -25,7 +25,7 @@ namespace Prism
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
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 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 RendererAPIType Current() { return s_CurrentRendererAPI; }

View File

@ -439,8 +439,8 @@ namespace Prism
// s_Data.SceneInfo.EnvironmentIrradianceMap->Bind(0);
Renderer::SubmitFullscreenQuad(s_Data.SceneData.SkyboxMaterial);
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;
// 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;
// Render entities
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 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
cascades[i].SplitDepth = (nearClip + splitDist * clipRange) * -1.0f;
cascades[i].ViewProj = lightOrthoMatrix * lightViewMatrix;

View File

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

View File

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

View File

@ -4,6 +4,8 @@
#include "SceneSerializer.h"
#include <filesystem>
#include "yaml-cpp/yaml.h"
#include "Prism/Script/ScriptEngine.h"
@ -277,7 +279,17 @@ namespace Prism
out << YAML::BeginMap; // 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::EndMap; // CameraComponent
@ -425,9 +437,13 @@ namespace Prism
out << YAML::BeginMap; // MeshColliderComponent
auto meshColliderComponent = entity.GetComponent<MeshColliderComponent>();
if (meshColliderComponent.OverrideMesh)
out << YAML::Key << "AssetPath" << YAML::Value << meshColliderComponent.CollisionMesh->GetFilePath();
out << YAML::Key << "IsConvex" << YAML::Value << meshColliderComponent.IsConvex;
out << YAML::Key << "IsTrigger" << YAML::Value << meshColliderComponent.IsTrigger;
out << YAML::Key << "OverrideMesh" << YAML::Value << meshColliderComponent.OverrideMesh;
out << YAML::EndMap; // MeshColliderComponent
}
@ -505,12 +521,19 @@ namespace Prism
PM_CORE_ASSERT(false);
}
bool CheckPath(const std::string& path)
{
return std::filesystem::exists(path);
}
bool SceneSerializer::Deserialize(const std::string& filepath)
{
std::ifstream stream(filepath);
std::stringstream strStream;
strStream << stream.rdbuf();
std::vector<std::string> missingPaths;
YAML::Node data = YAML::Load(strStream.str());
if (!data["Scene"])
return false;
@ -557,7 +580,20 @@ namespace Prism
auto& transform = deserializedEntity.GetComponent<TransformComponent>();
transform.Translation = transformComponent["Position"].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>();
PM_CORE_INFO("Entity Transform:");
@ -642,7 +678,15 @@ namespace Prism
const std::string meshPath = meshComponent["AssetPath"].as<std::string>();
// TEMP (because script creates mesh component...)
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);
}
@ -661,7 +705,16 @@ namespace Prism
auto& component = deserializedEntity.AddComponent<SkyLightComponent>();
const std::string env = skyLightComponent["EnvironmentAssetPath"].as<std::string>();
if (!env.empty())
{
if (!CheckPath(env))
{
missingPaths.emplace_back(env);
}
else
{
component.SceneEnvironment = Environment::Load(env);
}
}
component.Intensity = skyLightComponent["Intensity"].as<float>();
component.Angle = skyLightComponent["Angle"].as<float>();
}
@ -669,10 +722,25 @@ namespace Prism
if (auto cameraComponent = entity["CameraComponent"])
{
auto& component = deserializedEntity.AddComponent<CameraComponent>();
component.Camera = SceneCamera();
component.Primary = cameraComponent["Primary"].as<bool>();
const auto& cameraNode = cameraComponent["Camera"];
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"])
@ -766,17 +834,40 @@ namespace Prism
}
if (auto meshColliderComponent = entity["MeshColliderComponent"])
{
Ref<Mesh> collisionMesh = deserializedEntity.HasComponent<MeshComponent>() ? deserializedEntity.GetComponent<MeshComponent>().Mesh : nullptr;
bool overrideMesh = meshColliderComponent["OverrideMesh"] ? meshColliderComponent["OverrideMesh"].as<bool>() : false;
if (overrideMesh)
{
auto meshPath = meshColliderComponent["AssetPath"].as<std::string>();
auto& component = deserializedEntity.AddComponent<MeshColliderComponent>(Ref<Mesh>::Create(meshPath));
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;
if (component.IsConvex)
PhysicsWrappers::CreateConvexMesh(component);
else
PhysicsWrappers::CreateTriangleMesh(component);
component.OverrideMesh = overrideMesh;
PM_CORE_INFO(" Mesh Collider Asset Path: {0}", meshPath);
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;
}

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::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)
{
size_t a = sizeof(ScriptTransform);
Ref<Scene> scene = ScriptEngine::GetCurrentSceneContext();
PM_CORE_ASSERT(scene, "No active scene!");
@ -322,6 +321,7 @@ namespace Prism { namespace Script {
return 0;
}
/*
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!");
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::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 forward = glm::normalize(glm::rotate(rotation, glm::vec3(0.0f, 0.0f, -1.0f)));
*outTransform = {
transform.Translation, glm::degrees(transform.Rotation), transform.Scale,
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!");
Entity entity = entityMap.at(entityID);
auto& transform = entity.GetComponent<TransformComponent>();
auto transform = entity.GetComponent<TransformComponent>();
transform.Translation = inTransform->Translation;
transform.Rotation = glm::radians(inTransform->Rotation);
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)
{
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_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
void Prism_RigidBody2DComponent_ApplyLinearImpulse(uint64_t entityID, const glm::vec2* impulse, const glm::vec2* offset, bool wake);