Fixed picking visitor and source node inclusion test for source

manipulation in GeometryView
This commit is contained in:
brunoherbelin
2020-09-13 00:06:23 +02:00
parent 526e0f29cb
commit 29a9b1daf8
5 changed files with 36 additions and 29 deletions

View File

@@ -29,10 +29,6 @@ void PickingVisitor::visit(Node &n)
{ {
// use the transform modified during update // use the transform modified during update
modelview_ *= n.transform_; 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) void PickingVisitor::visit(Group &n)
@@ -73,26 +69,24 @@ void PickingVisitor::visit(Surface &n)
// create bounding box for those points (2 in practice) // create bounding box for those points (2 in practice)
GlmToolkit::AxisAlignedBoundingBox bb_points; GlmToolkit::AxisAlignedBoundingBox bb_points;
bb_points.extend(points_); bb_points.extend(points_);
// apply inverse transform // apply inverse transform
bb_points = bb_points.transformed(glm::inverse(modelview_)) ; bb_points = bb_points.transformed(glm::inverse(modelview_)) ;
// test bounding box for overlap with inverse transform bbox // test bounding box for overlap with inverse transform bbox
if ( bb_points.intersect( n.bbox() ) ) if ( bb_points.intersect( n.bbox() ) ) {
// if ( n.bbox().contains( bb_points ) ) // if ( n.bbox().contains( bb_points ) ) // alternative selection by total inclusion of source inside BB
// add this surface to the nodes picked // add this surface to the nodes picked
nodes_.push_back( std::pair(&n, glm::vec2(0.f)) ); nodes_.push_back( std::pair(&n, glm::vec2(0.f)) );
}
} }
// only one point // only one point
else if (points_.size() > 0) { else if (points_.size() > 0) {
// apply inverse transform to the point of interest // apply inverse transform to the point of interest
glm::vec4 P = glm::inverse(modelview_) * glm::vec4( points_[0], 1.f ); glm::vec4 P = glm::inverse(modelview_) * glm::vec4( points_[0], 1.f );
// test bounding box for picking from a single point // 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 // add this surface to the nodes picked
nodes_.push_back( std::pair(&n, glm::vec2(P)) ); nodes_.push_back( std::pair(&n, glm::vec2(P)) );
}
} }
} }

View File

@@ -26,7 +26,11 @@ public:
PickingVisitor(glm::vec3 coordinates); PickingVisitor(glm::vec3 coordinates);
PickingVisitor(glm::vec3 selectionstart, glm::vec3 selection_end); PickingVisitor(glm::vec3 selectionstart, glm::vec3 selection_end);
std::vector< std::pair<Node *, glm::vec2> > picked() { return nodes_; }
bool empty() const {return nodes_.empty(); }
std::pair<Node *, glm::vec2> back() const { return nodes_.back(); }
std::vector< std::pair<Node *, glm::vec2> >::const_reverse_iterator rbegin() { return nodes_.rbegin(); }
std::vector< std::pair<Node *, glm::vec2> >::const_reverse_iterator rend() { return nodes_.rend(); }
// Elements of Scene // Elements of Scene
void visit(Scene& n) override; void visit(Scene& n) override;

View File

@@ -24,7 +24,7 @@ Node::Node() : initialized_(false), visible_(true), refcount_(0)
{ {
// create unique id // create unique id
auto duration = std::chrono::high_resolution_clock::now().time_since_epoch(); auto duration = std::chrono::high_resolution_clock::now().time_since_epoch();
id_ = std::chrono::duration_cast<std::chrono::nanoseconds>(duration).count() % 1000000000; id_ = std::chrono::duration_cast<std::chrono::nanoseconds>(duration).count() % 100000000;
transform_ = glm::identity<glm::mat4>(); transform_ = glm::identity<glm::mat4>();
scale_ = glm::vec3(1.f); scale_ = glm::vec3(1.f);

View File

@@ -388,11 +388,18 @@ bool Source::hasNode::operator()(const Source* elem) const
// general case: traverse tree of all Groups recursively using a SearchVisitor // general case: traverse tree of all Groups recursively using a SearchVisitor
SearchVisitor sv(_n); SearchVisitor sv(_n);
// search in groups for all views
for (auto g = elem->groups_.begin(); g != elem->groups_.end(); g++) { for (auto g = elem->groups_.begin(); g != elem->groups_.end(); g++) {
(*g).second->accept(sv); (*g).second->accept(sv);
if (sv.found()) if (sv.found())
return true; 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; return false;

View File

@@ -99,9 +99,9 @@ std::pair<Node *, glm::vec2> View::pick(glm::vec2 P)
scene.accept(pv); scene.accept(pv);
// picking visitor found nodes? // picking visitor found nodes?
if ( !pv.picked().empty()) { if ( !pv.empty()) {
// select top-most Node picked // select top-most Node picked
pick = pv.picked().back(); pick = pv.back();
} }
return pick; return pick;
@@ -193,13 +193,14 @@ void View::select(glm::vec2 A, glm::vec2 B)
Mixer::selection().clear(); Mixer::selection().clear();
// picking visitor found nodes in the area? // 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 // create a list of source matching the list of picked nodes
SourceList selection; SourceList selection;
std::vector< std::pair<Node *, glm::vec2> > pick = pv.picked(); // std::vector< std::pair<Node *, glm::vec2> > pick = pv.picked();
// loop over the nodes and add all sources found. // loop over the nodes and add all sources found.
for(std::vector< std::pair<Node *, glm::vec2> >::iterator p = pick.begin(); p != pick.end(); p++){ // for(std::vector< std::pair<Node *, glm::vec2> >::iterator p = pick.begin(); p != pick.end(); p++){
for(std::vector< std::pair<Node *, glm::vec2> >::const_reverse_iterator p = pv.rbegin(); p != pv.rend(); p++){
Source *s = Mixer::manager().findSource( p->first ); Source *s = Mixer::manager().findSource( p->first );
if (s) if (s)
selection.push_back( s ); selection.push_back( s );
@@ -756,28 +757,29 @@ std::pair<Node *, glm::vec2> GeometryView::pick(glm::vec2 P)
scene.accept(pv); scene.accept(pv);
// picking visitor found nodes? // 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(); Source *s = Mixer::manager().currentSource();
if (s != nullptr) { if (s != nullptr) {
// find if the current source was picked // find if the current source was picked
auto itp = pv.picked().rbegin(); auto itp = pv.rbegin();
for (; itp != pv.picked().rend(); itp++){ for (; itp != pv.rend(); itp++){
if ( s->contains( (*itp).first ) ){ // 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; pick = *itp;
break; break;
} }
} }
// not found: the current source was not clicked // not found: the current source was not clicked
if (itp == pv.picked().rend()) if (itp == pv.rend())
s = nullptr; s = nullptr;
} }
// maybe the source changed // the clicked source changed (not the current source)
if (s == nullptr) if (s == nullptr) {
{
// select top-most Node picked // select top-most Node picked
pick = pv.picked().back(); pick = pv.back();
} }
} }