mirror of
https://github.com/brunoherbelin/vimix.git
synced 2025-12-11 18:34:58 +01:00
Fixed picking visitor and source node inclusion test for source
manipulation in GeometryView
This commit is contained in:
@@ -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)) );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
34
View.cpp
34
View.cpp
@@ -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();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user