Implemented selection of multiple sources

This commit is contained in:
brunoherbelin
2020-06-15 23:38:01 +02:00
parent bfdeb0b52f
commit 89fed033e9
10 changed files with 140 additions and 59 deletions

View File

@@ -95,7 +95,7 @@ void Frame::draw(glm::mat4 modelview, glm::mat4 projection)
// shadow (scaled)
if(shadow_){
shadow_->shader()->color.a = 0.8f;
shadow_->shader()->color.a = 0.98f;
shadow_->draw( ctm, projection);
}

View File

@@ -22,7 +22,7 @@ GlmToolkit::AxisAlignedBoundingBox::AxisAlignedBoundingBox() {
mMax = glm::vec3(-1.f);
}
void GlmToolkit::AxisAlignedBoundingBox::extend(const glm::vec3& point)
void GlmToolkit::AxisAlignedBoundingBox::extend(const glm::vec3& point) // TODO why ref to point?
{
if (isNull()) {
mMin = point;

View File

@@ -12,9 +12,17 @@
#include <glm/gtx/vector_angle.hpp>
PickingVisitor::PickingVisitor(glm::vec2 coordinates) : Visitor(), point_(coordinates)
PickingVisitor::PickingVisitor(glm::vec3 coordinates) : Visitor()
{
modelview_ = glm::mat4(1.f);
points_.push_back( coordinates );
}
PickingVisitor::PickingVisitor(glm::vec3 selectionstart, glm::vec3 selection_end) : Visitor()
{
modelview_ = glm::mat4(1.f);
points_.push_back( selectionstart );
points_.push_back( selection_end );
}
void PickingVisitor::visit(Node &n)
@@ -31,6 +39,7 @@ void PickingVisitor::visit(Group &n)
{
if (!n.visible_)
return;
glm::mat4 mv = modelview_;
for (NodeSet::iterator node = n.begin(); node != n.end(); node++) {
if ( (*node)->visible_ )
@@ -43,6 +52,7 @@ void PickingVisitor::visit(Switch &n)
{
if (!n.visible_ || n.numChildren()<1)
return;
glm::mat4 mv = modelview_;
n.activeChild()->accept(*this);
modelview_ = mv;
@@ -59,13 +69,32 @@ void PickingVisitor::visit(Surface &n)
if (!n.visible_)
return;
// apply inverse transform to the point of interest
glm::vec4 P = glm::inverse(modelview_) * glm::vec4( point_, 0.f, 1.f );
// if more than one point given for testing: test overlap
if (points_.size() > 1) {
// create bounding box for those points (2 in practice)
GlmToolkit::AxisAlignedBoundingBox bb_points;
bb_points.extend(points_);
// test bounding box: it is an exact fit for a resctangular surface
if ( n.bbox().contains( glm::vec3(P)) )
// add this surface to the nodes picked
nodes_.push_back( std::pair(&n, glm::vec2(P)) );
// 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 ) )
// 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)) )
// add this surface to the nodes picked
nodes_.push_back( std::pair(&n, glm::vec2(P)) );
}
}
void PickingVisitor::visit(Frame &n)
@@ -76,11 +105,12 @@ void PickingVisitor::visit(Frame &n)
void PickingVisitor::visit(Handles &n)
{
if (!n.visible_)
// discard if not visible or if not exactly one point given for picking
if (!n.visible_ || points_.size() != 1)
return;
// apply inverse transform to the point of interest
glm::vec4 P = glm::inverse(modelview_) * glm::vec4( point_, 0.f, 1.f );
glm::vec4 P = glm::inverse(modelview_) * glm::vec4( points_[0], 1.f );
// inverse transform to check the scale
glm::vec4 S = glm::inverse(modelview_) * glm::vec4( 0.05f, 0.05f, 0.f, 0.f );
@@ -108,7 +138,7 @@ void PickingVisitor::visit(Handles &n)
// the icon for rotation is on the right top corner at (0.12, 0.12) in scene coordinates
glm::vec4 vec = glm::inverse(modelview_) * glm::vec4( 0.1f, 0.1f, 0.f, 0.f );
float l = glm::length( glm::vec2(vec) );
picked = glm::length( glm::vec2( 1.f + l, 1.f + l) - glm::vec2(P) ) < 1.5f * scale;
picked = glm::length( glm::vec2( 1.f + l, 1.f + l) - glm::vec2(P) ) < 1.5f * scale;
}
if ( picked )
@@ -119,26 +149,26 @@ void PickingVisitor::visit(Handles &n)
void PickingVisitor::visit(LineSquare &)
{
// apply inverse transform to the point of interest
glm::vec4 P = glm::inverse(modelview_) * glm::vec4( point_, 0.f, 1.f );
// // apply inverse transform to the point of interest
// glm::vec4 P = glm::inverse(modelview_) * glm::vec4( point_A_, 0.f, 1.f );
// lower left corner
glm::vec3 LL = glm::vec3( -1.f, -1.f, 0.f );
// up right corner
glm::vec3 UR = glm::vec3( 1.f, 1.f, 0.f );
// // lower left corner
// glm::vec3 LL = glm::vec3( -1.f, -1.f, 0.f );
// // up right corner
// glm::vec3 UR = glm::vec3( 1.f, 1.f, 0.f );
// if P is over a line [LL UR] rectangle:
// TODO
// // if P is over a line [LL UR] rectangle:
// // TODO
}
void PickingVisitor::visit(LineCircle &n)
{
// apply inverse transform to the point of interest
glm::vec4 P = glm::inverse(modelview_) * glm::vec4( point_, 0.f, 1.f );
// // apply inverse transform to the point of interest
// glm::vec4 P = glm::inverse(modelview_) * glm::vec4( point_A_, 0.f, 1.f );
float r = glm::length( glm::vec2(P) );
if ( r < 1.02 && r > 0.98)
nodes_.push_back( std::pair(&n, glm::vec2(P)) );
// float r = glm::length( glm::vec2(P) );
// if ( r < 1.02 && r > 0.98)
// nodes_.push_back( std::pair(&n, glm::vec2(P)) );
}
void PickingVisitor::visit(Scene &n)

View File

@@ -9,13 +9,14 @@
class PickingVisitor: public Visitor
{
glm::vec2 point_;
std::vector<glm::vec3> points_;
glm::mat4 modelview_;
std::vector< std::pair<Node *, glm::vec2> > nodes_;
public:
PickingVisitor(glm::vec2 coordinates);
PickingVisitor(glm::vec3 coordinates);
PickingVisitor(glm::vec3 selectionstart, glm::vec3 selection_end);
std::vector< std::pair<Node *, glm::vec2> > picked() { return nodes_; }
// Elements of Scene

View File

@@ -14,6 +14,16 @@ void Selection::add(Source *s)
s->setMode(Source::ACTIVE);
}
void Selection::set(SourceList l)
{
clear();
for(auto it = l.begin(); it != l.end(); it++)
(*it)->setMode(Source::ACTIVE);
selection_ = l;
}
void Selection::add(SourceList l)
{
for(auto it = l.begin(); it != l.end(); it++)
@@ -65,3 +75,13 @@ bool Selection::contains (Source *s)
{
return (find(s) != selection_.end());
}
SourceList::iterator Selection::begin()
{
return selection_.begin();
}
SourceList::iterator Selection::end()
{
return selection_.end();
}

View File

@@ -13,8 +13,12 @@ public:
void add (SourceList l);
void remove (Source *s);
void remove (SourceList l);
void set (SourceList l);
void clear ();
SourceList::iterator begin ();
SourceList::iterator end ();
bool contains (Source *s);
protected:

View File

@@ -37,7 +37,7 @@ Source::Source() : initialized_(false), need_update_(true)
frames_[View::MIXING] = new Switch;
Frame *frame = new Frame(Frame::ROUND_THIN);
frame->translation_.z = 0.1;
frame->color = glm::vec4( COLOR_DEFAULT_SOURCE, 0.7f);
frame->color = glm::vec4( COLOR_DEFAULT_SOURCE, 0.9f);
frames_[View::MIXING]->attach(frame);
frame = new Frame(Frame::ROUND_LARGE);
frame->translation_.z = 0.01;

View File

@@ -383,10 +383,16 @@ void UserInterface::handleMouse()
{
if (current)
{
// grab current source
View::Cursor c = Mixer::manager().currentView()->grab( mouseclic[ImGuiMouseButton_Left], mousepos, current, picked);
setMouseCursor(c);
// if ( Mixer::selection().contains(current)) {
// for (auto it = Mixer::selection().begin(); it != Mixer::selection().end(); it++)
// c = Mixer::manager().currentView()->grab( mouseclic[ImGuiMouseButton_Left], mousepos, *it, picked);
// }
}
else {
// Log::Info("Mouse drag (%.1f,%.1f)(%.1f,%.1f)", io.MouseClickedPos[0].x, io.MouseClickedPos[0].y, io.MousePos.x, io.MousePos.y);
@@ -405,9 +411,9 @@ void UserInterface::handleMouse()
else if ( ImGui::IsMouseDown(ImGuiMouseButton_Left) ) {
// get coordinate in world coordinate of mouse cursor
glm::vec3 point = Rendering::manager().unProject(mousepos);
// glm::vec3 point = Rendering::manager().unProject(mousepos);
// ask the view what was picked
picked = Mixer::manager().currentView()->pick(point);
picked = Mixer::manager().currentView()->pick(mousepos);
// if nothing picked,
if ( picked.first == nullptr ) {

View File

@@ -82,41 +82,54 @@ View::Cursor View::drag (glm::vec2 from, glm::vec2 to)
return Cursor(Cursor_ResizeAll);
}
std::pair<Node *, glm::vec2> View::pick(glm::vec3 point)
std::pair<Node *, glm::vec2> View::pick(glm::vec2 P)
{
std::pair<Node *, glm::vec2> picked = { nullptr, glm::vec2(0.f) };
// prepare empty return value
std::pair<Node *, glm::vec2> pick = { nullptr, glm::vec2(0.f) };
// unproject mouse coordinate into scene coordinates
glm::vec3 scene_point_ = Rendering::manager().unProject(P);
// picking visitor traverses the scene
PickingVisitor pv(point);
PickingVisitor pv(scene_point_);
scene.accept(pv);
// picking visitor found nodes?
if ( !pv.picked().empty()) {
// select top-most Node picked
picked = pv.picked().back();
//DEBUG
// select(glm::vec2(-1.f, -1.f), glm::vec2(1.f, 1.f));
pick = pv.picked().back();
}
// cancel selection on clic in background
else {
// deselect();
}
return picked;
return pick;
}
void GeometryView::select(glm::vec2 A, glm::vec2 B)
void View::select(glm::vec2 A, glm::vec2 B)
{
// for(auto it = scene.ws()->begin(); it != scene.ws()->end(); it++) {
// if ( *it != selection_box_)
// selection_box_->attach(*it);
// }
// unproject mouse coordinate into scene coordinates
glm::vec3 scene_point_A = Rendering::manager().unProject(A);
glm::vec3 scene_point_B = Rendering::manager().unProject(B);
// selection_box_->visible_ = true;
// picking visitor traverses the scene
PickingVisitor pv(scene_point_A, scene_point_B);
scene.accept(pv);
// reset selection
Mixer::selection().clear();
// picking visitor found nodes in the area?
if ( !pv.picked().empty()) {
SourceList selection;
for(auto p = pv.picked().begin(); p != pv.picked().end(); p++){
Source *s = Mixer::manager().findSource( p->first );
if (s)
selection.push_back( s );
}
// set the selection with list of picked (overlaped) sources
Mixer::selection().add(selection);
}
}
@@ -368,12 +381,16 @@ void GeometryView::draw()
}
std::pair<Node *, glm::vec2> GeometryView::pick(glm::vec3 point)
std::pair<Node *, glm::vec2> GeometryView::pick(glm::vec2 P)
{
// prepare empty return value
std::pair<Node *, glm::vec2> pick = { nullptr, glm::vec2(0.f) };
// unproject mouse coordinate into scene coordinates
glm::vec3 scene_point_ = Rendering::manager().unProject(P);
// picking visitor traverses the scene
PickingVisitor pv(point);
PickingVisitor pv(scene_point_);
scene.accept(pv);
// picking visitor found nodes?
@@ -631,6 +648,7 @@ float LayerView::setDepth(Source *s, float d)
return sourceNode->translation_.z;
}
View::Cursor LayerView::grab (glm::vec2 from, glm::vec2 to, Source *s, std::pair<Node *, glm::vec2> pick)
{
if (!s)

14
View.h
View File

@@ -43,8 +43,11 @@ public:
Cursor(CursorType t, std::string i = "") { type = t; info = i;}
} Cursor;
// picking of nodes in a view provided a point coordinates in scene reference frame
virtual std::pair<Node *, glm::vec2> pick(glm::vec3 point);
// picking of nodes in a view provided a point coordinates in screen coordinates
virtual std::pair<Node *, glm::vec2> pick(glm::vec2);
// select sources provided a start and end selection points in screen coordinates
virtual void select(glm::vec2, glm::vec2);
// drag the view provided a start and an end point in screen coordinates
virtual Cursor drag (glm::vec2, glm::vec2);
@@ -53,12 +56,11 @@ public:
virtual Cursor grab (glm::vec2, glm::vec2, Source*, std::pair<Node *, glm::vec2>) {
return Cursor();
}
// test mouse over provided a point in screen coordinates and the picking point
virtual Cursor over (glm::vec2, Source*, std::pair<Node *, glm::vec2>) {
return Cursor();
}
// select sources provided a start and end selection points in screen coordinates
virtual void select(glm::vec2, glm::vec2) {}
virtual void restoreSettings();
virtual void saveSettings();
@@ -114,10 +116,10 @@ public:
void draw () override;
void update (float dt) override;
void zoom (float factor) override;
std::pair<Node *, glm::vec2> pick(glm::vec3 point) override;
std::pair<Node *, glm::vec2> pick(glm::vec2 P) override;
Cursor grab (glm::vec2 from, glm::vec2 to, Source *s, std::pair<Node *, glm::vec2> pick) override;
Cursor over (glm::vec2, Source*, std::pair<Node *, glm::vec2>) override;
void select(glm::vec2, glm::vec2) override;
// void select(glm::vec2, glm::vec2) override;
// class Box *selection_box_;
};