Initial implementation of handles on sources to manipulate in geometry

view (only resize implemented so far)
This commit is contained in:
brunoherbelin
2020-05-16 12:06:52 +02:00
parent ab75c342f4
commit 20cafa388f
26 changed files with 1623 additions and 379 deletions

View File

@@ -226,6 +226,7 @@ set(VMIX_SRCS
ImGuiToolkit.cpp ImGuiToolkit.cpp
ImGuiVisitor.cpp ImGuiVisitor.cpp
GstToolkit.cpp GstToolkit.cpp
GlmToolkit.cpp
SystemToolkit.cpp SystemToolkit.cpp
tinyxml2Toolkit.cpp tinyxml2Toolkit.cpp
) )

View File

@@ -20,7 +20,6 @@ glm::vec3 FrameBuffer::getResolutionFromParameters(int ar, int h)
return res; return res;
} }
FrameBuffer::FrameBuffer(glm::vec3 resolution): textureid_(0), framebufferid_(0), usedepth_(false) FrameBuffer::FrameBuffer(glm::vec3 resolution): textureid_(0), framebufferid_(0), usedepth_(false)
{ {
attrib_.viewport = glm::ivec2(resolution); attrib_.viewport = glm::ivec2(resolution);

136
GlmToolkit.cpp Normal file
View File

@@ -0,0 +1,136 @@
// Freely inspired from https://github.com/alter-rokuz/glm-aabb.git
#include "GlmToolkit.h"
#include <glm/gtc/matrix_access.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtc/random.hpp>
glm::mat4 GlmToolkit::transform(glm::vec3 translation, glm::vec3 rotation, glm::vec3 scale)
{
glm::mat4 View = glm::translate(glm::identity<glm::mat4>(), translation);
View = glm::rotate(View, rotation.x, glm::vec3(1.f, 0.f, 0.f));
View = glm::rotate(View, rotation.y, glm::vec3(0.f, 1.f, 0.f));
View = glm::rotate(View, rotation.z, glm::vec3(0.f, 0.f, 1.f));
glm::mat4 Model = glm::scale(glm::identity<glm::mat4>(), scale);
return View * Model;
}
GlmToolkit::AxisAlignedBoundingBox::AxisAlignedBoundingBox() {
mMin = glm::vec3(1.f);
mMax = glm::vec3(-1.f);
}
void GlmToolkit::AxisAlignedBoundingBox::extend(const glm::vec3& point)
{
if (isNull()) {
mMin = point;
mMax = point;
}
// general case
else {
mMin = glm::min(point, mMin);
mMax = glm::max(point, mMax);
}
}
void GlmToolkit::AxisAlignedBoundingBox::extend(std::vector<glm::vec3> points)
{
for (auto p = points.begin(); p != points.end(); p++)
extend(*p);
}
void GlmToolkit::AxisAlignedBoundingBox::extend(const AxisAlignedBoundingBox& bb)
{
if (bb.isNull())
return;
if (isNull()) {
mMin = bb.mMin;
mMax = bb.mMax;
}
// general case
else {
mMin = glm::min(bb.mMin, mMin);
mMax = glm::max(bb.mMax, mMax);
}
}
glm::vec3 GlmToolkit::AxisAlignedBoundingBox::center() const
{
if (!isNull())
{
glm::vec3 d = mMax - mMin;
return mMin + (d * 0.5f);
}
else
{
return glm::vec3(0.f);
}
}
bool GlmToolkit::AxisAlignedBoundingBox::intersect(const AxisAlignedBoundingBox& bb, bool ignore_z) const
{
if (isNull() || bb.isNull())
return false;
if ( (mMax.x < bb.mMin.x) || (mMin.x > bb.mMax.x) ||
(mMax.y < bb.mMin.y) || (mMin.y > bb.mMax.y) ||
( !ignore_z && ((mMax.z < bb.mMin.z) || (mMin.z > bb.mMax.z)) ) )
{
return false;
}
return true;
}
bool GlmToolkit::AxisAlignedBoundingBox::contains(const AxisAlignedBoundingBox& bb, bool ignore_z) const
{
if ( !intersect(bb, ignore_z))
return false;
if ( (mMin.x <= bb.mMin.x) && (mMax.x >= bb.mMax.x) &&
(mMin.y <= bb.mMin.y) && (mMax.y >= bb.mMax.y) &&
( ignore_z || ((mMin.z <= bb.mMin.z) && (mMax.z >= bb.mMax.z)) ) )
{
return true;
}
return false;
}
bool GlmToolkit::AxisAlignedBoundingBox::contains(glm::vec3 point, bool ignore_z) const
{
if ( (mMax.x < point.x) || (mMin.x > point.x) ||
(mMax.y < point.y) || (mMin.y > point.y) ||
( !ignore_z && ((mMax.z < point.z) || (mMin.z > point.z)) ) )
return false;
return true;
}
GlmToolkit::AxisAlignedBoundingBox GlmToolkit::AxisAlignedBoundingBox::translated(glm::vec3 t)
{
GlmToolkit::AxisAlignedBoundingBox bb;
bb = *this;
bb.mMin += t;
bb.mMax += t;
return bb;
}
GlmToolkit::AxisAlignedBoundingBox GlmToolkit::AxisAlignedBoundingBox::scaled(glm::vec3 s)
{
GlmToolkit::AxisAlignedBoundingBox bb;
bb = *this;
bb.mMin *= s;
bb.mMax *= s;
return bb;
}

48
GlmToolkit.h Normal file
View File

@@ -0,0 +1,48 @@
#ifndef GLMTOOLKIT_H
#define GLMTOOLKIT_H
#include <vector>
#include <glm/glm.hpp>
namespace GlmToolkit
{
glm::mat4 transform(glm::vec3 translation, glm::vec3 rotation, glm::vec3 scale);
class AxisAlignedBoundingBox
{
glm::vec3 mMin;
glm::vec3 mMax;
public:
AxisAlignedBoundingBox();
void operator = (const AxisAlignedBoundingBox &D ) {
mMin = D.mMin;
mMax = D.mMax;
}
// test
inline bool isNull() const { return mMin.x > mMax.x || mMin.y > mMax.y || mMin.z > mMax.z;}
inline glm::vec3 min() const { return mMin; }
inline glm::vec3 max() const { return mMax; }
glm::vec3 center() const;
bool intersect(const AxisAlignedBoundingBox& bb, bool ignore_z = true) const;
bool contains(const AxisAlignedBoundingBox& bb, bool ignore_z = true) const;
bool contains(glm::vec3 point, bool ignore_z = true) const;
// build
void extend(const glm::vec3& point);
void extend(std::vector<glm::vec3> points);
void extend(const AxisAlignedBoundingBox& bb);
AxisAlignedBoundingBox translated(glm::vec3 t);
AxisAlignedBoundingBox scaled(glm::vec3 s);
};
}
#endif // GLMTOOLKIT_H

View File

@@ -15,15 +15,8 @@ public:
void visit(Switch& n) override; void visit(Switch& n) override;
void visit(Animation& n) override; void visit(Animation& n) override;
void visit(Primitive& n) override; void visit(Primitive& n) override;
void visit(Surface&) override {}
void visit(ImageSurface&) override {}
void visit(MediaSurface& n) override; void visit(MediaSurface& n) override;
void visit(FrameBufferSurface& n) override; void visit(FrameBufferSurface& n) override;
void visit(LineStrip&) override {}
void visit(LineSquare&) override {}
void visit(LineCircle&) override {}
void visit(Mesh&) override {}
void visit(Frame&) override {}
// Elements with attributes // Elements with attributes
void visit(MediaPlayer& n) override; void visit(MediaPlayer& n) override;

119
Mesh.cpp
View File

@@ -8,11 +8,14 @@
#include <glad/glad.h> #include <glad/glad.h>
#include <glm/gtc/matrix_transform.hpp>
#include "Resource.h" #include "Resource.h"
#include "ImageShader.h" #include "ImageShader.h"
#include "Visitor.h" #include "Visitor.h"
#include "Log.h" #include "Log.h"
#include "Mesh.h" #include "Mesh.h"
#include "GlmToolkit.h"
using namespace std; using namespace std;
using namespace glm; using namespace glm;
@@ -321,6 +324,7 @@ bool parsePLY(string ascii,
} }
Mesh::Mesh(const std::string& ply_path, const std::string& tex_path) : Primitive(), mesh_resource_(ply_path), texture_resource_(tex_path), textureindex_(0) Mesh::Mesh(const std::string& ply_path, const std::string& tex_path) : Primitive(), mesh_resource_(ply_path), texture_resource_(tex_path), textureindex_(0)
{ {
if ( !parsePLY( Resource::getText(mesh_resource_), points_, colors_, texCoords_, indices_, drawMode_) ) if ( !parsePLY( Resource::getText(mesh_resource_), points_, colors_, texCoords_, indices_, drawMode_) )
@@ -361,12 +365,14 @@ void Mesh::draw(glm::mat4 modelview, glm::mat4 projection)
if ( !initialized() ) if ( !initialized() )
init(); init();
if (textureindex_) if ( visible_ ) {
glBindTexture(GL_TEXTURE_2D, textureindex_); if (textureindex_)
glBindTexture(GL_TEXTURE_2D, textureindex_);
Primitive::draw(modelview, projection); Primitive::draw(modelview, projection);
glBindTexture(GL_TEXTURE_2D, 0); glBindTexture(GL_TEXTURE_2D, 0);
}
} }
void Mesh::accept(Visitor& v) void Mesh::accept(Visitor& v)
@@ -375,19 +381,17 @@ void Mesh::accept(Visitor& v)
v.visit(*this); v.visit(*this);
} }
Frame::Frame(Style style) : Node() Frame::Frame(Type style) : Node()
{ {
overlay_ = nullptr;
shadow_ = nullptr;
color = glm::vec4( 1.f, 1.f, 1.f, 1.f); color = glm::vec4( 1.f, 1.f, 1.f, 1.f);
switch (style) { switch (style) {
case SHARP_HANDLES: case SHARP_LARGE:
border_ = new Mesh("mesh/border_handles_sharp.ply"); border_ = new Mesh("mesh/border_large_sharp.ply");
overlay_ = new Mesh("mesh/border_handles_overlay.ply");
shadow_ = new Mesh("mesh/shadow.ply", "images/shadow.png"); shadow_ = new Mesh("mesh/shadow.ply", "images/shadow.png");
break; break;
case SHARP_THIN: case SHARP_THIN:
border_ = new Mesh("mesh/border_sharp.ply"); border_ = new Mesh("mesh/border_sharp.ply");
shadow_ = nullptr;
break; break;
case ROUND_LARGE: case ROUND_LARGE:
border_ = new Mesh("mesh/border_large_round.ply"); border_ = new Mesh("mesh/border_large_round.ply");
@@ -403,7 +407,6 @@ Frame::Frame(Style style) : Node()
Frame::~Frame() Frame::~Frame()
{ {
if(overlay_) delete overlay_;
if(border_) delete border_; if(border_) delete border_;
if(shadow_) delete shadow_; if(shadow_) delete shadow_;
} }
@@ -411,29 +414,23 @@ Frame::~Frame()
void Frame::draw(glm::mat4 modelview, glm::mat4 projection) void Frame::draw(glm::mat4 modelview, glm::mat4 projection)
{ {
if ( !initialized() ) { if ( !initialized() ) {
if(overlay_) overlay_->init();
if(border_) border_->init(); if(border_) border_->init();
if(shadow_) shadow_->init(); if(shadow_) shadow_->init();
init(); init();
} }
if ( visible_ ) { // not absolutely necessary but saves some CPU time.. if ( visible_ ) {
// shadow // shadow
if(shadow_) if(shadow_)
shadow_->draw( modelview * transform_, projection); shadow_->draw( modelview * transform_, projection);
if (overlay_) {
// overlat is not altered
overlay_->shader()->color = color;
overlay_->draw( modelview, projection );
}
// right side // right side
float ar = scale_.x / scale_.y; float ar = scale_.x / scale_.y;
glm::vec3 s(scale_.y, scale_.y, 1.0); glm::vec3 s(1.f, 1.f, 1.f);
glm::vec3 t(translation_.x - 1.0 +ar, translation_.y, translation_.z); // glm::vec3 s(scale_.y, scale_.y, 1.0);
glm::mat4 ctm = modelview * transform(t, rotation_, s); glm::vec3 t(translation_.x - 1.0 + ar, translation_.y, translation_.z);
glm::mat4 ctm = modelview * GlmToolkit::transform(t, rotation_, s);
if(border_) { if(border_) {
// right side // right side
@@ -442,7 +439,7 @@ void Frame::draw(glm::mat4 modelview, glm::mat4 projection)
// left side // left side
t.x = -t.x; t.x = -t.x;
s.x = -s.x; s.x = -s.x;
ctm = modelview * transform(t, rotation_, s); ctm = modelview * GlmToolkit::transform(t, rotation_, s);
border_->draw( ctm, projection ); border_->draw( ctm, projection );
} }
@@ -455,3 +452,79 @@ void Frame::accept(Visitor& v)
Node::accept(v); Node::accept(v);
v.visit(*this); v.visit(*this);
} }
Handles::Handles(Type type) : Node(), type_(type)
{
color = glm::vec4( 1.f, 1.f, 1.f, 1.f);
handle_ = new Mesh("mesh/border_handles_overlay.ply");
}
Handles::~Handles()
{
if(handle_) delete handle_;
}
void Handles::draw(glm::mat4 modelview, glm::mat4 projection)
{
if ( !initialized() ) {
if(handle_) handle_->init();
init();
}
if ( visible_ ) {
// set color
handle_->shader()->color = color;
float ar = scale_.x / scale_.y;
glm::mat4 ctm;
if ( type_ == RESIZE ) {
// 4 corners
ctm = modelview * glm::translate(glm::identity<glm::mat4>(), glm::vec3(ar, -1.f, 0.f) );
ctm[0][0] = ctm[1][1] = ctm[2][2] = 1.f;
handle_->draw( ctm, projection );
ctm = modelview * glm::translate(glm::identity<glm::mat4>(), glm::vec3(ar, +1.f, 0.f));
ctm[0][0] = ctm[1][1] = ctm[2][2] = 1.f;
handle_->draw( ctm, projection );
ctm = modelview * glm::translate(glm::identity<glm::mat4>(), glm::vec3(-ar, -1.f, 0.f));
ctm[0][0] = ctm[1][1] = ctm[2][2] = 1.f;
handle_->draw( ctm, projection );
ctm = modelview * glm::translate(glm::identity<glm::mat4>(), glm::vec3(-ar, +1.f, 0.f));
ctm[0][0] = ctm[1][1] = ctm[2][2] = 1.f;
handle_->draw( ctm, projection );
}
else if ( type_ == RESIZE_H ){
// left and right
ctm = modelview * glm::translate(glm::identity<glm::mat4>(), glm::vec3(ar, 0.f, 0.f) );
ctm[0][0] = ctm[1][1] = ctm[2][2] = 1.f;
handle_->draw( ctm, projection );
ctm = modelview * glm::translate(glm::identity<glm::mat4>(), glm::vec3(-ar, 0.f, 0.f));
ctm[0][0] = ctm[1][1] = ctm[2][2] = 1.f;
handle_->draw( ctm, projection );
}
else if ( type_ == RESIZE_V ){
// top and bottom
ctm = modelview * glm::translate(glm::identity<glm::mat4>(), glm::vec3(0.f, +1.f, 0.f) );
ctm[0][0] = ctm[1][1] = ctm[2][2] = 1.f;
handle_->draw( ctm, projection );
ctm = modelview * glm::translate(glm::identity<glm::mat4>(), glm::vec3(0.f, -1.f, 0.f));
ctm[0][0] = ctm[1][1] = ctm[2][2] = 1.f;
handle_->draw( ctm, projection );
}
else if ( type_ == ROTATE ){
}
}
}
void Handles::accept(Visitor& v)
{
Node::accept(v);
v.visit(*this);
}

40
Mesh.h
View File

@@ -36,20 +36,48 @@ protected:
class Frame : public Node class Frame : public Node
{ {
Mesh *border_;
Mesh *shadow_;
public: public:
typedef enum { ROUND_THIN = 0, ROUND_LARGE, SHARP_THIN, SHARP_HANDLES } Style; typedef enum { ROUND_THIN = 0, ROUND_LARGE, SHARP_THIN, SHARP_LARGE } Type;
Frame(Style style); Frame(Type style);
~Frame(); ~Frame();
void draw (glm::mat4 modelview, glm::mat4 projection) override; void draw (glm::mat4 modelview, glm::mat4 projection) override;
void accept (Visitor& v) override; void accept (Visitor& v) override;
Mesh *overlay_; Type type() const { return type_; }
Mesh *border() const { return border_; }
glm::vec4 color; glm::vec4 color;
protected:
Mesh *border_;
Mesh *shadow_;
Type type_;
}; };
class Handles : public Node
{
public:
typedef enum { RESIZE = 0, RESIZE_H, RESIZE_V, ROTATE } Type;
Handles(Type type);
~Handles();
void draw (glm::mat4 modelview, glm::mat4 projection) override;
void accept (Visitor& v) override;
Type type() const { return type_; }
Mesh *handle() const { return handle_; }
glm::vec4 color;
protected:
Mesh *handle_;
Type type_;
};
// TODO Shadow mesh with unique vao
// TODO dedicated source .cpp .h files for Frame and Handles
#endif // MESH_H #endif // MESH_H

View File

@@ -2,6 +2,7 @@
#include "Log.h" #include "Log.h"
#include "Primitives.h" #include "Primitives.h"
#include "GlmToolkit.h"
#include "Mesh.h" #include "Mesh.h"
#include <glm/gtc/type_ptr.hpp> #include <glm/gtc/type_ptr.hpp>
@@ -17,8 +18,9 @@ PickingVisitor::PickingVisitor(glm::vec2 coordinates) : Visitor(), point_(coordi
void PickingVisitor::visit(Node &n) void PickingVisitor::visit(Node &n)
{ {
// use the transform modified during update
modelview_ *= n.transform_;
modelview_ *= n.transform_;
// modelview_ *= transform(n.translation_, n.rotation_, n.scale_); // modelview_ *= transform(n.translation_, n.rotation_, n.scale_);
// Log::Info("Node %d", n.id()); // Log::Info("Node %d", n.id());
// Log::Info("%s", glm::to_string(modelview_).c_str()); // Log::Info("%s", glm::to_string(modelview_).c_str());
@@ -27,9 +29,9 @@ void PickingVisitor::visit(Node &n)
void PickingVisitor::visit(Group &n) void PickingVisitor::visit(Group &n)
{ {
glm::mat4 mv = modelview_; glm::mat4 mv = modelview_;
//Log::Info("Group %d", n.id());
for (NodeSet::iterator node = n.begin(); node != n.end(); node++) { for (NodeSet::iterator node = n.begin(); node != n.end(); node++) {
(*node)->accept(*this); if ( (*node)->visible_ )
(*node)->accept(*this);
modelview_ = mv; modelview_ = mv;
} }
} }
@@ -41,33 +43,71 @@ void PickingVisitor::visit(Switch &n)
modelview_ = mv; modelview_ = mv;
} }
void PickingVisitor::visit(Animation &n)
{
}
void PickingVisitor::visit(Primitive &n) void PickingVisitor::visit(Primitive &n)
{ {
// TODO: generic visitor for primitive with random shape
} }
void PickingVisitor::visit(Surface &n) void PickingVisitor::visit(Surface &n)
{ {
// Log::Info("Surface %d", n.id()); if (!n.visible_)
return;
// apply inverse transform to the point of interest // 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( point_, 0.f, 1.f );
// lower left corner // test bounding box: it is an exact fit for a resctangular surface
glm::vec3 LL = glm::vec3( -1.f, -1.f, 0.f ); if ( n.bbox().contains( glm::vec3(P)) )
// up right corner
glm::vec3 UR = glm::vec3( 1.f, 1.f, 0.f );
// if P is inside [LL UR] rectangle:
if ( P.x > LL.x && P.x < UR.x && P.y > LL.y && P.y < UR.y )
// 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)) );
} }
void PickingVisitor::visit(Frame &n)
{
n.border()->accept(*this);
}
void PickingVisitor::visit(Handles &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 );
// get the bounding box of a handle
GlmToolkit::AxisAlignedBoundingBox bb = n.handle()->bbox();
// test picking depending on type of handle
bool picked = false;
if ( n.type() == Handles::RESIZE ) {
// 4 corners
picked = ( bb.translated(glm::vec3(+1.f, +1.f, 0.f)).contains( glm::vec3(P) ) ||
bb.translated(glm::vec3(+1.f, -1.f, 0.f)).contains( glm::vec3(P) ) ||
bb.translated(glm::vec3(-1.f, +1.f, 0.f)).contains( glm::vec3(P) ) ||
bb.translated(glm::vec3(-1.f, -1.f, 0.f)).contains( glm::vec3(P) ) );
}
else if ( n.type() == Handles::RESIZE_H ){
// left & right
picked = ( bb.translated(glm::vec3(+1.f, 0.f, 0.f)).contains( glm::vec3(P) ) ||
bb.translated(glm::vec3(-1.f, 0.f, 0.f)).contains( glm::vec3(P) ) );
}
else if ( n.type() == Handles::RESIZE_V ){
// top & bottom
picked = ( bb.translated(glm::vec3(0.f, +1.f, 0.f)).contains( glm::vec3(P) ) ||
bb.translated(glm::vec3(0.f, -1.f, 0.f)).contains( glm::vec3(P) ) );
}
else if ( n.type() == Handles::ROTATE ){
// TODO Picking Rotation
}
if ( picked )
// add this surface to the nodes picked
nodes_.push_back( std::pair(&n, glm::vec2(P)) );
}
void PickingVisitor::visit(LineSquare &) void PickingVisitor::visit(LineSquare &)
{ {
// apply inverse transform to the point of interest // apply inverse transform to the point of interest

View File

@@ -20,21 +20,17 @@ public:
std::vector< std::pair<Node *, glm::vec2> > picked() { return nodes_; } std::vector< std::pair<Node *, glm::vec2> > picked() { return nodes_; }
// Elements of Scene // Elements of Scene
void visit(Scene& n); void visit(Scene& n) override;
void visit(Node& n); void visit(Node& n) override;
void visit(Group& n); void visit(Group& n) override;
void visit(Switch& n); void visit(Switch& n) override;
void visit(Animation& n); void visit(Primitive& n) override;
void visit(Primitive& n); void visit(Surface& n) override;
void visit(Surface& n); void visit(Frame& n) override;
void visit(ImageSurface&){} void visit(Handles& n) override;
void visit(MediaSurface&){} void visit(LineSquare&) override;
void visit(FrameBufferSurface&){} void visit(LineCircle& n) override;
void visit(LineStrip&){}
void visit(LineSquare&);
void visit(LineCircle& n);
void visit(Mesh&){}
void visit(Frame&){}
}; };
#endif // PICKINGVISITOR_H #endif // PICKINGVISITOR_H

View File

@@ -66,6 +66,9 @@ void Surface::init()
unique_drawCount = drawCount_; unique_drawCount = drawCount_;
// 3. unique_vao_ will NOT be deleted // 3. unique_vao_ will NOT be deleted
} }
// replace AxisAlignedBoundingBox
bbox_.extend(square_points);
} }
void Surface::accept(Visitor& v) void Surface::accept(Visitor& v)
@@ -220,6 +223,8 @@ void Points::draw(glm::mat4 modelview, glm::mat4 projection)
glPointSize(pointsize_); glPointSize(pointsize_);
Primitive::draw(modelview, projection); Primitive::draw(modelview, projection);
glPointSize(1);
} }
void Points::accept(Visitor& v) void Points::accept(Visitor& v)
@@ -248,6 +253,8 @@ void LineStrip::draw(glm::mat4 modelview, glm::mat4 projection)
glLineWidth(linewidth_); glLineWidth(linewidth_);
Primitive::draw(modelview, projection); Primitive::draw(modelview, projection);
glLineWidth(1);
} }
void LineStrip::accept(Visitor& v) void LineStrip::accept(Visitor& v)
@@ -272,6 +279,11 @@ void LineSquare::init()
// 2. use the global vertex array object // 2. use the global vertex array object
vao_ = unique_vao_; vao_ = unique_vao_;
drawCount_ = unique_drawCount; drawCount_ = unique_drawCount;
// arrays of vertices are not needed anymore (STATIC DRAW of vertex object)
points_.clear();
colors_.clear();
texCoords_.clear();
indices_.clear();
} }
else { else {
// 1. init the Primitive (only once) // 1. init the Primitive (only once)
@@ -279,8 +291,10 @@ void LineSquare::init()
// 2. remember global vertex array object // 2. remember global vertex array object
unique_vao_ = vao_; unique_vao_ = vao_;
unique_drawCount = drawCount_; unique_drawCount = drawCount_;
// 3. unique_vao_ will NOT be deleted because LineCircle::deleteGLBuffers_() is empty
} }
// compute AxisAlignedBoundingBox
bbox_.extend(square_points);
} }
void LineSquare::accept(Visitor& v) void LineSquare::accept(Visitor& v)
@@ -300,6 +314,7 @@ LineCircle::LineCircle(glm::vec4 color, uint linewidth) : LineStrip(std::vector<
{ {
static int N = 72; static int N = 72;
static float a = glm::two_pi<float>() / static_cast<float>(N); static float a = glm::two_pi<float>() / static_cast<float>(N);
// loop to build a circle
glm::vec3 P(1.f, 0.f, 0.f); glm::vec3 P(1.f, 0.f, 0.f);
for (int i = 0; i < N ; i++ ){ for (int i = 0; i < N ; i++ ){
points_.push_back( glm::vec3(P) ); points_.push_back( glm::vec3(P) );
@@ -308,7 +323,7 @@ LineCircle::LineCircle(glm::vec4 color, uint linewidth) : LineStrip(std::vector<
P = glm::rotateZ(P, a); P = glm::rotateZ(P, a);
} }
// loop // close loop
points_.push_back( glm::vec3(1.f, 0.f, 0.f) ); points_.push_back( glm::vec3(1.f, 0.f, 0.f) );
colors_.push_back( color ); colors_.push_back( color );
indices_.push_back ( N ); indices_.push_back ( N );
@@ -324,7 +339,14 @@ void LineCircle::init()
Node::init(); Node::init();
// 2. use the global vertex array object // 2. use the global vertex array object
vao_ = unique_vao_; vao_ = unique_vao_;
drawCount_ = unique_drawCount; drawCount_ = unique_drawCount;
// replace AxisAlignedBoundingBox
bbox_.extend(points_);
// arrays of vertices are not needed anymore (STATIC DRAW of vertex object)
points_.clear();
colors_.clear();
texCoords_.clear();
indices_.clear();
} }
else { else {
// 1. init the Primitive (only once) // 1. init the Primitive (only once)

View File

@@ -5,7 +5,7 @@
#include "Visitor.h" #include "Visitor.h"
#include "GarbageVisitor.h" #include "GarbageVisitor.h"
#include "Log.h" #include "Log.h"
#include "GlmToolkit.h"
#include "SessionVisitor.h" #include "SessionVisitor.h"
#include <glad/glad.h> #include <glad/glad.h>
@@ -20,18 +20,6 @@
#include <algorithm> #include <algorithm>
//Group *Scene::limbo = new Group;
glm::mat4 transform(glm::vec3 translation, glm::vec3 rotation, glm::vec3 scale)
{
glm::mat4 View = glm::translate(glm::identity<glm::mat4>(), translation);
View = glm::rotate(View, rotation.x, glm::vec3(1.f, 0.f, 0.f));
View = glm::rotate(View, rotation.y, glm::vec3(0.f, 1.f, 0.f));
View = glm::rotate(View, rotation.z, glm::vec3(0.f, 0.f, 1.f));
glm::mat4 Model = glm::scale(glm::identity<glm::mat4>(), scale);
return View * Model;
}
// Node // Node
Node::Node() : initialized_(false), visible_(true), refcount_(0) Node::Node() : initialized_(false), visible_(true), refcount_(0)
{ {
@@ -63,7 +51,7 @@ void Node::copyTransform(Node *other)
void Node::update( float ) void Node::update( float )
{ {
// update transform matrix from attributes // update transform matrix from attributes
transform_ = transform(translation_, rotation_, scale_); transform_ = GlmToolkit::transform(translation_, rotation_, scale_);
} }
@@ -137,6 +125,9 @@ void Primitive::init()
if ( elementBuffer_ ) if ( elementBuffer_ )
glDeleteBuffers ( 1, &elementBuffer_); glDeleteBuffers ( 1, &elementBuffer_);
// compute AxisAlignedBoundingBox
bbox_.extend(points_);
// arrays of vertices are not needed anymore (STATIC DRAW of vertex object) // arrays of vertices are not needed anymore (STATIC DRAW of vertex object)
points_.clear(); points_.clear();
colors_.clear(); colors_.clear();

10
Scene.h
View File

@@ -10,16 +10,14 @@
#include <set> #include <set>
#include <list> #include <list>
#include <vector> #include <vector>
#include <glm/glm.hpp>
glm::mat4 transform(glm::vec3 translation, glm::vec3 rotation, glm::vec3 scale); #include "GlmToolkit.h"
// Forward declare classes referenced // Forward declare classes referenced
class Shader; class Shader;
class Visitor; class Visitor;
class Group; class Group;
/** /**
* @brief The Node class is the base virtual class for all Node types * @brief The Node class is the base virtual class for all Node types
* *
@@ -104,14 +102,16 @@ public:
inline Shader *shader () const { return shader_; } inline Shader *shader () const { return shader_; }
void replaceShader (Shader* newshader); void replaceShader (Shader* newshader);
GlmToolkit::AxisAlignedBoundingBox bbox() const { return bbox_; }
protected: protected:
Shader* shader_; Shader* shader_;
uint vao_, drawMode_, drawCount_; uint vao_, drawMode_, drawCount_;
std::vector<glm::vec3> points_; std::vector<glm::vec3> points_;
std::vector<glm::vec4> colors_; std::vector<glm::vec4> colors_;
std::vector<glm::vec2> texCoords_; std::vector<glm::vec2> texCoords_;
std::vector<uint> indices_; std::vector<uint> indices_;
GlmToolkit::AxisAlignedBoundingBox bbox_;
}; };
// //

View File

@@ -18,22 +18,10 @@ public:
// Elements of Scene // Elements of Scene
void visit(Scene& n); void visit(Scene& n);
void visit(Node& n); void visit(Node& n);
void visit(Primitive&) {}
void visit(Group& n); void visit(Group& n);
void visit(Switch& n); void visit(Switch& n);
// already a Node or a Group
void visit(Animation&) {}
void visit(Primitive&) {}
void visit(Surface&) {}
void visit(ImageSurface&) {}
void visit(MediaSurface&) {}
void visit(FrameBufferSurface&) {}
void visit(LineStrip&) {}
void visit(LineSquare&) {}
void visit(LineCircle&) {}
void visit(Mesh&) {}
void visit(Frame&) {}
}; };
#endif // SEARCHVISITOR_H #endif // SEARCHVISITOR_H

View File

@@ -187,10 +187,10 @@ void SessionCreator::visit (Source& s)
s.setName(pName); s.setName(pName);
xmlCurrent_ = sourceNode->FirstChildElement("Mixing"); xmlCurrent_ = sourceNode->FirstChildElement("Mixing");
s.node(View::MIXING)->accept(*this); s.groupNode(View::MIXING)->accept(*this);
xmlCurrent_ = sourceNode->FirstChildElement("Geometry"); xmlCurrent_ = sourceNode->FirstChildElement("Geometry");
s.node(View::GEOMETRY)->accept(*this); s.groupNode(View::GEOMETRY)->accept(*this);
xmlCurrent_ = sourceNode->FirstChildElement("Blending"); xmlCurrent_ = sourceNode->FirstChildElement("Blending");
s.blendingShader()->accept(*this); s.blendingShader()->accept(*this);

View File

@@ -37,7 +37,6 @@ public:
void visit(LineSquare&) override {} void visit(LineSquare&) override {}
void visit(LineCircle& n) override {} void visit(LineCircle& n) override {}
void visit(Mesh& n) override {} void visit(Mesh& n) override {}
void visit(Frame& n) override {}
// Elements with attributes // Elements with attributes
void visit(MediaPlayer& n) override; void visit(MediaPlayer& n) override;

View File

@@ -305,11 +305,11 @@ void SessionVisitor::visit (Source& s)
xmlCurrent_ = xmlDoc_->NewElement( "Mixing" ); xmlCurrent_ = xmlDoc_->NewElement( "Mixing" );
sourceNode->InsertEndChild(xmlCurrent_); sourceNode->InsertEndChild(xmlCurrent_);
s.node(View::MIXING)->accept(*this); s.groupNode(View::MIXING)->accept(*this);
xmlCurrent_ = xmlDoc_->NewElement( "Geometry" ); xmlCurrent_ = xmlDoc_->NewElement( "Geometry" );
sourceNode->InsertEndChild(xmlCurrent_); sourceNode->InsertEndChild(xmlCurrent_);
s.node(View::GEOMETRY)->accept(*this); s.groupNode(View::GEOMETRY)->accept(*this);
xmlCurrent_ = xmlDoc_->NewElement( "Blending" ); xmlCurrent_ = xmlDoc_->NewElement( "Blending" );
sourceNode->InsertEndChild(xmlCurrent_); sourceNode->InsertEndChild(xmlCurrent_);

View File

@@ -31,6 +31,11 @@ Source::Source(const std::string &name) : name_(name), initialized_(false)
groups_[View::MIXING]->attach(frame); groups_[View::MIXING]->attach(frame);
groups_[View::MIXING]->scale_ = glm::vec3(0.15f, 0.15f, 1.f); groups_[View::MIXING]->scale_ = glm::vec3(0.15f, 0.15f, 1.f);
overlays_[View::MIXING] = new Group;
overlays_[View::MIXING]->translation_.z = 0.1;
overlays_[View::MIXING]->visible_ = false;
groups_[View::MIXING]->attach(overlays_[View::MIXING]);
// default geometry nodes // default geometry nodes
groups_[View::GEOMETRY] = new Group; groups_[View::GEOMETRY] = new Group;
frame = new Frame(Frame::SHARP_THIN); frame = new Frame(Frame::SHARP_THIN);
@@ -38,11 +43,20 @@ Source::Source(const std::string &name) : name_(name), initialized_(false)
frame->color = glm::vec4( 0.8f, 0.8f, 0.0f, 0.9f); frame->color = glm::vec4( 0.8f, 0.8f, 0.0f, 0.9f);
groups_[View::GEOMETRY]->attach(frame); groups_[View::GEOMETRY]->attach(frame);
overlays_[View::GEOMETRY] = new Group;
overlays_[View::GEOMETRY]->translation_.z = 0.1;
overlays_[View::GEOMETRY]->visible_ = false;
groups_[View::GEOMETRY]->attach(overlays_[View::GEOMETRY]);
// will be associated to nodes later // will be associated to nodes later
blendingshader_ = new ImageShader; blendingshader_ = new ImageShader;
rendershader_ = new ImageProcessingShader; rendershader_ = new ImageProcessingShader;
renderbuffer_ = nullptr; renderbuffer_ = nullptr;
rendersurface_ = nullptr; rendersurface_ = nullptr;
resize_handle_ = nullptr;
resize_H_handle_ = nullptr;
resize_V_handle_ = nullptr;
rotate_handle_ = nullptr;
} }
Source::~Source() Source::~Source()
@@ -82,6 +96,19 @@ void Source::setOverlayVisible(bool on)
(*o).second->visible_ = on; (*o).second->visible_ = on;
} }
Handles *Source::handleNode(Handles::Type t) const
{
if ( t == Handles::ROTATE )
return rotate_handle_;
else if ( t == Handles::RESIZE_H )
return resize_H_handle_;
else if ( t == Handles::RESIZE_V )
return resize_V_handle_;
else
return resize_handle_;
}
bool hasNode::operator()(const Source* elem) const bool hasNode::operator()(const Source* elem) const
{ {
if (elem) if (elem)
@@ -112,18 +139,29 @@ MediaSource::MediaSource(const std::string &name) : Source(name), path_("")
mediasurface_ = new Surface(rendershader_); mediasurface_ = new Surface(rendershader_);
// extra overlay for mixing view // extra overlay for mixing view
overlays_[View::MIXING] = new Frame(Frame::ROUND_LARGE); Frame *frame = new Frame(Frame::ROUND_LARGE);
overlays_[View::MIXING]->translation_.z = 0.1; frame->translation_.z = 0.1;
overlays_[View::MIXING]->color = glm::vec4( 0.8f, 0.8f, 0.0f, 1.f); frame->color = glm::vec4( 0.8f, 0.8f, 0.0f, 1.f);
overlays_[View::MIXING]->visible_ = false; overlays_[View::MIXING]->attach(frame);
groups_[View::MIXING]->attach(overlays_[View::MIXING]);
// extra overlay for geometry view // extra overlay for geometry view
overlays_[View::GEOMETRY] = new Frame(Frame::SHARP_HANDLES); frame = new Frame(Frame::SHARP_LARGE);
overlays_[View::GEOMETRY]->translation_.z = 0.1; frame->color = glm::vec4( 0.8f, 0.8f, 0.0f, 1.f);
overlays_[View::GEOMETRY]->color = glm::vec4( 0.8f, 0.8f, 0.0f, 1.f); frame->translation_.z = 0.1;
overlays_[View::GEOMETRY]->visible_ = false; overlays_[View::GEOMETRY]->attach(frame);
groups_[View::GEOMETRY]->attach(overlays_[View::GEOMETRY]); resize_handle_ = new Handles(Handles::RESIZE);
resize_handle_->color = glm::vec4( 0.8f, 0.8f, 0.0f, 1.f);
resize_handle_->translation_.z = 0.15;
overlays_[View::GEOMETRY]->attach(resize_handle_);
resize_H_handle_ = new Handles(Handles::RESIZE_H);
resize_H_handle_->color = glm::vec4( 0.8f, 0.8f, 0.0f, 1.f);
resize_H_handle_->translation_.z = 0.15;
overlays_[View::GEOMETRY]->attach(resize_H_handle_);
resize_V_handle_ = new Handles(Handles::RESIZE_V);
resize_V_handle_->color = glm::vec4( 0.8f, 0.8f, 0.0f, 1.f);
resize_V_handle_->translation_.z = 0.15;
overlays_[View::GEOMETRY]->attach(resize_V_handle_);
} }
MediaSource::~MediaSource() MediaSource::~MediaSource()
@@ -190,9 +228,9 @@ void MediaSource::init()
if (is) is->stipple = 1.0; if (is) is->stipple = 1.0;
groups_[View::MIXING]->attach(surfacemix); groups_[View::MIXING]->attach(surfacemix);
if (mediaplayer_->duration() == GST_CLOCK_TIME_NONE) if (mediaplayer_->duration() == GST_CLOCK_TIME_NONE)
overlays_[View::MIXING]->overlay_ = new Mesh("mesh/icon_image.ply"); overlays_[View::MIXING]->attach( new Mesh("mesh/icon_image.ply") );
else else
overlays_[View::MIXING]->overlay_ = new Mesh("mesh/icon_video.ply"); overlays_[View::MIXING]->attach( new Mesh("mesh/icon_video.ply") );
// scale all mixing nodes to match aspect ratio of the media // scale all mixing nodes to match aspect ratio of the media
for (NodeSet::iterator node = groups_[View::MIXING]->begin(); for (NodeSet::iterator node = groups_[View::MIXING]->begin();
@@ -203,7 +241,6 @@ void MediaSource::init()
node != groups_[View::GEOMETRY]->end(); node++) { node != groups_[View::GEOMETRY]->end(); node++) {
(*node)->scale_.x = mediaplayer_->aspectRatio(); (*node)->scale_.x = mediaplayer_->aspectRatio();
} }
// mixingshader_->mask = ImageShader::mask_presets["Halo"];
// done init once and for all // done init once and for all
initialized_ = true; initialized_ = true;

View File

@@ -6,6 +6,7 @@
#include <list> #include <list>
#include "View.h" #include "View.h"
#include "Mesh.h"
class ImageShader; class ImageShader;
class ImageProcessingShader; class ImageProcessingShader;
@@ -33,7 +34,8 @@ public:
// get handle on the node used to manipulate the source in a view // get handle on the node used to manipulate the source in a view
inline Group *group(View::Mode m) const { return groups_.at(m); } inline Group *group(View::Mode m) const { return groups_.at(m); }
inline Node *node(View::Mode m) const { return static_cast<Node*>(groups_.at(m)); } inline Node *groupNode(View::Mode m) const { return static_cast<Node*>(groups_.at(m)); }
Handles *handleNode(Handles::Type t) const;
// every Source has a shader to control image processing effects // every Source has a shader to control image processing effects
inline ImageProcessingShader *processingShader() const { return rendershader_; } inline ImageProcessingShader *processingShader() const { return rendershader_; }
@@ -50,7 +52,7 @@ public:
// accept all kind of visitors // accept all kind of visitors
virtual void accept (Visitor& v); virtual void accept (Visitor& v);
// informs if the source failed (and might have to be deleted) // every Source shall informs if the source failed (i.e. shall be deleted)
virtual bool failed() const { return false; } virtual bool failed() const { return false; }
protected: protected:
@@ -73,17 +75,18 @@ protected:
// It is associated to the rendershader for mixing effects // It is associated to the rendershader for mixing effects
FrameBufferSurface *rendersurface_; FrameBufferSurface *rendersurface_;
// rendershader provides image processing controls // rendershader performs image processing
ImageProcessingShader *rendershader_; ImageProcessingShader *rendershader_;
// mixingshader provides mixing controls // blendingshader provides mixing controls
ImageShader *blendingshader_; ImageShader *blendingshader_;
// overlay to be displayed on top of source // overlay to be displayed on top of source
std::map<View::Mode, Frame*> overlays_; std::map<View::Mode, Group*> overlays_;
Handles *resize_handle_, *resize_H_handle_, *resize_V_handle_, *rotate_handle_;
}; };
// TODO : source set sorted by shader // TODO SourceSet sorted by shader
// so that the render loop avoid switching // so that the render loop avoid switching
typedef std::list<Source *> SourceList; typedef std::list<Source *> SourceList;
@@ -134,5 +137,6 @@ protected:
MediaPlayer *mediaplayer_; MediaPlayer *mediaplayer_;
}; };
// TODO dedicated source .cpp .h files for MediaSource
#endif // SOURCE_H #endif // SOURCE_H

View File

@@ -239,17 +239,23 @@ void UserInterface::handleKeyboard()
} }
} }
else {
// Normal keys
if (ImGui::IsKeyPressed( GLFW_KEY_BACKSPACE ))
Mixer::manager().deleteCurrentSource();
// Application F-Keys
else if (ImGui::IsKeyPressed( GLFW_KEY_F1 ))
Mixer::manager().setCurrentView(View::MIXING);
else if (ImGui::IsKeyPressed( GLFW_KEY_F2 ))
Mixer::manager().setCurrentView(View::GEOMETRY);
else if (ImGui::IsKeyPressed( GLFW_KEY_F12 ))
Rendering::manager().ToggleFullscreen();
else if (ImGui::IsKeyPressed( GLFW_KEY_PRINT_SCREEN ))
toolbox.StartScreenshot();
else if (ImGui::IsKeyPressed( GLFW_KEY_GRAVE_ACCENT ))
navigator.toggleMenu();
}
// Application F-Keys
if (ImGui::IsKeyPressed( GLFW_KEY_F1 ))
Mixer::manager().setCurrentView(View::MIXING);
if (ImGui::IsKeyPressed( GLFW_KEY_F2 ))
Mixer::manager().setCurrentView(View::GEOMETRY);
if (ImGui::IsKeyPressed( GLFW_KEY_F12 ))
Rendering::manager().ToggleFullscreen();
else if (ImGui::IsKeyPressed( GLFW_KEY_F11 ))
toolbox.StartScreenshot();
} }
void UserInterface::handleMouse() void UserInterface::handleMouse()
@@ -261,6 +267,8 @@ void UserInterface::handleMouse()
mouseclic[ImGuiMouseButton_Left] = glm::vec2(io.MouseClickedPos[ImGuiMouseButton_Left].x * io.DisplayFramebufferScale.y, io.MouseClickedPos[ImGuiMouseButton_Left].y* io.DisplayFramebufferScale.x); mouseclic[ImGuiMouseButton_Left] = glm::vec2(io.MouseClickedPos[ImGuiMouseButton_Left].x * io.DisplayFramebufferScale.y, io.MouseClickedPos[ImGuiMouseButton_Left].y* io.DisplayFramebufferScale.x);
mouseclic[ImGuiMouseButton_Right] = glm::vec2(io.MouseClickedPos[ImGuiMouseButton_Right].x * io.DisplayFramebufferScale.y, io.MouseClickedPos[ImGuiMouseButton_Right].y* io.DisplayFramebufferScale.x); mouseclic[ImGuiMouseButton_Right] = glm::vec2(io.MouseClickedPos[ImGuiMouseButton_Right].x * io.DisplayFramebufferScale.y, io.MouseClickedPos[ImGuiMouseButton_Right].y* io.DisplayFramebufferScale.x);
static std::pair<Node *, glm::vec2> pick = { nullptr, glm::vec2(0.f) };
// if not on any window // if not on any window
if ( !ImGui::IsAnyWindowHovered() && !ImGui::IsAnyWindowFocused() ) if ( !ImGui::IsAnyWindowHovered() && !ImGui::IsAnyWindowFocused() )
{ {
@@ -305,7 +313,7 @@ void UserInterface::handleMouse()
if (current) if (current)
{ {
// drag current source // drag current source
Mixer::manager().currentView()->grab( mouseclic[ImGuiMouseButton_Left], mousepos, current); Mixer::manager().currentView()->grab( mouseclic[ImGuiMouseButton_Left], mousepos, current, pick);
} }
else { else {
// Log::Info("Mouse drag (%.1f,%.1f)(%.1f,%.1f)", io.MouseClickedPos[0].x, io.MouseClickedPos[0].y, io.MousePos.x, io.MousePos.y); // Log::Info("Mouse drag (%.1f,%.1f)(%.1f,%.1f)", io.MouseClickedPos[0].x, io.MouseClickedPos[0].y, io.MousePos.x, io.MousePos.y);
@@ -328,13 +336,15 @@ void UserInterface::handleMouse()
// picking visitor found nodes? // picking visitor found nodes?
if (pv.picked().empty()) if (pv.picked().empty())
Mixer::manager().unsetCurrentSource(); Mixer::manager().unsetCurrentSource();
else else {
Mixer::manager().setCurrentSource(pv.picked().back().first); pick = pv.picked().back();
Mixer::manager().setCurrentSource( pick.first );
}
} }
else if ( ImGui::IsMouseReleased(ImGuiMouseButton_Left) ) else if ( ImGui::IsMouseReleased(ImGuiMouseButton_Left) )
{ {
pick = { nullptr, glm::vec2(0.f) };
} }
if ( ImGui::IsMouseDoubleClicked(ImGuiMouseButton_Left) ) if ( ImGui::IsMouseDoubleClicked(ImGuiMouseButton_Left) )
@@ -858,6 +868,13 @@ void Navigator::showPannelSource(int index)
selected_source_index = index; selected_source_index = index;
} }
void Navigator::toggleMenu()
{
bool previous = selected_button[NAV_MENU];
hidePannel();
selected_button[NAV_MENU] = !previous;
}
void Navigator::hidePannel() void Navigator::hidePannel()
{ {
clearSelection(); clearSelection();

View File

@@ -38,6 +38,7 @@ class Navigator
public: public:
Navigator(); Navigator();
void toggleMenu();
void hidePannel(); void hidePannel();
void showPannelSource(int index); void showPannelSource(int index);
void Render(); void Render();

153
View.cpp
View File

@@ -106,7 +106,7 @@ void MixingView::drag (glm::vec2 from, glm::vec2 to)
} }
void MixingView::grab (glm::vec2 from, glm::vec2 to, Source *s) void MixingView::grab (glm::vec2 from, glm::vec2 to, Source *s, std::pair<Node *, glm::vec2>)
{ {
if (!s) if (!s)
return; return;
@@ -201,6 +201,7 @@ void RenderView::setResolution(glm::vec3 resolution)
delete frame_buffer_; delete frame_buffer_;
frame_buffer_ = new FrameBuffer(resolution); frame_buffer_ = new FrameBuffer(resolution);
frame_buffer_->setClearColor(glm::vec4(0.f, 0.f, 0.f, 1.f));
} }
void RenderView::draw() void RenderView::draw()
@@ -230,7 +231,6 @@ GeometryView::GeometryView() : View(GEOMETRY)
scene.bg()->attach(rect); scene.bg()->attach(rect);
Frame *border = new Frame(Frame::SHARP_THIN); Frame *border = new Frame(Frame::SHARP_THIN);
border->overlay_ = new Mesh("mesh/border_vertical_overlay.ply");
border->color = glm::vec4( 0.8f, 0.f, 0.8f, 1.f ); border->color = glm::vec4( 0.8f, 0.f, 0.8f, 1.f );
scene.bg()->attach(border); scene.bg()->attach(border);
@@ -282,77 +282,118 @@ void GeometryView::drag (glm::vec2 from, glm::vec2 to)
} }
void GeometryView::grab (glm::vec2 from, glm::vec2 to, Source *s) void GeometryView::grab (glm::vec2 from, glm::vec2 to, Source *s, std::pair<Node *, glm::vec2> pick)
{ {
// work on the given source
if (!s) if (!s)
return; return;
Group *sourceNode = s->group(View::GEOMETRY); Group *sourceNode = s->group(View::GEOMETRY);
static glm::vec3 start_translation = glm::vec3(0.f); // remember
static glm::vec3 start_scale = glm::vec3(0.f);
static glm::vec2 start_position = glm::vec2(0.f); static glm::vec2 start_position = glm::vec2(0.f);
static glm::vec3 start_translation = glm::vec3(0.f);
static glm::vec3 start_scale = glm::vec3(1.f);
if ( start_position != from ) { if ( start_position != from ) {
start_position = from; start_position = from;
start_translation = sourceNode->translation_; start_translation = sourceNode->translation_;
start_scale = sourceNode->scale_; start_scale = sourceNode->scale_;
} }
// unproject in scene coordinates // grab coordinates in scene View reference frame
glm::vec3 gl_Position_from = Rendering::manager().unProject(from, scene.root()->transform_); glm::vec3 gl_Position_from = Rendering::manager().unProject(from, scene.root()->transform_);
glm::vec3 gl_Position_to = Rendering::manager().unProject(to, scene.root()->transform_); glm::vec3 gl_Position_to = Rendering::manager().unProject(to, scene.root()->transform_);
// coordinate in source // grab coordinates in source root reference frame
glm::mat4 modelview; glm::vec4 S_from = glm::inverse(sourceNode->transform_) * glm::vec4( gl_Position_from, 1.f );
glm::vec2 clicpos(0.f); glm::vec4 S_to = glm::inverse(sourceNode->transform_) * glm::vec4( gl_Position_to, 1.f );
PickingVisitor pv(gl_Position_to); glm::vec3 S_resize = glm::vec3(S_to) / glm::vec3(S_from);
sourceNode->accept(pv);
if (!pv.picked().empty()){ // Log::Info(" screen coordinates ( %.1f, %.1f ) ", to.x, to.y);
clicpos = pv.picked().back().second; // Log::Info(" scene coordinates ( %.1f, %.1f ) ", gl_Position_to.x, gl_Position_to.y);
modelview = pv.picked().back().first->transform_; // Log::Info(" source coordinates ( %.1f, %.1f ) ", P_to.x, P_to.y);
// Log::Info("clic pos source %.2f. %.2f", clicpos.x, clicpos.y);
// which manipulation to perform?
if (pick.first) {
// picking on the resizing handles in the corners
if ( pick.first == s->handleNode(Handles::RESIZE) ) {
sourceNode->scale_ = start_scale * S_resize;
}
// picking on the resizing handles left or right
else if ( pick.first == s->handleNode(Handles::RESIZE_H) ) {
sourceNode->scale_ = start_scale * glm::vec3(S_resize.x, 1.f, 1.f);
}
// picking on the resizing handles top or bottom
else if ( pick.first == s->handleNode(Handles::RESIZE_V) ) {
sourceNode->scale_ = start_scale * glm::vec3(1.f, S_resize.y, 1.f);
}
// TODO picking on the rotating handle
else if ( pick.first == s->handleNode(Handles::ROTATE) ) {
}
// picking anywhere but on a handle: user wants to move the source
else {
sourceNode->translation_ = start_translation + gl_Position_to - gl_Position_from;
}
} }
// don't have a handle, we can only move the source
// glm::vec4 P = glm::inverse(sourceNode->transform_ * modelview) * glm::vec4( gl_Position_to, 1.f ); else {
if ( ABS(clicpos.x)>0.9f && ABS(clicpos.y)>0.9f )
{
// clic inside corner
Log::Info("corner %.2f. %.2f", clicpos.x, clicpos.y);
// Log::Info(" %.2f. %.2f", P.x, P.y);
// glm::vec2 topos = clicpos;
// PickingVisitor pv(gl_Position_from);
// sourceNode->accept(pv);
// if (!pv.picked().empty()){
// topos = pv.picked().back().second;
//// Log::Info("scale %.2f. %.2f", topos.x, topos.y);
// }
glm::vec4 P = glm::inverse(sourceNode->transform_ * modelview) * glm::vec4( gl_Position_from, 1.f );
sourceNode->scale_ = start_scale * (glm::vec3(clicpos, 1.f) / glm::vec3(P) );
Log::Info("scale %.2f. %.2f", sourceNode->scale_.x, sourceNode->scale_.y);
Log::Info(" %.2f. %.2f", start_scale.x, start_scale.y);
}
else if ( ABS(clicpos.x)>0.95f && ABS(clicpos.y)<0.05f )
{
// clic resize horizontal
Log::Info("H resize %.2f. %.2f", clicpos.x, clicpos.y);
}
else if ( ABS(clicpos.x)<0.05f && ABS(clicpos.y)>0.95f )
{
// clic resize vertical
Log::Info("V resize %.2f. %.2f", clicpos.x, clicpos.y);
}
else
// clic inside source: compute delta translation
sourceNode->translation_ = start_translation + gl_Position_to - gl_Position_from; sourceNode->translation_ = start_translation + gl_Position_to - gl_Position_from;
}
// // coordinate in source
// glm::mat4 modelview(1.f);
// glm::vec2 clicpos(0.f);
//// PickingVisitor pv(gl_Position_to);
//// sourceNode->accept(pv);
//// if (!pv.picked().empty()){
//// clicpos = pv.picked().back().second;
////// modelview = pv.picked().back().first->transform_;
////// Log::Info("clic pos source %.2f. %.2f", clicpos.x, clicpos.y);
//// }
// glm::vec4 P_from = glm::inverse(sourceNode->transform_ * modelview) * glm::vec4( gl_Position_from, 1.f );
// glm::vec4 P_to = glm::inverse(sourceNode->transform_ * modelview) * glm::vec4( gl_Position_to, 1.f );
//// glm::vec4 P = glm::inverse(sourceNode->transform_ * modelview) * glm::vec4( gl_Position_to, 1.f );
// if ( pick.first == s->handleNode(Handles::RESIZE) )
// {
// // clic inside corner
//// Log::Info("corner %.2f. %.2f", clicpos.x, clicpos.y);
////// Log::Info(" %.2f. %.2f", P.x, P.y);
////// glm::vec2 topos = clicpos;
////// PickingVisitor pv(gl_Position_from);
////// sourceNode->accept(pv);
////// if (!pv.picked().empty()){
////// topos = pv.picked().back().second;
//////// Log::Info("scale %.2f. %.2f", topos.x, topos.y);
////// }
////// glm::vec4 P = glm::inverse(sourceNode->transform_ * modelview) * glm::vec4( gl_Position_from, 1.f );
// sourceNode->scale_ = start_scale * (glm::vec3(P_to) / glm::vec3(P_from) );
//// Log::Info("scale %.2f. %.2f", sourceNode->scale_.x, sourceNode->scale_.y);
//// Log::Info(" %.2f. %.2f", start_scale.x, start_scale.y);
// }
// else if ( ABS(clicpos.x)>0.95f && ABS(clicpos.y)<0.05f )
// {
// // clic resize horizontal
// Log::Info("H resize %.2f. %.2f", clicpos.x, clicpos.y);
// }
// else if ( ABS(clicpos.x)<0.05f && ABS(clicpos.y)>0.95f )
// {
// // clic resize vertical
// Log::Info("V resize %.2f. %.2f", clicpos.x, clicpos.y);
// }
// else
// clic inside source: compute delta translation
// sourceNode->translation_ = start_translation + gl_Position_to - gl_Position_from;
} }

6
View.h
View File

@@ -20,7 +20,7 @@ public:
virtual void draw () = 0; virtual void draw () = 0;
virtual void zoom (float) {} virtual void zoom (float) {}
virtual void drag (glm::vec2, glm::vec2) {} virtual void drag (glm::vec2, glm::vec2) {}
virtual void grab (glm::vec2, glm::vec2, Source*) {} virtual void grab (glm::vec2, glm::vec2, Source*, std::pair<Node *, glm::vec2>) {}
virtual void restoreSettings(); virtual void restoreSettings();
virtual void saveSettings(); virtual void saveSettings();
@@ -41,7 +41,7 @@ public:
void draw () override; void draw () override;
void zoom (float factor) override; void zoom (float factor) override;
void drag (glm::vec2 from, glm::vec2 to) override; void drag (glm::vec2 from, glm::vec2 to) override;
void grab (glm::vec2 from, glm::vec2 to, Source *s) override; void grab (glm::vec2 from, glm::vec2 to, Source *s, std::pair<Node *, glm::vec2>) override;
private: private:
uint textureMixingQuadratic(); uint textureMixingQuadratic();
@@ -73,7 +73,7 @@ public:
void draw () override; void draw () override;
void zoom (float factor) override; void zoom (float factor) override;
void drag (glm::vec2 from, glm::vec2 to) override; void drag (glm::vec2 from, glm::vec2 to) override;
void grab (glm::vec2 from, glm::vec2 to, Source *s) override; void grab (glm::vec2 from, glm::vec2 to, Source *s, std::pair<Node *, glm::vec2> pick) override;
private: private:

View File

@@ -19,6 +19,7 @@ class LineSquare;
class LineCircle; class LineCircle;
class Mesh; class Mesh;
class Frame; class Frame;
class Handles;
class MediaPlayer; class MediaPlayer;
class Shader; class Shader;
class ImageShader; class ImageShader;
@@ -30,24 +31,25 @@ class MediaSource;
class Visitor { class Visitor {
public: public:
// Declare overloads for each kind of Node to visit // Need to declare overloads for basic kind of Nodes to visit
virtual void visit (Scene&) = 0; virtual void visit (Scene&) = 0;
virtual void visit (Node&) = 0; virtual void visit (Node&) = 0;
virtual void visit (Group&) = 0;
virtual void visit (Switch&) = 0;
virtual void visit (Animation&) = 0;
virtual void visit (Primitive&) = 0; virtual void visit (Primitive&) = 0;
virtual void visit (Surface&) = 0; virtual void visit (Group&) = 0;
virtual void visit (ImageSurface&) = 0;
virtual void visit (MediaSurface&) = 0;
virtual void visit (FrameBufferSurface&) = 0;
virtual void visit (LineStrip&) = 0;
virtual void visit (LineSquare&) = 0;
virtual void visit (LineCircle&) = 0;
virtual void visit (Mesh&) = 0;
virtual void visit (Frame&) = 0;
// not mandatory // not mandatory for all others
virtual void visit (Switch&) {}
virtual void visit (Animation&) {}
virtual void visit (Surface&) {}
virtual void visit (ImageSurface&) {}
virtual void visit (MediaSurface&) {}
virtual void visit (FrameBufferSurface&) {}
virtual void visit (LineStrip&) {}
virtual void visit (LineSquare&) {}
virtual void visit (LineCircle&) {}
virtual void visit (Mesh&) {}
virtual void visit (Frame&) {}
virtual void visit (Handles&) {}
virtual void visit (MediaPlayer&) {} virtual void visit (MediaPlayer&) {}
virtual void visit (Shader&) {} virtual void visit (Shader&) {}
virtual void visit (ImageShader&) {} virtual void visit (ImageShader&) {}

View File

@@ -1,33 +1,21 @@
ply ply
format ascii 1.0 format ascii 1.0
comment Created by Blender 2.82 (sub 7) - www.blender.org, source file: 'border_large_sharp_2.blend' comment Created by Blender 2.82 (sub 7) - www.blender.org, source file: 'border_large_sharp_2.blend'
element vertex 16 element vertex 8
property float x property float x
property float y property float y
property float z property float z
property uchar red element face 8
property uchar green
property uchar blue
property uchar alpha
element face 16
property list uchar uint vertex_indices property list uchar uint vertex_indices
end_header end_header
0.040053 -1.008800 0.000000 255 255 255 255 0.091161 0.091238 0.000000
-0.031947 -1.000800 0.000000 255 255 255 255 0.073023 -0.072006 0.000000
-0.039947 -1.008800 0.000000 255 255 255 255 0.091161 -0.090145 0.000000
-0.031947 -0.957118 0.000000 255 255 255 255 -0.072083 -0.072006 0.000000
-0.039947 -0.949118 0.000000 255 255 255 255 -0.090222 -0.090145 0.000000
0.040053 -0.949118 0.000000 255 255 255 255 -0.090222 0.091238 0.000000
0.032053 -0.957118 0.000000 255 255 255 255 -0.072083 0.073100 0.000000
0.032053 -1.000800 0.000000 255 255 255 255 0.073023 0.073100 0.000000
0.040053 0.949146 0.000000 255 255 255 255
-0.031947 0.957146 0.000000 255 255 255 255
-0.039947 0.949146 0.000000 255 255 255 255
-0.031947 1.000827 0.000000 255 255 255 255
-0.039947 1.008827 0.000000 255 255 255 255
0.040053 1.008827 0.000000 255 255 255 255
0.032053 1.000827 0.000000 255 255 255 255
0.032053 0.957146 0.000000 255 255 255 255
3 0 1 2 3 0 1 2
3 2 3 4 3 2 3 4
3 3 5 4 3 3 5 4
@@ -36,11 +24,3 @@ end_header
3 2 1 3 3 2 1 3
3 3 6 5 3 3 6 5
3 0 5 6 3 0 5 6
3 8 9 10
3 10 11 12
3 11 13 12
3 8 14 15
3 8 15 9
3 10 9 11
3 11 14 13
3 8 13 14

View File

@@ -1,7 +1,7 @@
ply ply
format ascii 1.0 format ascii 1.0
comment Created by Blender 2.82 (sub 7) - www.blender.org, source file: 'border_large_sharp.blend' comment Created by Blender 2.82 (sub 7) - www.blender.org, source file: 'border_large_sharp.blend'
element vertex 52 element vertex 45
property float x property float x
property float y property float y
property float z property float z
@@ -9,7 +9,7 @@ property uchar red
property uchar green property uchar green
property uchar blue property uchar blue
property uchar alpha property uchar alpha
element face 62 element face 57
property list uchar uint vertex_indices property list uchar uint vertex_indices
end_header end_header
-0.950647 -1.000000 0.000000 255 255 255 255 -0.950647 -1.000000 0.000000 255 255 255 255
@@ -57,13 +57,6 @@ end_header
1.000000 0.000000 0.000000 255 255 255 255 1.000000 0.000000 0.000000 255 255 255 255
-0.000064 1.000000 0.000000 255 255 255 255 -0.000064 1.000000 0.000000 255 255 255 255
-0.995340 1.015000 0.000000 255 255 255 255 -0.995340 1.015000 0.000000 255 255 255 255
1.012389 -0.007651 0.000000 255 255 255 255
1.050200 -0.000169 0.000000 255 255 255 255
1.011916 -0.000169 0.000000 255 255 255 255
1.050200 0.007965 0.000000 255 255 255 255
1.011319 -0.007674 0.000000 255 255 255 255
1.050200 -0.007651 0.000000 255 255 255 255
1.011401 0.007965 0.000000 255 255 255 255
3 0 1 2 3 0 1 2
3 3 4 1 3 3 4 1
3 4 5 1 3 4 5 1
@@ -121,8 +114,3 @@ end_header
3 29 31 40 3 29 31 40
3 40 44 38 3 40 44 38
3 19 14 22 3 19 14 22
3 45 46 47
3 48 47 46
3 49 45 47
3 45 50 46
3 48 51 47

File diff suppressed because it is too large Load Diff