From b3e7386bc9ebe9b8cdbdb118f1f019738cf01bb5 Mon Sep 17 00:00:00 2001
From: Sebastian Pape <Sebastian.Pape@rwth-aachen.de>
Date: Mon, 30 Jul 2018 14:22:52 +0200
Subject: [PATCH] Fixed some bugs that lead to a crash/bugs, when deleting
 objects

---
 .../src/hmd_navigation_behavior.cpp           | 19 ++++++++++++++++---
 demos/optical_bench/src/lens.cpp              |  3 +++
 demos/optical_bench/src/lens.hpp              |  3 +++
 demos/optical_bench/src/object_manager.cpp    | 11 ++++++++---
 demos/optical_bench/src/object_manager.hpp    |  2 ++
 .../optical_bench/src/object_support_rod.cpp  |  8 ++++++++
 .../optical_bench/src/object_support_rod.hpp  |  3 +++
 demos/optical_bench/src/selection_system.cpp  |  9 ++++++++-
 demos/optical_bench/src/selection_system.hpp  |  4 ++++
 demos/optical_bench/src/selector.hpp          |  4 ++++
 .../optical_bench/src/test_pattern_frame.cpp  |  5 ++++-
 .../optical_bench/src/test_pattern_frame.hpp  |  3 +++
 12 files changed, 66 insertions(+), 8 deletions(-)

diff --git a/demos/optical_bench/src/hmd_navigation_behavior.cpp b/demos/optical_bench/src/hmd_navigation_behavior.cpp
index 81d7e44c..95ccb68e 100644
--- a/demos/optical_bench/src/hmd_navigation_behavior.cpp
+++ b/demos/optical_bench/src/hmd_navigation_behavior.cpp
@@ -305,9 +305,22 @@ void HMDNavigationBehavior::UpdateInsersectionData() {
   glm::vec3 ori = ori_ / ori_.w;
   glm::vec3 forward = normalize(glm::vec3(transform * glm::vec4(0, 0, -1, 0)));
 
-  select_->UpdateInsersectThreadData(
-      ori, forward, transform,
-      scene_->GetEntitiesWithComponents<phx::Selector>());
+  // filter out elements that are not interactable
+  auto entities_with_selector =
+      scene_->GetEntitiesWithComponents<phx::Selector>();
+  std::vector<phx::Entity*> entities_interactable(
+      entities_with_selector.size());
+  ;
+  auto it = std::copy_if(
+      entities_with_selector.begin(), entities_with_selector.end(),
+      entities_interactable.begin(), [](phx::Entity* e) {
+        return e->GetFirstComponent<phx::Selector>()->IsInteractable();
+      });
+  entities_interactable.resize(std::distance(
+      entities_interactable.begin(), it));  // shrink container to new size
+
+  select_->UpdateInsersectThreadData(ori, forward, transform,
+                                     entities_interactable);
 }
 
 void HMDNavigationBehavior::ButtonChange(
diff --git a/demos/optical_bench/src/lens.cpp b/demos/optical_bench/src/lens.cpp
index 109617c8..fa25306f 100644
--- a/demos/optical_bench/src/lens.cpp
+++ b/demos/optical_bench/src/lens.cpp
@@ -45,6 +45,7 @@ Lens::Lens(phx::Engine* engine, phx::Scene* scene, OptixContextManager* manager,
            LensSideType type1, LensSideType type2, optix::float3 frontCenter,
            float lensradius, float thickness, float radius, float radius2) {
   manager_ = manager;
+  scene_ = scene;
 
   CreateGlassMaterialInstance();
   geometry_ = manager->GetContext()->createGeometryInstance(
@@ -136,7 +137,9 @@ Lens::~Lens() {
   geometry_group_->destroy();
   transform_->destroy();
   acceleration_structure_->destroy();
+  scene_->RemoveEntity(entity_);
   delete support_rod_;
+  manager_->TopAccelerationMarkDirty();
 }
 
 void Lens::NextLensSideType1() {
diff --git a/demos/optical_bench/src/lens.hpp b/demos/optical_bench/src/lens.hpp
index 59929fc3..acccc3eb 100644
--- a/demos/optical_bench/src/lens.hpp
+++ b/demos/optical_bench/src/lens.hpp
@@ -116,6 +116,8 @@ class Lens {
 
   void ChangedWaveLength(float wavelength_nm);
 
+  void RemoveSupportRod() { support_rod_->Remove(); }
+
  private:
   std::array<glm::vec3, 2u> ComputeAABBFromCylinder(glm::vec3 orientation,
                                                     float halfLength1,
@@ -141,6 +143,7 @@ class Lens {
   void RecalculateBoundingBox();
   SupportRod* support_rod_;
   OptixContextManager* manager_;
+  phx::Scene* scene_;
   phx::Selector* selector_;
   bool grabbed_ = false;
 
diff --git a/demos/optical_bench/src/object_manager.cpp b/demos/optical_bench/src/object_manager.cpp
index f3f1a48a..3bd53a53 100644
--- a/demos/optical_bench/src/object_manager.cpp
+++ b/demos/optical_bench/src/object_manager.cpp
@@ -43,10 +43,13 @@ ObjectManager::ObjectManager(phx::Engine* engine, phx::Scene* scene,
     : phx::System(engine) {
   manager_ = manager;
   scene_ = scene;
+  selection_system_ = engine->GetSystem<SelectionSystem>();
 
   bin_ = phx::SceneLoader::InsertModelIntoScene(
       "models/opticalBench/room/bin.obj", scene);
-  bin_->AddComponent<phx::Selector>(bin_)->SetMove(nullptr);  // deactivate move
+  auto select_bin = bin_->AddComponent<phx::Selector>(bin_);
+  select_bin->SetMove(nullptr);  // deactivate move
+  select_bin->SetInteractable(false);
 
   bin_->GetFirstComponent<phx::Transform>()->Translate(
       glm::vec3(0.0f, 0.0f, -1.5f));  // Position on floor
@@ -142,9 +145,10 @@ void ObjectManager::DeleteLens(Lens* l) {
       registered_lenses_.end());
 
   if (hmd_nav_ != nullptr) hmd_nav_->DeletedObject();
-
   menu_->UnregisterLens(l);
   make_invalid_ = true;
+  selection_system_->ResetHoveredGrabbed();
+  l->RemoveSupportRod();
   delete l;
 }
 
@@ -154,8 +158,9 @@ void ObjectManager::DeleteTarget(TestPatternFrame* t) {
       registered_frames_.end());
 
   if (hmd_nav_ != nullptr) hmd_nav_->DeletedObject();
-
   make_invalid_ = true;
+  selection_system_->ResetHoveredGrabbed();
+  t->RemoveSupportRod();
   delete t;
 }
 
diff --git a/demos/optical_bench/src/object_manager.hpp b/demos/optical_bench/src/object_manager.hpp
index ba0f6ef0..bb009e02 100644
--- a/demos/optical_bench/src/object_manager.hpp
+++ b/demos/optical_bench/src/object_manager.hpp
@@ -27,6 +27,7 @@
 #include "lens.hpp"
 #include "menu_manager.hpp"
 #include "phx/suppress_warnings.hpp"
+#include "selection_system.hpp"
 #include "test_pattern_frame.hpp"
 
 #include <mutex>
@@ -83,6 +84,7 @@ class ObjectManager : public phx::System {
 
  private:
   phx::Entity* bin_;
+  SelectionSystem* selection_system_;
 
   phx::MaterialHandle* bin_mat_ = nullptr;
   const glm::vec3 kBinColorBase_ = glm::vec3(0.189474f, 0.189474f, 0.189474f);
diff --git a/demos/optical_bench/src/object_support_rod.cpp b/demos/optical_bench/src/object_support_rod.cpp
index c0b7d26e..a4162a93 100644
--- a/demos/optical_bench/src/object_support_rod.cpp
+++ b/demos/optical_bench/src/object_support_rod.cpp
@@ -41,6 +41,7 @@ SUPPRESS_WARNINGS_END
 SupportRod::SupportRod(phx::Scene* scene, phx::Selector* selector,
                        bool append_to_move) {
   selector_ = selector;
+  scene_ = scene;
   rod_support_entity_ = LoadAndInsertRod(scene);
   rod_holder_entity_ = LoadAndInsertRod(scene);
 
@@ -93,6 +94,13 @@ SupportRod::SupportRod(phx::Scene* scene, phx::Selector* selector,
 
 SupportRod::~SupportRod() {}
 
+// Cant be done in Destructor, else it crashes at close, since the entities
+// might be deleted already
+void SupportRod::Remove() {
+  scene_->RemoveEntity(rod_support_entity_);
+  scene_->RemoveEntity(rod_holder_entity_);
+}
+
 phx::Entity* SupportRod::LoadAndInsertRod(phx::Scene* scene) {
   auto model = phx::ResourceUtils::LoadResourceFromFile<phx::Model>(
       "models/opticalBench/rod/rod.obj");
diff --git a/demos/optical_bench/src/object_support_rod.hpp b/demos/optical_bench/src/object_support_rod.hpp
index d0793aeb..ff0ebdc4 100644
--- a/demos/optical_bench/src/object_support_rod.hpp
+++ b/demos/optical_bench/src/object_support_rod.hpp
@@ -50,8 +50,11 @@ class SupportRod {
 
   void Moved() { move_function_(); }
 
+  void Remove();
+
  private:
   phx::Entity* LoadAndInsertRod(phx::Scene* scene);
+  phx::Scene* scene_;
   phx::Entity* rod_support_entity_;
   phx::Entity* rod_holder_entity_;
   phx::Selector* selector_;
diff --git a/demos/optical_bench/src/selection_system.cpp b/demos/optical_bench/src/selection_system.cpp
index 1bd8bb58..38384810 100644
--- a/demos/optical_bench/src/selection_system.cpp
+++ b/demos/optical_bench/src/selection_system.cpp
@@ -45,7 +45,8 @@ SUPPRESS_WARNINGS_END
 #include "phx/rendering/components/transform.hpp"
 
 SelectionSystem::SelectionSystem(phx::Engine* engine) : phx::System(engine) {
-  intersection_thread_ = std::thread(&SelectionSystem::IntersectionThreadFunction, this);
+  intersection_thread_ =
+      std::thread(&SelectionSystem::IntersectionThreadFunction, this);
 }
 
 SelectionSystem::~SelectionSystem() {}
@@ -159,6 +160,12 @@ void SelectionSystem::IntersectionThreadFunction() {
     res = nullptr;
 
     for (auto i = 0u; i < entities.size(); ++i) {
+      auto scene_entities = engine_->GetScene()->GetEntities();
+      // Check if already deleted
+      if (std::find(scene_entities.begin(), scene_entities.end(),
+                    entities[i]) == scene_entities.end()) {
+        continue;
+      }
       curr = entities[i]->GetFirstComponent<phx::Selector>();
       current_intersection = curr->Intersect(ori, dir);
 
diff --git a/demos/optical_bench/src/selection_system.hpp b/demos/optical_bench/src/selection_system.hpp
index 176f9562..38c45238 100644
--- a/demos/optical_bench/src/selection_system.hpp
+++ b/demos/optical_bench/src/selection_system.hpp
@@ -56,6 +56,10 @@ class SelectionSystem : public phx::System {
                                  std::vector<phx::Entity*> entities);
 
   void KillThread();
+  void ResetHoveredGrabbed() {
+    selector_currently_grabbed_entity_ = nullptr;
+    selector_currently_hovered_entity_ = nullptr;
+  }
 
  private:
   std::thread intersection_thread_;
diff --git a/demos/optical_bench/src/selector.hpp b/demos/optical_bench/src/selector.hpp
index fe5820f5..15b27b96 100644
--- a/demos/optical_bench/src/selector.hpp
+++ b/demos/optical_bench/src/selector.hpp
@@ -138,11 +138,15 @@ class Selector : public Component {
     if (external_update_function_ != nullptr) external_update_function_();
   }
 
+  bool IsInteractable() { return interactable; }
+  void SetInteractable(bool b) { interactable = b; }
+
  private:
   AABB collider_;
   void SwapMinMaxVectorEntries(glm::vec3& min, glm::vec3& max);
   bool manipulation_helper_attachable_ = false;
   float intersection_dist_ = 0.05f;
+  bool interactable = true;
 
   // selection functions
   std::function<void(glm::mat4, std::chrono::milliseconds)> hover_function_ =
diff --git a/demos/optical_bench/src/test_pattern_frame.cpp b/demos/optical_bench/src/test_pattern_frame.cpp
index f58417aa..751d7ee9 100644
--- a/demos/optical_bench/src/test_pattern_frame.cpp
+++ b/demos/optical_bench/src/test_pattern_frame.cpp
@@ -40,6 +40,7 @@ TestPatternFrame::TestPatternFrame(phx::Scene* scene,
                                    std::string image, glm::vec3 pos,
                                    bool use_interpolation) {
   manager_ = manager;
+  scene_ = scene;
   material_ = manager_->GetTargetMaterial();
 
   transform_ = manager_->GetContext()->createTransform();
@@ -109,9 +110,11 @@ TestPatternFrame::TestPatternFrame(phx::Scene* scene,
 TestPatternFrame::~TestPatternFrame() {
   manager_->GetTopObject()->removeChild(transform_);
   geometry_->destroy();
+  acceleration_->destroy();
   geometry_group_->destroy();
   transform_->destroy();
-  acceleration_->destroy();
+  scene_->RemoveEntity(entity_);
+  manager_->TopAccelerationMarkDirty();
   delete support_rod_;
 }
 
diff --git a/demos/optical_bench/src/test_pattern_frame.hpp b/demos/optical_bench/src/test_pattern_frame.hpp
index 83e06ff9..3fa5404d 100644
--- a/demos/optical_bench/src/test_pattern_frame.hpp
+++ b/demos/optical_bench/src/test_pattern_frame.hpp
@@ -49,6 +49,8 @@ class TestPatternFrame {
 
   void Translate(glm::vec3 pos);
 
+  void RemoveSupportRod() { support_rod_->Remove(); }
+
  private:
   optix::Transform transform_;
   optix::GeometryInstance geometry_;
@@ -64,6 +66,7 @@ class TestPatternFrame {
   }
 
   phx::Entity* entity_;
+  phx::Scene* scene_;
   SupportRod* support_rod_;
 };
 
-- 
GitLab