Compare commits
2 Commits
d68da8fc04
...
d4061386ec
| Author | SHA1 | Date | |
|---|---|---|---|
| d4061386ec | |||
| ec2695bc6c |
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
@@ -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>();
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user