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
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)) );
}
}
}

View File

@@ -26,7 +26,11 @@ public:
PickingVisitor(glm::vec3 coordinates);
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
void visit(Scene& n) override;

View File

@@ -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<std::chrono::nanoseconds>(duration).count() % 1000000000;
id_ = std::chrono::duration_cast<std::chrono::nanoseconds>(duration).count() % 100000000;
transform_ = glm::identity<glm::mat4>();
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
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;

View File

@@ -99,9 +99,9 @@ std::pair<Node *, glm::vec2> 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<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.
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 );
if (s)
selection.push_back( s );
@@ -756,28 +757,29 @@ std::pair<Node *, glm::vec2> 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();
}
}