From c33796e97c1083ff057cd204d2864a2606a66dcf Mon Sep 17 00:00:00 2001 From: brunoherbelin Date: Sun, 22 Nov 2020 21:58:04 +0100 Subject: [PATCH] Beta implementation of FrameBuffer projection change for cropping. --- FrameBuffer.cpp | 20 +++++++ FrameBuffer.h | 6 ++ ImGuiVisitor.cpp | 9 ++- MediaSource.cpp | 4 +- Source.cpp | 44 +++++++-------- Source.h | 20 +++---- View.cpp | 142 +++++++++++++++++++---------------------------- View.h | 2 + 8 files changed, 122 insertions(+), 125 deletions(-) diff --git a/FrameBuffer.cpp b/FrameBuffer.cpp index 0635e58..a5a8b4e 100644 --- a/FrameBuffer.cpp +++ b/FrameBuffer.cpp @@ -4,6 +4,7 @@ #include "Settings.h" #include "Log.h" +#include #include @@ -27,6 +28,7 @@ FrameBuffer::FrameBuffer(glm::vec3 resolution, bool useAlpha, bool multiSampling { attrib_.viewport = glm::ivec2(resolution); attrib_.clear_color = glm::vec4(0.f, 0.f, 0.f, use_alpha_ ? 0.f : 1.f); + projection_ = glm::ortho(-1.f, 1.f, 1.f, -1.f, -1.f, 1.f); } FrameBuffer::FrameBuffer(uint width, uint height, bool useAlpha, bool multiSampling): @@ -35,6 +37,7 @@ FrameBuffer::FrameBuffer(uint width, uint height, bool useAlpha, bool multiSampl { attrib_.viewport = glm::ivec2(width, height); attrib_.clear_color = glm::vec4(0.f, 0.f, 0.f, use_alpha_ ? 0.f : 1.f); + projection_ = glm::ortho(-1.f, 1.f, 1.f, -1.f, -1.f, 1.f); } void FrameBuffer::init() @@ -243,3 +246,20 @@ void FrameBuffer::checkFramebufferStatus() } } + +glm::mat4 FrameBuffer::projection() const +{ + return projection_; +} + +float FrameBuffer::projectionAspectRatio() const +{ + return ( 1.f / projection_[0][0] ); // TODO height +} + +void FrameBuffer::crop(glm::vec2 c) +{ + glm::vec2 scale = glm::clamp(c, glm::vec2(0.2f, 0.2f), glm::vec2(1.f, 1.f)); + projection_ = glm::ortho(-scale.x, scale.x, scale.y, -scale.y, -1.f, 1.f); +} + diff --git a/FrameBuffer.h b/FrameBuffer.h index c2b1106..1b76cc2 100644 --- a/FrameBuffer.h +++ b/FrameBuffer.h @@ -42,6 +42,11 @@ public: float aspectRatio() const; std::string info() const; + // projection and crop + glm::mat4 projection() const; + float projectionAspectRatio() const; + void crop(glm::vec2 c); + // internal pixel format inline bool use_alpha() const { return use_alpha_; } inline bool use_multisampling() const { return use_multi_sampling_; } @@ -54,6 +59,7 @@ private: void checkFramebufferStatus(); RenderingAttrib attrib_; + glm::mat4 projection_; uint textureid_, intermediate_textureid_; uint framebufferid_, intermediate_framebufferid_; bool use_alpha_, use_multi_sampling_; diff --git a/ImGuiVisitor.cpp b/ImGuiVisitor.cpp index 6c648c5..db6a478 100644 --- a/ImGuiVisitor.cpp +++ b/ImGuiVisitor.cpp @@ -395,8 +395,13 @@ void ImGuiVisitor::visit (Source& s) // preview float preview_width = ImGui::GetContentRegionAvail().x IMGUI_RIGHT_ALIGN; - ImVec2 imagesize ( preview_width, preview_width / s.frame()->aspectRatio()); - ImGui::Image((void*)(uintptr_t) s.frame()->texture(), imagesize); + float width = preview_width; + float height = width / ( s.frame()->aspectRatio() * s.frame()->projectionAspectRatio() ); + if (height > 200) { + height = 200; + width = height * ( s.frame()->aspectRatio() * s.frame()->projectionAspectRatio() ); + } + ImGui::Image((void*)(uintptr_t) s.frame()->texture(), ImVec2(width, height)); ImVec2 pos = ImGui::GetCursorPos(); // remember where we were... diff --git a/MediaSource.cpp b/MediaSource.cpp index 2e823ce..f30fe94 100644 --- a/MediaSource.cpp +++ b/MediaSource.cpp @@ -127,13 +127,13 @@ void MediaSource::render() // blendingshader_->color.g = mediaplayer_->currentTimelineFading(); // blendingshader_->color.b = mediaplayer_->currentTimelineFading(); // render the media player into frame buffer - static glm::mat4 projection = glm::ortho(-1.f, 1.f, 1.f, -1.f, -1.f, 1.f); +// static glm::mat4 projection = glm::ortho(-1.f, 1.f, 1.f, -1.f, -1.f, 1.f); renderbuffer_->begin(); // texturesurface_->shader()->color.a = mediaplayer_->currentTimelineFading(); texturesurface_->shader()->color.r = mediaplayer_->currentTimelineFading(); texturesurface_->shader()->color.g = mediaplayer_->currentTimelineFading(); texturesurface_->shader()->color.b = mediaplayer_->currentTimelineFading(); - texturesurface_->draw(glm::identity(), projection); + texturesurface_->draw(glm::identity(), renderbuffer_->projection()); renderbuffer_->end(); } } diff --git a/Source.cpp b/Source.cpp index ea8b3a5..bbac18c 100644 --- a/Source.cpp +++ b/Source.cpp @@ -307,13 +307,14 @@ void Source::render() init(); else { // render the view into frame buffer - static glm::mat4 projection = glm::ortho(-1.f, 1.f, 1.f, -1.f, -1.f, 1.f); +// static glm::mat4 projection = glm::ortho(-1.f, 1.f, 1.f, -1.f, -1.f, 1.f); renderbuffer_->begin(); - texturesurface_->draw(glm::identity(), projection); + texturesurface_->draw(glm::identity(), renderbuffer_->projection()); renderbuffer_->end(); } } + void Source::attach(FrameBuffer *renderbuffer) { renderbuffer_ = renderbuffer; @@ -339,37 +340,22 @@ void Source::attach(FrameBuffer *renderbuffer) groups_[View::MIXING]->attach(surfacemix); groups_[View::LAYER]->attach(surfacemix); -// // for appearance view, a dedicated surface without blending - // Surface *surfacepreview = new FrameBufferSurface(renderbuffer_); + // for appearance view, a dedicated surface without blending Surface *surfacetmp = new Surface(); surfacetmp->setTextureIndex(Resource::getTextureTransparent()); groups_[View::APPEARANCE]->attach(surfacetmp); - // scale all icon nodes to match aspect ratio of the media - NodeSet::iterator node; - for (node = groups_[View::MIXING]->begin(); - node != groups_[View::MIXING]->end(); node++) { - (*node)->scale_.x = renderbuffer_->aspectRatio(); - } - for (node = groups_[View::GEOMETRY]->begin(); - node != groups_[View::GEOMETRY]->end(); node++) { - (*node)->scale_.x = renderbuffer_->aspectRatio(); - } - for (node = groups_[View::LAYER]->begin(); - node != groups_[View::LAYER]->end(); node++) { - (*node)->scale_.x = renderbuffer_->aspectRatio(); - } - for (node = groups_[View::APPEARANCE]->begin(); - node != groups_[View::APPEARANCE]->end(); node++) { - (*node)->scale_.x = renderbuffer_->aspectRatio(); - } - // Transition group node is optionnal if ( groups_[View::TRANSITION]->numChildren() > 0 ) { groups_[View::TRANSITION]->attach(rendersurface_); groups_[View::TRANSITION]->attach(surfacemix); - for (NodeSet::iterator node = groups_[View::TRANSITION]->begin(); - node != groups_[View::TRANSITION]->end(); node++) { + } + + // scale all icon nodes to match aspect ratio + for (int v = View::MIXING; v < View::INVALID; v++) { + NodeSet::iterator node; + for (node = groups_[(View::Mode) v]->begin(); + node != groups_[(View::Mode) v]->end(); node++) { (*node)->scale_.x = renderbuffer_->aspectRatio(); } } @@ -381,6 +367,7 @@ void Source::attach(FrameBuffer *renderbuffer) } } + void Source::setActive (bool on) { active_ = on; @@ -447,6 +434,7 @@ void Source::update(float dt) glm::vec3 center = groups_[View::APPEARANCE]->translation_; if (renderbuffer_) center.x /= renderbuffer_->aspectRatio(); + glm::vec3 UL = glm::vec3(-1.f, 1.f, 0.f) - center; glm::vec3 BR = glm::vec3(1.f, -1.f, 0.f) - center; UL /= groups_[View::APPEARANCE]->scale_; @@ -458,6 +446,12 @@ void Source::update(float dt) uv.w = BR.y * -0.5f + 0.5f; texturesurface_->setTextureUV(uv); + // MODIFY CROP + if (renderbuffer_) { + groups_[View::MIXING]->scale_.x *= renderbuffer_->projectionAspectRatio(); + groups_[View::LAYER]->scale_.x = renderbuffer_->projectionAspectRatio(); + } + need_update_ = false; } } diff --git a/Source.h b/Source.h index 578e660..e8db735 100644 --- a/Source.h +++ b/Source.h @@ -35,11 +35,11 @@ class Source public: // create a source and add it to the list // only subclasses of sources can actually be instanciated - Source(); - virtual ~Source(); + Source (); + virtual ~Source (); // Get unique id - inline uint64_t id() const { return id_; } + inline uint64_t id () const { return id_; } // manipulate name of source void setName (const std::string &name); @@ -67,7 +67,7 @@ public: bool contains (Node *node) const; // a Source has a shader used to render in fbo - inline Shader *renderingShader() const { return renderingshader_; } + inline Shader *renderingShader () const { return renderingshader_; } // the rendering shader always have an image processing shader inline ImageProcessingShader *processingShader () const { return processingshader_; } @@ -75,7 +75,7 @@ public: // the image processing shader can be enabled or disabled // (NB: when disabled, a simple ImageShader is applied) void setImageProcessingEnabled (bool on); - bool imageProcessingEnabled(); + bool imageProcessingEnabled (); // a Source has a shader to control mixing effects inline ImageShader *blendingShader () const { return blendingshader_; } @@ -87,7 +87,7 @@ public: inline void touch () { need_update_ = true; } // informs if its ready (i.e. initialized) - inline bool ready() const { return initialized_; } + inline bool ready () const { return initialized_; } // a Source shall be updated before displayed (Mixing, Geometry and Layer) virtual void update (float dt); @@ -97,13 +97,13 @@ public: inline bool active () { return active_; } // a Source shall informs if the source failed (i.e. shall be deleted) - virtual bool failed() const = 0; + virtual bool failed () const = 0; // a Source shall define a way to get a texture - virtual uint texture() const = 0; + virtual uint texture () const = 0; // a Source shall define how to render into the frame buffer - virtual void render(); + virtual void render (); // accept all kind of visitors virtual void accept (Visitor& v); @@ -136,7 +136,7 @@ public: uint64_t _id; }; - virtual glm::ivec2 icon() const { return glm::ivec2(12, 11); } + virtual glm::ivec2 icon () const { return glm::ivec2(12, 11); } protected: // name diff --git a/View.cpp b/View.cpp index 2085f4e..2affa48 100644 --- a/View.cpp +++ b/View.cpp @@ -1964,58 +1964,32 @@ std::pair AppearanceView::pick(glm::vec2 P) return pick; } +void AppearanceView::adjustBackground() +{ + // by default consider edit source is null + float width_scale = 1.f; + surfacepreview->setTextureIndex(0); + + // if its a valid index + if (edit_source_ != nullptr) { + // update rendering frame to match edit source AR + width_scale = edit_source_->frame()->aspectRatio(); + width_scale *= edit_source_->frame()->projectionAspectRatio();; + surfacepreview->setTextureIndex( edit_source_->frame()->texture() ); + } + + // update aspect ratio + surfacepreview->scale_.x = width_scale; + backgroundpreview->scale_.x = width_scale; + backgroundpreview->setTextureUV(glm::vec4(0.5f, 0.5f, 64.f * width_scale, 64.f)); + for (NodeSet::iterator node = scene.fg()->begin(); node != scene.fg()->end(); node++) { + (*node)->scale_.x = width_scale; + } +} void AppearanceView::draw() { -// Source *current_source = Mixer::manager().currentSource(); -// if ( current_source != edit_source_ ) -// { -// // current source is not the edited source -// if (current_source != nullptr) { -// // there is a valid current source, just edit it -// edit_source_ = current_source; -// } -// // no current source, but we have a pointer to source to edit -// else { -// // if the edit source exists? -// if (Mixer::manager().session()->find(edit_source_)!=Mixer::manager().session()->end()) { -// // restore current as current -// Mixer::manager().setCurrentSource(edit_source_); -// } -// else { -// if (Mixer::manager().session()->empty()) -// // nothing in the session, nothing to edit -// edit_source_ = nullptr; -// else { -// // pick the first source of the session -// edit_source_ = *Mixer::manager().session()->begin(); -// Mixer::manager().setCurrentSource(edit_source_); -// } -// } - -// } - -// // Update display -// float scale = 1.f; -// surfacepreview->setTextureIndex(0); - -// // if its a valid index -// if (edit_source_ != nullptr) { -// // update rendering frame to match edit source AR -// scale = edit_source_->frame()->aspectRatio(); -// surfacepreview->setTextureIndex( edit_source_->frame()->texture() ); -// } - -// // update aspect ratio -// surfacepreview->scale_.x = scale; -// backgroundpreview->scale_.x = scale; -// backgroundpreview->setTextureUV(glm::vec4(0.5f, 0.5f, 64.f * scale, 64.f)); -// for (NodeSet::iterator node = scene.fg()->begin(); node != scene.fg()->end(); node++) { -// (*node)->scale_.x = scale; -// } -// } - - // a more complete update is requested (e.g. after switching to view) + // edit view needs to be updated (source changed) if ( need_edit_update_ ) { need_edit_update_ = false; @@ -2023,31 +1997,10 @@ void AppearanceView::draw() // & remember source to edit edit_source_ = EditCurrent(); - // by default consider edit source is null - float scale = 1.f; - surfacepreview->setTextureIndex(0); - - // if its a valid index - if (edit_source_ != nullptr) { - // update rendering frame to match edit source AR - scale = edit_source_->frame()->aspectRatio(); - surfacepreview->setTextureIndex( edit_source_->frame()->texture() ); - } - - // update aspect ratio - surfacepreview->scale_.x = scale; - backgroundpreview->scale_.x = scale; - backgroundpreview->setTextureUV(glm::vec4(0.5f, 0.5f, 64.f * scale, 64.f)); - for (NodeSet::iterator node = scene.fg()->begin(); node != scene.fg()->end(); node++) { - (*node)->scale_.x = scale; - } - + // update background and frame to match editsource + adjustBackground(); } - Shader::force_blending_opacity = true; - View::draw(); - Shader::force_blending_opacity = false; - // display popup menu if (show_context_menu_) { ImGui::OpenPopup( "AppearanceContextMenu" ); @@ -2055,21 +2008,38 @@ void AppearanceView::draw() } showContextMenu(mode_,"AppearanceContextMenu"); -// // display interface duration -// glm::vec2 P = Rendering::manager().project(glm::vec3(1.1f, 1.14f, 0.f), scene.root()->transform_, false); -// ImGui::SetNextWindowPos(ImVec2(P.x, P.y), ImGuiCond_Always); -// if (ImGui::Begin("##WIDTH", NULL, ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoDecoration | ImGuiWindowFlags_NoBackground -// | ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoSavedSettings -// | ImGuiWindowFlags_NoFocusOnAppearing | ImGuiWindowFlags_NoNav)) -// { -// ImGuiToolkit::PushFont(ImGuiToolkit::FONT_LARGE); -// ImGui::SetNextItemWidth(100.f); -// float width = 1.f; -// ImGui::DragFloat("##apppearancewidth", &width, 0.1f, 0.3f, 2.f, "%.1f "); + // display interface duration + if ( edit_source_ != nullptr ) { + + glm::vec2 P = Rendering::manager().project(glm::vec3(1.1f, 1.14f, 0.f), scene.root()->transform_, false); + ImGui::SetNextWindowPos(ImVec2(P.x, P.y), ImGuiCond_Always); + if (ImGui::Begin("##WIDTH", NULL, ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoDecoration | ImGuiWindowFlags_NoBackground + | ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoSavedSettings + | ImGuiWindowFlags_NoFocusOnAppearing | ImGuiWindowFlags_NoNav)) + { + ImGuiToolkit::PushFont(ImGuiToolkit::FONT_LARGE); + ImGui::SetNextItemWidth(100.f); + float crop_width = edit_source_->frame()->projectionAspectRatio(); + if ( ImGui::DragFloat("##apppearancewidth", &crop_width, 0.05f, 0.2f, 1.f, "%.1f ") ) + { + // crop horizontally + edit_source_->frame()->crop(glm::vec2(crop_width, 1.f)); + // TODO scale GEOMETRY and RENDER groups + edit_source_->touch(); + // update background and frame + adjustBackground(); + } + + ImGui::PopFont(); + ImGui::End(); + } + + } + + Shader::force_blending_opacity = true; + View::draw(); + Shader::force_blending_opacity = false; -// ImGui::PopFont(); -// ImGui::End(); -// } } View::Cursor AppearanceView::grab (Source *s, glm::vec2 from, glm::vec2 to, std::pair pick) diff --git a/View.h b/View.h index 87607f2..e93e8b1 100644 --- a/View.h +++ b/View.h @@ -245,6 +245,8 @@ private: bool need_edit_update_; Source *EditCurrent(); + void adjustBackground(); + Surface *backgroundpreview; Surface *surfacepreview;