From 2b7531dc382e6eb451850105c7a1853ee7f0061d Mon Sep 17 00:00:00 2001 From: brunoherbelin Date: Sun, 5 Apr 2020 17:59:16 +0200 Subject: [PATCH] Cleanup Scene classes --- ImGuiToolkit.cpp | 4 +- ImGuiVisitor.cpp | 5 +- Primitives.cpp | 23 +++++----- Scene.cpp | 111 +++++++++++++++++++++++++++++++++------------ Scene.h | 95 ++++++++++++++++++++++++++++---------- SessionVisitor.cpp | 9 ++-- 6 files changed, 171 insertions(+), 76 deletions(-) diff --git a/ImGuiToolkit.cpp b/ImGuiToolkit.cpp index 47afdc8..bb30748 100644 --- a/ImGuiToolkit.cpp +++ b/ImGuiToolkit.cpp @@ -639,7 +639,7 @@ void ImGuiToolkit::SetAccentColor(accent_color color) colors[ImGuiCol_Separator] = ImVec4(0.50f, 0.43f, 0.43f, 0.50f); colors[ImGuiCol_SeparatorHovered] = ImVec4(0.75f, 0.40f, 0.10f, 0.67f); colors[ImGuiCol_SeparatorActive] = ImVec4(0.90f, 0.73f, 0.59f, 0.95f); - colors[ImGuiCol_ResizeGrip] = ImVec4(0.49f, 0.49f, 0.52f, 0.50f); + colors[ImGuiCol_ResizeGrip] = ImVec4(0.52f, 0.49f, 0.49f, 0.50f); colors[ImGuiCol_ResizeGripHovered] = ImVec4(0.90f, 0.73f, 0.59f, 0.67f); colors[ImGuiCol_ResizeGripActive] = ImVec4(0.90f, 0.73f, 0.59f, 0.95f); colors[ImGuiCol_Tab] = ImVec4(0.58f, 0.35f, 0.18f, 0.82f); @@ -690,7 +690,7 @@ void ImGuiToolkit::SetAccentColor(accent_color color) colors[ImGuiCol_Separator] = ImVec4(0.43f, 0.43f, 0.50f, 0.50f); colors[ImGuiCol_SeparatorHovered] = ImVec4(0.75f, 0.75f, 0.75f, 0.67f); colors[ImGuiCol_SeparatorActive] = ImVec4(0.75f, 0.75f, 0.75f, 0.95f); - colors[ImGuiCol_ResizeGrip] = ImVec4(0.49f, 0.49f, 0.52f, 0.50f); + colors[ImGuiCol_ResizeGrip] = ImVec4(0.49f, 0.49f, 0.49f, 0.50f); colors[ImGuiCol_ResizeGripHovered] = ImVec4(0.90f, 0.90f, 0.90f, 0.67f); colors[ImGuiCol_ResizeGripActive] = ImVec4(0.90f, 0.90f, 0.90f, 0.95f); colors[ImGuiCol_Tab] = ImVec4(0.47f, 0.47f, 0.47f, 0.82f); diff --git a/ImGuiVisitor.cpp b/ImGuiVisitor.cpp index 45afe04..a9134e7 100644 --- a/ImGuiVisitor.cpp +++ b/ImGuiVisitor.cpp @@ -62,9 +62,8 @@ void ImGuiVisitor::visit(Group &n) } // loop over members of a group - for (int i = 0; i < n.numChildren(); ++i) - { - n.getChild(i)->accept(*this); + for (NodeSet::iterator node = n.begin(); node != n.end(); node++) { + (*node)->accept(*this); } ImGui::TreePop(); diff --git a/Primitives.cpp b/Primitives.cpp index 2dfc2dc..b81cea7 100644 --- a/Primitives.cpp +++ b/Primitives.cpp @@ -56,25 +56,24 @@ void ImageSurface::init() shader_ = new ImageShader(); // use static global vertex array object - if (square_vao) + if (square_vao) { + // only init Node (not the primitive vao + Node::init(); // 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 + // 3. vao_ will NOT be deleted because deleteGLBuffers_() is empty } - - // all good - visible_ = true; - initialized_ = true; } void ImageSurface::draw(glm::mat4 modelview, glm::mat4 projection) { - if ( !initialized_ ) + if ( !initialized() ) init(); glBindTexture(GL_TEXTURE_2D, textureindex_); @@ -114,7 +113,7 @@ void MediaSurface::init() void MediaSurface::draw(glm::mat4 modelview, glm::mat4 projection) { - if ( !initialized_ ) + if ( !initialized() ) init(); if ( mediaplayer_->isOpen() ) @@ -164,7 +163,7 @@ void LineStrip::init() void LineStrip::draw(glm::mat4 modelview, glm::mat4 projection) { - if ( !initialized_ ) + if ( !initialized() ) init(); glLineWidth(linewidth_); @@ -203,9 +202,11 @@ LineCircle::LineCircle(glm::vec3 color, uint linewidth) : LineStrip(square_point void LineCircle::init() { // use static global vertex array object - if (circle_vao) + if (circle_vao) { + Node::init(); // if set, use the global vertex array object vao_ = square_vao; + } else { // 1. init as usual (only once) Primitive::init(); @@ -215,8 +216,6 @@ void LineCircle::init() } shader_ = new Shader(); - visible_ = true; - initialized_ = true; } void LineCircle::accept(Visitor& v) diff --git a/Scene.cpp b/Scene.cpp index e6e42ea..17c0687 100644 --- a/Scene.cpp +++ b/Scene.cpp @@ -16,6 +16,7 @@ #include #include +#include glm::mat4 transform(glm::vec3 translation, glm::vec3 rotation, glm::vec3 scale) @@ -29,7 +30,7 @@ glm::mat4 transform(glm::vec3 translation, glm::vec3 rotation, glm::vec3 scale) } // Node -Node::Node() : parent_(nullptr), visible_(false), initialized_(false) +Node::Node() : initialized_(false), parent_(nullptr), visible_(true) { // create unique id auto duration = std::chrono::system_clock::now().time_since_epoch(); @@ -123,13 +124,12 @@ void Primitive::init() if ( arrayBuffer_ ) glDeleteBuffers ( 1, &arrayBuffer_); if ( elementBuffer_ ) glDeleteBuffers ( 1, &elementBuffer_); - initialized_ = true; - visible_ = true; + Node::init(); } void Primitive::draw(glm::mat4 modelview, glm::mat4 projection) { - if ( !initialized_ ) + if ( !initialized() ) init(); if ( visible_ ) { @@ -172,13 +172,12 @@ Group::~Group() void Group::init() { - for (std::vector::iterator node = children_.begin(); + for (NodeSet::iterator node = children_.begin(); node != children_.end(); node++) { (*node)->init(); } - visible_ = true; - initialized_ = true; + Node::init(); } void Group::update( float dt ) @@ -186,7 +185,7 @@ void Group::update( float dt ) Node::update(dt); // update every child node - for (std::vector::iterator node = children_.begin(); + for (NodeSet::iterator node = children_.begin(); node != children_.end(); node++) { (*node)->update ( dt ); } @@ -194,7 +193,7 @@ void Group::update( float dt ) void Group::draw(glm::mat4 modelview, glm::mat4 projection) { - if ( !initialized_ ) + if ( !initialized() ) init(); if ( visible_ ) { @@ -203,7 +202,7 @@ void Group::draw(glm::mat4 modelview, glm::mat4 projection) glm::mat4 ctm = modelview * transform_; // draw every child node - for (std::vector::iterator node = children_.begin(); + for (NodeSet::iterator node = children_.begin(); node != children_.end(); node++) { (*node)->draw ( ctm, projection ); } @@ -216,19 +215,31 @@ void Group::accept(Visitor& v) v.visit(*this); } - void Group::addChild(Node *child) { - children_.push_back( child ); + children_.insert(child); child->parent_ = this; } -Node *Group::getChild(uint i) +void Group::removeChild(Node *child) { - if ( i >= 0 && i < children_.size() ) - return children_[i]; - else - return nullptr; + NodeSet::iterator it = std::find_if(children_.begin(), children_.end(), hasId(child->id())); + + if ( it != children_.end()) + { + children_.erase(it); + child->parent_ = nullptr; + } +} + +NodeSet::iterator Group::begin() +{ + return children_.begin(); +} + +NodeSet::iterator Group::end() +{ + return children_.end(); } uint Group::numChildren() const @@ -241,20 +252,22 @@ void Switch::update( float dt ) Node::update(dt); // update active child node - children_[active_]->update( dt ); + if (active_ != children_.end()) + (*active_)->update( dt ); } void Switch::draw(glm::mat4 modelview, glm::mat4 projection) { - if ( !initialized_ ) + if ( !initialized() ) init(); if ( visible_ ) { // append the instance transform to the ctm glm::mat4 ctm = modelview * transform_; - // draw current child - children_[active_]->draw(ctm, projection); + // draw current child + if (active_ != children_.end()) + (*active_)->draw(ctm, projection); } } @@ -264,19 +277,61 @@ void Switch::accept(Visitor& v) v.visit(*this); } -void Switch::setActiveIndex(uint index) +void Switch::addChild(Node *child) { - active_ = CLAMP( index, 0, children_.size() - 1); + Group::addChild(child); + setActiveChild(child); } -Node* Switch::activeNode() +void Switch::removeChild(Node *child) { - if ( children_.empty() ) - return nullptr; - - return children_[active_]; + Group::removeChild(child); + active_ = children_.begin(); } + +void Switch::setActiveChild(Node *child) +{ + setActiveChild( std::find_if(children_.begin(), children_.end(), hasId(child->id())) ); +} + +void Switch::setActiveChild(NodeSet::iterator n) +{ + if ( n != children_.end()) + active_ = n; + else + active_ = children_.begin(); +} + +NodeSet::iterator Switch::activeChild() const +{ + return active_; +} + +void Switch::setIndexActiveChild(int index) +{ + int i = 0; + for (NodeSet::iterator node = children_.begin(); + node != children_.end(); node++, i++) { + if ( i == index ) { + active_ = node; + break; + } + } +} + +int Switch::getIndexActiveChild() const +{ + int index = 0; + for (NodeSet::iterator node = children_.begin(); + node != children_.end(); node++, index++) { + if (node == active_) + break; + } + return index; +} + + void Scene::accept(Visitor& v) { v.visit(*this); diff --git a/Scene.h b/Scene.h index 5dd1274..b781a50 100644 --- a/Scene.h +++ b/Scene.h @@ -1,6 +1,9 @@ #ifndef SCENE_H #define SCENE_H +#define INVALID_ID -1 + +#include #include #include @@ -14,23 +17,35 @@ class Visitor; // Manages modelview transformations and culling class Node { + int id_; + bool initialized_; + public: Node(); - virtual ~Node() {} - inline int id() { return id_; } + virtual ~Node () {} - virtual void init() = 0; - virtual void draw( glm::mat4 modelview, glm::mat4 projection) = 0; - virtual void accept(Visitor& v); - virtual void update( float dt ); - virtual bool initialized() { return initialized_; } - virtual glm::mat4 getWorldToLocalMatrix() { return worldToLocal_; } - virtual glm::mat4 getLocalToWorldMatrix() { return localToWorld_; } + // unique identifyer generated at instanciation + inline int id () const { return id_; } + // must initialize the node before draw + virtual void init() { initialized_ = true; } + virtual bool initialized () { return initialized_; } + + // pure virtual draw : to be instanciated to define node behavior + virtual void draw (glm::mat4 modelview, glm::mat4 projection) = 0; + + // update every frame + virtual void update (float dt); + + // accept all kind of visitors + virtual void accept (Visitor& v); + + virtual glm::mat4 getWorldToLocalMatrix () { return worldToLocal_; } + virtual glm::mat4 getLocalToWorldMatrix () { return localToWorld_; } + + // public members, to manipulate with care Node* parent_; bool visible_; - bool initialized_; - int id_; glm::mat4 worldToLocal_; glm::mat4 localToWorld_; glm::mat4 transform_; @@ -38,6 +53,27 @@ public: }; +struct z_comparator +{ + inline bool operator () (const Node *a, const Node *b) const + { + //Sort Furthest to Closest + return (a && b && a->translation_.z < b->translation_.z); + } +}; +struct hasId: public std::unary_function +{ + inline bool operator()(const Node* e) const + { + return (e && e->id() == _id); + } + hasId(int id) : _id(id) { } +private: + int _id; +}; +typedef std::multiset NodeSet; + + // Leaf Nodes are primitives that can be rendered class Primitive : public Node { @@ -46,8 +82,8 @@ public: virtual ~Primitive(); virtual void init () override; - virtual void draw ( glm::mat4 modelview, glm::mat4 projection) override; - virtual void accept(Visitor& v) override; + virtual void accept (Visitor& v) override; + virtual void draw (glm::mat4 modelview, glm::mat4 projection) override; Shader *getShader() { return shader_; } void setShader( Shader* e ) { shader_ = e; } @@ -71,33 +107,42 @@ public: virtual ~Group(); virtual void init () override; - virtual void update ( float dt ) override; - virtual void draw ( glm::mat4 modelview, glm::mat4 projection) override; - virtual void accept(Visitor& v) override; + virtual void update (float dt) override; + virtual void accept (Visitor& v) override; + virtual void draw (glm::mat4 modelview, glm::mat4 projection) override; - void addChild ( Node *child ); - Node* getChild ( uint i ); + virtual void addChild (Node *child); + virtual void removeChild (Node *child); + + NodeSet::iterator begin(); + NodeSet::iterator end(); uint numChildren() const; protected: - std::vector< Node* > children_; + NodeSet children_; }; class Switch : public Group { public: - Switch() : Group(), active_(0) {} + Switch() : Group(), active_(end()) {} virtual void update ( float dt ) override; + virtual void accept (Visitor& v) override; virtual void draw ( glm::mat4 modelview, glm::mat4 projection) override; - virtual void accept(Visitor& v) override; - void setActiveIndex(uint index); - uint activeIndex() const { return active_; } - Node* activeNode(); + void addChild (Node *child) override; + void removeChild (Node *child) override; + + void setActiveChild (Node *child); + void setActiveChild (NodeSet::iterator n); + NodeSet::iterator activeChild () const; + + void setIndexActiveChild (int index); + int getIndexActiveChild () const; protected: - uint active_; + NodeSet::iterator active_; }; // A scene contains a root node and gives a simplified API to add nodes diff --git a/SessionVisitor.cpp b/SessionVisitor.cpp index 88a2ce3..dd45d9c 100644 --- a/SessionVisitor.cpp +++ b/SessionVisitor.cpp @@ -45,11 +45,8 @@ void SessionVisitor::visit(Group &n) // loop over members of a group XMLElement *group = xmlCurrent_; - for (int i = 0; i < n.numChildren(); ++i) - { - // recursive - n.getChild(i)->accept(*this); - xmlCurrent_->SetAttribute("index", i); + for (NodeSet::iterator node = n.begin(); node != n.end(); node++) { + (*node)->accept(*this); // revert to group as current xmlCurrent_ = group; } @@ -60,7 +57,7 @@ void SessionVisitor::visit(Switch &n) { // Node of a different type xmlCurrent_->SetAttribute("type", "Switch"); - xmlCurrent_->SetAttribute("active", n.activeIndex()); + xmlCurrent_->SetAttribute("active", n.getIndexActiveChild()); } void SessionVisitor::visit(Primitive &n)