diff --git a/include/vierkant/Object3D.hpp b/include/vierkant/Object3D.hpp index ae07911f..7ea49889 100644 --- a/include/vierkant/Object3D.hpp +++ b/include/vierkant/Object3D.hpp @@ -55,6 +55,8 @@ class Object3D : public std::enable_shared_from_this void set_global_transform(const vierkant::transform_t &t); + bool global_enable() const; + /** * @return the axis-aligned boundingbox (AABB) in object coords. */ diff --git a/src/Object3D.cpp b/src/Object3D.cpp index 78aaeed6..b818df88 100644 --- a/src/Object3D.cpp +++ b/src/Object3D.cpp @@ -44,6 +44,18 @@ void Object3D::set_global_transform(const vierkant::transform_t &t) transform = parent_inverse * t; } +bool Object3D::global_enable() const +{ + if(!enabled) { return false; } + Object3DPtr ancestor = parent(); + while(ancestor) + { + if(!ancestor->enabled) { return false; } + ancestor = ancestor->parent(); + } + return true; +} + void Object3D::set_parent(const Object3DPtr &parent_object) { // detach object from former parent diff --git a/src/physics_context.cpp b/src/physics_context.cpp index 73fbe638..f28c0c6f 100644 --- a/src/physics_context.cpp +++ b/src/physics_context.cpp @@ -1,6 +1,7 @@ #include #include +#include #include // The Jolt headers don't include Jolt.h. Always include Jolt.h before including any other Jolt header. @@ -925,10 +926,7 @@ CollisionShapeId PhysicsContext::create_collision_shape(const vierkant::collisio } } } - if(new_id) - { - m_engine->jolt.shape_ids[s] = {new_id, 1}; - } + if(new_id) { m_engine->jolt.shape_ids[s] = {new_id, 1}; } return new_id; }, shape); @@ -959,8 +957,14 @@ void PhysicsScene::add_object(const Object3DPtr &object) if(object) { - auto phy_cmp_ptr = object->get_component_ptr(); - if(phy_cmp_ptr) { m_context.add_object(object->id(), object->transform, *phy_cmp_ptr); } + vierkant::LambdaVisitor visitor; + visitor.traverse(*object, [this](const auto &obj) -> bool { + if(auto phy_cmp_ptr = obj.template get_component_ptr()) + { + m_context.add_object(obj.id(), obj.global_transform(), *phy_cmp_ptr); + } + return true; + }); } } @@ -968,8 +972,14 @@ void PhysicsScene::remove_object(const Object3DPtr &object) { if(object) { - auto phy_cmp_ptr = object->get_component_ptr(); - if(phy_cmp_ptr) { m_context.remove_object(object->id(), *phy_cmp_ptr); } + vierkant::LambdaVisitor visitor; + visitor.traverse(*object, [this](const auto &obj) -> bool { + if(auto phy_cmp_ptr = obj.template get_component_ptr()) + { + m_context.remove_object(obj.id(), *phy_cmp_ptr); + } + return true; + }); } vierkant::Scene::remove_object(object); } @@ -987,6 +997,8 @@ void PhysicsScene::update(double time_delta) for(const auto &[entity, cmp]: view.each()) { auto obj = object_by_id(static_cast(entity)); + bool obj_enabled = obj->global_enable(); + if(cmp.mode == physics_component_t::UPDATE) { if(auto mesh_shape = std::get_if(&cmp.shape)) @@ -999,12 +1011,12 @@ void PhysicsScene::update(double time_delta) m_context.add_object(obj->id(), obj->transform, cmp); cmp.mode = physics_component_t::ACTIVE; } - else if(obj->enabled && cmp.mode == physics_component_t::INACTIVE) + else if(obj_enabled && cmp.mode == physics_component_t::INACTIVE) { cmp.mode = physics_component_t::ACTIVE; m_context.add_object(obj->id(), obj->transform, cmp); } - else if(!obj->enabled) + else if(!obj_enabled) { cmp.mode = physics_component_t::INACTIVE; m_context.remove_object(obj->id(), cmp); @@ -1016,7 +1028,7 @@ void PhysicsScene::update(double time_delta) continue; } - if(cmp.kinematic) + if(cmp.kinematic || cmp.mass == 0.f) { // object -> physics m_context.body_interface().set_transform(static_cast(entity), obj->transform);