From ae95727cac8006837a2444fa58bae353be42e5a3 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Martin=20=C5=A0toura=C4=8D?= <525032@mail.muni.cz>
Date: Fri, 2 Jun 2023 12:07:29 +0200
Subject: [PATCH] scuffed object selection implemented (needs fixes)

---
 src/studio/include/studio/simulator.hpp |   5 +
 src/studio/src/simulator.cpp            | 133 +++++++++++++++++++++---
 2 files changed, 122 insertions(+), 16 deletions(-)

diff --git a/src/studio/include/studio/simulator.hpp b/src/studio/include/studio/simulator.hpp
index 09a8a8f..1989e1f 100644
--- a/src/studio/include/studio/simulator.hpp
+++ b/src/studio/include/studio/simulator.hpp
@@ -53,8 +53,11 @@ struct Simulator : public osi::Simulator
     void create_scene();
     void process_input();
 
+    void intersect_axis(glm::vec3 rayPosition, glm::vec3 rayDirection, std::pair<glm::vec3, glm::vec3> LH, float t_small, float t_big);
+    std::pair<float, float> intersect(glm::vec3 rayPosition, glm::vec3 rayDirection, std::pair<glm::vec3, glm::vec3> LH);
     void find_intersection(glm::vec3 rayPosition, glm::vec3 rayDirection);
     void add_ray(glm::vec3 rayPosition, glm::vec3 rayDirection);
+    void display_selection_AABB(node_ptr node);
     void select_object();
     void process_mouse();
 
@@ -63,6 +66,7 @@ private:
 
     /* CONTROLS */
     int active_object_idx = -1; // FTO DO: vector of active objects
+    node_ptr active_object;
     int object_ctrl_type = 0;
     int active_camera_type = 0;
 
@@ -74,6 +78,7 @@ private:
     /* SCENE */
     std::vector<node_ptr> scene;
     node_ptr selection;
+    node_ptr selection_AABB;
 
     std::vector<light_ptr> lights;
 
diff --git a/src/studio/src/simulator.cpp b/src/studio/src/simulator.cpp
index 1846a17..f3335d8 100644
--- a/src/studio/src/simulator.cpp
+++ b/src/studio/src/simulator.cpp
@@ -10,6 +10,8 @@
 #include <vector>
 
 #include <glm/gtc/constants.hpp>
+#include <limits>
+#include <algorithm>
 
 namespace studio {
 std::vector<float> obj_vertices =
@@ -241,28 +243,28 @@ void Simulator::create_scene()
     scene.emplace_back(std::make_shared<Node>(std::make_shared<Frame>(Frame{})));
     scene.back()->addObject(std::make_shared<Object>(std::move(cube))); // TO DO: No move constructor?
     /* ADD CUBE AABB */
-    Object cube_bbox(cube.getAABB().getVertices(), cube.getAABB().getIndices(), std::vector<float>{}, glm::vec3(0.5f, 1, 0.31f), "basic");
-    cube_bbox.setDrawMode(GL_LINES);
-    // scene.emplace_back(std::make_shared<Node>(std::make_shared<Frame>(scene.back()->getFrame()->getPosition())));
-    scene.back()->addObject(std::make_shared<Object>(std::move(cube_bbox))); 
+    // Object cube_bbox(cube.getAABB().getVertices(), cube.getAABB().getIndices(), std::vector<float>{}, glm::vec3(0.5f, 1, 0.31f), "basic");
+    // cube_bbox.setDrawMode(GL_LINES);
+    // // scene.emplace_back(std::make_shared<Node>(std::make_shared<Frame>(scene.back()->getFrame()->getPosition())));
+    // scene.back()->addObject(std::make_shared<Object>(std::move(cube_bbox))); 
 
     // AXIS OBJECT
     Object axis(axis_obj_vertices, axis_obj_indices, axis_obj_normals);
     axis.setShaderType("basic");
     scene.emplace_back(std::make_shared<Node>(std::make_shared<Frame>(Frame{glm::vec3(3, 2, 0)})));
     scene.back()->addObject(std::make_shared<Object>(std::move(axis)));
-    Object axis_bbox(axis.getAABB().getVertices(), axis.getAABB().getIndices(), std::vector<float>{}, glm::vec3(0.5f, 1, 0.31f), "basic");
-    axis_bbox.setDrawMode(GL_LINES);
-    scene.back()->addObject(std::make_shared<Object>(std::move(axis_bbox)));
+    // Object axis_bbox(axis.getAABB().getVertices(), axis.getAABB().getIndices(), std::vector<float>{}, glm::vec3(0.5f, 1, 0.31f), "basic");
+    // axis_bbox.setDrawMode(GL_LINES);
+    // scene.back()->addObject(std::make_shared<Object>(std::move(axis_bbox)));
 
     // TRIANGLE
     Object triangle(triangle_vertices, triangle_indices);
     triangle.setShaderType("basic");
     scene.emplace_back(std::make_shared<Node>(std::make_shared<Frame>(Frame{glm::vec3(-2, 1, 0)})));
     scene.back()->addObject(std::make_shared<Object>(std::move(triangle)));
-    Object triangle_bbox(triangle.getAABB().getVertices(), triangle.getAABB().getIndices(), std::vector<float>{}, glm::vec3(0.5f, 1, 0.31f), "basic");
-    triangle_bbox.setDrawMode(GL_LINES);
-    scene.back()->addObject(std::make_shared<Object>(std::move(triangle_bbox)));
+    // Object triangle_bbox(triangle.getAABB().getVertices(), triangle.getAABB().getIndices(), std::vector<float>{}, glm::vec3(0.5f, 1, 0.31f), "basic");
+    // triangle_bbox.setDrawMode(GL_LINES);
+    // scene.back()->addObject(std::make_shared<Object>(std::move(triangle_bbox)));
 
     /* ADD LIGHT CUBE AND ITS LIGHT */
     scene.emplace_back(std::make_shared<Node>(std::make_shared<Frame>(Frame{glm::vec3(1.2f, 2.0f, 2.0f)})));
@@ -296,10 +298,11 @@ void Simulator::process_input()
     if (!window().has_keyboard_focus())
         return;
 
-    if (keyboard().down().contains("O"))
+    if (keyboard().down().contains("O") && selection)
     {
         for (auto &controller : obj_controls)
         {
+            controller->setFrame(selection->getFrame());
             controller->setStep(timer().dt());
             controller->move(keyboard().down());
         }
@@ -315,10 +318,62 @@ void Simulator::process_input()
     ASSUMPTION(glGetError() == GL_NO_ERROR);
 }
 
+void Simulator::intersect_axis(glm::vec3 rayPosition, glm::vec3 rayDirection, std::pair<glm::vec3, glm::vec3> LH, float t_small, float t_big)
+{
+
+}
+
+std::pair<float, float> Simulator::intersect(glm::vec3 rayPosition, glm::vec3 rayDirection, std::pair<glm::vec3, glm::vec3> LH)
+{
+    float tx;
+    float tX;
+    if (rayDirection.x == 0 && LH.first.x <= rayPosition.x && rayPosition.x <= LH.second.x)
+    {
+        tx = -std::numeric_limits<float>::infinity();
+        tX = std::numeric_limits<float>::infinity();
+    }
+    else
+    {
+        tx = glm::min((LH.first.x - rayPosition.x) / rayDirection.x, (LH.second.x - rayPosition.x) / rayDirection.x);
+        tX = glm::max((LH.first.x - rayPosition.x) / rayDirection.x, (LH.second.x - rayPosition.x) / rayDirection.x);
+    }
+
+    float ty;
+    float tY;
+    if (rayDirection.y == 0 && LH.first.y <= rayPosition.y && rayPosition.y <= LH.second.y)
+    {
+        ty = -std::numeric_limits<float>::infinity();
+        tY = std::numeric_limits<float>::infinity();
+    }
+    else
+    {
+        ty = glm::min((LH.first.y - rayPosition.y) / rayDirection.y, (LH.second.y - rayPosition.y) / rayDirection.y);
+        tY = glm::max((LH.first.y - rayPosition.y) / rayDirection.y, (LH.second.y - rayPosition.y) / rayDirection.y);
+    }
+
+    float tz;
+    float tZ;
+    if (rayDirection.z == 0 && LH.first.z <= rayPosition.z && rayPosition.z <= LH.second.z)
+    {
+        tz = -std::numeric_limits<float>::infinity();
+        tZ = std::numeric_limits<float>::infinity(); 
+    }
+    else
+    {
+        tz = glm::min((LH.first.z - rayPosition.z) / rayDirection.z, (LH.second.z - rayPosition.z) / rayDirection.z);
+        tZ = glm::max((LH.first.z - rayPosition.z) / rayDirection.z, (LH.second.z - rayPosition.z) / rayDirection.z);
+    }
+
+    float t0 = glm::max(tx, glm::max(ty, tz));
+    float t1 = glm::min(tX, glm::min(tY, tZ));
+
+    return {t0, t1};
+}
+
 void Simulator::find_intersection(glm::vec3 rayPosition, glm::vec3 rayDirection)
 {
     node_ptr nearest_node = nullptr;
-    float nearest_t = 0;
+    float nearest_t = std::numeric_limits<float>::infinity();
     for (auto &node : scene)
     {
         for (auto &object : node->getObjects())
@@ -328,11 +383,55 @@ void Simulator::find_intersection(glm::vec3 rayPosition, glm::vec3 rayDirection)
                 continue;
             
             auto LH = obj->getAABB().getLH();
-            // float t = intersect(rayPosition, rayDirection, LH);
-            // if (t < nearest_t)
-            //      nearest_t = t;
+            auto t = intersect(rayPosition, rayDirection, LH);
+            if (t.second > t.first || t.second < 0)
+                continue;
+            if (t.first < 0 && t.second < nearest_t)
+            {
+                nearest_t = t.second;
+                nearest_node = node;
+            }
+            else if (t.first < nearest_t)
+            {
+                nearest_t = t.first;
+                nearest_node = node;
+            }
         }
     }
+    if (nearest_node)
+    {
+        selection = nearest_node;
+        display_selection_AABB(nearest_node);
+    }
+    else
+    {
+        selection = nullptr;
+        if (selection_AABB)
+        {
+            // Not node tree compatible
+            auto it = std::find(scene.begin(), scene.end(), selection_AABB);
+            if (it != scene.end())
+                scene.erase(it);
+            selection_AABB = nullptr;
+        }
+    }    
+}
+
+void Simulator::display_selection_AABB(node_ptr node)
+{
+    scene.emplace_back(std::make_shared<Node>(node->getFrame()));
+    selection_AABB = scene.back();
+    for (auto &object : node->getObjects())
+    {
+        auto obj = dynamic_pointer_cast<Object>(object);
+        if (!obj)
+            continue;
+        
+        std::cout << "added AABB into scene" << std::endl;
+        Object obj_bbox(obj->getAABB().getVertices(), obj->getAABB().getIndices(), std::vector<float>{}, glm::vec3(0.5f, 1, 0.31f), "basic");
+        obj_bbox.setDrawMode(GL_LINES);
+        scene.back()->addObject(std::make_shared<Object>(std::move(obj_bbox)));
+    }
 }
 
 void Simulator::add_ray(glm::vec3 rayPosition, glm::vec3 rayDirection)
@@ -415,7 +514,7 @@ void Simulator::select_object()
     //Unproject the 2D window into 3D to see where in 3D we're actually clicking
     glm::mat4 tmpView = glm::mat4(view);
     glm::mat4 invView = glm::inverse(tmpView);
-    //Matrix4f.transform(invView, cameraSpaceNear, worldSpaceNear); ??????????????
+    // Matrix4f.transform(invView, cameraSpaceNear, worldSpaceNear); ??????????????
     glm::vec4 worldSpaceNear = invView * cameraSpaceNear;
     // Matrix4f.transform(invView, cameraSpaceFar, worldSpaceFar); ???????????????
     glm::vec4 worldSpaceFar = cameraSpaceFar * worldSpaceFar;
@@ -430,6 +529,8 @@ void Simulator::select_object()
     rayDirection = glm::normalize(rayDirection);
 
     std::cout << "rayDirection vector is: " << rayDirection.x << ", " << rayDirection.y << ", " << rayDirection.z << std::endl << std::endl;
+
+    find_intersection(rayPosition, rayDirection);
 }
 
 void Simulator::process_mouse()
-- 
GitLab