From 29a9b1daf8fdd1fdf92f6f8479a3fba0003c2c65 Mon Sep 17 00:00:00 2001 From: brunoherbelin Date: Sun, 13 Sep 2020 00:06:23 +0200 Subject: [PATCH] Fixed picking visitor and source node inclusion test for source manipulation in GeometryView --- PickingVisitor.cpp | 16 +++++----------- PickingVisitor.h | 6 +++++- Scene.cpp | 2 +- Source.cpp | 7 +++++++ View.cpp | 34 ++++++++++++++++++---------------- 5 files changed, 36 insertions(+), 29 deletions(-) diff --git a/PickingVisitor.cpp b/PickingVisitor.cpp index 415f162..c261715 100644 --- a/PickingVisitor.cpp +++ b/PickingVisitor.cpp @@ -29,10 +29,6 @@ void PickingVisitor::visit(Node &n) { // use the transform modified during update modelview_ *= n.transform_; - -// modelview_ *= transform(n.translation_, n.rotation_, n.scale_); -// Log::Info("Node %d", n.id()); -// Log::Info("%s", glm::to_string(modelview_).c_str()); } void PickingVisitor::visit(Group &n) @@ -73,26 +69,24 @@ void PickingVisitor::visit(Surface &n) // create bounding box for those points (2 in practice) GlmToolkit::AxisAlignedBoundingBox bb_points; bb_points.extend(points_); - // apply inverse transform bb_points = bb_points.transformed(glm::inverse(modelview_)) ; - // test bounding box for overlap with inverse transform bbox - if ( bb_points.intersect( n.bbox() ) ) -// if ( n.bbox().contains( bb_points ) ) + if ( bb_points.intersect( n.bbox() ) ) { +// if ( n.bbox().contains( bb_points ) ) // alternative selection by total inclusion of source inside BB // add this surface to the nodes picked nodes_.push_back( std::pair(&n, glm::vec2(0.f)) ); + } } // only one point else if (points_.size() > 0) { - // apply inverse transform to the point of interest glm::vec4 P = glm::inverse(modelview_) * glm::vec4( points_[0], 1.f ); - // test bounding box for picking from a single point - if ( n.bbox().contains( glm::vec3(P)) ) + if ( n.bbox().contains( glm::vec3(P)) ) { // add this surface to the nodes picked nodes_.push_back( std::pair(&n, glm::vec2(P)) ); + } } } diff --git a/PickingVisitor.h b/PickingVisitor.h index 6c7d681..eda682a 100644 --- a/PickingVisitor.h +++ b/PickingVisitor.h @@ -26,7 +26,11 @@ public: PickingVisitor(glm::vec3 coordinates); PickingVisitor(glm::vec3 selectionstart, glm::vec3 selection_end); - std::vector< std::pair > picked() { return nodes_; } + + bool empty() const {return nodes_.empty(); } + std::pair back() const { return nodes_.back(); } + std::vector< std::pair >::const_reverse_iterator rbegin() { return nodes_.rbegin(); } + std::vector< std::pair >::const_reverse_iterator rend() { return nodes_.rend(); } // Elements of Scene void visit(Scene& n) override; diff --git a/Scene.cpp b/Scene.cpp index 3ee4ada..d391cf4 100644 --- a/Scene.cpp +++ b/Scene.cpp @@ -24,7 +24,7 @@ Node::Node() : initialized_(false), visible_(true), refcount_(0) { // create unique id auto duration = std::chrono::high_resolution_clock::now().time_since_epoch(); - id_ = std::chrono::duration_cast(duration).count() % 1000000000; + id_ = std::chrono::duration_cast(duration).count() % 100000000; transform_ = glm::identity(); scale_ = glm::vec3(1.f); diff --git a/Source.cpp b/Source.cpp index b0a91ec..941ac55 100644 --- a/Source.cpp +++ b/Source.cpp @@ -388,11 +388,18 @@ bool Source::hasNode::operator()(const Source* elem) const // general case: traverse tree of all Groups recursively using a SearchVisitor SearchVisitor sv(_n); + // search in groups for all views for (auto g = elem->groups_.begin(); g != elem->groups_.end(); g++) { (*g).second->accept(sv); if (sv.found()) return true; } + // search in overlays for all views + for (auto g = elem->overlays_.begin(); g != elem->overlays_.end(); g++) { + (*g).second->accept(sv); + if (sv.found()) + return true; + } } return false; diff --git a/View.cpp b/View.cpp index 9a42dc7..08e2083 100644 --- a/View.cpp +++ b/View.cpp @@ -99,9 +99,9 @@ std::pair View::pick(glm::vec2 P) scene.accept(pv); // picking visitor found nodes? - if ( !pv.picked().empty()) { + if ( !pv.empty()) { // select top-most Node picked - pick = pv.picked().back(); + pick = pv.back(); } return pick; @@ -193,13 +193,14 @@ void View::select(glm::vec2 A, glm::vec2 B) Mixer::selection().clear(); // picking visitor found nodes in the area? - if ( !pv.picked().empty()) { + if ( !pv.empty()) { // create a list of source matching the list of picked nodes SourceList selection; - std::vector< std::pair > pick = pv.picked(); +// std::vector< std::pair > pick = pv.picked(); // loop over the nodes and add all sources found. - for(std::vector< std::pair >::iterator p = pick.begin(); p != pick.end(); p++){ +// for(std::vector< std::pair >::iterator p = pick.begin(); p != pick.end(); p++){ + for(std::vector< std::pair >::const_reverse_iterator p = pv.rbegin(); p != pv.rend(); p++){ Source *s = Mixer::manager().findSource( p->first ); if (s) selection.push_back( s ); @@ -756,28 +757,29 @@ std::pair GeometryView::pick(glm::vec2 P) scene.accept(pv); // picking visitor found nodes? - if ( pv.picked().size() > 0) { - + if ( !pv.empty() ) { + // keep current source active if it is clicked Source *s = Mixer::manager().currentSource(); if (s != nullptr) { - // find if the current source was picked - auto itp = pv.picked().rbegin(); - for (; itp != pv.picked().rend(); itp++){ - if ( s->contains( (*itp).first ) ){ + auto itp = pv.rbegin(); + for (; itp != pv.rend(); itp++){ + // test if source contains this node + Source::hasNode is_in_source((*itp).first ); + if ( is_in_source( s ) ){ + // a node in the current source was clicked ! pick = *itp; break; } } // not found: the current source was not clicked - if (itp == pv.picked().rend()) + if (itp == pv.rend()) s = nullptr; } - // maybe the source changed - if (s == nullptr) - { + // the clicked source changed (not the current source) + if (s == nullptr) { // select top-most Node picked - pick = pv.picked().back(); + pick = pv.back(); } }