diff --git a/src/algo/include/algo/raycast.hpp b/src/algo/include/algo/raycast.hpp index 1aaffe0ea59c7360e52c5ecdf83be5240c850603..104647e6484585b7919199fc8c0181bb6af0a808 100644 --- a/src/algo/include/algo/raycast.hpp +++ b/src/algo/include/algo/raycast.hpp @@ -7,6 +7,7 @@ #include <osi/window.hpp> #include <utils/math.hpp> +#include <array> #include <memory> #include <utility> #include <vector> @@ -16,7 +17,9 @@ using scene_ptr = std::shared_ptr<Scene>; std::pair<float, float> intersect_axis(float ray_direction_a, float ray_position_a, float LH_first_a, float LH_second_a); std::pair<float, float> intersect(glm::vec3 ray_position, glm::vec3 ray_direction, std::pair<glm::vec3, glm::vec3> LH); // findIntersection uses functions 'intersect_axis' and 'intersect' and is NOT node tree compatible yet -node_ptr find_intersection(const std::vector<node_ptr> &scene, glm::vec3 ray_position, glm::vec3 ray_direction); +std::pair<glm::vec3, node_ptr> find_intersection(const std::vector<node_ptr> &scene, glm::vec3 ray_position, glm::vec3 ray_direction); + +std::array<glm::vec3, 4> find_cube_side(node_ptr node, glm::vec3 hit_coords); std::pair<glm::vec3, glm::vec3> get_pick_ray(const scene_ptr &scene, const osi::Mouse &mouse, const osi::Window &window); diff --git a/src/algo/src/raycast.cpp b/src/algo/src/raycast.cpp index 82d3becf618af4bbba25463c32ccf22745c2a4a9..69f5aff59d634e7276f746c809b3d9896bee2145 100644 --- a/src/algo/src/raycast.cpp +++ b/src/algo/src/raycast.cpp @@ -1,9 +1,15 @@ #include <algo/raycast.hpp> +#include <edit/scene.hpp> #include <gfx/camera.hpp> #include <gfx/mesh.hpp> #include <gfx/render.hpp> +#include <utils/math.hpp> +#include <algorithm> #include <limits> +#include <map> + +using scene_ptr = std::shared_ptr<Scene>; std::pair<float, float> intersect_axis(float ray_direction_a, float ray_position_a, float LH_first_a, float LH_second_a) @@ -39,7 +45,7 @@ std::pair<float, float> intersect(glm::vec3 ray_position, glm::vec3 ray_directio return {t0, t1}; } -node_ptr find_intersection(const std::vector<node_ptr> &scene, glm::vec3 ray_position, glm::vec3 ray_direction) +std::pair<glm::vec3, node_ptr> find_intersection(const std::vector<node_ptr> &scene, glm::vec3 ray_position, glm::vec3 ray_direction) { node_ptr nearest_node = nullptr; float nearest_t = std::numeric_limits<float>::infinity(); @@ -69,7 +75,47 @@ node_ptr find_intersection(const std::vector<node_ptr> &scene, glm::vec3 ray_pos } } - return nearest_node; + return { ray_position + (nearest_t * ray_direction), nearest_node }; +} + +std::array<glm::vec3, 4> nearest_vertices(std::array<glm::vec3, 8> AABB_local, std::array<glm::vec3, 8> AABB_world, glm::vec3 hit_coords) +{ + std::map<float, std::vector<glm::vec3>> candidates; + for (int i = 0; i < 8; ++i) + { + candidates[glm::distance(AABB_world[i], hit_coords)].emplace_back(AABB_local[i]); + } + + std::array<glm::vec3, 4> result; + int i = 0; + for (auto [dist, vertices] : candidates) + { + for (auto vertex : vertices) + { + if (i >= 4) + break; + result[i] = vertex; + ++i; + } + } + return result; +} + +std::array<glm::vec3, 4> find_cube_side(node_ptr node, glm::vec3 hit_coords) +{ + std::array<glm::vec3, 4> side_vertices; + for (auto &object : node->getObjects()) + { + auto obj = dynamic_pointer_cast<Mesh>(object); + if (!obj) + continue; + + auto AABB_local = obj->getAABB().getFullAABB(); + auto AABB_world = obj->getAABB().getAABBWorld(node); + side_vertices = nearest_vertices(AABB_local, AABB_world , hit_coords); + break; // possibly not needed - should receive selection_AABB node + } + return side_vertices; } std::pair<glm::vec3, glm::vec3> get_pick_ray_perspective(const camera_ptr &camera, const glm::mat4 view, const osi::Mouse &mouse, const osi::Window &window) diff --git a/src/common/include/common/aabb.hpp b/src/common/include/common/aabb.hpp index 64fd9aeac399ab075b2542fa84859c457a464af1..63cf9400dbcdbb1b4180d99d403eb53c63d3152e 100644 --- a/src/common/include/common/aabb.hpp +++ b/src/common/include/common/aabb.hpp @@ -17,14 +17,17 @@ class AABB std::array<glm::vec3, 8> full_bbox; void findLH(std::vector<float> const &vertices); - void getFullAABB(); + void createFullAABB(); public: AABB(std::vector<float> const &vertices); std::pair<glm::vec3, glm::vec3> const &getLH() const { return LH; } + std::array<glm::vec3, 8> const &getFullAABB() const { return full_bbox; } std::vector<float> getVertices() const; std::vector<unsigned int> getIndices() const; + std::pair<glm::vec3, glm::vec3> getLHWorld(node_ptr node) const; + std::array<glm::vec3, 8> getAABBWorld(node_ptr node) const; }; #endif \ No newline at end of file diff --git a/src/common/src/aabb.cpp b/src/common/src/aabb.cpp index c75a59f531e29d0d819e222d89d948a013db8545..a579ee1de5b8963c5f24d65269f6bc2f5701b526 100644 --- a/src/common/src/aabb.cpp +++ b/src/common/src/aabb.cpp @@ -3,7 +3,7 @@ AABB::AABB(std::vector<float> const &vertices) { findLH(vertices); - getFullAABB(); + createFullAABB(); } void AABB::findLH(std::vector<float> const &vertices) @@ -24,7 +24,7 @@ void AABB::findLH(std::vector<float> const &vertices) } } -void AABB::getFullAABB() +void AABB::createFullAABB() { full_bbox[0] = LH.first; @@ -74,4 +74,19 @@ std::pair<glm::vec3, glm::vec3> AABB::getLHWorld(node_ptr node) const LH_world.second = node_trans * node_scale * glm::vec4(LH.second, 1); return LH_world; +} +std::array<glm::vec3, 8> AABB::getAABBWorld(node_ptr node) const +{ + std::array<glm::vec3, 8> AABB_world; + + auto node_trans = node->getFrame()->getTranslationMat(); + auto node_scale = node->getFrame()->getScaleMat(); + + for (int i = 0; i < 8; ++i) + { + AABB_world[i] = node_trans * node_scale * glm::vec4(full_bbox[i], 1); + } + + + return AABB_world; } \ No newline at end of file diff --git a/src/edit/include/edit/editor.hpp b/src/edit/include/edit/editor.hpp index 0d82a41d21c5f485a9365820c65d54434c5482c3..118737811fdc134f89c78dca30293740d41c920b 100644 --- a/src/edit/include/edit/editor.hpp +++ b/src/edit/include/edit/editor.hpp @@ -81,11 +81,11 @@ public: void setPrevPlaneIntersect(glm::vec3 _prev_plane_intersect) { prev_plane_intersect = _prev_plane_intersect; } void doObjectAction(scene_ptr scene, ctrlhub_ptr controls); - void updateAxesCamera(scene_ptr scene, ctrlhub_ptr controls); + void changeOrthoCamAxes(scene_ptr scene, ctrlhub_ptr controls); void changeLevel(scene_ptr scene, ctrlhub_ptr controls); void adjustGridPosition(scene_ptr scene, ctrlhub_ptr controls, glm::vec3 position); - void adjustGridRotation(scene_ptr scene, ctrlhub_ptr controls, glm::vec3 rotation); + void adjustGridRotation(scene_ptr scene, ctrlhub_ptr controls, glm::quat rotation); void selectObject(scene_ptr scene, ctrlhub_ptr controls); void rotateObject(scene_ptr scene, ctrlhub_ptr controls); diff --git a/src/edit/include/edit/scene.hpp b/src/edit/include/edit/scene.hpp index c3033841268ac35f51380d10ec7c62214bcbc54b..f88ed6815e16848311cb6d20e7ab16e1bdfd0472 100644 --- a/src/edit/include/edit/scene.hpp +++ b/src/edit/include/edit/scene.hpp @@ -23,6 +23,7 @@ private: std::vector<node_ptr> scene; node_ptr selection; node_ptr selection_AABB; + node_ptr side_higlight; node_ptr pre_add_AABB; node_ptr grid; @@ -90,12 +91,14 @@ public: void addRay(glm::vec3 ray_position, glm::vec3 ray_direction); void addSelectionAABB(node_ptr node); void addPreAddAABB(node_ptr node, Frame position); + void addSideHighlight(node_ptr node, std::array<glm::vec3, 4> &side_vertices); void findLights(const std::vector<node_ptr> &nodes); void findCameras(const std::vector<node_ptr> &nodes); void changeDrawMode(node_ptr node, unsigned int mode); void manageSelection(node_ptr nearest_node); // Not node tree compatible + void manageHighlight(glm::vec3 hit_coord, node_ptr nearest_node); }; #endif \ No newline at end of file diff --git a/src/edit/src/editor.cpp b/src/edit/src/editor.cpp index 60cb236c6b62780c6af06190d835215fb9c6d665..7de8aa34e3355a2c73f507b29ae2a582305bdb5b 100644 --- a/src/edit/src/editor.cpp +++ b/src/edit/src/editor.cpp @@ -24,7 +24,7 @@ void Editor::doObjectAction(scene_ptr scene, ctrlhub_ptr controls) } } -void Editor::updateAxesCamera(scene_ptr scene, ctrlhub_ptr controls) +void Editor::changeOrthoCamAxes(scene_ptr scene, ctrlhub_ptr controls) { if (!keyboard.just_pressed().contains("I") && !keyboard.just_pressed().contains("K") @@ -32,13 +32,13 @@ void Editor::updateAxesCamera(scene_ptr scene, ctrlhub_ptr controls) return; glm::vec3 cam_levels = build_level.getAll(); - std::array<glm::vec3, 3> rotations = { glm::vec3(0.0f, -90.0f, 0.0f), // L(x-depth) - glm::vec3(-90.0f, 0.0f, 0.0f), // I (y-depth) // FIX - breaks things - glm::vec3(0.0f, 180.0f, 0.0f) }; // K (z-depth) + std::array<glm::quat, 3> rotations = { glm::angleAxis(glm::radians(-90.0f), glm::vec3(0.0f, 1.0f, 0.0f)), // L(x-depth) + glm::angleAxis(glm::radians(-90.0f), glm::vec3(1.0f, 0.0f, 0.0f)), // I (y-depth) // FIX - breaks things + glm::angleAxis(glm::radians(180.0f), glm::vec3(0.0f, 1.0f, 0.0f)) }; // K (z-depth) - std::array<glm::vec3, 3> grid_rotations = { glm::vec3(-90.0f, -90.0f, 0.0f), // L(x-depth) - glm::vec3(0.0f, 0.0f, 0.0f), // I (y-depth) - glm::vec3(-90.0f, 0.0f, 0.0f) }; // K (z-depth) + std::array<glm::quat, 3> grid_rotations = {glm::angleAxis(glm::radians(-90.0f), glm::vec3(1.0f, 0.0f, 0.0f)) * glm::angleAxis(glm::radians(-90.0f), glm::vec3(0.0f, 1.0f, 0.0f)), // L(x-depth) + glm::quat(), // I (y-depth) + glm::angleAxis(glm::radians(-90.0f), glm::vec3(1.0f, 0.0f, 0.0f)) }; // K (z-depth) std::uint8_t new_active = 0; if (keyboard.just_pressed().contains("I")) @@ -51,16 +51,14 @@ void Editor::updateAxesCamera(scene_ptr scene, ctrlhub_ptr controls) new_active = 0; cam_levels[new_active] += new_active == 1 ? 5.0f : -5.0f; // +5 for up-down, else -5 - build_level.setActiveIndex(new_active); + // build_level.setActiveIndex(new_active); controls->getActiveCamCtrl()->setRotation(rotations[new_active]); controls->getActiveCamCtrl()->setPos(cam_levels[0], cam_levels[1], cam_levels[2]); - // NOTE: grid could have its own controller ? - // scene->getGrid()->getFrame()->setRotationQuat(grid_rotations[new_active]); - adjustGridRotation(scene, controls, grid_rotations[new_active]); + // adjustGridRotation(scene, controls, grid_rotations[new_active]); } -void Editor::changeLevel(scene_ptr scene, ctrlhub_ptr controls) +void Editor::changeLevel(scene_ptr scene, ctrlhub_ptr controls) // Unused & incorrect { auto prev_build_level = build_level; if (keyboard.just_pressed().contains("P")) @@ -69,7 +67,7 @@ void Editor::changeLevel(scene_ptr scene, ctrlhub_ptr controls) if (keyboard.just_pressed().contains("O")) --build_level; - adjustGridPosition(scene, controls, build_level - prev_build_level); + // adjustGridPosition(scene, controls, build_level - prev_build_level); } void Editor::adjustGridPosition(scene_ptr scene, ctrlhub_ptr controls, glm::vec3 position) @@ -80,13 +78,12 @@ void Editor::adjustGridPosition(scene_ptr scene, ctrlhub_ptr controls, glm::vec3 controls->bindObject(prev_active_object); } -void Editor::adjustGridRotation(scene_ptr scene, ctrlhub_ptr controls, glm::vec3 rotation) +void Editor::adjustGridRotation(scene_ptr scene, ctrlhub_ptr controls, glm::quat rotation) { auto prev_active_object = controls->getActiveObjCtrl()->getFrame(); controls->bindObject(scene->getGrid()->getFrame()); controls->getActiveObjCtrl()->setRotation(rotation); controls->bindObject(prev_active_object); - } void Editor::selectObject(scene_ptr scene, ctrlhub_ptr controls) @@ -96,9 +93,10 @@ void Editor::selectObject(scene_ptr scene, ctrlhub_ptr controls) auto [ ray_position, ray_direction ] = get_pick_ray(scene, mouse, window); - auto nearest_node = find_intersection(scene->getScene(), ray_position, ray_direction); + auto [ hit_coord, nearest_node ] = find_intersection(scene->getScene(), ray_position, ray_direction); scene->manageSelection(nearest_node); + scene->manageHighlight(hit_coord, nearest_node); } void Editor::rotateObject(scene_ptr scene, ctrlhub_ptr controls) @@ -129,7 +127,7 @@ void Editor::moveObject(scene_ptr scene, ctrlhub_ptr controls) auto [ ray_position, ray_direction ] = get_pick_ray(scene, mouse, window); // Initial click not onto the selected object - if (!object_moving && find_intersection(scene->getScene(), ray_position, ray_direction) != scene->getSelection()) + if (!object_moving && find_intersection(scene->getScene(), ray_position, ray_direction).second != scene->getSelection()) return; /* Controller setup */ diff --git a/src/edit/src/scene.cpp b/src/edit/src/scene.cpp index 08da752354dc043df990d1c23b5fbb26a1198fd0..7207f4f769eaeede3ccf0c1452f094ce61636e52 100644 --- a/src/edit/src/scene.cpp +++ b/src/edit/src/scene.cpp @@ -1,4 +1,5 @@ #include <edit/scene.hpp> +#include <algo/raycast.hpp> #include <gfx/shapes.hpp> #include <gfx/render.hpp> // for grid vertices #include <filein/obj_loader.hpp> @@ -21,16 +22,20 @@ void Scene::createScene() addNode(Frame{}); addMesh(scene.back(), cube); + scene.back()->getFrame()->setScale(glm::vec3(0.5f, 0.5f, 0.5f)); addNode(glm::vec3(5, 1, -4)); addMesh(scene.back(), cube); - addNode(glm::vec3(2, 0, 1)); + addNode(glm::vec3(1, 0, 1)); addMesh(scene.back(), cube); - addNode(glm::vec3(2, 2, 1)); + scene.back()->getFrame()->setScale(glm::vec3(0.5f, 0.5f, 0.5f)); + addNode(glm::vec3(1, 1, 1)); addMesh(scene.back(), cube); - addNode(glm::vec3(2, 2, 2)); + scene.back()->getFrame()->setScale(glm::vec3(0.5f, 0.5f, 0.5f)); + addNode(glm::vec3(1, 1, 2)); addMesh(scene.back(), cube); + scene.back()->getFrame()->setScale(glm::vec3(0.5f, 0.5f, 0.5f)); /* ADD AXIS OBJECT */ // Mesh axis(axis_obj_vertices, axis_obj_indices, axis_obj_normals); @@ -278,6 +283,27 @@ void Scene::addPreAddAABB(node_ptr node, Frame position) addMesh(scene.back(), std::move(obj_bbox)); } } +void Scene::addSideHighlight(node_ptr node, std::array<glm::vec3, 4> &side_vertices) +{ + addNode(node->getFrame()); + side_higlight = scene.back(); + std::vector<float> vertices; + for (auto v : side_vertices) + { + vertices.emplace_back(v.x); + vertices.emplace_back(v.y); + vertices.emplace_back(v.z - 0.05f); // TO DO: determine which side and offset higlight in front + } + + std::vector<float> normals; + std::vector<unsigned int> indices = { 0, 1, 2, 1, 2, 3 }; + + Mesh m(vertices, indices, std::vector<float>{}, glm::vec3(0.0f, 1.0f, 0.0f), "basic"); + m.setSelectability(false); + + addMesh(side_higlight, std::move(m)); +} + void Scene::findLights(const std::vector<node_ptr> &nodes) { for (auto &node : nodes) @@ -328,3 +354,16 @@ void Scene::manageSelection(node_ptr nearest_node) selection = nearest_node; addSelectionAABB(nearest_node); } + +void Scene::manageHighlight(glm::vec3 hit_coord, node_ptr selection_AABB) +{ + removeNode(side_higlight); + if (!selection_AABB) + { + side_higlight = nullptr; + return; + } + + auto side_vertices = find_cube_side(selection_AABB, hit_coord); + addSideHighlight(selection_AABB, side_vertices); +} diff --git a/src/studio/src/simulator.cpp b/src/studio/src/simulator.cpp index 32f19896c104f05981f7b1b21ef10c183d4c08c2..36abbe39605e018e351f7867c9caa28bd6be8acd 100644 --- a/src/studio/src/simulator.cpp +++ b/src/studio/src/simulator.cpp @@ -37,12 +37,14 @@ void Simulator::update() controls->processInput(scene, keyboard(), timer(), window()); controls->processMouse(mouse(), window(), editor->getEditorRunning()); - editor->updateAxesCamera(scene, controls); editor->doObjectAction(scene, controls); - editor->changeLevel(scene, controls); + editor->changeOrthoCamAxes(scene, controls); + // editor->changeLevel(scene, controls); auto cam_frame = scene->getActiveCameras()[0].lock()->getFrame()->getPosition(); - std::cout << "Camera coords: X " << cam_frame.x << " | Y " << cam_frame.y << " | Z " << cam_frame.z << std::endl; + auto cam_front_vec = controls->getActiveCamCtrl()->getFrontVec(); + // std::cout << "Camera coords: X " << cam_frame.x << " | Y " << cam_frame.y << " | Z " << cam_frame.z << std::endl; + // std::cout << "Camera frontVec: X " << cam_front_vec.x << " | Y " << cam_front_vec.y << " | Z " << cam_front_vec.z << std::endl; /* Rotation around x-axis demo */ // controls->rotate_obj(glm::vec3(1.0f, 0.0f, 0.0f));