Introducing scene graph

This commit is contained in:
brunoherbelin
2020-03-31 17:01:33 +02:00
parent cf5a3b3fc9
commit 2fc01e8435
17 changed files with 837 additions and 184 deletions

View File

@@ -187,16 +187,6 @@ message(STATUS "Compiling 'TinyFileDialog' from https://github.com/native-toolki
#
# SCENE GRAPH
#
set(SSG_INCLUDE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/ext/ssg)
set(SSG_SRCS
${CMAKE_CURRENT_SOURCE_DIR}/ext/ssg/ssg.cpp
${CMAKE_CURRENT_SOURCE_DIR}/ext/ssg/Texture.cpp
${CMAKE_CURRENT_SOURCE_DIR}/ext/ssg/TextureLoader.cpp
${CMAKE_CURRENT_SOURCE_DIR}/ext/ssg/ObjLoader.cpp
${CMAKE_CURRENT_SOURCE_DIR}/ext/ssg/InitShader.cpp
${CMAKE_CURRENT_SOURCE_DIR}/ext/ssg/FrameBufferObject.cpp
)
add_library(SSG "${SSG_SRCS}")
# Setup the environment
@@ -218,7 +208,6 @@ include_directories(
${TINYFD_INCLUDE_DIR}
${STB_INCLUDE_DIR}
${DIRENT_INCLUDE_DIR}
${SSG_INCLUDE_DIR}
)
@@ -228,6 +217,9 @@ set(VMIX_SRCS
Log.cpp
Shader.cpp
ImageShader.cpp
Scene.cpp
Primitives.cpp
Visitor.cpp
Settings.cpp
Resource.cpp
FileDialog.cpp
@@ -288,7 +280,6 @@ target_link_libraries(${VMIX_BINARY} LINK_PRIVATE
TINYXML2
TINYFD
IMGUI
SSG
vmix::rc
)

View File

@@ -20,6 +20,7 @@ string GstToolkit::date_time_string()
oss << setw(2) << setfill('0') << std::to_string(now->tm_hour );
oss << setw(2) << setfill('0') << std::to_string(now->tm_min );
oss << setw(2) << setfill('0') << std::to_string(now->tm_sec );
// TODO : add milisecond precision
return oss.str();
}

View File

@@ -66,6 +66,7 @@ MediaPlayer::MediaPlayer(string name) : id(name)
desired_state = GST_STATE_PAUSED;
loop = LoopMode::LOOP_REWIND;
current_segment = segments.begin();
v_frame.buffer = nullptr;
textureindex = 0;
}
@@ -447,7 +448,8 @@ std::list< std::pair<guint64, guint64> > MediaPlayer::getPlaySegments() const
void MediaPlayer::Update()
{
// discard
if (!ready) return;
if (!ready)
return;
// done discovering stream
if (discoverer != nullptr) {

135
Primitives.cpp Normal file
View File

@@ -0,0 +1,135 @@
#include "Primitives.h"
#include "ImageShader.h"
#include "Resource.h"
#include "MediaPlayer.h"
#include "Log.h"
#include <glad/glad.h>
#include <glm/gtc/type_ptr.hpp>
#include <glm/ext/vector_float3.hpp>
#include <glm/ext/vector_float4.hpp>
#include <glm/ext/matrix_float4x4.hpp>
#include <glm/gtc/matrix_access.hpp>
#include <glm/gtc/matrix_transform.hpp>
TexturedRectangle::TexturedRectangle(const std::string& resourcepath)
{
texturepath_ = resourcepath;
float ar = 1.0;
textureindex_ = Resource::getTextureImage(texturepath_, &ar);
transform_ = glm::scale(glm::identity<glm::mat4>(), 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 );
// setup shader for textured image
shader_ = new ImageShader();
}
void TexturedRectangle::draw(glm::mat4 modelview, glm::mat4 projection)
{
glBindTexture(GL_TEXTURE_2D, textureindex_);
Primitive::draw(modelview, projection);
glBindTexture(GL_TEXTURE_2D, 0);
}
MediaRectangle::MediaRectangle(const std::string& mediapath)
{
mediapath_ = mediapath;
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();
}
MediaRectangle::~MediaRectangle()
{
delete mediaplayer_;
}
void MediaRectangle::draw(glm::mat4 modelview, glm::mat4 projection)
{
mediaplayer_->Bind();
Primitive::draw(modelview, projection);
glBindTexture(GL_TEXTURE_2D, 0);
}
void MediaRectangle::update( float dt )
{
if ( mediaplayer_->isOpen() )
mediaplayer_->Update();
transform_ = glm::scale(glm::identity<glm::mat4>(), glm::vec3(mediaplayer_->AspectRatio(), 1.f, 1.f));
Primitive::update( dt );
}
LineStrip::LineStrip(std::vector<glm::vec3> points, glm::vec3 color)
{
for(int i = 0; i < points.size(); ++i)
{
points_.push_back( points[i] );
colors_.push_back( color );
indices_.push_back ( i );
}
shader_ = new Shader();
drawingPrimitive_ = GL_LINE_STRIP;
}

60
Primitives.h Normal file
View File

@@ -0,0 +1,60 @@
#ifndef PRIMITIVES_H
#define PRIMITIVES_H
#include <string>
#include "Scene.h"
// Draw a Rectangle (triangle strip) with a texture
class TexturedRectangle : public Primitive {
std::string texturepath_;
unsigned int textureindex_;
public:
TexturedRectangle(const std::string& resourcepath);
void draw(glm::mat4 modelview, glm::mat4 projection);
void accept(Visitor& v) override { v.visit(*this); }
std::string getResourcePath() { return texturepath_; }
};
// Draw a Rectangle (triangle strip) with a media as animated texture
class MediaPlayer;
class MediaRectangle : public Primitive {
MediaPlayer *mediaplayer_;
std::string mediapath_;
unsigned int textureindex_;
public:
MediaRectangle(const std::string& mediapath);
~MediaRectangle();
void update ( float dt );
void draw(glm::mat4 modelview, glm::mat4 projection);
void accept(Visitor& v) override { v.visit(*this); }
std::string getMediaPath() { return mediapath_; }
MediaPlayer *getMediaPlayer() { return mediaplayer_; }
};
// Draw a line strip
class LineStrip : public Primitive {
public:
LineStrip(std::vector<glm::vec3> points, glm::vec3 color);
void accept(Visitor& v) override { v.visit(*this); }
std::vector<glm::vec3> getPoints() { return points_; }
glm::vec3 getColor() { return colors_[0]; }
};
#endif // PRIMITIVES_H

View File

@@ -22,6 +22,7 @@ CMRC_DECLARE(vmix);
std::map<std::string, unsigned int> textureIndex;
std::map<std::string, float> textureAspectRatio;
const char *Resource::getData(const std::string& path, size_t* out_file_size){
@@ -65,12 +66,14 @@ std::string Resource::getText(const std::string& path){
#define FOURCC_DXT3 0x33545844 // Equivalent to "DXT3" in ASCII
#define FOURCC_DXT5 0x35545844 // Equivalent to "DXT5" in ASCII
unsigned int Resource::getTextureDDS(const std::string& path)
unsigned int Resource::getTextureDDS(const std::string& path, float *aspect_ratio)
{
GLuint textureID = 0;
if (textureIndex.count(path) > 0)
if (textureIndex.count(path) > 0){
if (aspect_ratio) *aspect_ratio = textureAspectRatio[path];
return textureIndex[path];
}
// Get the pointer
size_t size = 0;
@@ -103,7 +106,7 @@ unsigned int Resource::getTextureDDS(const std::string& path)
const char *buffer = fp + 128;
unsigned int components = (fourCC == FOURCC_DXT1) ? 3 : 4;
unsigned int format;
unsigned int format = 0;
switch(fourCC)
{
case FOURCC_DXT1:
@@ -122,6 +125,12 @@ unsigned int Resource::getTextureDDS(const std::string& path)
}
}
if (height == 0){
Log::Error("Invalid image in ressource %s", std::string(path).c_str());
return 0;
}
float ar = static_cast<float>(width) / static_cast<float>(height);
// Create one OpenGL texture
glGenTextures(1, &textureID);
@@ -151,20 +160,29 @@ unsigned int Resource::getTextureDDS(const std::string& path)
}
// remember to avoid openning the same resource twice
textureIndex[path] = textureID;
textureAspectRatio[path] = ar;
// return values
if (aspect_ratio) *aspect_ratio = ar;
return textureID;
}
unsigned int Resource::getTextureImage(const std::string& path)
unsigned int Resource::getTextureImage(const std::string& path, float *aspect_ratio)
{
GLuint textureID = 0;
if (textureIndex.count(path) > 0)
// return previously openned resource if already openned before
if (textureIndex.count(path) > 0) {
if (aspect_ratio) *aspect_ratio = textureAspectRatio[path];
return textureIndex[path];
}
float ar = 1.0;
int w, h, n;
unsigned char* img;
unsigned char* img = nullptr;
// Get the pointer
size_t size = 0;
@@ -179,6 +197,11 @@ unsigned int Resource::getTextureImage(const std::string& path)
Log::Error("Failed to open ressource %s: %s", std::string(path).c_str(), stbi_failure_reason() );
return 0;
}
if (h == 0){
Log::Error("Invalid image in ressource %s", std::string(path).c_str());
return 0;
}
ar = static_cast<float>(w) / static_cast<float>(h);
glGenTextures(1, &textureID);
glBindTexture( GL_TEXTURE_2D, textureID);
@@ -186,12 +209,17 @@ unsigned int Resource::getTextureImage(const std::string& path)
glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
//glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, img);
// free memory
stbi_image_free(img);
// remember to avoid openning the same resource twice
textureIndex[path] = textureID;
textureAspectRatio[path] = ar;
// return values
if (aspect_ratio) *aspect_ratio = ar;
return textureID;
}

View File

@@ -13,11 +13,11 @@ namespace Resource
// Support DDS files, DXT1, DXT5 and DXT5
// Returns the OpenGL generated Texture index
unsigned int getTextureDDS(const std::string& path);
unsigned int getTextureDDS(const std::string& path, float *aspect_ratio = nullptr);
// Support PNG, JPEG, TGA, BMP, PSD, GIF, HDR, PIC, PNM
// Returns the OpenGL generated Texture index
unsigned int getTextureImage(const std::string& path);
unsigned int getTextureImage(const std::string& path, float *aspect_ratio = nullptr);
// Generic access to pointer to data
const char *getData(const std::string& path, size_t* out_file_size);

178
Scene.cpp Normal file
View File

@@ -0,0 +1,178 @@
#include "Scene.h"
#include "Shader.h"
#include "Log.h"
#include <glad/glad.h>
#include <glm/gtc/type_ptr.hpp>
#include <glm/ext/vector_float3.hpp>
#include <glm/ext/vector_float4.hpp>
#include <glm/ext/matrix_float4x4.hpp>
#include <glm/gtc/matrix_access.hpp>
#include <glm/gtc/matrix_transform.hpp>
// Node
Node::Node() : parent_(nullptr), visible_(false)
{
worldToLocal_ = glm::identity<glm::mat4>();
localToWorld_ = glm::identity<glm::mat4>();
transform_ = glm::identity<glm::mat4>();
}
void Node::update( float dt )
{
if ( parent_ ) {
localToWorld_ = dynamic_cast<Group*>(parent_)->getLocalToWorldMatrix() * transform_;
worldToLocal_ = glm::inverse(transform_) * dynamic_cast<Group*>(parent_)->getWorldToLocalMatrix();
}
else {
localToWorld_ = transform_;
worldToLocal_ = glm::inverse(transform_);
}
}
// Primitive
Primitive::~Primitive()
{
deleteGLBuffers_();
points_.clear();
colors_.clear();
texCoords_.clear();
indices_.clear();
}
void Primitive::init()
{
deleteGLBuffers_();
// Vertex Array
glGenVertexArrays( 1, &vao_ );
// Create and initialize buffer objects
glGenBuffers( 1, &arrayBuffer_ );
glGenBuffers( 1, &elementBuffer_);
glBindVertexArray( vao_ );
// compute the memory needs for points normals and indicies
std::size_t sizeofPoints = sizeof(glm::vec3)*points_.size();
std::size_t sizeofColors = sizeof(glm::vec3)*colors_.size();
std::size_t sizeofTexCoords = sizeof(glm::vec2) * texCoords_.size();
// setup the array buffers for vertices
glBindBuffer( GL_ARRAY_BUFFER, arrayBuffer_ );
glBufferData(GL_ARRAY_BUFFER, sizeofPoints + sizeofColors + sizeofTexCoords, NULL, GL_STATIC_DRAW);
glBufferSubData( GL_ARRAY_BUFFER, 0, sizeofPoints, &points_[0] );
glBufferSubData( GL_ARRAY_BUFFER, sizeofPoints, sizeofColors, &colors_[0] );
if ( sizeofTexCoords )
glBufferSubData( GL_ARRAY_BUFFER, sizeofPoints + sizeofColors, sizeofTexCoords, &texCoords_[0] );
// setup the element array for the triangle indices
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, elementBuffer_);
int sizeofIndices = indices_.size()*sizeof(unsigned int);
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)
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(glm::vec3), (void *)0 );
glEnableVertexAttribArray(0);
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, sizeof(glm::vec3), (void *)(sizeofPoints) );
glEnableVertexAttribArray(1);
if ( sizeofTexCoords ) {
glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, sizeof(glm::vec2), (void *)(sizeofPoints + sizeofColors) );
glEnableVertexAttribArray(2);
}
// done
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindVertexArray(0);
drawingPrimitive_ = GL_TRIANGLE_STRIP;
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
//
glBindVertexArray( vao_ );
glDrawElements( drawingPrimitive_, indices_.size(), GL_UNSIGNED_INT, 0 );
glBindVertexArray(0);
}
}
void Primitive::deleteGLBuffers_()
{
if ( arrayBuffer_ ) glDeleteBuffers ( 1, &arrayBuffer_);
if ( elementBuffer_ ) glDeleteBuffers ( 1, &elementBuffer_);
if ( vao_ ) glDeleteVertexArrays ( 1, &vao_);
}
// Group
Group::~Group()
{
children_.clear();
}
void Group::init()
{
visible_ = true;
}
void Group::update( float dt )
{
Node::update(dt);
// update every child node
for (std::vector<Node*>::iterator node = children_.begin();
node != children_.end(); node++) {
(*node)->update ( dt );
}
}
void Group::draw(glm::mat4 modelview, glm::mat4 projection)
{
if ( visible_ ) {
// append the instance transform to the ctm
glm::mat4 ctm = modelview * transform_;
// draw every child node
for (std::vector<Node*>::iterator node = children_.begin();
node != children_.end(); node++) {
(*node)->draw ( ctm, projection );
}
}
}
void Group::addChild(Node *child)
{
children_.push_back ( child );
child->parent_ = this;
}
Node *Group::getChild(int i)
{
if ( i >= 0 && i < children_.size() )
return children_[i];
else
return nullptr;
}
int Group::numChildren()
{
return children_.size();
}

78
Scene.h
View File

@@ -1,88 +1,67 @@
#ifndef SCENE_H
#define SCENE_H
#include <iostream>
#include <vector>
#include <glm/glm.hpp>
#include <glm/gtc/matrix_access.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtc/type_ptr.hpp>
#include "Shader.h"
class Visitor;
#include "Visitor.h"
// Forward declare classes referenced
class Shader;
// Base virtual class for all Node types
// Manages modelview transformations and culling
class Node {
public:
Node() : parent_(), visible_(true), count_(0), localToWorld_(glm::mat4()), worldToLocal_(glm::mat4()) {}
virtual ~ModelNode() {}
Node();
virtual ~Node() {}
virtual void init() = 0;
virtual void update( float dt ) = 0;
virtual void draw ( glm::mat4 modelview, glm::mat4 projection) = 0;
virtual void Accept(Visitor& dispatcher) = 0;
virtual void draw( glm::mat4 modelview, glm::mat4 projection) = 0;
virtual void accept(Visitor& v) = 0;
virtual void update( float dt );
virtual glm::mat4 getWorldToLocalMatrix() {return worldToLocal_;}
virtual glm::mat4 getLocalToWorldMatrix() {return localToWorld_;}
protected:
Node* parent_;
bool visible_;
glm::mat4 worldToLocal_;
glm::mat4 localToWorld_;
glm::mat4 transform_;
};
// Forward declare different kind of Node
class Primitive;
class Group;
// Declares the interface for the visitors
class Visitor {
public:
// Declare overloads for each kind of Node to visit
virtual void Visit(Primitive& file) = 0;
virtual void Visit(Group& file) = 0;
};
// Leaf Nodes are primitives that can be rendered
class Primitive : public Node {
public:
Primitive() : Node(), effect(nullptr), vao_(0), arrayBuffer_(0), elementBuffer_(0), drawingPrimitive_(0) {}
Primitive() : Node(), shader_(nullptr), vao_(0), arrayBuffer_(0), elementBuffer_(0), drawingPrimitive_(0) {}
virtual ~Primitive();
virtual void init ();
virtual void update ( float dt );
virtual void draw ( glm::mat4 modelview, glm::mat4 projection);
virtual void Accept(Visitor& dispatcher) override {
dispatcher.Visit(*this);
}
virtual void accept(Visitor& v) override { v.visit(*this); }
virtual glm::mat4 getWorldToLocalMatrix();
virtual glm::mat4 getLocalToWorldMatrix();
virtual void setEffect( Effect* e );
virtual void setDrawingPrimitive ( GLuint prim );
virtual void generateAndLoadArrayBuffer();
Shader *getShader() { return shader_; }
void setShader( Shader* e ) { shader_ = e; }
protected:
Effect* effect_;
Shader* shader_;
unsigned int vao_;
unsigned int arrayBuffer_;
unsigned int elementBuffer_;
unsigned int drawingPrimitive_;
std::vector<glm::vec3> points_;
std::vector<glm::vec3> normals_;
std::vector<unsigned int> indices_;
std::vector<glm::vec2> texCoords_;
std::vector<glm::vec3> colors_;
std::vector<glm::vec2> texCoords_;
std::vector<unsigned int> indices_;
void deleteGLBuffers_();
};
// Other Nodes establish hierarchy with a group of nodes
class Group : public Node {
public:
@@ -92,12 +71,7 @@ public:
virtual void init ();
virtual void update ( float dt );
virtual void draw ( glm::mat4 modelview, glm::mat4 projection);
virtual void Accept(Visitor& dispatcher)override {
dispatcher.Visit(*this);
}
virtual glm::mat4 getWorldToLocalMatrix();
virtual glm::mat4 getLocalToWorldMatrix();
virtual void accept(Visitor& v) override { v.visit(*this); }
virtual void addChild ( Node *child );
virtual Node* getChild ( int i );
@@ -107,7 +81,19 @@ protected:
std::vector< Node* > children_;
};
// A scene contains a root node and gives a simplified API to add nodes
class Scene {
public:
Scene() {}
Group *getRoot() { return &root_; }
void accept(Visitor& v) { v.visit(*this); }
Group root_;
};

View File

@@ -69,7 +69,8 @@ void ShadingProgram::link()
void ShadingProgram::use()
{
if (currentProgram_ == nullptr || currentProgram_ != this) {
if (currentProgram_ == nullptr || currentProgram_ != this)
{
currentProgram_ = this;
glUseProgram(id_);
}
@@ -168,15 +169,15 @@ void Shader::use()
program_->use();
// set uniforms
program_->setUniform("projection", Rendering::manager().Projection());
program_->setUniform("projection", projection);
program_->setUniform("modelview", modelview);
program_->setUniform("color", color);
}
void Shader::reset()
{
projection = glm::identity<glm::mat4>();
modelview = glm::identity<glm::mat4>();
color = glm::vec4(1.f, 1.f, 1.f, 1.f);
}

View File

@@ -41,6 +41,7 @@ public:
virtual void use();
virtual void reset();
glm::mat4 projection;
glm::mat4 modelview;
glm::vec4 color;

144
Visitor.cpp Normal file
View File

@@ -0,0 +1,144 @@
#include "Visitor.h"
#include "Log.h"
#include "Scene.h"
#include "Primitives.h"
#include "MediaPlayer.h"
#include "GstToolkit.h"
#include <iostream>
#include <glm/glm.hpp>
#include <glm/ext/vector_float4.hpp>
#include <glm/ext/matrix_float4x4.hpp>
#include <glm/gtc/type_ptr.hpp>
#define GLM_ENABLE_EXPERIMENTAL
#include <glm/gtx/string_cast.hpp>
#include <glm/virtrev/xstream.hpp>
#include <tinyxml2.h>
using namespace tinyxml2;
#ifndef XMLCheckResult
#define XMLCheckResult(a_eResult) if (a_eResult != XML_SUCCESS) { Log::Warning("XML error %i\n", a_eResult); return; }
#endif
SessionVisitor::SessionVisitor(std::string filename) : filename_(filename)
{
xmlDoc_ = new XMLDocument;
xmlCurrent_ = nullptr;
}
void SessionVisitor::visit(Group &n)
{
std::cerr << "Group" << std::endl;
XMLElement *xmlParent = xmlCurrent_;
xmlCurrent_ = xmlDoc_->NewElement("Group");
visit( (Node&) n);
for (int node = 0; node < n.numChildren(); ++node)
{
Node *child = n.getChild(node);
Group *g = dynamic_cast<Group *>(child);
if (g != nullptr) {
g->accept(*this);
continue;
}
TexturedRectangle *tr = dynamic_cast<TexturedRectangle *>(child);
if (tr != nullptr) {
tr->accept(*this);
continue;
}
MediaRectangle *mr = dynamic_cast<MediaRectangle *>(child);
if (mr != nullptr) {
mr->accept(*this);
continue;
}
LineStrip *ls = dynamic_cast<LineStrip *>(child);
if (ls != nullptr) {
ls->accept(*this);
continue;
}
Primitive *p = dynamic_cast<Primitive *>(child);
if (p != nullptr) {
p->accept(*this);
continue;
}
}
// recursive
xmlParent->InsertEndChild(xmlCurrent_);
xmlCurrent_ = xmlParent;
}
void SessionVisitor::visit(Node &n)
{
XMLElement *transform = xmlDoc_->NewElement("Transform");
XMLText *matrix = xmlDoc_->NewText( glm::to_string(n.transform_).c_str() );
transform->InsertEndChild(matrix);
xmlCurrent_->InsertEndChild(transform);
}
void SessionVisitor::visit(Primitive &n)
{
std::cerr << "Primitive" << std::endl;
visit( (Node&) n);
}
void SessionVisitor::visit(TexturedRectangle &n)
{
std::cerr << "TexturedRectangle" << std::endl;
}
void SessionVisitor::visit(MediaRectangle &n)
{
std::cerr << "MediaRectangle" << std::endl;
// type specific
XMLElement *xmlParent = xmlCurrent_;
xmlCurrent_ = xmlDoc_->NewElement("MediaRectangle");
xmlCurrent_->SetAttribute("Filename", n.getMediaPath().c_str() );
// inherited from Primitive
visit( (Primitive&) n);
// recursive
xmlParent->InsertEndChild(xmlCurrent_);
xmlCurrent_ = xmlParent;
}
void SessionVisitor::visit(LineStrip &n)
{
std::cerr << "LineStrip" << std::endl;
}
void SessionVisitor::visit(Scene &n)
{
std::cerr << "root" << std::endl;
XMLDeclaration *pDec = xmlDoc_->NewDeclaration();
xmlDoc_->InsertFirstChild(pDec);
XMLElement *pRoot = xmlDoc_->NewElement("Session");
xmlDoc_->InsertEndChild(pRoot);
std::string s = "Saved on " + GstToolkit::date_time_string();
XMLComment *pComment = xmlDoc_->NewComment(s.c_str());
pRoot->InsertEndChild(pComment);
// save scene
xmlCurrent_ = pRoot;
n.getRoot()->accept(*this);
XMLError eResult = xmlDoc_->SaveFile(filename_.c_str());
XMLCheckResult(eResult);
}

53
Visitor.h Normal file
View File

@@ -0,0 +1,53 @@
#ifndef VISITOR_H
#define VISITOR_H
#include <string>
namespace tinyxml2 {
class XMLDocument;
class XMLElement;
}
// Forward declare different kind of Node
class Node;
class Primitive;
class Group;
class Scene;
class TexturedRectangle;
class MediaRectangle;
class LineStrip;
// Declares the interface for the visitors
class Visitor {
public:
// Declare overloads for each kind of Node to visit
virtual void visit(Node& n) = 0;
virtual void visit(Primitive& n) = 0;
virtual void visit(Group& n) = 0;
virtual void visit(TexturedRectangle& n) = 0;
virtual void visit(MediaRectangle& n) = 0;
virtual void visit(LineStrip& n) = 0;
virtual void visit(Scene& n) = 0;
};
class SessionVisitor : public Visitor {
std::string filename_;
tinyxml2::XMLDocument *xmlDoc_;
tinyxml2::XMLElement *xmlCurrent_;
public:
SessionVisitor(std::string filename);
void visit(Node& n) override;
void visit(Primitive& n) override;
void visit(Group& n) override;
void visit(TexturedRectangle& n) override;
void visit(MediaRectangle& n) override;
void visit(LineStrip& n) override;
void visit(Scene& n) override;
};
#endif // VISITOR_H

183
main.cpp
View File

@@ -9,9 +9,11 @@
#include <glad/glad.h>
#include <glm/glm.hpp>
#include <glm/gtc/type_ptr.hpp>
#include <glm/ext/vector_float2.hpp>
#include <glm/ext/vector_float3.hpp>
#include <glm/ext/vector_float4.hpp>
#include <glm/ext/matrix_float4x4.hpp>
#include <glm/gtc/matrix_access.hpp>
#include <glm/ext/matrix_transform.hpp>
// GStreamer
@@ -31,9 +33,13 @@
#include "ImGuiToolkit.h"
#include "GstToolkit.h"
#include "MediaPlayer.h"
#include "Scene.h"
#include "Primitives.h"
#include "Visitor.h"
#define PI 3.14159265358979323846
Scene scene;
MediaPlayer testmedia;
MediaPlayer testmedia2("testmedia2");
ImageShader rendering_shader;
@@ -41,81 +47,6 @@ unsigned int vbo, vao, ebo;
float texturear = 1.0;
GLuint textureimagepng = 0;
void create_square(unsigned int &vbo, unsigned int &vao, unsigned int &ebo)
{
// create the triangles
float _vertices[] = {
-1.f, -1.f, 0.f, // position vertex 3
1.f, 0.f, 1.f, // color vertex 3
0.f, 1.f, 0.f, // uv vertex 3
-1.f, 1.f, 0.f, // position vertex 0
1.f, 1.f, 0.f, // color vertex 0
0.f, 0.f, 0.f, // uv vertex 0
1.f, -1.f, 0.f, // position vertex 2
1.f, 1.f, 1.f, // color vertex 2
1.f, 1.f, 0.f, // uv vertex 2
1.f, 1.f, 0.f, // position vertex 1
0.f, 1.f, 1.f, // color vertex 1
1.f, 0.f, 0.f, // uv vertex 1
};
unsigned int _indices[] = { 0, 1, 2, 3 };
// create the opengl objects
glGenVertexArrays(1, &vao);
glGenBuffers(1, &vbo);
glGenBuffers(1, &ebo);
glBindVertexArray(vao);
// bind vertext array and its buffer
glBindBuffer(GL_ARRAY_BUFFER, vbo);
glBufferData(GL_ARRAY_BUFFER, sizeof(_vertices), _vertices, GL_STATIC_DRAW);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ebo);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(_indices), _indices, GL_STATIC_DRAW);
// explain how to read attributes 1, 2 and 3
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 9 * sizeof(float), (void *)0);
glEnableVertexAttribArray(0);
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 9 * sizeof(float), (void *)(3 * sizeof(float)));
glEnableVertexAttribArray(1);
glVertexAttribPointer(2, 3, GL_FLOAT, GL_FALSE, 9 * sizeof(float), (void *)(6 * sizeof(float)));
glEnableVertexAttribArray(2);
// done
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindVertexArray(0);
}
GLuint loadPNG(const char *imagepath, float *aspectrato)
{
int w, h, n, image;
/* FIXME: remove once the example supports gl3 and/or gles2 */
g_setenv ("GST_GL_API", "opengl", FALSE);
unsigned char* img;
*aspectrato = 1.f;
img = stbi_load(imagepath, &w, &h, &n, 3);
if (img == NULL) {
printf("Failed to load png - %s\n", stbi_failure_reason());
return 0;
}
GLuint tex;
glGenTextures(1, &tex);
glBindTexture( GL_TEXTURE_2D, tex);
glPixelStorei(GL_UNPACK_ALIGNMENT, 3);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
//glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, w, h, 0, GL_RGB, GL_UNSIGNED_BYTE, img);
stbi_image_free(img);
glBindTexture( GL_TEXTURE_2D, 0);
*aspectrato = static_cast<float>(w) / static_cast<float>(h);
return tex;
}
// from https://gstreamer.freedesktop.org/documentation/application-development/advanced/pipeline-manipulation.html?gi-language=c
@@ -127,10 +58,13 @@ void drawMediaBackgound()
//
// RENDER SOURCE
//
testmedia2.Update();
// use the shader
rendering_shader.projection = Rendering::manager().Projection();
rendering_shader.modelview = glm::identity<glm::mat4>();;
rendering_shader.use();
// use the media
testmedia2.Update();
testmedia2.Bind();
// draw the vertex array
glBindVertexArray(vao);
@@ -164,7 +98,7 @@ void drawMediaBackgound()
ImGui::SliderFloat("scale", &scale, 0.1f, 10.f, "%.3f", 3.f);
// set modelview
rendering_shader.setModelview(translation[0], translation[1], rotation, scale, testmedia2.AspectRatio());
// rendering_shader.setModelview(translation[0], translation[1], rotation, scale, testmedia2.AspectRatio());
// color picker
if (ImGuiToolkit::ButtonIcon(16, 8)) rendering_shader.color = glm::vec4(1.f);
@@ -322,6 +256,23 @@ void drawMediaPlayer()
}
void drawScene()
{
static gint64 last_time = gst_util_get_timestamp ();
gint64 current_time = gst_util_get_timestamp ();
gint64 dt = current_time - last_time;
glm::mat4 mv = glm::identity<glm::mat4>();
// glm::mat4 View = glm::translate(glm::identity<glm::mat4>(), glm::vec3(0, 0, 0.f));
// View = glm::rotate(View, 0.f, glm::vec3(0.0f, 0.0f, 1.0f));
// glm::mat4 Model = glm::scale(glm::identity<glm::mat4>(), glm::vec3(1, 1, 1));
// mv = View * Model;
scene.root_.update( static_cast<float>( GST_TIME_AS_MSECONDS(dt)) * 0.001f );
scene.root_.draw(mv, Rendering::manager().Projection());
last_time = current_time;
}
int main(int, char**)
{
@@ -350,38 +301,62 @@ int main(int, char**)
gst_debug_set_active(TRUE);
#endif
// 1
// testmedia.Open("file:///home/bhbn/Videos/MOV001.MOD");
// testmedia.Open("file:///home/bhbn/Videos/TestFormats/Commodore64GameReviewMoondust.flv");
// testmedia.Open("file:///home/bhbn/Videos/fish.mp4");
// testmedia.Open("file:///home/bhbn/Videos/jean/Solitude1080p.mov");
testmedia.Open("file:///home/bhbn/Videos/TearsOfSteel_720p_h265.mkv");
// testmedia.Open("file:///home/bhbn/Videos/TestFormats/_h264GoldenLamps.mkv");
// testmedia.Open("file:///home/bhbn/Videos/TestEncoding/vpxvp9high.webm");
// testmedia.Open("file:///home/bhbn/Videos/iss.mov");
testmedia.Play(false);
//// testmedia.Open("file:///home/bhbn/Videos/MOV001.MOD");
//// testmedia.Open("file:///home/bhbn/Videos/TestFormats/Commodore64GameReviewMoondust.flv");
//// testmedia.Open("file:///home/bhbn/Videos/fish.mp4");
//// testmedia.Open("file:///home/bhbn/Videos/jean/Solitude1080p.mov");
// testmedia.Open("file:///home/bhbn/Videos/TearsOfSteel_720p_h265.mkv");
//// testmedia.Open("file:///home/bhbn/Videos/TestFormats/_h264GoldenLamps.mkv");
//// testmedia.Open("file:///home/bhbn/Videos/TestEncoding/vpxvp9high.webm");
//// testmedia.Open("file:///home/bhbn/Videos/iss.mov");
// testmedia.Play(false);
// Add draw callbacks to the Rendering
Rendering::manager().AddDrawCallback(drawMediaPlayer);
// Rendering::manager().AddDrawCallback(drawMediaPlayer);
// 2
// testmedia2.Open("file:///home/bhbn/Images/Butterfly.gif");
// testmedia2.Open("file:///home/bhbn/Images/Scan-090614-0022.jpg");
// testmedia2.Open("file:///home/bhbn/Images/svg/abstract.svg");
testmedia2.Open("file:///home/bhbn/Videos/iss.mov");
// testmedia2.Open("file:///home/bhbn/Images/4k/colors-3840x2160-splash-4k-18458.jpg");
// testmedia2.Open("file:///home/bhbn/Videos/Upgrade.2018.720p.AMZN.WEB-DL.DDP5.1.H.264-NTG.m4v");
testmedia2.Play(true);
// create our geometries
create_square(vbo, vao, ebo);
// Add draw callbacks to the Rendering
Rendering::manager().AddDrawCallback(drawMediaBackgound);
//// testmedia2.Open("file:///home/bhbn/Images/Butterfly.gif");
//// testmedia2.Open("file:///home/bhbn/Images/Scan-090614-0022.jpg");
//// testmedia2.Open("file:///home/bhbn/Images/svg/abstract.svg");
// testmedia2.Open("file:///home/bhbn/Videos/iss.mov");
//// testmedia2.Open("file:///home/bhbn/Images/4k/colors-3840x2160-splash-4k-18458.jpg");
//// testmedia2.Open("file:///home/bhbn/Videos/Upgrade.2018.720p.AMZN.WEB-DL.DDP5.1.H.264-NTG.m4v");
// testmedia2.Play(true);
// // create our geometries
// create_square_glm(vbo, vao, ebo);
// // Add draw callbacks to the Rendering
// Rendering::manager().AddDrawCallback(drawMediaBackgound);
// // load an image
// textureimagepng = loadPNG("/home/bhbn/Videos/iss_snap.png", &texturear);
// test text editor
// UserInterface::manager().OpenTextEditor( Resource::getText("shaders/texture-shader.fs") );
UserInterface::manager().OpenTextEditor( Resource::getText("shaders/texture-shader.fs") );
// init the scene
scene.root_.init();
Rendering::manager().AddDrawCallback(drawScene);
// create and add a elements to the scene
MediaRectangle testnode1("file:///home/bhbn/Videos/iss.mov");
testnode1.init();
MediaRectangle testnode2("file:///home/bhbn/Videos/fish.mp4");
testnode2.init();
Group g1;
g1.init();
g1.transform_ = glm::translate(glm::identity<glm::mat4>(), glm::vec3(1.f, 1.f, 0.f));
Group g2;
g2.init();
g2.transform_ = glm::translate(glm::identity<glm::mat4>(), glm::vec3(-1.f, -1.f, 0.f));
// build tree
g1.addChild(&testnode1);
scene.root_.addChild(&g1);
g2.addChild(&testnode2);
scene.root_.addChild(&g2);
SessionVisitor savetoxml("/home/bhbn/test.vmx");
scene.accept(savetoxml);
///
/// Main LOOP

View File

@@ -2,8 +2,8 @@
out vec4 FragColor;
in vec3 vertexUV;
in vec3 vertexColor;
in vec2 vertexUV;
uniform sampler2D sourceTexture;
uniform vec4 color;
@@ -12,7 +12,7 @@ uniform float brightness;
void main()
{
vec4 texturecolor = texture(sourceTexture, vertexUV.xy);
vec4 texturecolor = texture(sourceTexture, vertexUV);
vec3 transformedRGB = mix(vec3(0.62), texturecolor.rgb, contrast + 1.0) + brightness;
transformedRGB *= vertexColor;

View File

@@ -2,17 +2,17 @@
layout (location = 0) in vec3 position;
layout (location = 1) in vec3 color;
layout (location = 2) in vec3 texCoord;
layout (location = 2) in vec2 texCoord;
out vec3 vertexColor;
out vec3 vertexUV;
out vec2 vertexUV;
uniform mat4 modelview;
uniform mat4 projection;
void main()
{
vec4 pos = modelview * vec4(position.xyz, 1.0);
vec4 pos = modelview * vec4(position, 1.0);
// output
gl_Position = projection * pos;

98
snippets.cpp Normal file
View File

@@ -0,0 +1,98 @@
GLuint loadPNG(const char *imagepath, float *aspectrato)
{
int w, h, n, image;
/* FIXME: remove once the example supports gl3 and/or gles2 */
g_setenv ("GST_GL_API", "opengl", FALSE);
unsigned char* img;
*aspectrato = 1.f;
img = stbi_load(imagepath, &w, &h, &n, 3);
if (img == NULL) {
printf("Failed to load png - %s\n", stbi_failure_reason());
return 0;
}
GLuint tex;
glGenTextures(1, &tex);
glBindTexture( GL_TEXTURE_2D, tex);
glPixelStorei(GL_UNPACK_ALIGNMENT, 3);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
//glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, w, h, 0, GL_RGB, GL_UNSIGNED_BYTE, img);
stbi_image_free(img);
glBindTexture( GL_TEXTURE_2D, 0);
*aspectrato = static_cast<float>(w) / static_cast<float>(h);
return tex;
}
void create_square_glm(unsigned int &vbo, unsigned int &vao, unsigned int &ebo)
{
std::vector<glm::vec3> points_;
std::vector<glm::vec3> colors_;
std::vector<glm::vec2> texCoords_;
std::vector<unsigned int> indices_;
// point 0
points_.push_back( glm::vec3( -1.f, -1.f, 0.f ) );
colors_.push_back( glm::vec3( 1.f, 0.f, 0.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( 0.f, 1.f, 0.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 );
// create the opengl objects
glGenVertexArrays(1, &vao);
glGenBuffers(1, &vbo);
glGenBuffers(1, &ebo);
glBindVertexArray(vao);
// compute the memory needs for points normals and indicies
std::size_t sizeofPoints = sizeof(glm::vec3) * points_.size();
std::size_t sizeofColors = sizeof(glm::vec3) * colors_.size();
std::size_t sizeofTexCoords = sizeof(glm::vec2) * texCoords_.size();
// bind vertext array and its buffer
glBindBuffer(GL_ARRAY_BUFFER, vbo);
glBufferData(GL_ARRAY_BUFFER, sizeofPoints + sizeofColors + sizeofTexCoords, NULL, GL_STATIC_DRAW);
glBufferSubData( GL_ARRAY_BUFFER, 0, sizeofPoints, &points_[0] );
glBufferSubData( GL_ARRAY_BUFFER, sizeofPoints, sizeofColors, &colors_[0] );
glBufferSubData( GL_ARRAY_BUFFER, sizeofPoints + sizeofColors, sizeofTexCoords, &texCoords_[0] );
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ebo);
int sizeofIndices = indices_.size()*sizeof(unsigned int);
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)
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(glm::vec3), (void *)0);
glEnableVertexAttribArray(0);
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, sizeof(glm::vec3), (void *)(sizeofPoints) );
glEnableVertexAttribArray(1);
glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, sizeof(glm::vec2), (void *)(sizeofPoints + sizeofColors) );
glEnableVertexAttribArray(2);
// done
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindVertexArray(0);
}