From f071a49187a531e1051ce7c14d7ff667256d6320 Mon Sep 17 00:00:00 2001 From: brunoherbelin Date: Fri, 3 Apr 2020 23:10:23 +0200 Subject: [PATCH] Fixed implementation of Visitor in hierarchy of Nodes. --- CMakeLists.txt | 2 + FrameBuffer.cpp | 108 +++++++++++++++++++++++++++- FrameBuffer.h | 32 +++++++-- Primitives.cpp | 172 +++++++++++++++++++++++++++------------------ Primitives.h | 67 +++++++++++++----- Scene.cpp | 49 +++++++------ Scene.h | 12 ++-- SessionVisitor.cpp | 74 ++++++++++++------- SessionVisitor.h | 14 ++-- Visitor.h | 14 ++-- defines.h | 5 +- main.cpp | 71 +++++++++---------- 12 files changed, 426 insertions(+), 194 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 098da87..5bf96cd 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -224,6 +224,7 @@ set(VMIX_SRCS Resource.cpp FileDialog.cpp MediaPlayer.cpp + FrameBuffer.cpp RenderingManager.cpp UserInterfaceManager.cpp ImGuiToolkit.cpp @@ -243,6 +244,7 @@ set(VMIX_RSC_FILES ./rsc/fonts/fa-regular-400.ttf ./rsc/fonts/fa-solid-900.ttf ./rsc/images/v-mix_256x256.png + ./rsc/images/busy.png ./rsc/images/icons.dds ./rsc/images/seed_512.jpg ) diff --git a/FrameBuffer.cpp b/FrameBuffer.cpp index 71af317..073f23d 100644 --- a/FrameBuffer.cpp +++ b/FrameBuffer.cpp @@ -1,6 +1,112 @@ #include "FrameBuffer.h" +#include "ImageShader.h" +#include "Log.h" -FrameBuffer::FrameBuffer() + +#include + +FrameBuffer::FrameBuffer(uint width, uint height, bool useDepthBuffer) { + // create a renderbuffer object to store depth info + GLuint rboId; + if (useDepthBuffer){ + glGenRenderbuffers(1, &rboId); + glBindRenderbuffer(GL_RENDERBUFFER, rboId); + glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT, width, height); + glBindRenderbuffer(GL_RENDERBUFFER, 0); + } + // create a framebuffer object + glGenFramebuffers(1, &framebufferid_); + bind(); + + // attach the texture to FBO color attachment point + glGenTextures(1, &textureid_); + glBindTexture(GL_TEXTURE_2D, textureid_); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width_, height_, 0, GL_RGB, GL_UNSIGNED_BYTE, NULL); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, + GL_TEXTURE_2D, textureid_, 0); + + // attach the renderbuffer to depth attachment point + if (useDepthBuffer){ + glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, + GL_RENDERBUFFER, rboId); + } + checkFramebufferStatus(); } + + +FrameBuffer::~FrameBuffer() +{ + glDeleteFramebuffers(1, &framebufferid_); +} + +float FrameBuffer::aspectRatio() const +{ + return static_cast(width_) / static_cast(height_); +} + +void FrameBuffer::bind() +{ + glBindFramebuffer(GL_FRAMEBUFFER, framebufferid_); +} + +void FrameBuffer::release() +{ + glBindFramebuffer(GL_FRAMEBUFFER, 0); +} + + +bool FrameBuffer::blit(FrameBuffer *other) +{ + if (width_ != other->width() || height_ != other->height()) + return false; + + glBindFramebuffer(GL_DRAW_FRAMEBUFFER, other->framebufferid_); + glBindFramebuffer(GL_READ_FRAMEBUFFER, framebufferid_); + // blit to the frame buffer object + glBlitFramebuffer(0, height_, width_, 0, 0, 0, + other->width(), other->height(), + GL_COLOR_BUFFER_BIT, GL_NEAREST); + glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0); + + return true; +} + +void FrameBuffer::checkFramebufferStatus() +{ + GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER); + switch (status){ + case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT: + Log::Warning("GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT​ is returned if any of the framebuffer attachment points are framebuffer incomplete."); + break; + case GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT: + Log::Warning("GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT​ is returned if the framebuffer does not have at least one image attached to it."); + break; + case GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER: + Log::Warning("GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER​ is returned if the value of GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE​ is GL_NONE​ for any color attachment point(s) named by GL_DRAWBUFFERi​."); + break; + case GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER: + Log::Warning("GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER​ is returned if GL_READ_BUFFER​ is not GL_NONE​ and the value of GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE​ is GL_NONE​ for the color attachment point named by GL_READ_BUFFER."); + break; + case GL_FRAMEBUFFER_UNSUPPORTED: + Log::Warning("GL_FRAMEBUFFER_UNSUPPORTED​ is returned if the combination of internal formats of the attached images violates an implementation-dependent set of restrictions."); + break; + case GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE: + Log::Warning("GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE​ is returned if the value of GL_RENDERBUFFER_SAMPLES​ is not the same for all attached renderbuffers; if the value of GL_TEXTURE_SAMPLES​ is the not same for all attached textures; or, if the attached images are a mix of renderbuffers and textures, the value of GL_RENDERBUFFER_SAMPLES​ does not match the value of GL_TEXTURE_SAMPLES.\nGL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE​ is also returned if the value of GL_TEXTURE_FIXED_SAMPLE_LOCATIONS​ is not the same for all attached textures; or, if the attached images are a mix of renderbuffers and textures, the value of GL_TEXTURE_FIXED_SAMPLE_LOCATIONS​ is not GL_TRUE​ for all attached textures."); + break; + case GL_FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS: + Log::Warning("GL_FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS​ is returned if any framebuffer attachment is layered, and any populated attachment is not layered, or if all populated color attachments are not from textures of the same target."); + break; + case GL_FRAMEBUFFER_UNDEFINED: + Log::Warning(" GL_FRAMEBUFFER_UNDEFINED​ is returned if target​ is the default framebuffer, but the default framebuffer does not exist."); + break; + case GL_FRAMEBUFFER_COMPLETE: + Log::Warning("Framebuffer complete"); + break; + } +} + diff --git a/FrameBuffer.h b/FrameBuffer.h index aa268ff..e74ffd9 100644 --- a/FrameBuffer.h +++ b/FrameBuffer.h @@ -1,11 +1,35 @@ #ifndef FRAMEBUFFER_H #define FRAMEBUFFER_H +#include "Scene.h" + + +class FrameBuffer { -class FrameBuffer -{ public: - FrameBuffer(); + FrameBuffer(uint width, uint height, bool useDepthBuffer = false); + ~FrameBuffer(); + + // bind the FrameBuffer as current to draw into + void bind(); + // releases the framebuffer object + static void release(); + // blit copy to another, returns true on success + bool blit(FrameBuffer *other); + + inline uint width() const { return width_; } + inline uint height() const { return height_; } + inline uint texture() const { return textureid_; } + float aspectRatio() const; + +private: + void checkFramebufferStatus(); + uint width_; + uint height_; + uint textureid_; + uint framebufferid_; }; -#endif // FRAMEBUFFER_H \ No newline at end of file + + +#endif // FRAMEBUFFER_H diff --git a/Primitives.cpp b/Primitives.cpp index 7dbf735..15cea1b 100644 --- a/Primitives.cpp +++ b/Primitives.cpp @@ -13,45 +13,60 @@ #include #include #include +#include + +#define GLM_ENABLE_EXPERIMENTAL +#include +static const std::vector square_points { glm::vec3( -1.f, -1.f, 0.f ), glm::vec3( -1.f, 1.f, 0.f ), + glm::vec3( 1.f, 1.f, 0.f ), glm::vec3( 1.f, -1.f, 0.f ) }; +static uint square_vao = 0; +static uint circle_vao = 0; +static const std::string default_texture = "images/busy.png"; -TexturedRectangle::TexturedRectangle(const std::string& resourcepath) : Primitive() + +ImageSurface::ImageSurface(const std::string& path) : Primitive() { - texturepath_ = resourcepath; + filename_ = path; float ar = 1.0; - textureindex_ = Resource::getTextureImage(texturepath_, &ar); + textureindex_ = Resource::getTextureImage(filename_, &ar); transform_ = glm::scale(glm::identity(), glm::vec3(ar, 1.f, 1.f)); - // point 0 - points_.push_back( glm::vec3( -ar, -1.f, 0.f ) ); - colors_.push_back( glm::vec3( 1.f, 1.f, 1.f ) ); - texCoords_.push_back( glm::vec2( 0.f, 1.f ) ); - // point 1 - points_.push_back( glm::vec3( -ar, 1.f, 0.f ) ); - colors_.push_back( glm::vec3( 1.f, 1.f, 1.f ) ); - texCoords_.push_back( glm::vec2( 0.f, 0.f ) ); - // point 2 - points_.push_back( glm::vec3( ar, -1.f, 0.f ) ); - colors_.push_back( glm::vec3( 1.f, 1.f, 1.f ) ); - texCoords_.push_back( glm::vec2( 1.f, 1.f ) ); - // point 3 - points_.push_back( glm::vec3( ar, 1.f, 0.f ) ); - colors_.push_back( glm::vec3( 1.f, 1.f, 1.f ) ); - texCoords_.push_back( glm::vec2( 1.f, 0.f ) ); - // indices - indices_.push_back ( 0 ); - indices_.push_back ( 1 ); - indices_.push_back ( 2 ); - indices_.push_back ( 3 ); + // geometry + points_ = std::vector { glm::vec3( -1.f, -1.f, 0.f ), glm::vec3( -1.f, 1.f, 0.f ), + glm::vec3( 1.f, -1.f, 0.f ), glm::vec3( 1.f, 1.f, 0.f ) }; + colors_ = std::vector { glm::vec3( 1.f, 1.f, 1.f ), glm::vec3( 1.f, 1.f, 1.f ), + glm::vec3( 1.f, 1.f, 1.f ), glm::vec3( 1.f, 1.f, 1.f ) }; + texCoords_ = std::vector { glm::vec2( 0.f, 1.f ), glm::vec2( 0.f, 0.f ), + glm::vec2( 1.f, 1.f ), glm::vec2( 1.f, 0.f ) }; + indices_ = std::vector { 0, 1, 2, 3 }; // setup shader for textured image shader_ = new ImageShader(); drawingPrimitive_ = GL_TRIANGLE_STRIP; } -void TexturedRectangle::draw(glm::mat4 modelview, glm::mat4 projection) + +void ImageSurface::init() +{ + // use static global vertex array object + if (square_vao) + // if set, use the global vertex array object + vao_ = square_vao; + else { + // 1. init as usual (only once) + Primitive::init(); + // 2. remember global vao + square_vao = vao_; + // 3. vao_ will not be deleted because deleteGLBuffers_() is empty + } + + visible_ = true; +} + +void ImageSurface::draw(glm::mat4 modelview, glm::mat4 projection) { glBindTexture(GL_TEXTURE_2D, textureindex_); @@ -60,79 +75,54 @@ void TexturedRectangle::draw(glm::mat4 modelview, glm::mat4 projection) glBindTexture(GL_TEXTURE_2D, 0); } -void TexturedRectangle::accept(Visitor& v) +void ImageSurface::accept(Visitor& v) { Primitive::accept(v); v.visit(*this); } - -MediaRectangle::MediaRectangle(const std::string& mediapath) : Primitive() +MediaSurface::MediaSurface(const std::string& path) : ImageSurface(default_texture) { - mediapath_ = mediapath; - + filename_ = path; mediaplayer_ = new MediaPlayer; - mediaplayer_->Open(mediapath_); - mediaplayer_->Play(true); - - // point 0 - points_.push_back( glm::vec3( -1.f, -1.f, 0.f ) ); - colors_.push_back( glm::vec3( 1.f, 1.f, 1.f ) ); - texCoords_.push_back( glm::vec2( 0.f, 1.f ) ); - // point 1 - points_.push_back( glm::vec3( -1.f, 1.f, 0.f ) ); - colors_.push_back( glm::vec3( 1.f, 1.f, 1.f ) ); - texCoords_.push_back( glm::vec2( 0.f, 0.f ) ); - // point 2 - points_.push_back( glm::vec3( 1.f, -1.f, 0.f ) ); - colors_.push_back( glm::vec3( 1.f, 1.f, 1.f ) ); - texCoords_.push_back( glm::vec2( 1.f, 1.f ) ); - // point 3 - points_.push_back( glm::vec3( 1.f, 1.f, 0.f ) ); - colors_.push_back( glm::vec3( 1.f, 1.f, 1.f ) ); - texCoords_.push_back( glm::vec2( 1.f, 0.f ) ); - // indices - indices_.push_back ( 0 ); - indices_.push_back ( 1 ); - indices_.push_back ( 2 ); - indices_.push_back ( 3 ); - - // setup shader for textured image - shader_ = new ImageShader(); - drawingPrimitive_ = GL_TRIANGLE_STRIP; + mediaplayer_->open(filename_); + mediaplayer_->play(true); } -MediaRectangle::~MediaRectangle() +MediaSurface::~MediaSurface() { delete mediaplayer_; } -void MediaRectangle::draw(glm::mat4 modelview, glm::mat4 projection) +void MediaSurface::draw(glm::mat4 modelview, glm::mat4 projection) { - mediaplayer_->Bind(); + if ( mediaplayer_->isOpen() ) + mediaplayer_->bind(); + else + glBindTexture(GL_TEXTURE_2D, textureindex_); Primitive::draw(modelview, projection); glBindTexture(GL_TEXTURE_2D, 0); } -void MediaRectangle::update( float dt ) +void MediaSurface::update( float dt ) { if ( mediaplayer_->isOpen() ) - mediaplayer_->Update(); + mediaplayer_->update(); - transform_ = glm::scale(glm::identity(), glm::vec3(mediaplayer_->AspectRatio(), 1.f, 1.f)); + transform_ = glm::scale(glm::identity(), glm::vec3(mediaplayer_->aspectRatio(), 1.f, 1.f)); Primitive::update( dt ); } -void MediaRectangle::accept(Visitor& v) +void MediaSurface::accept(Visitor& v) { - Primitive::accept(v); + ImageSurface::accept(v); v.visit(*this); } -LineStrip::LineStrip(std::vector points, glm::vec3 color) : Primitive() +LineStrip::LineStrip(std::vector points, glm::vec3 color, uint linewidth) : Primitive() { for(size_t i = 0; i < points.size(); ++i) { @@ -144,7 +134,7 @@ LineStrip::LineStrip(std::vector points, glm::vec3 color) : Primitive shader_ = new Shader(); drawingPrimitive_ = GL_LINE_LOOP; - linewidth_ = 2; + linewidth_ = linewidth; } void LineStrip::draw(glm::mat4 modelview, glm::mat4 projection) @@ -158,3 +148,49 @@ void LineStrip::accept(Visitor& v) Primitive::accept(v); v.visit(*this); } + + +LineSquare::LineSquare(glm::vec3 color, uint linewidth) : LineStrip(square_points, color, linewidth) +{ +} + +LineCircle::LineCircle(glm::vec3 color, uint linewidth) : LineStrip(square_points, color, linewidth) +{ + points_.clear(); + colors_.clear(); + indices_.clear(); + + int N = 72; + float a = glm::two_pi() / static_cast(N); + glm::vec3 P(1.f, 0.f, 0.f); + for (int i = 0; i < N ; i++ ){ + points_.push_back( glm::vec3(P) ); + colors_.push_back( color ); + indices_.push_back ( i ); + + P = glm::rotateZ(P, a); + } +} + +void LineCircle::init() +{ + // use static global vertex array object + if (circle_vao) + // if set, use the global vertex array object + vao_ = square_vao; + else { + // 1. init as usual (only once) + Primitive::init(); + // 2. remember global vao + circle_vao = vao_; + // 3. vao_ will not be deleted because deleteGLBuffers_() is empty + } + + visible_ = true; +} + +void LineCircle::accept(Visitor& v) +{ + Primitive::accept(v); + v.visit(*this); +} diff --git a/Primitives.h b/Primitives.h index 2bfb2a9..838ac24 100644 --- a/Primitives.h +++ b/Primitives.h @@ -6,58 +6,89 @@ #include "Scene.h" // Draw a Rectangle (triangle strip) with a texture -class TexturedRectangle : public Primitive { +class ImageSurface : public Primitive { - std::string texturepath_; - unsigned int textureindex_; + void deleteGLBuffers_() {} public: - TexturedRectangle(const std::string& resourcepath); + ImageSurface(const std::string& path); + void init() override; void draw(glm::mat4 modelview, glm::mat4 projection) override; void accept(Visitor& v) override; - std::string getResourcePath() { return texturepath_; } + std::string getFilename() { return filename_; } + +protected: + std::string filename_; + uint textureindex_; }; // Draw a Rectangle (triangle strip) with a media as animated texture class MediaPlayer; -class MediaRectangle : public Primitive { +class MediaSurface : public ImageSurface { MediaPlayer *mediaplayer_; - std::string mediapath_; - unsigned int textureindex_; public: - MediaRectangle(const std::string& mediapath); - ~MediaRectangle(); + MediaSurface(const std::string& path); + ~MediaSurface(); - void update ( float dt ) override; void draw(glm::mat4 modelview, glm::mat4 projection) override; void accept(Visitor& v) override; + void update ( float dt ) override; - std::string getMediaPath() { return mediapath_; } - MediaPlayer *getMediaPlayer() { return mediaplayer_; } + MediaPlayer *getMediaPlayer() { return mediaplayer_; } }; +//// Draw a Frame Buffer +//class FrameBufferSurface : public Primitive { + +// void deleteGLBuffers_() {} + +//public: +// FrameBufferSurface(); + +// void init () override; +// void draw(glm::mat4 modelview, glm::mat4 projection) override; +// void accept(Visitor& v) override; + +//}; // Draw a line strip class LineStrip : public Primitive { - int linewidth_; + uint linewidth_; public: - LineStrip(std::vector points, glm::vec3 color); + LineStrip(std::vector points, glm::vec3 color, uint linewidth = 1); - void draw(glm::mat4 modelview, glm::mat4 projection) override; - void accept(Visitor& v) override; + virtual void draw(glm::mat4 modelview, glm::mat4 projection) override; + virtual void accept(Visitor& v) override; std::vector getPoints() { return points_; } glm::vec3 getColor() { return colors_[0]; } + uint getLineWidth() { return linewidth_; } +}; + +class LineSquare : public LineStrip { + +public: + LineSquare(glm::vec3 color, uint linewidth = 1); +}; + +class LineCircle : public LineStrip { + + void deleteGLBuffers_() {} + +public: + LineCircle(glm::vec3 color, uint linewidth = 1); + + void init() override; + void accept(Visitor& v) override; }; - #endif // PRIMITIVES_H diff --git a/Scene.cpp b/Scene.cpp index 456dd90..59feb48 100644 --- a/Scene.cpp +++ b/Scene.cpp @@ -25,12 +25,12 @@ Node::Node() : parent_(nullptr), visible_(false) void Node::update( float dt ) { if ( parent_ ) { - localToWorld_ = dynamic_cast(parent_)->getLocalToWorldMatrix() * transform_; - worldToLocal_ = glm::inverse(transform_) * dynamic_cast(parent_)->getWorldToLocalMatrix(); + localToWorld_ = dynamic_cast(parent_)->getLocalToWorldMatrix() * transform_; + worldToLocal_ = glm::inverse(transform_) * dynamic_cast(parent_)->getWorldToLocalMatrix(); } else { - localToWorld_ = transform_; - worldToLocal_ = glm::inverse(transform_); + localToWorld_ = transform_; + worldToLocal_ = glm::inverse(transform_); } } @@ -49,6 +49,7 @@ Primitive::~Primitive() colors_.clear(); texCoords_.clear(); indices_.clear(); + } void Primitive::init() @@ -58,6 +59,8 @@ void Primitive::init() // Vertex Array glGenVertexArrays( 1, &vao_ ); // Create and initialize buffer objects + uint arrayBuffer_; + uint elementBuffer_; glGenBuffers( 1, &arrayBuffer_ ); glGenBuffers( 1, &elementBuffer_); glBindVertexArray( vao_ ); @@ -77,7 +80,7 @@ void Primitive::init() // setup the element array for the triangle indices glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, elementBuffer_); - int sizeofIndices = indices_.size()*sizeof(unsigned int); + int sizeofIndices = indices_.size()*sizeof(uint); glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeofIndices, &(indices_[0]), GL_STATIC_DRAW); // explain how to read attributes 0, 1 and 2 (for point, color and textcoord respectively) @@ -94,25 +97,30 @@ void Primitive::init() glBindBuffer(GL_ARRAY_BUFFER, 0); glBindVertexArray(0); + // delete temporary buffers + if ( arrayBuffer_ ) glDeleteBuffers ( 1, &arrayBuffer_); + if ( elementBuffer_ ) glDeleteBuffers ( 1, &elementBuffer_); + visible_ = true; } void Primitive::draw(glm::mat4 modelview, glm::mat4 projection) { if ( visible_ ) { - - if (shader_) { - shader_->projection = projection; - shader_->modelview = modelview * transform_; - shader_->use(); - } - - // - // draw vertex array object - // - glBindVertexArray( vao_ ); - glDrawElements( drawingPrimitive_, indices_.size(), GL_UNSIGNED_INT, 0 ); - glBindVertexArray(0); + // + // prepare and use shader + // + if (shader_) { + shader_->projection = projection; + shader_->modelview = modelview * transform_; + shader_->use(); + } + // + // draw vertex array object + // + glBindVertexArray( vao_ ); + glDrawElements( drawingPrimitive_, indices_.size(), GL_UNSIGNED_INT, 0 ); + glBindVertexArray(0); } } @@ -125,9 +133,8 @@ void Primitive::accept(Visitor& v) void Primitive::deleteGLBuffers_() { - if ( arrayBuffer_ ) glDeleteBuffers ( 1, &arrayBuffer_); - if ( elementBuffer_ ) glDeleteBuffers ( 1, &elementBuffer_); - if ( vao_ ) glDeleteVertexArrays ( 1, &vao_); + if ( vao_ ) + glDeleteVertexArrays ( 1, &vao_); } // Group diff --git a/Scene.h b/Scene.h index 294f577..69b4496 100644 --- a/Scene.h +++ b/Scene.h @@ -37,7 +37,7 @@ public: class Primitive : public Node { public: - Primitive() : Node(), shader_(nullptr), vao_(0), arrayBuffer_(0), elementBuffer_(0), drawingPrimitive_(0) {} + Primitive() : Node(), shader_(nullptr), vao_(0), drawingPrimitive_(0) {} virtual ~Primitive(); virtual void init () override; @@ -49,15 +49,13 @@ public: protected: Shader* shader_; - unsigned int vao_; - unsigned int arrayBuffer_; - unsigned int elementBuffer_; - unsigned int drawingPrimitive_; + uint vao_; + uint drawingPrimitive_; std::vector points_; std::vector colors_; std::vector texCoords_; - std::vector indices_; - void deleteGLBuffers_(); + std::vector indices_; + virtual void deleteGLBuffers_(); }; // Other Nodes establish hierarchy with a group of nodes diff --git a/SessionVisitor.cpp b/SessionVisitor.cpp index 715bffe..014005d 100644 --- a/SessionVisitor.cpp +++ b/SessionVisitor.cpp @@ -13,16 +13,18 @@ using namespace tinyxml2; -SessionVisitor::SessionVisitor(std::string filename) : filename_(filename) +SessionVisitor::SessionVisitor() { xmlDoc_ = new XMLDocument; + xmlCurrent_ = nullptr; + xmlRoot_ = nullptr; } void SessionVisitor::visit(Node &n) { XMLElement *newelement = xmlDoc_->NewElement("Node"); -// xmlCurrent_->SetAttribute("type", "Undefined"); + newelement->SetAttribute("visible", n.visible_); XMLElement *transform = XMLElementFromGLM(xmlDoc_, n.transform_); newelement->InsertEndChild(transform); @@ -47,6 +49,7 @@ void SessionVisitor::visit(Group &n) // revert to group as current xmlCurrent_ = group; } + n.visible_; } void SessionVisitor::visit(Switch &n) @@ -73,37 +76,31 @@ void SessionVisitor::visit(Primitive &n) } -void SessionVisitor::visit(TexturedRectangle &n) +void SessionVisitor::visit(ImageSurface &n) { // Node of a different type - xmlCurrent_->SetAttribute("type", "TexturedRectangle"); + xmlCurrent_->SetAttribute("type", "ImageSurface"); - XMLText *filename = xmlDoc_->NewText( n.getResourcePath().c_str() ); + XMLText *filename = xmlDoc_->NewText( n.getFilename().c_str() ); XMLElement *image = xmlDoc_->NewElement("filename"); image->InsertEndChild(filename); xmlCurrent_->InsertEndChild(image); } -void SessionVisitor::visit(MediaRectangle &n) +void SessionVisitor::visit(MediaSurface &n) { // Node of a different type - xmlCurrent_->SetAttribute("type", "MediaRectangle"); - - XMLText *filename = xmlDoc_->NewText( n.getMediaPath().c_str() ); - XMLElement *media = xmlDoc_->NewElement("filename"); - media->InsertEndChild(filename); - xmlCurrent_->InsertEndChild(media); + xmlCurrent_->SetAttribute("type", "MediaSurface"); n.getMediaPlayer()->accept(*this); - } void SessionVisitor::visit(MediaPlayer &n) { XMLElement *newelement = xmlDoc_->NewElement("MediaPlayer"); newelement->SetAttribute("play", n.isPlaying()); - newelement->SetAttribute("loop", (int) n.Loop()); - newelement->SetAttribute("speed", n.PlaySpeed()); + newelement->SetAttribute("loop", (int) n.loop()); + newelement->SetAttribute("speed", n.playSpeed()); xmlCurrent_->InsertEndChild(newelement); } @@ -152,23 +149,48 @@ void SessionVisitor::visit(LineStrip &n) } } +void SessionVisitor::visit(LineSquare &n) +{ + // Node of a different type + xmlCurrent_->SetAttribute("type", "LineSquare"); + +} + +void SessionVisitor::visit(LineCircle &n) +{ + // Node of a different type + xmlCurrent_->SetAttribute("type", "LineCircle"); + + XMLElement *color = XMLElementFromGLM(xmlDoc_, n.getColor()); + color->SetAttribute("type", "RGBA"); + xmlCurrent_->InsertEndChild(color); +} + + void SessionVisitor::visit(Scene &n) +{ + std::string s = "Capture time " + GstToolkit::date_time_string(); + XMLComment *pComment = xmlDoc_->NewComment(s.c_str()); + xmlDoc_->InsertEndChild(pComment); + + xmlRoot_ = xmlDoc_->NewElement("Scene"); + xmlDoc_->InsertEndChild(xmlRoot_); + + // start recursive traverse from root node + xmlCurrent_ = xmlRoot_; + n.getRoot()->accept(*this); +} + +void SessionVisitor::save(std::string filename) { XMLDeclaration *pDec = xmlDoc_->NewDeclaration(); xmlDoc_->InsertFirstChild(pDec); - XMLElement *pRoot = xmlDoc_->NewElement("Scene"); - xmlDoc_->InsertEndChild(pRoot); - - std::string s = "Saved on " + GstToolkit::date_time_string(); + std::string s = "Save time " + GstToolkit::date_time_string(); XMLComment *pComment = xmlDoc_->NewComment(s.c_str()); - pRoot->InsertEndChild(pComment); + xmlDoc_->InsertEndChild(pComment); - // start recursive traverse from root node - xmlCurrent_ = pRoot; - n.getRoot()->accept(*this); - - // save scene - XMLError eResult = xmlDoc_->SaveFile(filename_.c_str()); + // save session + XMLError eResult = xmlDoc_->SaveFile(filename.c_str()); XMLCheckResult(eResult); } diff --git a/SessionVisitor.h b/SessionVisitor.h index d9f9dd0..ae60850 100644 --- a/SessionVisitor.h +++ b/SessionVisitor.h @@ -6,22 +6,26 @@ class SessionVisitor : public Visitor { - std::string filename_; tinyxml2::XMLDocument *xmlDoc_; tinyxml2::XMLElement *xmlCurrent_; + tinyxml2::XMLElement *xmlRoot_; public: - SessionVisitor(std::string filename); + SessionVisitor(); + void save(std::string filename); + tinyxml2::XMLElement *root() {return xmlRoot_;} // Elements of Scene + void visit(Scene& n) override; void visit(Node& n) override; void visit(Group& n) override; void visit(Switch& n) override; void visit(Primitive& n) override; - void visit(Scene& n) override; - void visit(TexturedRectangle& n) override; - void visit(MediaRectangle& n) override; + void visit(ImageSurface& n) override; + void visit(MediaSurface& n) override; void visit(LineStrip& n) override; + void visit(LineSquare& n) override; + void visit(LineCircle& n) override; // Elements with attributes void visit(MediaPlayer& n) override; diff --git a/Visitor.h b/Visitor.h index decf871..a876b55 100644 --- a/Visitor.h +++ b/Visitor.h @@ -9,9 +9,11 @@ class Group; class Switch; class Primitive; class Scene; -class TexturedRectangle; -class MediaRectangle; +class ImageSurface; +class MediaSurface; class LineStrip; +class LineSquare; +class LineCircle; class MediaPlayer; class Shader; class ImageShader; @@ -21,14 +23,16 @@ class Visitor { public: // Declare overloads for each kind of Node to visit + virtual void visit(Scene& n) = 0; virtual void visit(Node& n) = 0; virtual void visit(Group& n) = 0; virtual void visit(Switch& n) = 0; virtual void visit(Primitive& n) = 0; - virtual void visit(Scene& n) = 0; - virtual void visit(TexturedRectangle& n) = 0; - virtual void visit(MediaRectangle& n) = 0; + virtual void visit(ImageSurface& n) = 0; + virtual void visit(MediaSurface& n) = 0; virtual void visit(LineStrip& n) = 0; + virtual void visit(LineSquare& n) = 0; + virtual void visit(LineCircle& n) = 0; virtual void visit(MediaPlayer& n) = 0; virtual void visit(Shader& n) = 0; virtual void visit(ImageShader& n) = 0; diff --git a/defines.h b/defines.h index c16ddcf..f26f65e 100644 --- a/defines.h +++ b/defines.h @@ -16,8 +16,8 @@ #define EXP100(val) (exp(log(10.0)/50.0*(float)(val))-1.0) #define EUCLIDEAN(P1, P2) sqrt((P1.x() - P2.x()) * (P1.x() - P2.x()) + (P1.y() - P2.y()) * (P1.y() - P2.y())) -#define SOURCE_UNIT 10.0 -#define CIRCLE_SQUARE_DIST(x,y) ( (x*x + y*y) / (SOURCE_UNIT * SOURCE_UNIT * CIRCLE_SIZE * CIRCLE_SIZE) ) +#define SCENE_UNIT 10.0 +#define CIRCLE_SQUARE_DIST(x,y) ( (x*x + y*y) / (SCENE_UNIT * SCENE_UNIT * SCENE_UNIT * SCENE_UNIT) ) #define TEXTURE_REQUIRED_MAXIMUM 2048 #define CATALOG_TEXTURE_HEIGHT 96 @@ -54,6 +54,5 @@ #define COLOR_FRAME_MOVE 230, 30, 230 #define COLOR_CURSOR 10, 100, 255 -#define XML_PREFERENCE_FILE "vlmixer.xml" #endif // VMIX_DEFINES_H diff --git a/main.cpp b/main.cpp index 417d063..7f01a94 100644 --- a/main.cpp +++ b/main.cpp @@ -58,14 +58,14 @@ void drawMediaBackgound() // // RENDER SOURCE // - testmedia2.Update(); + testmedia2.update(); // use the shader rendering_shader.projection = Rendering::manager().Projection(); rendering_shader.modelview = glm::identity();; rendering_shader.use(); // use the media - testmedia2.Bind(); + testmedia2.bind(); // draw the vertex array glBindVertexArray(vao); glDrawElements(GL_TRIANGLE_STRIP, 4, GL_UNSIGNED_INT, 0); @@ -126,12 +126,12 @@ void drawMediaPlayer() if ( !testmedia.isOpen() ) return; - testmedia.Update(); + testmedia.update(); if ( begin == GST_CLOCK_TIME_NONE) { - begin = testmedia.Duration() / 5; - end = testmedia.Duration() / 3; + begin = testmedia.duration() / 5; + end = testmedia.duration() / 3; // if ( testmedia.addPlaySegment(begin, end) ) // std::cerr << " - first segment " << std::endl; @@ -146,11 +146,11 @@ void drawMediaPlayer() float width = ImGui::GetContentRegionAvail().x; float spacing = ImGui::GetStyle().ItemInnerSpacing.x; - ImVec2 imagesize ( width, width / testmedia.AspectRatio()); - ImGui::Image((void*)(intptr_t)testmedia.Texture(), imagesize); + ImVec2 imagesize ( width, width / testmedia.aspectRatio()); + ImGui::Image((void*)(intptr_t)testmedia.texture(), imagesize); if (ImGui::Button(ICON_FA_FAST_BACKWARD)) - testmedia.Rewind(); + testmedia.rewind(); ImGui::SameLine(0, spacing); // remember playing mode of the GUI @@ -165,7 +165,7 @@ void drawMediaPlayer() ImGui::PushButtonRepeat(true); if (ImGui::Button(ICON_FA_FORWARD)) - testmedia.FastForward (); + testmedia.fastForward (); ImGui::PopButtonRepeat(); } else { @@ -176,7 +176,7 @@ void drawMediaPlayer() ImGui::PushButtonRepeat(true); if (ImGui::Button(ICON_FA_STEP_FORWARD)) - testmedia.SeekNextFrame(); + testmedia.seekNextFrame(); ImGui::PopButtonRepeat(); } @@ -195,23 +195,23 @@ void drawMediaPlayer() if ( ImGui::SliderInt("", ¤t_loop, 0, 2, current_loop_name) ) testmedia.setLoop( (MediaPlayer::LoopMode) current_loop ); - float speed = static_cast(testmedia.PlaySpeed()); + float speed = static_cast(testmedia.playSpeed()); ImGui::SameLine(0, spacing); ImGui::SetNextItemWidth(270); // ImGui::SetNextItemWidth(width - 90.0); if (ImGui::SliderFloat( "Speed", &speed, -10.f, 10.f, "x %.1f", 2.f)) - testmedia.SetPlaySpeed( static_cast(speed) ); + testmedia.setPlaySpeed( static_cast(speed) ); ImGui::SameLine(0, spacing); if (ImGuiToolkit::ButtonIcon(19, 15)) { speed = 1.f; - testmedia.SetPlaySpeed( static_cast(speed) ); + testmedia.setPlaySpeed( static_cast(speed) ); } - guint64 current_t = testmedia.Position(); + guint64 current_t = testmedia.position(); guint64 seek_t = current_t; bool slider_pressed = ImGuiToolkit::TimelineSlider( "simpletimeline", &seek_t, - testmedia.Duration(), testmedia.FrameDuration()); + testmedia.duration(), testmedia.frameDuration()); // std::list > segments = testmedia.getPlaySegments(); // bool slider_pressed = ImGuiToolkit::TimelineSliderEdit( "timeline", &seek_t, testmedia.Duration(), @@ -231,10 +231,10 @@ void drawMediaPlayer() // if the seek target time is different from the current position time // (i.e. the difference is less than one frame) - if ( ABS_DIFF (current_t, seek_t) > testmedia.FrameDuration() ) { + if ( ABS_DIFF (current_t, seek_t) > testmedia.frameDuration() ) { // request seek (ASYNC) - testmedia.SeekTo(seek_t); + testmedia.seekTo(seek_t); } // play/stop command should be following the playing mode (buttons) @@ -245,12 +245,12 @@ void drawMediaPlayer() // NB: The seek command performed an ASYNC state change, but // gst_element_get_state called in isPlaying() will wait for the state change to complete. if ( testmedia.isPlaying() != media_play ) { - testmedia.Play( media_play ); + testmedia.play( media_play ); } // display info - ImGui::Text("%s %d x %d", testmedia.Codec().c_str(), testmedia.Width(), testmedia.Height()); - ImGui::Text("Framerate %.2f / %.2f", testmedia.UpdateFrameRate() , testmedia.FrameRate() ); + ImGui::Text("%s %d x %d", testmedia.codec().c_str(), testmedia.width(), testmedia.height()); + ImGui::Text("Framerate %.2f / %.2f", testmedia.updateFrameRate() , testmedia.frameRate() ); ImGui::End(); } @@ -331,27 +331,23 @@ int main(int, char**) // init the scene scene.root_.init(); - Rendering::manager().AddDrawCallback(drawScene); + Rendering::manager().PushBackDrawCallback(drawScene); // create and add a elements to the scene - MediaRectangle testnode1("file:///home/bhbn/Videos/iss.mov"); + MediaSurface testnode1("file:///home/bhbn/Videos/iss.mov"); testnode1.init(); - MediaRectangle testnode2("file:///home/bhbn/Videos/fish.mp4"); + MediaSurface testnode2("file:///home/bhbn/Videos/fish.mp4"); testnode2.init(); - TexturedRectangle testnode3("images/v-mix_256x256.png"); + ImageSurface testnode3("images/v-mix_256x256.png"); testnode3.init(); - testnode3.getShader()->blending = Shader::BLEND_SUBSTRACT; + testnode3.getShader()->blending = Shader::BLEND_ADD; - std::vector points; - points.push_back( glm::vec3( -1.f, -1.f, 0.f ) ); - points.push_back( glm::vec3( -1.f, 1.f, 0.f ) ); - points.push_back( glm::vec3( 1.f, 1.f, 0.f ) ); - points.push_back( glm::vec3( 1.f, -1.f, 0.f ) ); glm::vec3 color( 1.f, 1.f, 0.f ); - LineStrip border(points, color); + LineCircle border(color); +// LineSquare border(color); border.init(); Group g1; @@ -364,11 +360,12 @@ int main(int, char**) // build tree - g1.addChild(&testnode1); g1.addChild(&testnode3); + g1.addChild(&border); scene.root_.addChild(&g1); + + g2.addChild(&testnode1); g2.addChild(&testnode2); - g2.addChild(&border); g2.setActiveIndex(1); scene.root_.addChild(&g2); @@ -380,11 +377,13 @@ int main(int, char**) Rendering::manager().Draw(); } - testmedia.Close(); - testmedia2.Close(); + testmedia.close(); + testmedia2.close(); - SessionVisitor savetoxml("/home/bhbn/test.vmx"); + SessionVisitor savetoxml; scene.accept(savetoxml); + scene.accept(savetoxml); + savetoxml.save("/home/bhbn/test.vmx"); UserInterface::manager().Terminate(); Rendering::manager().Terminate();