Compare commits

..

2 Commits

Author SHA1 Message Date
d4061386ec Fixed crashes 2026-04-03 18:43:54 +03:00
ec2695bc6c Now Mesh collider works 2026-04-02 05:54:58 +03:00
5 changed files with 118 additions and 21 deletions

View File

@@ -42,10 +42,32 @@ Gizmo::Gizmo(Ogre::SceneManager *sceneMgr)
Gizmo::~Gizmo()
{
if (m_axisX) m_sceneMgr->destroyManualObject(m_axisX);
if (m_axisY) m_sceneMgr->destroyManualObject(m_axisY);
if (m_axisZ) m_sceneMgr->destroyManualObject(m_axisZ);
if (m_gizmoNode) m_sceneMgr->destroySceneNode(m_gizmoNode);
// Detach objects from node first to avoid double-delete
if (m_gizmoNode) {
if (m_axisX) m_gizmoNode->detachObject(m_axisX);
if (m_axisY) m_gizmoNode->detachObject(m_axisY);
if (m_axisZ) m_gizmoNode->detachObject(m_axisZ);
}
// Now destroy the manual objects
if (m_axisX) {
m_sceneMgr->destroyManualObject(m_axisX);
m_axisX = nullptr;
}
if (m_axisY) {
m_sceneMgr->destroyManualObject(m_axisY);
m_axisY = nullptr;
}
if (m_axisZ) {
m_sceneMgr->destroyManualObject(m_axisZ);
m_axisZ = nullptr;
}
// Finally destroy the node
if (m_gizmoNode) {
m_sceneMgr->destroySceneNode(m_gizmoNode);
m_gizmoNode = nullptr;
}
}
void Gizmo::attachTo(flecs::entity entity)

View File

@@ -1117,22 +1117,70 @@ public:
for (j = 0; j < indices.size() / 3; j++)
triangles[j] = { indices[j * 3 + 0], indices[j * 3 + 1],
indices[j * 3 + 2] };
// Validate we have enough data
if (vertices.size() < 3) {
Ogre::LogManager::getSingleton().logMessage(
"ERROR: Mesh has too few vertices: " + mesh->getName() +
" (" + Ogre::StringConverter::toString(vertices.size()) + ")");
return JPH::ShapeRefC();
}
if (triangles.size() < 1) {
Ogre::LogManager::getSingleton().logMessage(
"ERROR: Mesh has no triangles: " + mesh->getName());
return JPH::ShapeRefC();
}
JPH::MeshShapeSettings mesh_shape_settings(vertices, triangles);
// Configure settings to be more permissive
mesh_shape_settings.mPerTriangleUserData = false;
// Log mesh stats for debugging
Ogre::LogManager::getSingleton().logMessage(
"Creating mesh shape: " + mesh->getName() +
" - Vertices: " + Ogre::StringConverter::toString(vertices.size()) +
" - Triangles: " + Ogre::StringConverter::toString(triangles.size()));
// Sanitize the mesh data to help with validation
mesh_shape_settings.Sanitize();
JPH::ShapeSettings::ShapeResult result =
mesh_shape_settings.Create();
OgreAssert(result.Get(), "Can not create mesh shape");
if (!result.Get()) {
Ogre::LogManager::getSingleton().logMessage(
"ERROR: Failed to create mesh shape: " + mesh->getName() +
" - Error: " + result.GetError().c_str());
return JPH::ShapeRefC();
}
Ogre::LogManager::getSingleton().logMessage(
"Successfully created mesh shape for: " + mesh->getName());
return result.Get();
}
JPH::ShapeRefC createMeshShape(Ogre::String meshName)
{
Ogre::DefaultHardwareBufferManager dmgr;
Ogre::MeshPtr mesh =
Ogre::MeshManager::getSingleton().getByName(meshName);
if (!mesh->isLoaded()) {
mesh->setHardwareBufferManager(&dmgr);
mesh->load();
// Use singleton pattern like convex hull does
auto p = Ogre::DefaultHardwareBufferManager::getSingletonPtr();
if (!p) {
new Ogre::DefaultHardwareBufferManager;
p = Ogre::DefaultHardwareBufferManager::getSingletonPtr();
}
return createMeshShape(mesh);
Ogre::MeshPtr mesh = Ogre::MeshManager::getSingleton().load(
meshName, "General");
if (mesh.get()) {
if (!mesh->isLoaded()) {
mesh->setHardwareBufferManager(p);
mesh->load();
}
return createMeshShape(mesh);
}
Ogre::LogManager::getSingleton().logMessage(
"ERROR: Could not load mesh for collider: " + meshName);
return JPH::ShapeRefC();
}
JPH::ShapeRefC createConvexHullShape(Ogre::MeshPtr mesh)
{

View File

@@ -648,6 +648,14 @@ void EditorUISystem::deleteEntity(flecs::entity entity)
deleteEntity(child);
}
// Clean up physics body before removing component
if (entity.has<RigidBodyComponent>()) {
auto &rigidBody = entity.get_mut<RigidBodyComponent>();
if (m_physicsSystem && rigidBody.bodyCreated) {
m_physicsSystem->removeRigidBody(rigidBody);
}
}
// Clean up transform node
if (entity.has<TransformComponent>()) {
auto &transform = entity.get_mut<TransformComponent>();

View File

@@ -79,16 +79,18 @@ JPH::ShapeRefC EditorPhysicsSystem::createShape(PhysicsColliderComponent& collid
case PhysicsColliderComponent::ShapeType::Mesh: {
if (!collider.meshName.empty()) {
try {
// Ensure mesh is loaded first
Ogre::MeshPtr mesh = Ogre::MeshManager::getSingleton().load(
collider.meshName, "General");
if (mesh && mesh->isLoaded()) {
result = m_physics->createMeshShape(collider.meshName);
result = m_physics->createMeshShape(collider.meshName);
if (!result) {
Ogre::LogManager::getSingleton().logMessage(
"Mesh shape creation returned null for: " + collider.meshName);
}
} catch (const Ogre::Exception& e) {
Ogre::LogManager::getSingleton().logMessage(
"Failed to create mesh shape: " + collider.meshName +
"Exception creating mesh shape: " + collider.meshName +
" - " + e.getDescription());
} catch (...) {
Ogre::LogManager::getSingleton().logMessage(
"Unknown exception creating mesh shape: " + collider.meshName);
}
}
break;
@@ -171,6 +173,23 @@ void EditorPhysicsSystem::updateRigidBody(flecs::entity entity,
removeRigidBody(rigidBody);
}
// Check for mesh colliders on dynamic bodies (not supported by Jolt)
bool hasMeshCollider = false;
entity.children([&](flecs::entity child) {
if (child.has<PhysicsColliderComponent>()) {
auto& collider = child.get<PhysicsColliderComponent>();
if (collider.shapeType == PhysicsColliderComponent::ShapeType::Mesh) {
hasMeshCollider = true;
}
}
});
if (hasMeshCollider && rigidBody.bodyType == RigidBodyComponent::BodyType::Dynamic) {
Ogre::LogManager::getSingleton().logMessage(
"WARNING: Mesh colliders can only be used with Static or Kinematic bodies, not Dynamic."
" The body will be created but may not behave correctly.");
}
// Build collision shape
JPH::ShapeRefC shape = buildCompoundShape(entity);
if (!shape) return;

View File

@@ -33,6 +33,9 @@ public:
bool isInitialized() const { return m_initialized; }
// Remove a rigid body (public for external cleanup)
void removeRigidBody(RigidBodyComponent& rigidBody);
private:
// Create a shape from collider component
JPH::ShapeRefC createShape(PhysicsColliderComponent& collider);
@@ -44,9 +47,6 @@ private:
void updateRigidBody(flecs::entity entity, RigidBodyComponent& rigidBody,
class TransformComponent& transform);
// Remove a rigid body
void removeRigidBody(RigidBodyComponent& rigidBody);
flecs::world& m_world;
Ogre::SceneManager* m_sceneMgr;