Compare commits

...

51 Commits
0.4.2 ... 0.5

Author SHA1 Message Date
brunoherbelin
5262b8ae29 System configuration in main pannel: toggled with config button. Cleanup
the About vimix dialog, giving access to other about dialogs.
2021-01-17 23:59:25 +01:00
Bruno
1028aeea9f VERSION 0.5 2021-01-17 12:55:02 +01:00
Bruno
e02071047a Fine tuning appearance of layers view 2021-01-17 12:54:50 +01:00
brunoherbelin
227658d2fc Improved error message on different xml version. 2021-01-17 00:29:12 +01:00
brunoherbelin
56dc299fc9 Changed Mixing alpha transition function (less abrupt on the sides). 2021-01-17 00:28:45 +01:00
brunoherbelin
f7e1ff14d9 Fixed alpha blending and stippling 2021-01-16 23:37:43 +01:00
Bruno
9e865b3677 Preliminary implementation of source locking and layer stage levels 2021-01-16 22:32:02 +01:00
Bruno
e4da7de06f eye candy - changing icon 2021-01-16 15:17:11 +01:00
brunoherbelin
67f45793da Bugfix: forced DrawVisitor was not forcing actual draw() 2021-01-15 23:22:51 +01:00
brunoherbelin
5a2949609e reload view after clear new session 2021-01-13 23:46:35 +01:00
brunoherbelin
f20597656e Eye candy in texturing view 2021-01-13 23:37:02 +01:00
brunoherbelin
aaf700baba Implementation of arrow keys to move objects in views layer and
transition
2021-01-13 21:19:48 +01:00
brunoherbelin
a3e121d6a0 Fixed softwar FPS limiter when not v-sync 2021-01-13 18:38:44 +01:00
brunoherbelin
d3269e8aaa Merge commit 2021-01-13 18:38:08 +01:00
Bruno
b9104df26e Merge remote-tracking branch 'origin/master' 2021-01-13 18:23:29 +01:00
brunoherbelin
717f560326 software framerate limiter 60FPS if not v-sync 2021-01-13 18:20:55 +01:00
brunoherbelin
6fdb93a020 Support for Shift-Tab to loop backward in list of sources. 2021-01-13 14:06:54 +01:00
brunoherbelin
767b0d8084 Link zoom and grab in unified way for all views. 2021-01-12 21:49:05 +01:00
brunoherbelin
52eb9284f7 UI bugfix 2021-01-11 23:34:06 +01:00
brunoherbelin
c355486955 Improved interface mask, eye candies and new icons. 2021-01-11 23:09:52 +01:00
brunoherbelin
0e8f87d6c6 OSX compilation 2021-01-11 18:31:38 +01:00
Bruno
dbd3c071e8 Improved GUI for mask editing, added effects. 2021-01-10 23:56:50 +01:00
Bruno
398995648a Mask Paint!! New MaskShader for mouse paiting of masks and associated changes.
UI for pain mask, load & save of FrameBuffer Image.
2021-01-10 14:52:57 +01:00
brunoherbelin
3fc9401d97 Bugfix: do not forget settings for AppearanceView 2021-01-10 09:54:43 +01:00
brunoherbelin
d31320ae4b Code cleaning in screenshot 2021-01-10 09:53:55 +01:00
brunoherbelin
fe54afbe1c Cleanup and securing XMLElementEncode and DecodeArray 2021-01-10 09:52:58 +01:00
brunoherbelin
6b5ccb4450 Bugfix draw visitor (ensure clean start when visiting scene) 2021-01-10 09:51:22 +01:00
brunoherbelin
805baa75f4 Bugfix handle rotation 2021-01-02 13:59:21 +01:00
brunoherbelin
b1dd2f0bc9 Avoid unavailable pattern generators with versions of gstreamer < 18 2021-01-01 23:02:35 +01:00
brunoherbelin
f8e926040a Display transliterated filename in GUI 2021-01-01 20:41:39 +01:00
brunoherbelin
11690dfb8c ICU compilation error 2021-01-01 17:13:18 +01:00
brunoherbelin
63369223ca Compilation and snap with ICU libs 2021-01-01 15:41:31 +01:00
brunoherbelin
a1e81b58b1 OSX compilation fix 2021-01-01 14:36:44 +01:00
brunoherbelin
cf2b6b4b39 Improved information icon for source preview 2021-01-01 12:17:49 +01:00
brunoherbelin
c4e584a1da cleanup framebuffer info string 2021-01-01 12:00:30 +01:00
brunoherbelin
25b58b76f3 Enable resize of session frame buffer resolution 2021-01-01 11:54:40 +01:00
Bruno
b346403887 Try to use GPU video decoding plugins when possible 2021-01-01 10:09:17 +01:00
Bruno
e0cd560dfb Implementation of 2 corner masks 2020-12-31 18:27:33 +01:00
brunoherbelin
4313e51530 Minor GUI bugfix 2020-12-31 10:51:41 +01:00
brunoherbelin
e2bb90208e Bugs fixed and eye candies 2020-12-31 00:50:50 +01:00
Bruno
85d72a1c0e Transliteration of source name 2020-12-30 17:23:31 +01:00
Bruno
a073ab41dd Improved procedural masks 2020-12-27 21:43:33 +01:00
Bruno
34c24d99df Integration procedural GLSL masks 2020-12-27 14:05:03 +01:00
Bruno
69d9d9473b Implemented procedural GLSL masks
Create MaskShader and added manipulation of masks in Appearance view
2020-12-27 14:04:23 +01:00
brunoherbelin
a58c06c617 Fixed display cropped source in AppearanceView and code cleanup. 2020-12-08 23:43:50 +01:00
brunoherbelin
b7a54d0512 BugFix deep update views (depth and layout) and crop. 2020-12-08 23:04:12 +01:00
brunoherbelin
1677582034 Bug fix on deep update of views and scenes: incrementing a counter of
updates needed (instead of only a flag).
2020-12-07 23:39:41 +01:00
brunoherbelin
44b888fd04 Work in progress - implementation of cropping in Geometry view instead
of AppearanceView. Display of scaled mixing surface in Mixing and Layers
view. Changed stippling shading.
2020-12-07 00:17:10 +01:00
brunoherbelin
78f9216d32 Hiding grips in geometry manipulation when operating. 2020-12-05 00:22:46 +01:00
brunoherbelin
1ea0ec53af Minor fixed GUI and mouse cursor 2020-12-03 23:21:30 +01:00
brunoherbelin
688823e63f New doc images for Appearance view 2020-12-01 23:37:52 +01:00
80 changed files with 7193 additions and 1182 deletions

2
.gitignore vendored
View File

@@ -16,3 +16,5 @@ rules.ninja
/vmix
/vimix_*.snap
/CMakeLists.txt.user.*
rsc/shaders/paint.fs

View File

@@ -91,6 +91,10 @@ set(THREAD_LIBRARY Threads::Threads)
find_package(PNG REQUIRED)
set(PNG_LIBRARY PNG::PNG)
find_package(ICU REQUIRED COMPONENTS i18n io uc)
macro_log_feature(ICU_FOUND "ICU" "International Components for Unicode" "http://site.icu-project.org" TRUE)
#
# GLFW3
# NB: set glfw3_PATH to /usr/local/Cellar/glfw/3.3.2/lib/cmake/glfw3
@@ -227,6 +231,7 @@ include_directories(
${STB_INCLUDE_DIR}
${DIRENT_INCLUDE_DIR}
${OSCPACK_INCLUDE_DIR}
${ICU_INCLUDE_DIRS}
)
@@ -290,6 +295,12 @@ set(VMIX_RSC_FILES
./rsc/shaders/simple.fs
./rsc/shaders/simple.vs
./rsc/shaders/image.fs
./rsc/shaders/mask_elipse.fs
./rsc/shaders/mask_box.fs
./rsc/shaders/mask_round.fs
./rsc/shaders/mask_horizontal.fs
./rsc/shaders/mask_vertical.fs
./rsc/shaders/mask_draw.fs
./rsc/shaders/image.vs
./rsc/shaders/imageprocessing.fs
./rsc/fonts/Hack-Regular.ttf
@@ -321,6 +332,7 @@ set(VMIX_RSC_FILES
./rsc/images/soft_shadow.dds
./rsc/mesh/disk.ply
./rsc/mesh/circle.ply
./rsc/mesh/corner.ply
./rsc/mesh/shadow.ply
./rsc/mesh/glow.ply
./rsc/mesh/border_round.ply
@@ -334,10 +346,13 @@ set(VMIX_RSC_FILES
./rsc/mesh/border_handles_overlay_filled.ply
./rsc/mesh/border_handles_sharp.ply
./rsc/mesh/border_handles_menu.ply
./rsc/mesh/border_handles_crop.ply
./rsc/mesh/border_handles_shadow.ply
./rsc/mesh/border_large_sharp.ply
./rsc/mesh/border_vertical_overlay.ply
./rsc/mesh/perspective_layer.ply
./rsc/mesh/perspective_axis_left.ply
./rsc/mesh/perspective_axis_right.ply
./rsc/mesh/shadow_perspective.ply
./rsc/mesh/point.ply
./rsc/mesh/square_point.ply
@@ -361,6 +376,7 @@ set(VMIX_RSC_FILES
./rsc/mesh/icon_clock_hand.ply
./rsc/mesh/icon_grid.ply
./rsc/mesh/icon_rightarrow.ply
./rsc/mesh/icon_crop.ply
./rsc/mesh/h_line.ply
./rsc/mesh/h_mark.ply
)
@@ -438,6 +454,9 @@ target_link_libraries(${VMIX_BINARY} LINK_PRIVATE
IMGUI
OSCPACK
vmix::rc
ICU::i18n
ICU::io
ICU::uc
${PLATFORM_LIBS}
)

View File

@@ -159,10 +159,10 @@ Handles::Handles(Type type) : Node(), type_(type)
static Mesh *handle_rotation = new Mesh("mesh/border_handles_rotation.ply");
static Mesh *handle_corner = new Mesh("mesh/border_handles_overlay.ply");
static Mesh *handle_scale = new Mesh("mesh/border_handles_scale.ply");
static Mesh *handle_restore = new Mesh("mesh/border_handles_menu.ply");
static Mesh *handle_crop = new Mesh("mesh/border_handles_crop.ply");
static Mesh *handle_menu = new Mesh("mesh/border_handles_menu.ply");
static Mesh *handle_shadow = new Mesh("mesh/border_handles_shadow.ply", "images/soft_shadow.dds");
color = glm::vec4( 1.f, 1.f, 0.f, 1.f);
if ( type_ == Handles::ROTATE ) {
handle_ = handle_rotation;
}
@@ -170,14 +170,17 @@ Handles::Handles(Type type) : Node(), type_(type)
handle_ = handle_scale;
}
else if ( type_ == Handles::MENU ) {
handle_ = handle_restore;
handle_ = handle_menu;
}
else if ( type_ == Handles::CROP ) {
handle_ = handle_crop;
}
else {
handle_ = handle_corner;
}
color = glm::vec4( 1.f, 1.f, 1.f, 1.f);
corner_ = glm::vec2(0.f, 0.f);
shadow_ = handle_shadow;
}
@@ -207,6 +210,7 @@ void Handles::draw(glm::mat4 modelview, glm::mat4 projection)
// set color
handle_->shader()->color = color;
handle_active->shader()->color = color;
// extract rotation from modelview
glm::mat4 ctm;
@@ -300,6 +304,18 @@ void Handles::draw(glm::mat4 modelview, glm::mat4 projection)
shadow_->draw( ctm, projection );
handle_->draw( ctm, projection );
}
else if ( type_ == Handles::CROP ){
// one icon in bottom right corner
// 1. Fixed displacement by (0.12,0.12) along the rotation..
ctm = GlmToolkit::transform(glm::vec4(0.f), rot, mirror);
glm::vec4 pos = ctm * glm::vec4(mirror.x * 0.12f, mirror.x * 0.12f, 0.f, 1.f);
// 2. ..from the bottom right corner (1,1)
vec = ( modelview * glm::vec4(-1.f, -1.f, 0.f, 1.f) ) + pos;
ctm = GlmToolkit::transform(vec, rot, glm::vec3(mirror.x, mirror.y, 1.f));
// 3. draw
shadow_->draw( ctm, projection );
handle_->draw( ctm, projection );
}
else if ( type_ == Handles::MENU ){
// one icon in top left corner
// 1. Fixed displacement by (-0.12,0.12) along the rotation..
@@ -325,36 +341,59 @@ void Handles::accept(Visitor& v)
Symbol::Symbol(Type t, glm::vec3 pos) : Node(), type_(t)
{
static Mesh *shadow= new Mesh("mesh/border_handles_shadow.ply", "images/soft_shadow.dds");
static Mesh *shadows[(int)EMPTY+1] = {nullptr};
static Mesh *icons[(int)EMPTY+1] = {nullptr};
if (icons[0] == nullptr) {
icons[CIRCLE_POINT] = new Mesh("mesh/point.ply");
shadows[CIRCLE_POINT] = nullptr;
icons[SQUARE_POINT] = new Mesh("mesh/square_point.ply");
icons[IMAGE] = new Mesh("mesh/icon_image.ply");
icons[VIDEO] = new Mesh("mesh/icon_video.ply");
icons[SESSION] = new Mesh("mesh/icon_vimix.ply");
icons[CLONE] = new Mesh("mesh/icon_clone.ply");
icons[RENDER] = new Mesh("mesh/icon_render.ply");
icons[PATTERN] = new Mesh("mesh/icon_gear.ply");
icons[CAMERA] = new Mesh("mesh/icon_camera.ply");
icons[SHARE] = new Mesh("mesh/icon_share.ply");
icons[DOTS] = new Mesh("mesh/icon_dots.ply");
icons[BUSY] = new Mesh("mesh/icon_circles.ply");
icons[LOCK] = new Mesh("mesh/icon_lock.ply");
icons[UNLOCK] = new Mesh("mesh/icon_unlock.ply");
icons[CROP] = new Mesh("mesh/icon_rightarrow.ply");
icons[CIRCLE] = new Mesh("mesh/icon_circle.ply");
icons[CLOCK] = new Mesh("mesh/icon_clock.ply");
icons[CLOCK_H] = new Mesh("mesh/icon_clock_hand.ply");
icons[SQUARE] = new Mesh("mesh/icon_square.ply");
icons[CROSS] = new Mesh("mesh/icon_cross.ply");
icons[GRID] = new Mesh("mesh/icon_grid.ply");
icons[EMPTY] = new Mesh("mesh/icon_empty.ply");
shadows[SQUARE_POINT] = nullptr;
icons[IMAGE] = new Mesh("mesh/icon_image.ply");
shadows[IMAGE] = shadow;
icons[VIDEO] = new Mesh("mesh/icon_video.ply");
shadows[VIDEO] = shadow;
icons[SESSION] = new Mesh("mesh/icon_vimix.ply");
shadows[SESSION]= shadow;
icons[CLONE] = new Mesh("mesh/icon_clone.ply");
shadows[CLONE] = shadow;
icons[RENDER] = new Mesh("mesh/icon_render.ply");
shadows[RENDER] = shadow;
icons[PATTERN] = new Mesh("mesh/icon_gear.ply");
shadows[PATTERN]= shadow;
icons[CAMERA] = new Mesh("mesh/icon_camera.ply");
shadows[CAMERA] = shadow;
icons[SHARE] = new Mesh("mesh/icon_share.ply");
shadows[SHARE] = shadow;
icons[DOTS] = new Mesh("mesh/icon_dots.ply");
shadows[DOTS] = nullptr;
icons[BUSY] = new Mesh("mesh/icon_circles.ply");
shadows[BUSY] = nullptr;
icons[LOCK] = new Mesh("mesh/icon_lock.ply");
shadows[LOCK] = shadow;
icons[UNLOCK] = new Mesh("mesh/icon_unlock.ply");
shadows[UNLOCK] = shadow;
icons[ARROWS] = new Mesh("mesh/icon_rightarrow.ply");
shadows[ARROWS] = shadow;
icons[CIRCLE] = new Mesh("mesh/icon_circle.ply");
shadows[CIRCLE] = nullptr;
icons[CLOCK] = new Mesh("mesh/icon_clock.ply");
shadows[CLOCK] = nullptr;
icons[CLOCK_H] = new Mesh("mesh/icon_clock_hand.ply");
shadows[CLOCK_H]= nullptr;
icons[SQUARE] = new Mesh("mesh/icon_square.ply");
shadows[SQUARE] = nullptr;
icons[CROSS] = new Mesh("mesh/icon_cross.ply");
shadows[CROSS] = nullptr;
icons[GRID] = new Mesh("mesh/icon_grid.ply");
shadows[GRID] = nullptr;
icons[EMPTY] = new Mesh("mesh/icon_empty.ply");
shadows[EMPTY] = shadow;
}
static Mesh *shadow= new Mesh("mesh/border_handles_shadow.ply", "images/soft_shadow.dds");
symbol_ = icons[type_];
shadow_ = shadow;
shadow_ = shadows[type_];
translation_ = pos;
color = glm::vec4( 1.f, 1.f, 1.f, 1.f);
}
@@ -397,7 +436,8 @@ void Symbol::draw(glm::mat4 modelview, glm::mat4 projection)
// generate matrix
ctm = GlmToolkit::transform(tran, rot, sca);
shadow_->draw( ctm, projection );
if (shadow_)
shadow_->draw( ctm, projection );
symbol_->draw( ctm, projection);
}
}

View File

@@ -36,7 +36,7 @@ protected:
class Handles : public Node
{
public:
typedef enum { RESIZE = 0, RESIZE_H, RESIZE_V, ROTATE, SCALE, MENU } Type;
typedef enum { RESIZE = 0, RESIZE_H, RESIZE_V, ROTATE, SCALE, CROP, MENU } Type;
Handles(Type type);
~Handles();
@@ -61,7 +61,7 @@ class Symbol : public Node
{
public:
typedef enum { CIRCLE_POINT = 0, SQUARE_POINT, IMAGE, VIDEO, SESSION, CLONE, RENDER, PATTERN, CAMERA, SHARE,
DOTS, BUSY, LOCK, UNLOCK, CROP, CIRCLE, SQUARE, CLOCK, CLOCK_H, GRID, CROSS, EMPTY } Type;
DOTS, BUSY, LOCK, UNLOCK, ARROWS, CROP, CIRCLE, SQUARE, CLOCK, CLOCK_H, GRID, CROSS, EMPTY } Type;
Symbol(Type t = CIRCLE_POINT, glm::vec3 pos = glm::vec3(0.f));
~Symbol();

View File

@@ -25,6 +25,11 @@ void DrawVisitor::loop(int num, glm::mat4 transform)
void DrawVisitor::visit(Node &n)
{
// force visible status if required
bool v = n.visible_;
if (force_)
n.visible_ = true;
// draw the target
if ( target_ && n.id() == target_->id()) {
@@ -37,6 +42,9 @@ void DrawVisitor::visit(Node &n)
done_ = true;
}
// restore visibility
n.visible_ = v;
if (done_) return;
// update transform
@@ -60,17 +68,23 @@ void DrawVisitor::visit(Group &n)
void DrawVisitor::visit(Scene &n)
{
done_ = false;
modelview_ = glm::identity<glm::mat4>();
n.root()->accept(*this);
}
void DrawVisitor::visit(Switch &n)
{
// no need to traverse deeper if this node was drawn already
if (done_) return;
// traverse acive child
glm::mat4 mv = modelview_;
n.activeChild()->accept(*this);
if ( n.activeChild()->visible_ || force_)
n.activeChild()->accept(*this);
modelview_ = mv;
}
void DrawVisitor::visit(Primitive &n)
{
}

View File

@@ -1,3 +1,5 @@
#include <sstream>
#include "FrameBuffer.h"
#include "ImageShader.h"
#include "Resource.h"
@@ -7,10 +9,12 @@
#include <glm/gtc/matrix_transform.hpp>
#include <glad/glad.h>
#include <stb_image.h>
#include <stb_image_write.h>
const char* FrameBuffer::aspect_ratio_name[5] = { "4:3", "3:2", "16:10", "16:9", "21:9" };
glm::vec2 FrameBuffer::aspect_ratio_size[5] = { glm::vec2(4.f,3.f), glm::vec2(3.f,2.f), glm::vec2(16.f,10.f), glm::vec2(16.f,9.f) , glm::vec2(21.f,9.f) };
const char* FrameBuffer::resolution_name[4] = { "720", "1080", "1440", "4K" };
const char* FrameBuffer::resolution_name[4] = { "720", "1080", "1440", "2160" };
float FrameBuffer::resolution_height[4] = { 720.f, 1080.f, 1440.f, 2160.f };
@@ -22,6 +26,31 @@ glm::vec3 FrameBuffer::getResolutionFromParameters(int ar, int h)
return res;
}
glm::ivec2 FrameBuffer::getParametersFromResolution(glm::vec3 res)
{
glm::ivec2 p = glm::ivec2(-1);
// get aspect ratio parameter
static int num_ar = ((int)(sizeof(FrameBuffer::aspect_ratio_size) / sizeof(*FrameBuffer::aspect_ratio_size)));
float myratio = res.x / res.y;
for(int ar = 0; ar < num_ar; ar++) {
if ( myratio - (FrameBuffer::aspect_ratio_size[ar].x / FrameBuffer::aspect_ratio_size[ar].y ) < EPSILON){
p.x = ar;
break;
}
}
// get height parameter
static int num_height = ((int)(sizeof(FrameBuffer::resolution_height) / sizeof(*FrameBuffer::resolution_height)));
for(int h = 0; h < num_height; h++) {
if ( res.y - FrameBuffer::resolution_height[h] < 1){
p.y = h;
break;
}
}
return p;
}
FrameBuffer::FrameBuffer(glm::vec3 resolution, bool useAlpha, bool multiSampling):
textureid_(0), intermediate_textureid_(0), framebufferid_(0), intermediate_framebufferid_(0),
use_alpha_(useAlpha), use_multi_sampling_(multiSampling)
@@ -102,6 +131,12 @@ FrameBuffer::~FrameBuffer()
{
if (framebufferid_)
glDeleteFramebuffers(1, &framebufferid_);
if (intermediate_framebufferid_)
glDeleteFramebuffers(1, &intermediate_framebufferid_);
if (textureid_)
glDeleteTextures(1, &textureid_);
if (intermediate_textureid_)
glDeleteTextures(1, &intermediate_textureid_);
}
@@ -121,20 +156,14 @@ float FrameBuffer::aspectRatio() const
std::string FrameBuffer::info() const
{
std::string s = "";
glm::ivec2 p = FrameBuffer::getParametersFromResolution(resolution());
std::ostringstream info;
static int num_ar = ((int)(sizeof(FrameBuffer::aspect_ratio_size) / sizeof(*FrameBuffer::aspect_ratio_size)));
float myratio = aspectRatio();
for(int i= 0; i < num_ar; i++) {
if ( myratio - (FrameBuffer::aspect_ratio_size[i].x / FrameBuffer::aspect_ratio_size[i].y ) < EPSILON)
{
s += std::string( FrameBuffer::aspect_ratio_name[i]) + ", ";
break;
}
}
info << attrib_.viewport.x << "x" << attrib_.viewport.y;
if (p.x > -1)
info << "px, " << FrameBuffer::aspect_ratio_name[p.x];
s += std::to_string(width()) + "x" + std::to_string(height()) + " px";
return s;
return info.str();
}
glm::vec3 FrameBuffer::resolution() const
@@ -142,7 +171,7 @@ glm::vec3 FrameBuffer::resolution() const
return glm::vec3(attrib_.viewport.x, attrib_.viewport.y, 0.f);
}
void FrameBuffer::begin()
void FrameBuffer::begin(bool clear)
{
if (!framebufferid_)
init();
@@ -151,7 +180,8 @@ void FrameBuffer::begin()
Rendering::manager().pushAttrib(attrib_);
glClear(GL_COLOR_BUFFER_BIT);
if (clear)
glClear(GL_COLOR_BUFFER_BIT);
}
void FrameBuffer::end()
@@ -176,7 +206,7 @@ void FrameBuffer::release()
glBindFramebuffer(GL_FRAMEBUFFER, 0);
}
void FrameBuffer::readPixels()
void FrameBuffer::readPixels(uint8_t *target_data)
{
if (!framebufferid_)
return;
@@ -191,21 +221,24 @@ void FrameBuffer::readPixels()
else
glPixelStorei(GL_PACK_ALIGNMENT, 1);
glReadPixels(0, 0, attrib_.viewport.x, attrib_.viewport.y, (use_alpha_? GL_RGBA : GL_RGB), GL_UNSIGNED_BYTE, 0);
glReadPixels(0, 0, attrib_.viewport.x, attrib_.viewport.y, (use_alpha_? GL_RGBA : GL_RGB), GL_UNSIGNED_BYTE, target_data);
glBindFramebuffer(GL_FRAMEBUFFER, 0);
}
bool FrameBuffer::blit(FrameBuffer *other)
bool FrameBuffer::blit(FrameBuffer *destination)
{
if (!framebufferid_ || !other || !other->framebufferid_)
if (!framebufferid_ || !destination)
return false;
if (!destination->framebufferid_)
destination->init();
glBindFramebuffer(GL_READ_FRAMEBUFFER, framebufferid_);
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, other->framebufferid_);
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, destination->framebufferid_);
// blit to the frame buffer object
glBlitFramebuffer(0, 0, attrib_.viewport.x, attrib_.viewport.y,
0, 0, other->width(), other->height(), GL_COLOR_BUFFER_BIT, GL_NEAREST);
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
0, 0, destination->width(), destination->height(), GL_COLOR_BUFFER_BIT, GL_NEAREST);
glBindFramebuffer(GL_FRAMEBUFFER, 0);
return true;
}
@@ -252,16 +285,100 @@ glm::mat4 FrameBuffer::projection() const
return projection_;
}
glm::vec2 FrameBuffer::projectionArea() const
{
return projection_crop_;
return projection_area_;
}
void FrameBuffer::setProjectionArea(glm::vec2 c)
{
projection_crop_.x = CLAMP(c.x, 0.1f, 1.f);
projection_crop_.y = CLAMP(c.y, 0.1f, 1.f);
projection_ = glm::ortho(-projection_crop_.x, projection_crop_.x, projection_crop_.y, -projection_crop_.y, -1.f, 1.f);
projection_area_.x = CLAMP(c.x, 0.1f, 1.f);
projection_area_.y = CLAMP(c.y, 0.1f, 1.f);
projection_ = glm::ortho(-projection_area_.x, projection_area_.x, projection_area_.y, -projection_area_.y, -1.f, 1.f);
}
FrameBufferImage::FrameBufferImage(int w, int h) :
rgb(nullptr), width(w), height(h)
{
if (width>0 && height>0)
rgb = new uint8_t[width*height*3];
}
FrameBufferImage::FrameBufferImage(jpegBuffer jpgimg) :
rgb(nullptr), width(0), height(0)
{
int c = 0;
if (jpgimg.buffer != nullptr && jpgimg.len >0)
rgb = stbi_load_from_memory(jpgimg.buffer, jpgimg.len, &width, &height, &c, 3);
}
FrameBufferImage::~FrameBufferImage() {
if (rgb!=nullptr)
delete rgb;
}
FrameBufferImage::jpegBuffer FrameBufferImage::getJpeg()
{
jpegBuffer jpgimg;
// if we hold a valid image
if (rgb!=nullptr && width>0 && height>0) {
// allocate JPEG buffer
// (NB: JPEG will need less than this but we can't know before...)
jpgimg.buffer = (unsigned char *) malloc( width * height * 3 * sizeof(unsigned char));
stbi_write_jpg_to_func( [](void *context, void *data, int size)
{
memcpy(((FrameBufferImage::jpegBuffer*)context)->buffer + ((FrameBufferImage::jpegBuffer*)context)->len, data, size);
((FrameBufferImage::jpegBuffer*)context)->len += size;
}
,&jpgimg, width, height, 3, rgb, FBI_JPEG_QUALITY);
}
return jpgimg;
}
FrameBufferImage *FrameBuffer::image(){
FrameBufferImage *img = nullptr;
// not ready
if (!framebufferid_)
return img;
// allocate image
img = new FrameBufferImage(attrib_.viewport.x, attrib_.viewport.y);
// get pixels into image
glBindBuffer(GL_PIXEL_PACK_BUFFER, 0); // set buffer target readpixel
readPixels(img->rgb);
return img;
}
bool FrameBuffer::fill(FrameBufferImage *image)
{
if (!framebufferid_)
init();
// not compatible for RGB
if (use_alpha_ || use_multi_sampling_)
return false;
// invalid image
if ( image == nullptr ||
image->rgb==nullptr ||
image->width !=attrib_.viewport.x ||
image->height!=attrib_.viewport.y )
return false;
// fill texture with image
glBindTexture(GL_TEXTURE_2D, textureid_);
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, image->width, image->height,
GL_RGB, GL_UNSIGNED_BYTE, image->rgb);
return true;
}

View File

@@ -1,9 +1,35 @@
#ifndef FRAMEBUFFER_H
#define FRAMEBUFFER_H
#include "Scene.h"
#include "RenderingManager.h"
#define FBI_JPEG_QUALITY 90
/**
* @brief The FrameBufferImage class stores an RGB image in RAM
* Direct access to rgb array, and exchange format to JPEG in RAM
*/
class FrameBufferImage
{
public:
uint8_t *rgb = nullptr;
int width;
int height;
struct jpegBuffer {
unsigned char *buffer = nullptr;
uint len = 0;
};
jpegBuffer getJpeg();
FrameBufferImage(int w, int h);
FrameBufferImage(jpegBuffer jpgimg);
~FrameBufferImage();
};
/**
* @brief The FrameBuffer class holds an OpenGL Frame Buffer Object.
*/
class FrameBuffer {
public:
@@ -13,6 +39,7 @@ public:
static const char* resolution_name[4];
static float resolution_height[4];
static glm::vec3 getResolutionFromParameters(int ar, int h);
static glm::ivec2 getParametersFromResolution(glm::vec3 res);
// unbind any framebuffer object
static void release();
@@ -21,15 +48,14 @@ public:
~FrameBuffer();
// Bind & push attribs to prepare draw
void begin();
void begin(bool clear = true);
// pop attrib and unbind to end draw
void end();
// blit copy to another, returns true on success
bool blit(FrameBuffer *other);
bool blit(FrameBuffer *destination);
// bind the FrameBuffer in READ and perform glReadPixels
// return the size of the buffer
void readPixels();
// (to be used after preparing a target PBO)
void readPixels(uint8_t* target_data = 0);
// clear color
inline void setClearColor(glm::vec4 color) { attrib_.clear_color = color; }
@@ -42,7 +68,7 @@ public:
float aspectRatio() const;
std::string info() const;
// projection and crop
// projection area (crop)
glm::mat4 projection() const;
glm::vec2 projectionArea() const;
void setProjectionArea(glm::vec2 c);
@@ -54,16 +80,21 @@ public:
// index for texturing
uint texture() const;
// get and fill image
FrameBufferImage *image();
bool fill(FrameBufferImage *image);
private:
void init();
void checkFramebufferStatus();
RenderingAttrib attrib_;
glm::mat4 projection_;
glm::vec2 projection_crop_;
glm::vec2 projection_area_;
uint textureid_, intermediate_textureid_;
uint framebufferid_, intermediate_framebufferid_;
bool use_alpha_, use_multi_sampling_;
};

View File

@@ -2,6 +2,8 @@
#include <iomanip>
using namespace std;
#include <gst/gl/gl.h>
#include "GstToolkit.h"
string GstToolkit::time_to_string(guint64 t, time_string_mode m)
@@ -54,6 +56,16 @@ string GstToolkit::time_to_string(guint64 t, time_string_mode m)
}
std::string GstToolkit::filename_to_uri(std::string path)
{
// set uri to open
gchar *uritmp = gst_filename_to_uri(path.c_str(), NULL);
std::string uri( uritmp );
g_free(uritmp);
return uri;
}
list<string> GstToolkit::all_plugins()
{
list<string> pluginlist;
@@ -121,3 +133,40 @@ string GstToolkit::gst_version()
return oss.str();
}
// see https://developer.ridgerun.com/wiki/index.php?title=GStreamer_modify_the_elements_rank
std::list<std::string> GstToolkit::enable_gpu_decoding_plugins()
{
static list<string> pluginslist;
static GstRegistry* plugins_register = nullptr;
if ( plugins_register == nullptr ) {
plugins_register = gst_registry_get();
#if GST_GL_HAVE_PLATFORM_GLX
// https://gstreamer.freedesktop.org/documentation/nvcodec/index.html?gi-language=c#plugin-nvcodec
const char *plugins[6] = { "nvh264dec", "nvh265dec", "nvmpeg2videodec",
"nvmpeg4videodec", "nvvp8dec", "nvvp9dec" };
const int N = 6;
#elif GST_GL_HAVE_PLATFORM_CGL
const char *plugins[1] = { "vtdec_hw" };
const int N = 1;
#else
const char *plugins[0] = { };
const int N = 0;
#endif
for (int i = 0; i < N; i++) {
GstPluginFeature* feature = gst_registry_lookup_feature(plugins_register, plugins[i]);
if(feature != NULL) {
pluginslist.push_front( string( plugins[i] ) );
gst_plugin_feature_set_rank(feature, GST_RANK_PRIMARY + 1);
gst_object_unref(feature);
}
}
}
return pluginslist;
}

View File

@@ -16,11 +16,14 @@ typedef enum {
} time_string_mode;
std::string time_to_string(guint64 t, time_string_mode m = TIME_STRING_ADJUSTED);
std::string filename_to_uri(std::string filename);
std::string gst_version();
std::list<std::string> all_plugins();
std::list<std::string> all_plugin_features(std::string pluginname);
std::list<std::string> all_plugins();
std::list<std::string> enable_gpu_decoding_plugins();
std::list<std::string> all_plugin_features(std::string pluginname);
bool enable_feature (std::string name, bool enable);
}

View File

@@ -32,7 +32,9 @@ std::map <ImGuiToolkit::font_style, ImFont*>fontmap;
void ImGuiToolkit::ButtonOpenUrl( const char* url, const ImVec2& size_arg )
{
char label[512];
sprintf( label, "%s %s", ICON_FA_EXTERNAL_LINK_ALT, url );
std::string str = SystemToolkit::transliterate( url );
sprintf( label, "%s %s", ICON_FA_EXTERNAL_LINK_ALT, str.c_str() );
if ( ImGui::Button(label, size_arg) )
SystemToolkit::open(url);
@@ -137,12 +139,8 @@ bool ImGuiToolkit::ButtonIcon(int i, int j, const char *tooltip)
bool ret = ImGui::ImageButton((void*)(intptr_t)textureicons, ImVec2(ImGui::GetTextLineHeightWithSpacing(),ImGui::GetTextLineHeightWithSpacing()), uv0, uv1, 3);
ImGui::PopID();
if (tooltip != nullptr && ImGui::IsItemHovered())
{
ImGui::BeginTooltip();
ImGui::Text("%s", tooltip);
ImGui::EndTooltip();
}
if (tooltip != nullptr)
ImGuiToolkit::ToolTip(tooltip);
return ret;
}
@@ -271,17 +269,31 @@ void ImGuiToolkit::ShowIconsWindow(bool* p_open)
ImGui::End();
}
void ImGuiToolkit::ToolTip(const char* desc)
{
if (ImGui::IsItemHovered())
{
ImGuiToolkit::PushFont(ImGuiToolkit::FONT_DEFAULT);
ImGui::BeginTooltip();
ImGui::Text(desc);
ImGui::EndTooltip();
ImGui::PopFont();
}
}
// Helper to display a little (?) mark which shows a tooltip when hovered.
// In your own code you may want to display an actual icon if you are using a merged icon fonts (see docs/FONTS.txt)
void ImGuiToolkit::HelpMarker(const char* desc)
void ImGuiToolkit::HelpMarker(const char* desc, const char* icon)
{
ImGui::TextDisabled( ICON_FA_QUESTION_CIRCLE );
ImGui::TextDisabled( icon );
if (ImGui::IsItemHovered())
{
ImGui::BeginTooltip();
ImGuiToolkit::PushFont(ImGuiToolkit::FONT_DEFAULT);
ImGui::PushTextWrapPos(ImGui::GetFontSize() * 35.0f);
ImGui::TextUnformatted(desc);
ImGui::PopTextWrapPos();
ImGui::PopFont();
ImGui::EndTooltip();
}
}

View File

@@ -23,7 +23,8 @@ namespace ImGuiToolkit
bool IconToggle (int i, int j, int i_toggle, int j_toggle, bool* toggle, const char *tooltips[] = nullptr);
void ButtonOpenUrl (const char* url, const ImVec2& size_arg = ImVec2(0,0));
void HelpMarker (const char* desc);
void ToolTip (const char* desc);
void HelpMarker (const char* desc, const char* icon = ICON_FA_QUESTION_CIRCLE);
// utility sliders
bool TimelineSlider (const char* label, guint64 *time, guint64 start, guint64 end, guint64 step, const float width);

View File

@@ -161,6 +161,7 @@ void ImGuiVisitor::visit(Shader &n)
{
ImGui::PushID(std::to_string(n.id()).c_str());
// Base color
// if (ImGuiToolkit::ButtonIcon(10, 2)) {
// n.blending = Shader::BLEND_OPACITY;
// n.color = glm::vec4(1.f, 1.f, 1.f, 1.f);
@@ -201,29 +202,26 @@ void ImGuiVisitor::visit(Shader &n)
ImGui::PopID();
}
void ImGuiVisitor::visit(ImageShader &n)
{
ImGui::PushID(std::to_string(n.id()).c_str());
// get index of the mask used in this ImageShader
int item_current = n.mask;
// if (ImGuiToolkit::ButtonIcon(10, 3)) n.mask = 0;
// ImGui::SameLine(0, 10);
ImGui::SetNextItemWidth(IMGUI_RIGHT_ALIGN);
// combo list of masks
if ( ImGui::Combo("Mask", &item_current, ImageShader::mask_names, IM_ARRAYSIZE(ImageShader::mask_names) ) )
{
if (item_current < (int) ImageShader::mask_presets.size())
n.mask = item_current;
else {
// TODO ask for custom mask
}
Action::manager().store("Mask "+ std::string(ImageShader::mask_names[n.mask]), n.id());
}
ImGui::PopID();
}
//void ImGuiVisitor::visit(ImageShader &n)
//{
// ImGui::PushID(std::to_string(n.id()).c_str());
// // get index of the mask used in this ImageShader
// int item_current = n.mask;
//// if (ImGuiToolkit::ButtonIcon(10, 3)) n.mask = 0;
//// ImGui::SameLine(0, 10);
// ImGui::SetNextItemWidth(IMGUI_RIGHT_ALIGN);
// // combo list of masks
// if ( ImGui::Combo("Mask", &item_current, ImageShader::mask_names, IM_ARRAYSIZE(ImageShader::mask_names) ) )
// {
// if (item_current < (int) ImageShader::mask_presets.size())
// n.mask = item_current;
// else {
// // TODO ask for custom mask
// }
// Action::manager().store("Mask "+ std::string(ImageShader::mask_names[n.mask]), n.id());
// }
// ImGui::PopID();
//}
void ImGuiVisitor::visit(ImageProcessingShader &n)
{
@@ -258,7 +256,7 @@ void ImGuiVisitor::visit(ImageProcessingShader &n)
// ImGui::SetNextItemWidth(IMGUI_RIGHT_ALIGN);
// ImGui::SliderFloat4("Levels", glm::value_ptr(n.levels), 0.0, 1.0);
if (ImGuiToolkit::ButtonIcon(4, 1)) {
if (ImGuiToolkit::ButtonIcon(5, 16)) {
n.brightness = 0.f;
n.contrast = 0.f;
Action::manager().store("B & C 0.0 0.0", n.id());
@@ -277,7 +275,7 @@ void ImGuiVisitor::visit(ImageProcessingShader &n)
Action::manager().store(oss.str(), n.id());
}
if (ImGuiToolkit::ButtonIcon(2, 1)) {
if (ImGuiToolkit::ButtonIcon(9, 16)) {
n.saturation = 0.f;
Action::manager().store("Saturation 0.0", n.id());
}
@@ -363,7 +361,7 @@ void ImGuiVisitor::visit(ImageProcessingShader &n)
Action::manager().store(oss.str(), n.id());
}
if (ImGuiToolkit::ButtonIcon(7, 1)) {
if (ImGuiToolkit::ButtonIcon(6, 16)) {
n.invert = 0;
Action::manager().store("Invert None", n.id());
}
@@ -396,20 +394,32 @@ void ImGuiVisitor::visit (Source& s)
// preview
float preview_width = ImGui::GetContentRegionAvail().x IMGUI_RIGHT_ALIGN;
float width = preview_width;
float height = width / s.frame()->aspectRatio();
float height = s.frame()->projectionArea().y * width / ( s.frame()->projectionArea().x * s.frame()->aspectRatio());
if (height > 230) {
height = 230;
width = height * s.frame()->aspectRatio();
width = height * s.frame()->aspectRatio() * ( s.frame()->projectionArea().x / s.frame()->projectionArea().y);
}
ImGui::Image((void*)(uintptr_t) s.frame()->texture(), ImVec2(width, height));
ImVec2 pos = ImGui::GetCursorPos(); // remember where we were...
ImGui::SetCursorPos( ImVec2(preview_width + 15, pos.y -height ) );
if (s.active())
ImGuiToolkit::Icon(10, 4);
// inform on visibility status
ImGui::SetCursorPos( ImVec2(preview_width + 20, pos.y -height ) );
if (s.active()) {
if (s.blendingShader()->color.a > 0.f)
ImGuiToolkit::HelpMarker("Visible", ICON_FA_EYE);
else
ImGuiToolkit::HelpMarker("Not visible", ICON_FA_EYE_SLASH);
}
else
ImGuiToolkit::Icon(11, 4);
ImGuiToolkit::HelpMarker("Inactive", ICON_FA_SNOWFLAKE);
// Inform on status of lock
ImGui::SetCursorPos( ImVec2(preview_width + 20, pos.y -height + ImGui::GetFrameHeight()) );
if (s.locked())
ImGuiToolkit::HelpMarker("Locked", ICON_FA_LOCK);
else
ImGuiToolkit::HelpMarker("Unlocked", ICON_FA_LOCK_OPEN);
// toggle enable/disable image processing
bool on = s.imageProcessingEnabled();

View File

@@ -9,19 +9,18 @@ public:
ImGuiVisitor();
// 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(MediaSurface& n) override;
void visit(FrameBufferSurface& n) override;
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 (MediaSurface& n) override;
void visit (FrameBufferSurface& n) override;
// Elements with attributes
void visit(MediaPlayer& n) override;
void visit(Shader& n) override;
void visit(ImageShader& n) override;
void visit(ImageProcessingShader& n) override;
void visit (MediaPlayer& n) override;
void visit (Shader& n) override;
void visit (ImageProcessingShader& n) override;
void visit (Source& s) override;
void visit (MediaSource& s) override;
void visit (SessionSource& s) override;

View File

@@ -4,27 +4,17 @@
#include "Visitor.h"
#include "ImageShader.h"
#include "Resource.h"
#include "rsc/fonts/IconsFontAwesome5.h"
//#include
static ShadingProgram imageShadingProgram("shaders/image.vs", "shaders/image.fs");
const char* ImageShader::mask_names[11] = { "None", "Glow", "Halo", "Circle", "Round", "Vignette", "Top", "Botton", "Left", "Right", "Custom" };
std::vector< uint > ImageShader::mask_presets;
const char* MaskShader::mask_names[3] = { ICON_FA_EXPAND, ICON_FA_EDIT, ICON_FA_SHAPES };
const char* MaskShader::mask_shapes[5] = { "Elipse", "Oblong", "Rectangle", "Horizontal", "Vertical" };
std::vector< ShadingProgram* > MaskShader::mask_programs;
ImageShader::ImageShader(): Shader(), mask(0), custom_textureindex(0), stipple(0.0)
ImageShader::ImageShader(): Shader(), stipple(0.0)
{
// first initialization
if ( mask_presets.empty() ) {
mask_presets.push_back(Resource::getTextureWhite());
mask_presets.push_back(Resource::getTextureImage("images/mask_glow.png"));
mask_presets.push_back(Resource::getTextureImage("images/mask_halo.png"));
mask_presets.push_back(Resource::getTextureImage("images/mask_circle.png"));
mask_presets.push_back(Resource::getTextureImage("images/mask_roundcorner.png"));
mask_presets.push_back(Resource::getTextureImage("images/mask_vignette.png"));
mask_presets.push_back(Resource::getTextureImage("images/mask_linear_top.png"));
mask_presets.push_back(Resource::getTextureImage("images/mask_linear_bottom.png"));
mask_presets.push_back(Resource::getTextureImage("images/mask_linear_left.png"));
mask_presets.push_back(Resource::getTextureImage("images/mask_linear_right.png"));
}
// static program shader
program_ = &imageShadingProgram;
// reset instance
@@ -38,12 +28,9 @@ void ImageShader::use()
program_->setUniform("stipple", stipple);
glActiveTexture(GL_TEXTURE1);
if ( mask < 10 )
glBindTexture(GL_TEXTURE_2D, mask_presets[mask]);
else
glBindTexture(GL_TEXTURE_2D, custom_textureindex);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glBindTexture(GL_TEXTURE_2D, mask_texture);
glActiveTexture(GL_TEXTURE0);
@@ -54,18 +41,16 @@ void ImageShader::reset()
Shader::reset();
// default mask
mask = 0;
custom_textureindex = mask_presets[0];
mask_texture = Resource::getTextureWhite();
// no stippling
stipple = 0.f;
}
void ImageShader::operator = (const ImageShader &S )
void ImageShader::operator = (const ImageShader &S)
{
Shader::operator =(S);
mask = S.mask;
custom_textureindex = S.custom_textureindex;
mask_texture = S.mask_texture;
stipple = S.stipple;
}
@@ -74,3 +59,83 @@ void ImageShader::accept(Visitor& v) {
Shader::accept(v);
v.visit(*this);
}
MaskShader::MaskShader(): Shader(), mode(0)
{
// first initialization
if ( mask_programs.empty() ) {
mask_programs.push_back(new ShadingProgram("shaders/simple.vs", "shaders/simple.fs"));
mask_programs.push_back(new ShadingProgram("shaders/image.vs", "shaders/mask_draw.fs"));
mask_programs.push_back(new ShadingProgram("shaders/simple.vs", "shaders/mask_elipse.fs"));
mask_programs.push_back(new ShadingProgram("shaders/simple.vs", "shaders/mask_round.fs"));
mask_programs.push_back(new ShadingProgram("shaders/simple.vs", "shaders/mask_box.fs"));
mask_programs.push_back(new ShadingProgram("shaders/simple.vs", "shaders/mask_horizontal.fs"));
mask_programs.push_back(new ShadingProgram("shaders/simple.vs", "shaders/mask_vertical.fs"));
}
// reset instance
reset();
// static program shader
program_ = mask_programs[0];
}
void MaskShader::use()
{
// select program to use
mode = CLAMP(mode, 0, 2);
shape = CLAMP(shape, 0, 4);
program_ = mode < 2 ? mask_programs[mode] : mask_programs[shape+2] ;
// actual use of shader program
Shader::use();
// shape parameters
size = shape < HORIZONTAL ? glm::max(glm::abs(size), glm::vec2(0.2)) : size;
program_->setUniform("size", size);
program_->setUniform("blur", blur);
// brush parameters
program_->setUniform("cursor", cursor);
program_->setUniform("brush", brush);
program_->setUniform("option", option);
program_->setUniform("effect", effect);
}
void MaskShader::reset()
{
Shader::reset();
// default mask
mode = 0;
// default shape
shape = 0;
blur = 0.5f;
size = glm::vec2(1.f, 1.f);
// default brush
cursor = glm::vec4(-10.f, -10.f, 1.f, 1.f);
brush = glm::vec3(0.5f, 0.1f, 0.f);
option = 0;
effect = 0;
}
void MaskShader::operator = (const MaskShader &S)
{
Shader::operator =(S);
mode = S.mode;
shape = S.shape;
blur = S.blur;
size = S.size;
}
void MaskShader::accept(Visitor& v) {
Shader::accept(v);
v.visit(*this);
}

View File

@@ -1,4 +1,4 @@
#ifndef IMAGESHADER_H
#ifndef IMAGESHADER_H
#define IMAGESHADER_H
#include <string>
@@ -14,21 +14,59 @@ class ImageShader : public Shader
{
public:
ImageShader();
void use() override;
void reset() override;
void accept(Visitor& v) override;
void operator = (const ImageShader &S);
uint mask;
uint custom_textureindex;
float stipple;
uint mask_texture;
static const char* mask_names[11];
static std::vector< uint > mask_presets;
// uniforms
float stipple;
};
class MaskShader : public Shader
{
public:
MaskShader();
void use() override;
void reset() override;
void accept(Visitor& v) override;
void operator = (const MaskShader &S);
enum Modes {
NONE = 0,
PAINT = 1,
SHAPE = 2
};
uint mode;
enum Shapes {
ELIPSE = 0,
OBLONG = 1,
RECTANGLE = 2,
HORIZONTAL = 3,
VERTICAL = 4
};
uint shape;
// uniforms
glm::vec2 size;
float blur;
int option;
int effect;
glm::vec4 cursor;
glm::vec3 brush;
static const char* mask_names[3];
static const char* mask_shapes[5];
static std::vector< ShadingProgram* > mask_programs;
};
#endif // IMAGESHADER_H

View File

@@ -13,6 +13,7 @@ using namespace std;
#include "Visitor.h"
#include "SystemToolkit.h"
#include "GlmToolkit.h"
#include "GstToolkit.h"
#include "MediaPlayer.h"
@@ -186,12 +187,10 @@ static MediaInfo UriDiscoverer_(std::string uri)
void MediaPlayer::open(string path)
{
// set path
filename_ = path;
filename_ = SystemToolkit::transliterate( path );
// set uri to open
gchar *uritmp = gst_filename_to_uri(path.c_str(), NULL);
uri_ = string( uritmp );
g_free(uritmp);
uri_ = GstToolkit::filename_to_uri(path);
// reset
ready_ = false;
@@ -779,7 +778,7 @@ void MediaPlayer::update()
fill_texture(read_index);
// double update for pre-roll frame and dual PBO (ensure frame is displayed now)
if (frame_[read_index].status == PREROLL && pbo_size_ > 0)
if ( (frame_[read_index].status == PREROLL || seeking_ ) && pbo_size_ > 0)
fill_texture(read_index);
}

View File

@@ -86,13 +86,15 @@ void MediaSource::init()
// set the renderbuffer of the source and attach rendering nodes
attach(renderbuffer);
// force update of activation mode
active_ = true;
// deep update to reorder
View::need_deep_update_++;
// done init
initialized_ = true;
Log::Info("Source '%s' linked to Media %s.", name().c_str(), std::to_string(mediaplayer_->id()).c_str());
// force update of activation mode
active_ = true;
touch();
}
}

View File

@@ -211,8 +211,9 @@ void Mixer::update()
appearance_.update(dt_);
transition_.update(dt_);
// deep updates shall be performed only 1 frame
View::need_deep_update_ = false;
// deep update was performed
if (View::need_deep_update_ > 0)
View::need_deep_update_--;
}
void Mixer::draw()
@@ -641,6 +642,21 @@ void Mixer::setCurrentNext()
}
}
void Mixer::setCurrentPrevious()
{
if (session_->numSource() > 0) {
SourceList::iterator it = current_source_;
if (it == session_->begin()) {
it = session_->end();
}
it--;
setCurrentSource( it );
}
}
void Mixer::unsetCurrentSource()
{
// discard overlay for previously current source
@@ -707,7 +723,7 @@ void Mixer::setView(View::Mode m)
}
// need to deeply update view to apply eventual changes
View::need_deep_update_ = true;
View::need_deep_update_++;
Settings::application.current_view = (int) m;
}
@@ -750,6 +766,8 @@ void Mixer::saveas(const std::string& filename)
void Mixer::load(const std::string& filename)
{
if (filename.empty())
return;
#ifdef THREADED_LOADING
// load only one at a time
@@ -849,9 +867,6 @@ void Mixer::swap()
// transfer fading
session_->setFading( MAX(back_session_->fading(), session_->fading()), true );
// request complete update for views
View::need_deep_update_ = true;
// no current source
current_source_ = session_->end();
current_source_index_ = -1;
@@ -900,6 +915,9 @@ void Mixer::clear()
// swap current with empty
sessionSwapRequested_ = true;
// need to deeply update view to apply eventual changes
View::need_deep_update_++;
Log::Info("New session ready.");
}

View File

@@ -59,6 +59,7 @@ public:
void setCurrentSource (Node *node);
void setCurrentSource (uint64_t id);
void setCurrentNext ();
void setCurrentPrevious ();
void unsetCurrentSource ();
void setCurrentIndex (int index);

View File

@@ -11,7 +11,7 @@
#include "Visitor.h"
#include "Log.h"
#define MAX_PATTERN 23
#define MAX_PATTERN 24
// smpte (0) SMPTE 100%% color bars
// snow (1) Random (television snow)
@@ -38,59 +38,62 @@
// spokes (22) Spokes
// gradient (23) Gradient
// colors (24) Colors
const char* pattern_internal_[24] = { "videotestsrc pattern=black",
"videotestsrc pattern=white",
"videotestsrc pattern=gradient",
"videotestsrc pattern=checkers-1 ! video/x-raw,format=GRAY8 ! videoconvert",
"videotestsrc pattern=checkers-8 ! video/x-raw,format=GRAY8 ! videoconvert",
"videotestsrc pattern=circular",
"frei0r-src-lissajous0r ratiox=0.001 ratioy=0.999 ! videoconvert",
"videotestsrc pattern=pinwheel",
"videotestsrc pattern=spokes",
"videotestsrc pattern=red",
"videotestsrc pattern=green",
"videotestsrc pattern=blue",
"videotestsrc pattern=smpte100",
"videotestsrc pattern=colors",
"videotestsrc pattern=smpte",
"videotestsrc pattern=snow",
"videotestsrc pattern=blink",
"videotestsrc pattern=zone-plate",
"videotestsrc pattern=chroma-zone-plate",
"videotestsrc pattern=bar horizontal-speed=5",
"videotestsrc pattern=ball",
"frei0r-src-ising0r",
"videotestsrc pattern=black ! timeoverlay halignment=center valignment=center font-desc=\"Sans, 72\" ",
"videotestsrc pattern=black ! clockoverlay halignment=center valignment=center font-desc=\"Sans, 72\" "
const char* pattern_internal_[MAX_PATTERN] = { "videotestsrc pattern=black",
"videotestsrc pattern=white",
"videotestsrc pattern=gradient",
"videotestsrc pattern=checkers-1 ! video/x-raw,format=GRAY8 ! videoconvert",
"videotestsrc pattern=checkers-8 ! video/x-raw,format=GRAY8 ! videoconvert",
"videotestsrc pattern=circular",
"frei0r-src-lissajous0r ratiox=0.001 ratioy=0.999 ! videoconvert",
"videotestsrc pattern=pinwheel",
"videotestsrc pattern=spokes",
"videotestsrc pattern=red",
"videotestsrc pattern=green",
"videotestsrc pattern=blue",
"videotestsrc pattern=smpte100",
"videotestsrc pattern=colors",
"videotestsrc pattern=smpte",
"videotestsrc pattern=snow",
"videotestsrc pattern=blink",
"videotestsrc pattern=zone-plate",
"videotestsrc pattern=chroma-zone-plate",
"videotestsrc pattern=bar horizontal-speed=5",
"videotestsrc pattern=ball",
"frei0r-src-ising0r",
"videotestsrc pattern=black ! timeoverlay halignment=center valignment=center font-desc=\"Sans, 72\" ",
"videotestsrc pattern=black ! clockoverlay halignment=center valignment=center font-desc=\"Sans, 72\" "
};
std::vector<std::string> Pattern::pattern_types = { "Black",
"White",
"Gradient",
"Checkers 1x1 px",
"Checkers 8x8 px",
"Circles",
"Lissajous",
"Pinwheel",
"Spokes",
"Red",
"Green",
"Blue",
"Color bars",
"RGB grid",
"SMPTE test pattern",
"Television snow",
"Blink",
"Fresnel zone plate",
"Chroma zone plate",
"Bar moving",
"Ball bouncing",
"Blob",
"Timer",
"Clock"
};
"White",
"Gradient",
"Checkers 1x1 px",
"Checkers 8x8 px",
"Circles",
"Lissajous",
"Pinwheel",
"Spokes",
"Red",
"Green",
"Blue",
"Color bars",
"RGB grid",
"SMPTE test pattern",
"Television snow",
"Blink",
"Fresnel zone plate",
"Chroma zone plate",
"Bar moving",
"Ball bouncing"
#if GST_VERSION_MINOR > 17
,
"Blob",
"Timer",
"Clock"
#endif
};
Pattern::Pattern() : Stream(), type_(MAX_PATTERN+1) // invalid pattern
Pattern::Pattern() : Stream(), type_(MAX_PATTERN) // invalid pattern
{
}
@@ -103,7 +106,7 @@ glm::ivec2 Pattern::resolution()
void Pattern::open( uint pattern, glm::ivec2 res )
{
type_ = MIN(pattern, MAX_PATTERN);
type_ = MIN(pattern, MAX_PATTERN-1);
std::string gstreamer_pattern = pattern_internal_[type_];
// there is always a special case...

View File

@@ -126,6 +126,13 @@ void PickingVisitor::visit(Handles &n)
glm::vec4 S = glm::inverse(modelview_) * glm::vec4( 0.05f, 0.05f, 0.f, 0.f );
float scale = glm::length( glm::vec2(S) );
// extract rotation from modelview
glm::mat4 ctm;
glm::vec3 rot(0.f);
glm::vec4 vec = modelview_ * glm::vec4(1.f, 0.f, 0.f, 0.f);
rot.z = glm::orientedAngle( glm::vec3(1.f, 0.f, 0.f), glm::normalize(glm::vec3(vec)), glm::vec3(0.f, 0.f, 1.f) );
ctm = glm::rotate(glm::identity<glm::mat4>(), -rot.z, glm::vec3(0.f, 0.f, 1.f)) * modelview_ ;
bool picked = false;
if ( n.type() == Handles::RESIZE ) {
// 4 corners
@@ -146,21 +153,23 @@ void PickingVisitor::visit(Handles &n)
}
else if ( n.type() == Handles::ROTATE ){
// the icon for rotation is on the right top corner at (0.12, 0.12) in scene coordinates
glm::vec4 vec = glm::inverse(modelview_) * glm::vec4( 0.1f, 0.1f, 0.f, 0.f );
float l = glm::length( glm::vec2(vec) );
picked = glm::length( glm::vec2( 1.f + l, 1.f + l) - glm::vec2(P) ) < 1.5f * scale;
glm::vec4 pos = glm::inverse(ctm) * glm::vec4( 0.12f, 0.12f, 0.f, 0.f );
picked = glm::length( glm::vec2( 1.f, 1.f) + glm::vec2(pos) - glm::vec2(P) ) < 1.5f * scale;
}
else if ( n.type() == Handles::SCALE ){
// the icon for scaling is on the right bottom corner at (0.12, -0.12) in scene coordinates
glm::vec4 vec = glm::inverse(modelview_) * glm::vec4( 0.1f, 0.1f, 0.f, 0.f );
float l = glm::length( glm::vec2(vec) );
picked = glm::length( glm::vec2( 1.f + l, -1.f - l) - glm::vec2(P) ) < 1.5f * scale;
glm::vec4 pos = glm::inverse(ctm) * glm::vec4( 0.12f, -0.12f, 0.f, 0.f );
picked = glm::length( glm::vec2( 1.f, -1.f) + glm::vec2(pos) - glm::vec2(P) ) < 1.5f * scale;
}
else if ( n.type() == Handles::CROP ){
// the icon for cropping is on the left bottom corner at (0.12, 0.12) in scene coordinates
glm::vec4 pos = glm::inverse(ctm) * glm::vec4( 0.12f, 0.12f, 0.f, 0.f );
picked = glm::length( glm::vec2( -1.f, -1.f) + glm::vec2(pos) - glm::vec2(P) ) < 1.5f * scale;
}
else if ( n.type() == Handles::MENU ){
// the icon for restore is on the left top corner at (-0.12, 0.12) in scene coordinates
glm::vec4 vec = glm::inverse(modelview_) * glm::vec4( 0.1f, 0.1f, 0.f, 0.f );
float l = glm::length( glm::vec2(vec) );
picked = glm::length( glm::vec2( -1.f - l, 1.f + l) - glm::vec2(P) ) < 1.5f * scale;
glm::vec4 pos = glm::inverse(ctm) * glm::vec4( -0.12f, 0.12f, 0.f, 0.f );
picked = glm::length( glm::vec2( -1.f, 1.f) + glm::vec2(pos) - glm::vec2(P) ) < 1.5f * scale;
}
if ( picked )

View File

@@ -171,19 +171,8 @@ void MediaSurface::accept(Visitor& v)
v.visit(*this);
}
FrameBufferSurface::FrameBufferSurface(FrameBuffer *fb, Shader *s) : Surface(s), frame_buffer_(fb)
{
}
void FrameBufferSurface::init()
{
Surface::init();
// set aspect ratio
scale_.x = frame_buffer_->aspectRatio();
}
void FrameBufferSurface::draw(glm::mat4 modelview, glm::mat4 projection)
@@ -204,7 +193,6 @@ void FrameBufferSurface::accept(Visitor& v)
v.visit(*this);
}
Points::Points(std::vector<glm::vec3> points, glm::vec4 color, uint pointsize) : Primitive(new Shader)
{
for(size_t i = 0; i < points.size(); ++i)
@@ -218,8 +206,6 @@ Points::Points(std::vector<glm::vec3> points, glm::vec4 color, uint pointsize) :
pointsize_ = pointsize;
}
void Points::draw(glm::mat4 modelview, glm::mat4 projection)
{
if ( !initialized() )

View File

@@ -94,7 +94,6 @@ class FrameBufferSurface : public Surface {
public:
FrameBufferSurface(FrameBuffer *fb, Shader *s = new ImageShader);
void init () override;
void draw (glm::mat4 modelview, glm::mat4 projection) override;
void accept (Visitor& v) override;

View File

@@ -58,8 +58,8 @@ and (recursively) clone all the internal git Dependencies.
**Ubuntu**
apt-get install build-essential cmake libpng-dev libglfw3-dev libgstreamer1.0-dev libgstreamer-plugins-base1.0-dev
apt-get install build-essential cmake libpng-dev libglfw3-dev libgstreamer1.0-dev libgstreamer-plugins-base1.0-dev libicu-dev
**OSX with Brew**
brew install cmake libpng glfw gstreamer gst-libav gst-plugins-bad gst-plugins-base gst-plugins-good gst-plugins-ugly
brew install cmake libpng glfw gstreamer gst-libav gst-plugins-bad gst-plugins-base gst-plugins-good gst-plugins-ugly icu4c

View File

@@ -157,6 +157,15 @@ bool Rendering::init()
g_setenv ("GST_GL_API", "opengl3", TRUE);
gst_init (NULL, NULL);
// increase selection rank for GPU decoding plugins
if (Settings::application.render.gpu_decoding) {
std::list<std::string> gpuplugins = GstToolkit::enable_gpu_decoding_plugins();
if (gpuplugins.size() > 0) {
Log::Info("Video decoding favoring the following GPU decoding plugin(s):");
for(auto it = gpuplugins.begin(); it != gpuplugins.end(); it++)
Log::Info(" - %s", (*it).c_str());
}
}
//#if GST_GL_HAVE_PLATFORM_WGL
// global_gl_context = gst_gl_context_new_wrapped (display, (guintptr) wglGetCurrentContext (),
@@ -186,9 +195,6 @@ bool Rendering::init()
glfwSetKeyCallback( output_.window(), WindowEscapeFullscreen);
glfwSetMouseButtonCallback( output_.window(), WindowToggleFullscreen);
// GstDeviceMonitor *dm = GstToolkit::setup_raw_video_source_device_monitor();
return true;
}
@@ -267,6 +273,12 @@ void Rendering::draw()
// no g_main_loop_run(loop) : update global GMainContext
g_main_context_iteration(NULL, FALSE);
// software framerate limiter 60FPS if not v-sync
if ( Settings::application.render.vsync < 1 ) {
int dt = 18000 - int( 1000.f * Mixer::manager().dt() );
if (dt > 100)
g_usleep( dt );
}
}

View File

@@ -27,6 +27,7 @@ Node::Node() : initialized_(false), visible_(true), refcount_(0)
scale_ = glm::vec3(1.f);
rotation_ = glm::vec3(0.f);
translation_ = glm::vec3(0.f);
crop_ = glm::vec3(1.f);
}
Node::~Node ()
@@ -53,6 +54,7 @@ void Node::copyTransform(Node *other)
scale_ = other->scale_;
rotation_ = other->rotation_;
translation_ = other->translation_;
crop_ = other->crop_;
}
void Node::update( float dt)

View File

@@ -70,7 +70,7 @@ public:
bool visible_;
uint refcount_;
glm::mat4 transform_;
glm::vec3 scale_, rotation_, translation_;
glm::vec3 scale_, rotation_, translation_, crop_;
// animation update callbacks
// list of callbacks to call at each update

View File

@@ -39,7 +39,7 @@ void Screenshot::captureGL(int x, int y, int w, int h)
{
Width = w - x;
Height = h - y;
unsigned int size = Width * Height * 4;
unsigned int size = Width * Height * 3;
// create BPO
if (Pbo == 0)
@@ -58,7 +58,7 @@ void Screenshot::captureGL(int x, int y, int w, int h)
// screenshot to PBO (fast)
glPixelStorei(GL_PACK_ALIGNMENT, 1);
glReadPixels(x, y, w, h, GL_RGBA, GL_UNSIGNED_BYTE, 0);
glReadPixels(x, y, w, h, GL_RGB, GL_UNSIGNED_BYTE, 0);
Pbo_full = true;
// done
@@ -85,6 +85,7 @@ void Screenshot::save(std::string filename)
// ready for next
Pbo_full = false;
glBindBuffer(GL_PIXEL_PACK_BUFFER, 0);
}
}
@@ -128,11 +129,9 @@ void Screenshot::storeToFile(Screenshot *s, std::string filename)
ScreenshotSavePending_ = true;
// got data to save ?
if (s && s->Data) {
// make it usable
s->RemoveAlpha();
s->FlipVertical();
// save file
stbi_write_png(filename.c_str(), s->Width, s->Height, 4, s->Data, s->Width * 4);
stbi_flip_vertically_on_write(true);
stbi_write_png(filename.c_str(), s->Width, s->Height, 3, s->Data, s->Width * 3);
}
ScreenshotSavePending_ = false;
}

View File

@@ -106,10 +106,8 @@ SourceList::iterator Session::addSource(Source *s)
SourceList::iterator its = find(s);
// ok, its NOT in the list !
if (its == sources_.end()) {
// insert the source in the rendering
render_.scene.ws()->attach(s->group(View::RENDERING));
// insert the source to the beginning of the list
sources_.push_front(s);
}
@@ -130,13 +128,10 @@ SourceList::iterator Session::deleteSource(Source *s)
SourceList::iterator its = find(s);
// ok, its in the list !
if (its != sources_.end()) {
// remove Node from the rendering scene
render_.scene.ws()->detach( s->group(View::RENDERING) );
// erase the source from the update list & get next element
its = sources_.erase(its);
// delete the source : safe now
delete s;
}
@@ -158,10 +153,8 @@ void Session::removeSource(Source *s)
SourceList::iterator its = find(s);
// ok, its in the list !
if (its != sources_.end()) {
// remove Node from the rendering scene
render_.scene.ws()->detach( s->group(View::RENDERING) );
// erase the source from the update list & get next element
sources_.erase(its);
}
@@ -179,10 +172,8 @@ Source *Session::popSource()
if (its != sources_.end())
{
s = *its;
// remove Node from the rendering scene
render_.scene.ws()->detach( s->group(View::RENDERING) );
// erase the source from the update list & get next element
sources_.erase(its);
}

View File

@@ -75,7 +75,10 @@ void SessionCreator::load(const std::string& filename)
header->QueryIntAttribute("major", &version_major);
header->QueryIntAttribute("minor", &version_minor);
if (version_major != XML_VERSION_MAJOR || version_minor != XML_VERSION_MINOR){
Log::Warning("%s is in a different versions of session file. Loading might fail.", filename.c_str());
Log::Warning("%s session file is in version v%d.%d. but this vimix program expects v%d.%d.\n"
"Loading might fail or lead to different or incomplete configuration.\n"
"You can save this session again to avoid this warning.",
filename.c_str(), version_major, version_minor, XML_VERSION_MAJOR, XML_VERSION_MINOR);
// return;
}
@@ -100,6 +103,7 @@ void SessionCreator::loadConfig(XMLElement *viewsNode)
SessionLoader::XMLToNode( viewsNode->FirstChildElement("Mixing"), *session_->config(View::MIXING));
SessionLoader::XMLToNode( viewsNode->FirstChildElement("Geometry"), *session_->config(View::GEOMETRY));
SessionLoader::XMLToNode( viewsNode->FirstChildElement("Layer"), *session_->config(View::LAYER));
SessionLoader::XMLToNode( viewsNode->FirstChildElement("Appearance"), *session_->config(View::APPEARANCE));
SessionLoader::XMLToNode( viewsNode->FirstChildElement("Rendering"), *session_->config(View::RENDERING));
}
}
@@ -109,52 +113,6 @@ SessionLoader::SessionLoader(Session *session): Visitor(), session_(session)
}
//Source *SessionLoader::createSource(XMLElement *sourceNode)
//{
// // source to load
// Source *load_source = nullptr;
// // check if a source with the given id exists in the session
// uint64_t id__ = 0;
// sourceNode->QueryUnsigned64Attribute("id", &id__);
// SourceList::iterator sit = session_->find(id__);
// // no source with this id exists
// if ( sit == session_->end() ) {
// // create a new source depending on type
// const char *pType = sourceNode->Attribute("type");
// if (!pType)
// continue;
// if ( std::string(pType) == "MediaSource") {
// load_source = new MediaSource;
// }
// else if ( std::string(pType) == "SessionSource") {
// load_source = new SessionSource;
// }
// else if ( std::string(pType) == "RenderSource") {
// load_source = new RenderSource(session_);
// }
// else if ( std::string(pType) == "PatternSource") {
// load_source = new PatternSource;
// }
// else if ( std::string(pType) == "DeviceSource") {
// load_source = new DeviceSource;
// }
// // skip failed (including clones)
// if (!load_source)
// continue;
// // add source to session
// session_->addSource(load_source);
// }
// // get reference to the existing source
// else
// load_source = *sit;
// return load_source;
//}
void SessionLoader::load(XMLElement *sessionNode)
{
sources_id_.clear();
@@ -347,6 +305,9 @@ void SessionLoader::XMLToNode(tinyxml2::XMLElement *xml, Node &n)
XMLElement *rotationNode = node->FirstChildElement("rotation");
if (rotationNode)
tinyxml2::XMLElementToGLM( rotationNode->FirstChildElement("vec3"), n.rotation_);
XMLElement *cropNode = node->FirstChildElement("crop");
if (cropNode)
tinyxml2::XMLElementToGLM( cropNode->FirstChildElement("vec3"), n.crop_);
}
}
@@ -428,9 +389,26 @@ void SessionLoader::visit(ImageShader &n)
XMLElement* uniforms = xmlCurrent_->FirstChildElement("uniforms");
if (uniforms) {
uniforms->QueryFloatAttribute("stipple", &n.stipple);
uniforms->QueryUnsignedAttribute("mask", &n.mask);
}
}
void SessionLoader::visit(MaskShader &n)
{
const char *pType = xmlCurrent_->Attribute("type");
if ( std::string(pType) != "MaskShader" )
return;
xmlCurrent_->QueryUnsignedAttribute("mode", &n.mode);
xmlCurrent_->QueryUnsignedAttribute("shape", &n.shape);
XMLElement* uniforms = xmlCurrent_->FirstChildElement("uniforms");
if (uniforms) {
uniforms->QueryFloatAttribute("blur", &n.blur);
uniforms->QueryIntAttribute("option", &n.option);
XMLElement* size = uniforms->FirstChildElement("size");
if (size)
tinyxml2::XMLElementToGLM( size->FirstChildElement("vec2"), n.size);
}
}
void SessionLoader::visit(ImageProcessingShader &n)
@@ -471,27 +449,55 @@ void SessionLoader::visit (Source& s)
s.setName(pName);
xmlCurrent_ = sourceNode->FirstChildElement("Mixing");
s.groupNode(View::MIXING)->accept(*this);
if (xmlCurrent_) s.groupNode(View::MIXING)->accept(*this);
xmlCurrent_ = sourceNode->FirstChildElement("Geometry");
s.groupNode(View::GEOMETRY)->accept(*this);
if (xmlCurrent_) s.groupNode(View::GEOMETRY)->accept(*this);
xmlCurrent_ = sourceNode->FirstChildElement("Layer");
s.groupNode(View::LAYER)->accept(*this);
if (xmlCurrent_) s.groupNode(View::LAYER)->accept(*this);
xmlCurrent_ = sourceNode->FirstChildElement("Appearance");
s.groupNode(View::APPEARANCE)->accept(*this);
xmlCurrent_ = sourceNode->FirstChildElement("Crop");
s.renderingSurface()->accept(*this);
if (xmlCurrent_) s.groupNode(View::APPEARANCE)->accept(*this);
xmlCurrent_ = sourceNode->FirstChildElement("Blending");
s.blendingShader()->accept(*this);
if (xmlCurrent_) s.blendingShader()->accept(*this);
xmlCurrent_ = sourceNode->FirstChildElement("Mask");
if (xmlCurrent_) {
// read the mask shader attributes
s.maskShader()->accept(*this);
// if there is an Image mask stored
XMLElement* imageNode = xmlCurrent_->FirstChildElement("Image");
if (imageNode) {
// if there is an internal array of data
XMLElement* array = imageNode->FirstChildElement("array");
if (array) {
// create a temporary jpeg with size of the array
FrameBufferImage::jpegBuffer jpgimg;
array->QueryUnsignedAttribute("len", &jpgimg.len);
// ok, we got a size of data to load
if (jpgimg.len>0) {
// allocate jpeg buffer
jpgimg.buffer = (unsigned char*) malloc(jpgimg.len);
// actual decoding of array
if (XMLElementDecodeArray(array, jpgimg.buffer, jpgimg.len) )
// create and set the image from jpeg
s.setMask(new FrameBufferImage(jpgimg));
// free temporary buffer
if (jpgimg.buffer)
free(jpgimg.buffer);
}
}
}
}
xmlCurrent_ = sourceNode->FirstChildElement("ImageProcessing");
bool on = xmlCurrent_->BoolAttribute("enabled", true);
s.processingShader()->accept(*this);
s.setImageProcessingEnabled(on);
if (xmlCurrent_) {
bool on = xmlCurrent_->BoolAttribute("enabled", true);
s.processingShader()->accept(*this);
s.setImageProcessingEnabled(on);
}
// restore current
xmlCurrent_ = sourceNode;

View File

@@ -41,6 +41,7 @@ public:
void visit (MediaPlayer& n) override;
void visit (Shader& n) override;
void visit (ImageShader& n) override;
void visit (MaskShader& n) override;
void visit (ImageProcessingShader& n) override;
// Sources

View File

@@ -116,6 +116,8 @@ void SessionSource::init()
}
else {
session_->update(dt_);
if (wait_for_sources_) {
// force update of of all sources
@@ -145,8 +147,7 @@ void SessionSource::init()
// set resolution
session_->setResolution( session_->config(View::RENDERING)->scale_ );
// deep update once to draw framebuffer
View::need_deep_update_ = true;
// update to draw framebuffer
session_->update(dt_);
// get the texture index from framebuffer of session, apply it to the surface
@@ -173,6 +174,8 @@ void SessionSource::init()
Node *loader = overlays_[View::TRANSITION]->back();
overlays_[View::TRANSITION]->detach(loader);
delete loader;
// deep update to reorder
View::need_deep_update_++;
}
}
@@ -250,9 +253,11 @@ void RenderSource::init()
// set the renderbuffer of the source and attach rendering nodes
attach(renderbuffer);
// deep update to reorder
View::need_deep_update_++;
// done init
initialized_ = true;
Log::Info("Source Render linked to session (%d x %d).", int(fb->resolution().x), int(fb->resolution().y) );
}
}

View File

@@ -47,6 +47,10 @@ tinyxml2::XMLElement *SessionVisitor::NodeToXML(Node &n, tinyxml2::XMLDocument *
rotation->InsertEndChild( XMLElementFromGLM(doc, n.rotation_) );
newelement->InsertEndChild(rotation);
XMLElement *crop = doc->NewElement("crop");
crop->InsertEndChild( XMLElementFromGLM(doc, n.crop_) );
newelement->InsertEndChild(crop);
return newelement;
}
@@ -199,9 +203,24 @@ void SessionVisitor::visit(ImageShader &n)
XMLElement *uniforms = xmlDoc_->NewElement("uniforms");
uniforms->SetAttribute("stipple", n.stipple);
uniforms->SetAttribute("mask", n.mask);
xmlCurrent_->InsertEndChild(uniforms);
}
void SessionVisitor::visit(MaskShader &n)
{
// Shader of a mask type
xmlCurrent_->SetAttribute("type", "MaskShader");
xmlCurrent_->SetAttribute("id", n.id());
xmlCurrent_->SetAttribute("mode", n.mode);
xmlCurrent_->SetAttribute("shape", n.shape);
XMLElement *uniforms = xmlDoc_->NewElement("uniforms");
uniforms->SetAttribute("blur", n.blur);
uniforms->SetAttribute("option", n.option);
XMLElement *size = xmlDoc_->NewElement("size");
size->InsertEndChild( XMLElementFromGLM(xmlDoc_, n.size) );
uniforms->InsertEndChild(size);
xmlCurrent_->InsertEndChild(uniforms);
}
void SessionVisitor::visit(ImageProcessingShader &n)
@@ -343,14 +362,36 @@ void SessionVisitor::visit (Source& s)
sourceNode->InsertEndChild(xmlCurrent_);
s.groupNode(View::APPEARANCE)->accept(*this);
xmlCurrent_ = xmlDoc_->NewElement("Crop");
sourceNode->InsertEndChild(xmlCurrent_);
s.renderingSurface()->accept(*this);
xmlCurrent_ = xmlDoc_->NewElement( "Blending" );
sourceNode->InsertEndChild(xmlCurrent_);
s.blendingShader()->accept(*this);
xmlCurrent_ = xmlDoc_->NewElement( "Mask" );
sourceNode->InsertEndChild(xmlCurrent_);
s.maskShader()->accept(*this);
// if we are saving a pain mask
if (s.maskShader()->mode == MaskShader::PAINT) {
// get the mask previously stored
FrameBufferImage *img = s.getMask();
if (img != nullptr) {
// get the jpeg encoded buffer
FrameBufferImage::jpegBuffer jpgimg = img->getJpeg();
if (jpgimg.buffer != nullptr) {
// fill the xml array with jpeg buffer
XMLElement *array = XMLElementEncodeArray(xmlDoc_, jpgimg.buffer, jpgimg.len);
// free the buffer
free(jpgimg.buffer);
// if we could create the array
if (array) {
// create an Image node to store the mask image
XMLElement *imageelement = xmlDoc_->NewElement("Image");
imageelement->InsertEndChild(array);
xmlCurrent_->InsertEndChild(imageelement);
}
}
}
}
xmlCurrent_ = xmlDoc_->NewElement( "ImageProcessing" );
xmlCurrent_->SetAttribute("enabled", s.imageProcessingEnabled());
sourceNode->InsertEndChild(xmlCurrent_);

View File

@@ -38,6 +38,7 @@ public:
void visit(MediaPlayer& n) override;
void visit(Shader& n) override;
void visit(ImageShader& n) override;
void visit(MaskShader& n) override;
void visit(ImageProcessingShader& n) override;
// Sources

View File

@@ -82,6 +82,7 @@ void Settings::Save()
RenderNode->SetAttribute("vsync", application.render.vsync);
RenderNode->SetAttribute("multisampling", application.render.multisampling);
RenderNode->SetAttribute("blit", application.render.blit);
RenderNode->SetAttribute("gpu_decoding", application.render.gpu_decoding);
RenderNode->SetAttribute("ratio", application.render.ratio);
RenderNode->SetAttribute("res", application.render.res);
pRoot->InsertEndChild(RenderNode);
@@ -127,8 +128,8 @@ void Settings::Save()
// bloc views
{
XMLElement *viewsNode = xmlDoc.NewElement( "Views" );
// save current view only if [mixing, geometry or layers]
int v = application.current_view > 3 ? 1 : application.current_view;
// save current view only if [mixing, geometry, layers, appearance]
int v = application.current_view > 4 ? 1 : application.current_view;
viewsNode->SetAttribute("current", v);
map<int, Settings::ViewConfig>::iterator iter;
@@ -264,6 +265,7 @@ void Settings::Load()
rendernode->QueryIntAttribute("vsync", &application.render.vsync);
rendernode->QueryIntAttribute("multisampling", &application.render.multisampling);
rendernode->QueryBoolAttribute("blit", &application.render.blit);
rendernode->QueryBoolAttribute("gpu_decoding", &application.render.gpu_decoding);
rendernode->QueryIntAttribute("ratio", &application.render.ratio);
rendernode->QueryIntAttribute("res", &application.render.res);
}

View File

@@ -136,14 +136,16 @@ struct RenderConfig
int ratio;
int res;
float fading;
bool gpu_decoding;
RenderConfig() {
blit = false;
vsync = 1; // todo GUI selection
multisampling = 2; // todo GUI selection
vsync = 1;
multisampling = 2;
ratio = 3;
res = 1;
fading = 0.0;
gpu_decoding = true;
}
};

View File

@@ -1,5 +1,6 @@
#include "Shader.h"
#include "Resource.h"
#include "FrameBuffer.h"
#include "Log.h"
#include "Visitor.h"
#include "RenderingManager.h"
@@ -119,14 +120,20 @@ void ShadingProgram::setUniform<float>(const std::string& name, float val1, floa
}
template<>
void ShadingProgram::setUniform<glm::vec4>(const std::string& name, glm::vec4 val) {
glm::vec4 v(val);
glUniform4fv(glGetUniformLocation(id_, name.c_str()), 1, glm::value_ptr(v));
void ShadingProgram::setUniform<glm::vec2>(const std::string& name, glm::vec2 val) {
glm::vec2 v(val);
glUniform2fv(glGetUniformLocation(id_, name.c_str()), 1, glm::value_ptr(v));
}
template<>
void ShadingProgram::setUniform<glm::vec3>(const std::string& name, glm::vec3 val) {
glm::vec3 v(val);
glUniform3fv(glGetUniformLocation(id_, name.c_str()), 1, glm::value_ptr(v));
}
template<>
void ShadingProgram::setUniform<glm::vec4>(const std::string& name, glm::vec4 val) {
glm::vec4 v(val);
glUniform4fv(glGetUniformLocation(id_, name.c_str()), 1, glm::value_ptr(v));
}
@@ -208,7 +215,7 @@ void Shader::use()
program_->setUniform("iTransform", iTransform);
program_->setUniform("color", color);
iResolution = glm::vec3( Rendering::manager().currentAttrib().viewport, 0.f);
glm::vec3 iResolution = glm::vec3( Rendering::manager().currentAttrib().viewport, 0.f);
program_->setUniform("iResolution", iResolution);
// Blending Function
@@ -238,7 +245,6 @@ void Shader::reset()
projection = glm::identity<glm::mat4>();
modelview = glm::identity<glm::mat4>();
iTransform = glm::identity<glm::mat4>();
iResolution = glm::vec3(1280.f, 720.f, 0.f);
color = glm::vec4(1.f, 1.f, 1.f, 1.f);
}

View File

@@ -7,6 +7,7 @@
// Forward declare classes referenced
class Visitor;
class FrameBuffer;
class ShadingProgram
{
@@ -22,13 +23,13 @@ public:
static void enduse();
private:
void checkCompileErr();
void checkLinkingErr();
void compile();
void link();
unsigned int vertex_id_, fragment_id_, id_;
std::string vertex_code_;
std::string fragment_code_;
void checkCompileErr();
void checkLinkingErr();
void compile();
void link();
unsigned int vertex_id_, fragment_id_, id_;
std::string vertex_code_;
std::string fragment_code_;
std::string vertex_file_;
std::string fragment_file_;
@@ -71,7 +72,6 @@ public:
protected:
ShadingProgram *program_;
glm::vec3 iResolution;
};

View File

@@ -1,5 +1,5 @@
#include <algorithm>
#include <locale>
#include <glm/gtc/matrix_access.hpp>
#include <glm/gtc/matrix_transform.hpp>
@@ -13,10 +13,11 @@
#include "SearchVisitor.h"
#include "ImageShader.h"
#include "ImageProcessingShader.h"
#include "SystemToolkit.h"
#include "Log.h"
#include "Mixer.h"
Source::Source() : initialized_(false), active_(true), need_update_(true), symbol_(nullptr)
Source::Source() : initialized_(false), active_(true), locked_(false), need_update_(true), symbol_(nullptr)
{
// create unique id
id_ = GlmToolkit::uniqueId();
@@ -92,11 +93,15 @@ Source::Source() : initialized_(false), active_(true), need_update_(true), symbo
handles_[View::GEOMETRY][Handles::SCALE] = new Handles(Handles::SCALE);
handles_[View::GEOMETRY][Handles::SCALE]->color = glm::vec4( COLOR_HIGHLIGHT_SOURCE, 1.f);
handles_[View::GEOMETRY][Handles::SCALE]->translation_.z = 0.1;
overlays_[View::GEOMETRY]->attach(handles_[View::GEOMETRY][Handles::SCALE]);
overlays_[View::GEOMETRY]->attach(handles_[View::GEOMETRY][Handles::SCALE]);
handles_[View::GEOMETRY][Handles::MENU] = new Handles(Handles::MENU);
handles_[View::GEOMETRY][Handles::MENU]->color = glm::vec4( COLOR_HIGHLIGHT_SOURCE, 1.f);
handles_[View::GEOMETRY][Handles::MENU]->translation_.z = 0.1;
overlays_[View::GEOMETRY]->attach(handles_[View::GEOMETRY][Handles::MENU]);
handles_[View::GEOMETRY][Handles::CROP] = new Handles(Handles::CROP);
handles_[View::GEOMETRY][Handles::CROP]->color = glm::vec4( COLOR_HIGHLIGHT_SOURCE, 1.f);
handles_[View::GEOMETRY][Handles::CROP]->translation_.z = 0.1;
overlays_[View::GEOMETRY]->attach(handles_[View::GEOMETRY][Handles::CROP]);
frame = new Frame(Frame::SHARP, Frame::THIN, Frame::NONE);
frame->translation_.z = 0.1;
@@ -172,15 +177,41 @@ Source::Source() : initialized_(false), active_(true), need_update_(true), symbo
// empty transition node
groups_[View::TRANSITION] = new Group;
//
// shared locker symbol
//
locker_ = new Symbol(Symbol::LOCK, glm::vec3(0.8f, -0.8f, 0.01f));
locker_->color = glm::vec4(1.f, 1.f, 1.f, 0.6f);
// add semi transparent icon statically to mixing and layer views
Group *lockgroup = new Group;
lockgroup->translation_.z = 0.1;
lockgroup->attach( locker_ );
groups_[View::LAYER]->attach(lockgroup);
groups_[View::MIXING]->attach(lockgroup);
// add semi transparent icon dynamically with overlay
overlays_[View::LAYER]->attach( locker_ );
overlays_[View::MIXING]->attach( locker_ );
// create objects
stored_status_ = new Group;
// those will be associated to nodes later
// simple image shader (with texturing) for blending
blendingshader_ = new ImageShader;
// mask produced by dedicated shader
maskshader_ = new MaskShader;
masksurface_ = new Surface(maskshader_);
// filtered image shader (with texturing and processing) for rendering
processingshader_ = new ImageProcessingShader;
// default to image processing enabled
// default rendering with image processing enabled
renderingshader_ = (Shader *) processingshader_;
// for drawing in mixing view
mixingshader_ = new ImageShader;
mixingshader_->stipple = 1.0;
// create media surface:
// - textured with original texture from media player
// - crop & repeat UV can be managed here
@@ -190,7 +221,10 @@ Source::Source() : initialized_(false), active_(true), need_update_(true), symbo
// will be created at init
renderbuffer_ = nullptr;
rendersurface_ = nullptr;
mixingsurface_ = nullptr;
maskbuffer_ = nullptr;
maskimage_ = nullptr;
mask_need_update_ = false;
}
@@ -205,6 +239,10 @@ Source::~Source()
delete stored_status_;
if (renderbuffer_)
delete renderbuffer_;
if (maskbuffer_)
delete maskbuffer_;
if (maskimage_)
delete maskimage_;
// all groups and their children are deleted in the scene
// this includes rendersurface_, overlays, blendingshader_ and rendershader_
@@ -229,10 +267,10 @@ Source::~Source()
void Source::setName (const std::string &name)
{
name_ = name;
name_ = SystemToolkit::transliterate(name);
initials_[0] = std::toupper( name_.front() );
initials_[1] = std::toupper( name_.back() );
initials_[0] = std::toupper( name_.front(), std::locale("C") );
initials_[1] = std::toupper( name_.back(), std::locale("C") );
}
void Source::accept(Visitor& v)
@@ -253,13 +291,13 @@ void Source::setMode(Source::Mode m)
(*g).second->visible_ = true;
}
// choose frame if selected
// choose frame 0 if visible, 1 if selected
uint index_frame = m == Source::VISIBLE ? 0 : 1;
for (auto f = frames_.begin(); f != frames_.end(); f++)
(*f).second->setActive(index_frame);
// show overlay if current
bool current = m == Source::CURRENT;
bool current = m >= Source::CURRENT;
for (auto o = overlays_.begin(); o != overlays_.end(); o++)
(*o).second->visible_ = current;
@@ -323,7 +361,7 @@ void Source::attach(FrameBuffer *renderbuffer)
{
renderbuffer_ = renderbuffer;
// if a symbol is available, add it to icons
// if a symbol is available, add it to overlay
if (symbol_) {
overlays_[View::MIXING]->attach( symbol_ );
overlays_[View::LAYER]->attach( symbol_ );
@@ -333,27 +371,23 @@ void Source::attach(FrameBuffer *renderbuffer)
rendersurface_ = new FrameBufferSurface(renderbuffer_, blendingshader_);
groups_[View::RENDERING]->attach(rendersurface_);
groups_[View::GEOMETRY]->attach(rendersurface_);
groups_[View::MIXING]->attach(rendersurface_);
// groups_[View::LAYER]->attach(rendersurface_);
// for mixing and layer views, add another surface to overlay
// (stippled view on top with transparency)
Surface *surfacemix = new FrameBufferSurface(renderbuffer_);
ImageShader *is = static_cast<ImageShader *>(surfacemix->shader());
if (is) is->stipple = 1.0;
groups_[View::MIXING]->attach(surfacemix);
groups_[View::LAYER]->attach(surfacemix);
mixingsurface_ = new FrameBufferSurface(renderbuffer_, mixingshader_);
groups_[View::MIXING]->attach(mixingsurface_);
groups_[View::LAYER]->attach(mixingsurface_);
// for appearance view, a dedicated surface without blending
// for views showing a scaled mixing surface, a dedicated transparent surface allows grabbing
Surface *surfacetmp = new Surface();
surfacetmp->setTextureIndex(Resource::getTextureTransparent());
groups_[View::APPEARANCE]->attach(surfacetmp);
groups_[View::MIXING]->attach(surfacetmp);
groups_[View::LAYER]->attach(surfacetmp);
// Transition group node is optionnal
if ( groups_[View::TRANSITION]->numChildren() > 0 ) {
groups_[View::TRANSITION]->attach(rendersurface_);
groups_[View::TRANSITION]->attach(surfacemix);
}
if (groups_[View::TRANSITION]->numChildren() > 0)
groups_[View::TRANSITION]->attach(mixingsurface_);
// scale all icon nodes to match aspect ratio
for (int v = View::MIXING; v < View::INVALID; v++) {
@@ -364,11 +398,21 @@ void Source::attach(FrameBuffer *renderbuffer)
}
}
// hack to place the symbols in the corner independently of aspect ratio
symbol_->translation_.x += 0.1f * (renderbuffer_->aspectRatio()-1.f);
locker_->translation_.x += 0.1f * (renderbuffer_->aspectRatio()-1.f);
// (re) create the masking buffer
if (maskbuffer_)
delete maskbuffer_;
maskbuffer_ = new FrameBuffer( glm::vec3(0.5) * renderbuffer->resolution() );
// make the source visible
if ( mode_ == UNINITIALIZED ) {
if ( mode_ == UNINITIALIZED )
setMode(VISIBLE);
need_update_ = true;
}
// request update
need_update_ = true;
}
@@ -376,16 +420,32 @@ void Source::setActive (bool on)
{
active_ = on;
// do not disactivate if a clone depends on it
for(auto clone = clones_.begin(); clone != clones_.end(); clone++) {
if ( (*clone)->active() )
active_ = true;
}
// an inactive source is visible only in the MIXING view
groups_[View::RENDERING]->visible_ = active_;
groups_[View::GEOMETRY]->visible_ = active_;
groups_[View::LAYER]->visible_ = active_;
}
void Source::setLocked (bool on)
{
locked_ = on;
// the lock icon is visible when locked
locker_->visible_ = on;
// a locked source is not visible in the GEOMETRY view (that's the whole point of it!)
groups_[View::GEOMETRY]->visible_ = !locked_;
}
// Transfer functions from coordinates to alpha (1 - transparency)
float linear_(float x, float y) {
return 1.f - CLAMP( sqrt( ( x * x ) + ( y * y ) ), 0.f, 1.f );
@@ -396,7 +456,9 @@ float quad_(float x, float y) {
}
float sin_quad(float x, float y) {
return 0.5f + 0.5f * cos( M_PI * CLAMP( ( ( x * x ) + ( y * y ) ), 0.f, 1.f ) );
float D = sqrt( ( x * x ) + ( y * y ) );
return 0.5f + 0.5f * cos( M_PI * CLAMP( D * sqrt(D), 0.f, 1.f ) );
// return 0.5f + 0.5f * cos( M_PI * CLAMP( ( ( x * x ) + ( y * y ) ), 0.f, 1.f ) );
}
void Source::update(float dt)
@@ -405,30 +467,56 @@ void Source::update(float dt)
dt_ = dt;
// update nodes if needed
if (need_update_)
if (renderbuffer_ && mixingsurface_ && maskbuffer_ && need_update_)
{
// Log::Info("UPDATE %s %f", initials_, dt);
// ADJUST alpha based on MIXING node
// read position of the mixing node and interpret this as transparency of render output
glm::vec2 dist = glm::vec2(groups_[View::MIXING]->translation_);
// use the prefered transfer function
blendingshader_->color.a = sin_quad( dist.x, dist.y );
// use the sinusoidal transfer function
blendingshader_->color = glm::vec4(1.0, 1.0, 1.0, sin_quad( dist.x, dist.y ));
mixingshader_->color = blendingshader_->color;
// CHANGE update status based on limbo
bool a = glm::length(dist) < 1.3f;
bool a = glm::length(dist) < MIXING_LIMBO_SCALE;
setActive( a );
// adjust scale of mixing icon : smaller if not active
groups_[View::MIXING]->scale_ = glm::vec3(MIXING_ICON_SCALE) - ( a ? glm::vec3(0.f, 0.f, 0.f) : glm::vec3(0.03f, 0.03f, 0.f) );
// MODIFY geometry based on GEOMETRY node
groups_[View::RENDERING]->translation_ = groups_[View::GEOMETRY]->translation_;
groups_[View::RENDERING]->rotation_ = groups_[View::GEOMETRY]->rotation_;
// avoid any null scale
glm::vec3 s = groups_[View::GEOMETRY]->scale_;
// avoid any null scale
s.x = CLAMP_SCALE(s.x);
s.y = CLAMP_SCALE(s.y);
s.z = 1.f;
groups_[View::GEOMETRY]->scale_ = s;
groups_[View::RENDERING]->scale_ = s;
// MODIFY CROP projection based on GEOMETRY crop
renderbuffer_->setProjectionArea( glm::vec2(groups_[View::GEOMETRY]->crop_) );
// Mixing and layer icons scaled based on GEOMETRY crop
mixingsurface_->scale_ = groups_[View::GEOMETRY]->crop_;
mixingsurface_->scale_.x *= renderbuffer_->aspectRatio();
mixingsurface_->update(dt_);
// Layers icons are displayed in Perspective (diagonal)
groups_[View::LAYER]->translation_.y = groups_[View::LAYER]->translation_.x / LAYER_PERSPECTIVE;
// CHANGE lock based on range of layers stage
bool l = (groups_[View::LAYER]->translation_.x < -FOREGROUND_DEPTH)
|| (groups_[View::LAYER]->translation_.x > -BACKGROUND_DEPTH);
setLocked( l );
// adjust position of layer icon: step up when on stage
if (groups_[View::LAYER]->translation_.x < -FOREGROUND_DEPTH)
groups_[View::LAYER]->translation_.y -= 0.3f;
else if (groups_[View::LAYER]->translation_.x < -BACKGROUND_DEPTH)
groups_[View::LAYER]->translation_.y -= 0.15f;
// MODIFY depth based on LAYER node
groups_[View::MIXING]->translation_.z = groups_[View::LAYER]->translation_.z;
groups_[View::GEOMETRY]->translation_.z = groups_[View::LAYER]->translation_.z;
@@ -437,19 +525,14 @@ void Source::update(float dt)
// MODIFY texture projection based on APPEARANCE node
// UV to node coordinates
static glm::mat4 UVtoScene = GlmToolkit::transform(glm::vec3(1.f, -1.f, 0.f),
glm::vec3(0.f, 0.f, 0.f),
glm::vec3(-2.f, 2.f, 1.f));
// make sure to update rendering texture surface node
texturesurface_->update(dt);
glm::vec3(0.f, 0.f, 0.f),
glm::vec3(-2.f, 2.f, 1.f));
// Aspect Ratio correction transform : coordinates of Appearance Frame are scaled by render buffer width
glm::mat4 Ar = glm::identity<glm::mat4>();
if (renderbuffer_)
Ar = glm::scale(glm::identity<glm::mat4>(), glm::vec3(renderbuffer_->aspectRatio() * texturesurface_->scale_.x, texturesurface_->scale_.y, 1.f) );
glm::mat4 Ar = glm::scale(glm::identity<glm::mat4>(), glm::vec3(renderbuffer_->aspectRatio(), 1.f, 1.f) );
// Translation : same as Appearance Frame (modified by Ar)
glm::mat4 Tra = glm::translate(glm::identity<glm::mat4>(), groups_[View::APPEARANCE]->translation_);
// Scaling : inverse scaling (larger UV when smaller Appearance Frame)
glm::mat4 Sca = glm::scale(glm::identity<glm::mat4>(), glm::vec3( texturesurface_->scale_.x / groups_[View::APPEARANCE]->scale_.x,
texturesurface_->scale_.y / groups_[View::APPEARANCE]->scale_.y, 1.f));
glm::mat4 Sca = glm::scale(glm::identity<glm::mat4>(), glm::vec3(groups_[View::APPEARANCE]->scale_.x,groups_[View::APPEARANCE]->scale_.y, 1.f));
// Rotation : same angle than Appearance Frame, inverted axis
glm::mat4 Rot = glm::rotate(glm::identity<glm::mat4>(), groups_[View::APPEARANCE]->rotation_.z, glm::vec3(0.f, 0.f, -1.f) );
// Combine transformations (non transitive) in this order:
@@ -460,11 +543,33 @@ void Source::update(float dt)
// 5. Revert aspect ration correction
// 6. Apply the Scaling (independent of aspect ratio)
// 7. switch back to UV coordinate system
texturesurface_->shader()->iTransform = glm::inverse(UVtoScene) * Sca * glm::inverse(Ar) * Rot * Tra * Ar * UVtoScene;
texturesurface_->shader()->iTransform = glm::inverse(UVtoScene) * glm::inverse(Sca) * glm::inverse(Ar) * Rot * Tra * Ar * UVtoScene;
// if a mask image was given to be updated
if (mask_need_update_) {
// fill the mask buffer (once)
if (maskbuffer_->fill(maskimage_) )
mask_need_update_ = false;
}
// otherwise, render the mask buffer
else
{
// draw mask in mask frame buffer
maskbuffer_->begin(false);
// loopback maskbuffer texture for painting
masksurface_->setTextureIndex(maskbuffer_->texture());
// fill surface with mask texture
masksurface_->draw(glm::identity<glm::mat4>(), maskbuffer_->projection());
maskbuffer_->end();
}
// set the rendered mask as mask for blending
blendingshader_->mask_texture = maskbuffer_->texture();
// do not update next frame
need_update_ = false;
}
}
FrameBuffer *Source::frame() const
@@ -489,6 +594,49 @@ bool Source::contains(Node *node) const
}
void Source::storeMask(FrameBufferImage *img)
{
// free the output mask storage
if (maskimage_ != nullptr) {
delete maskimage_;
maskimage_ = nullptr;
}
// if no image is provided
if (img == nullptr) {
// if ready
if (maskbuffer_!=nullptr) {
// get & store image from mask buffer
maskimage_ = maskbuffer_->image();
}
}
else
// store the given image
maskimage_ = img;
// maskimage_ can now be accessed with Source::getStoredMask
}
void Source::setMask(FrameBufferImage *img)
{
// if a valid image is given
if (img != nullptr && img->width>0 && img->height>0) {
// remember this new image as the current mask
// NB: will be freed when replaced
storeMask(img);
// ask Source::update to use it at next update for filling mask buffer
mask_need_update_ = true;
// ask to update the source
touch();
}
else
mask_need_update_ = false;
}
bool Source::hasNode::operator()(const Source* elem) const
{
if (_n && elem)
@@ -560,9 +708,11 @@ void CloneSource::init()
// set the renderbuffer of the source and attach rendering nodes
attach(renderbuffer);
// deep update to reorder
View::need_deep_update_++;
// done init
initialized_ = true;
Log::Info("Source %s cloning source %s.", name().c_str(), origin_->name().c_str() );
}
}

View File

@@ -11,6 +11,7 @@
#define DEFAULT_MIXING_TRANSLATION -1.f, 1.f
class ImageShader;
class MaskShader;
class ImageProcessingShader;
class FrameBuffer;
class FrameBufferSurface;
@@ -66,12 +67,6 @@ public:
// tests if a given node is part of the source
bool contains (Node *node) const;
// a Source has a shader used to render in fbo
inline Shader *renderingShader () const { return renderingshader_; }
// a Source has a surface used to draw images
inline Surface *renderingSurface () const { return texturesurface_; }
// the rendering shader always have an image processing shader
inline ImageProcessingShader *processingShader () const { return processingshader_; }
@@ -82,10 +77,15 @@ public:
// a Source has a shader to control mixing effects
inline ImageShader *blendingShader () const { return blendingshader_; }
// a Source has a shader used to render in fbo
inline Shader *renderingShader () const { return renderingshader_; }
// every Source has a frame buffer from the renderbuffer
virtual FrameBuffer *frame () const;
// a Source has a shader used to render mask
inline MaskShader *maskShader () const { return maskshader_; }
// touch to request update
inline void touch () { need_update_ = true; }
@@ -99,6 +99,10 @@ public:
virtual void setActive (bool on);
inline bool active () { return active_; }
// lock mode
virtual void setLocked (bool on);
inline bool locked () { return locked_; }
// a Source shall informs if the source failed (i.e. shall be deleted)
virtual bool failed () const = 0;
@@ -111,6 +115,11 @@ public:
// accept all kind of visitors
virtual void accept (Visitor& v);
// operations on mask
void storeMask(FrameBufferImage *img = nullptr);
FrameBufferImage *getMask() const { return maskimage_; }
void setMask(FrameBufferImage *img);
struct hasNode: public std::unary_function<Source*, bool>
{
bool operator()(const Source* elem) const;
@@ -162,6 +171,7 @@ protected:
// the rendersurface draws the renderbuffer in the scene
// It is associated to the rendershader for mixing effects
FrameBufferSurface *rendersurface_;
FrameBufferSurface *mixingsurface_;
// image processing shaders
ImageProcessingShader *processingshader_;
@@ -171,6 +181,14 @@ protected:
// blendingshader provides mixing controls
ImageShader *blendingshader_;
ImageShader *mixingshader_;
// shader and buffer to draw mask
MaskShader *maskshader_;
FrameBuffer *maskbuffer_;
Surface *masksurface_;
bool mask_need_update_;
FrameBufferImage *maskimage_;
// surface to draw on
Surface *texturesurface_;
@@ -181,11 +199,12 @@ protected:
// overlays and frames to be displayed on top of source
std::map<View::Mode, Group*> overlays_;
std::map<View::Mode, Switch*> frames_;
std::map<View::Mode, Handles*[6]> handles_;
Symbol *symbol_;
std::map<View::Mode, Handles*[7]> handles_;
Symbol *symbol_, *locker_;
// update
bool active_;
bool locked_;
bool need_update_;
float dt_;
Group *stored_status_;

View File

@@ -80,13 +80,15 @@ void StreamSource::init()
// set the renderbuffer of the source and attach rendering nodes
attach(renderbuffer);
// done init
initialized_ = true;
Log::Info("Source '%s' linked to Stream %s", name().c_str(), std::to_string(stream_->id()).c_str());
// deep update to reorder
View::need_deep_update_++;
// force update of activation mode
active_ = true;
touch();
// done init
initialized_ = true;
Log::Info("Source '%s' linked to Stream %s", name().c_str(), std::to_string(stream_->id()).c_str());
}
}

View File

@@ -7,6 +7,10 @@
#include <ctime>
#include <chrono>
#include <locale>
#include <unicode/ustream.h>
#include <unicode/translit.h>
using namespace std;
#ifdef WIN32
@@ -355,4 +359,23 @@ void SystemToolkit::execute(const string& command)
// "gst-launch-1.0 udpsrc port=5000 ! application/x-rtp,encoding-name=JPEG,payload=26 ! rtpjpegdepay ! jpegdec ! autovideosink").detach();;
// Using ICU transliteration :
// https://unicode-org.github.io/icu/userguide/transforms/general/#icu-transliterators
std::string SystemToolkit::transliterate(std::string input)
{
auto ucs = icu::UnicodeString::fromUTF8(input);
UErrorCode status = U_ZERO_ERROR;
icu::Transliterator *firstTrans = icu::Transliterator::createInstance(
"any-NFKD ; [:Nonspacing Mark:] Remove; NFKC; Latin", UTRANS_FORWARD, status);
firstTrans->transliterate(ucs);
icu::Transliterator *secondTrans = icu::Transliterator::createInstance(
"any-NFKD ; [:Nonspacing Mark:] Remove; [@!#$*%~] Remove; NFKC", UTRANS_FORWARD, status);
secondTrans->transliterate(ucs);
std::ostringstream output;
output << ucs;
return output.str();
}

View File

@@ -65,6 +65,7 @@ namespace SystemToolkit
// try to open the file with system
void open(const std::string& path);
// try to execute a command
void execute(const std::string& command);
@@ -74,6 +75,9 @@ namespace SystemToolkit
// get a string to display memory size with unit KB, MB, GB, TB
std::string byte_to_string(long b);
// get a transliteration to Latin of any string
std::string transliterate(std::string input);
}
#endif // SYSTEMTOOLKIT_H

View File

@@ -15,7 +15,7 @@ using namespace std;
#include "imgui_impl_opengl3.h"
// Desktop OpenGL function loader
#include <glad/glad.h>
#include <glad/glad.h>
// Include glfw3.h after our OpenGL definitions
#include <GLFW/glfw3.h>
@@ -158,7 +158,7 @@ UserInterface::UserInterface()
ctrl_modifier_active = false;
alt_modifier_active = false;
shift_modifier_active = false;
show_vimix_config = false;
show_vimix_about = false;
show_imgui_about = false;
show_gst_about = false;
show_opengl_about = false;
@@ -178,9 +178,7 @@ bool UserInterface::Init()
// Setup Dear ImGui context
IMGUI_CHECKVERSION();
ImGui::CreateContext();
ImGuiIO& io = ImGui::GetIO(); (void)io;
io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard;
io.MouseDrawCursor = true;
ImGuiIO& io = ImGui::GetIO();
io.FontGlobalScale = Settings::application.scale;
// Setup Platform/Renderer bindings
@@ -256,7 +254,7 @@ void UserInterface::handleKeyboard()
}
else if (ImGui::IsKeyPressed( GLFW_KEY_O )) {
// SHIFT + CTRL + O : reopen current session
if (ctrl_modifier_active && !Mixer::manager().session()->filename().empty())
if (shift_modifier_active && !Mixer::manager().session()->filename().empty())
Mixer::manager().load( Mixer::manager().session()->filename() );
// CTRL + O : Open session
else
@@ -384,8 +382,21 @@ void UserInterface::handleKeyboard()
else if (ImGui::IsKeyPressed( GLFW_KEY_INSERT ))
navigator.togglePannelNew();
// button tab to select next
else if (ImGui::IsKeyPressed( GLFW_KEY_TAB ))
Mixer::manager().setCurrentNext();
else if (ImGui::IsKeyPressed( GLFW_KEY_TAB )) {
if (shift_modifier_active)
Mixer::manager().setCurrentPrevious();
else
Mixer::manager().setCurrentNext();
}
// arrow keys to act on current view
else if (ImGui::IsKeyPressed( GLFW_KEY_LEFT ))
Mixer::manager().view()->arrow( glm::vec2(-1.f, 0.f) );
else if (ImGui::IsKeyPressed( GLFW_KEY_RIGHT ))
Mixer::manager().view()->arrow( glm::vec2(+1.f, 0.f) );
else if (ImGui::IsKeyPressed( GLFW_KEY_UP ))
Mixer::manager().view()->arrow( glm::vec2(0.f, -1.f) );
else if (ImGui::IsKeyPressed( GLFW_KEY_DOWN ))
Mixer::manager().view()->arrow( glm::vec2(0.f, 1.f) );
}
}
@@ -405,6 +416,10 @@ void UserInterface::handleKeyboard()
void setMouseCursor(ImVec2 mousepos, View::Cursor c = View::Cursor())
{
// Hack if GLFW does not have all cursors, ask IMGUI to redraw cursor
#if GLFW_HAS_NEW_CURSORS == 0
ImGui::GetIO().MouseDrawCursor = (c.type > 0); // only redraw non-arrow cursor
#endif
ImGui::SetMouseCursor(c.type);
if ( !c.info.empty()) {
@@ -444,10 +459,18 @@ void UserInterface::handleMouse()
if (ImGui::IsMouseClicked(ImGuiMouseButton_Right) /*|| ImGui::IsMouseClicked(ImGuiMouseButton_Middle)*/)
ImGui::FocusWindow(NULL);
//
// Mouse over
//
{
View::Cursor c = Mixer::manager().view()->over(mousepos);
if (c.type > 0)
setMouseCursor(io.MousePos, c);
}
// if not on any window
if ( !ImGui::IsAnyWindowHovered() && !ImGui::IsAnyWindowFocused() )
{
//
// Mouse wheel over background
//
@@ -632,12 +655,13 @@ void UserInterface::handleMouse()
}
if ( ImGui::IsMouseReleased(ImGuiMouseButton_Left) )
if ( ImGui::IsMouseReleased(ImGuiMouseButton_Left) || ImGui::IsMouseReleased(ImGuiMouseButton_Right) )
{
view_drag = nullptr;
mousedown = false;
picked = { nullptr, glm::vec2(0.f) };
Mixer::manager().view()->terminate();
setMouseCursor(io.MousePos);
// special case of one single source in selection : make current after release
if (Mixer::selection().size() == 1)
@@ -761,8 +785,8 @@ void UserInterface::Render()
Log::ShowLogWindow(&Settings::application.widget.logs);
// about dialogs
if (show_vimix_config)
ShowConfig(&show_vimix_config);
if (show_vimix_about)
RenderAbout(&show_vimix_about);
if (show_imgui_about)
ImGui::ShowAboutWindow(&show_imgui_about);
if (show_gst_about)
@@ -807,10 +831,10 @@ void UserInterface::showMenuFile()
Mixer::manager().close();
navigator.hidePannel();
}
ImGui::SetNextItemWidth( ImGui::GetContentRegionAvail().x );
ImGui::Combo("##AR", &Settings::application.render.ratio, FrameBuffer::aspect_ratio_name, IM_ARRAYSIZE(FrameBuffer::aspect_ratio_name) );
ImGui::SetNextItemWidth( ImGui::GetContentRegionAvail().x );
ImGui::Combo("##HEIGHT", &Settings::application.render.res, FrameBuffer::resolution_name, IM_ARRAYSIZE(FrameBuffer::resolution_name) );
ImGui::SetNextItemWidth( ImGui::GetContentRegionAvail().x * 0.6f);
ImGui::Combo("Ratio", &Settings::application.render.ratio, FrameBuffer::aspect_ratio_name, IM_ARRAYSIZE(FrameBuffer::aspect_ratio_name) );
ImGui::SetNextItemWidth( ImGui::GetContentRegionAvail().x * 0.6f);
ImGui::Combo("Height", &Settings::application.render.res, FrameBuffer::resolution_name, IM_ARRAYSIZE(FrameBuffer::resolution_name) );
ImGui::Separator();
@@ -818,6 +842,8 @@ void UserInterface::showMenuFile()
if (ImGui::MenuItem( ICON_FA_FILE_UPLOAD " Open", CTRL_MOD "O"))
selectOpenFilename();
if (ImGui::MenuItem( ICON_FA_FILE_UPLOAD " Reload", CTRL_MOD "+Shift+O"))
Mixer::manager().load( Mixer::manager().session()->filename() );
if (ImGui::MenuItem( ICON_FA_FILE_EXPORT " Import")) {
// launch file dialog to open a session file
@@ -997,7 +1023,7 @@ void ToolBox::Render()
// About and other utility windows
if (show_icons_window)
ImGuiToolkit::ShowIconsWindow(&show_icons_window);
ImGuiToolkit::ShowIconsWindow(&show_icons_window);
if (show_sandbox)
ShowSandbox(&show_sandbox);
if (show_demo_window)
@@ -1011,7 +1037,7 @@ void UserInterface::RenderHistory()
ImVec2 MinWindowSize = ImVec2(250.f, history_height);
ImGui::SetNextWindowPos(ImVec2(1180, 400), ImGuiCond_FirstUseEver);
ImGui::SetNextWindowSize(ImVec2(250, 400), ImGuiCond_FirstUseEver);
ImGui::SetNextWindowSize(ImVec2(400, 400), ImGuiCond_FirstUseEver);
ImGui::SetNextWindowSizeConstraints(MinWindowSize, ImVec2(FLT_MAX, FLT_MAX));
if ( !ImGui::Begin(IMGUI_TITLE_HISTORY, &Settings::application.widget.history, ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_MenuBar | ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoCollapse ))
{
@@ -1027,7 +1053,7 @@ void UserInterface::RenderHistory()
{
if ( ImGui::MenuItem( ICON_FA_UNDO " Undo", CTRL_MOD "Z") )
Action::manager().undo();
if ( ImGui::MenuItem( ICON_FA_REDO " Redo", CTRL_MOD "+Shift Z") )
if ( ImGui::MenuItem( ICON_FA_REDO " Redo", CTRL_MOD "Shift+Z") )
Action::manager().redo();
ImGui::MenuItem( ICON_FA_DIRECTIONS " Follow view", nullptr, &Settings::application.action_history_follow_view);
@@ -1051,7 +1077,7 @@ void UserInterface::RenderHistory()
if (ImGui::ListBoxHeader("##History", ImGui::GetContentRegionAvail() ) )
{
for (int i = 1; i <= Action::manager().max(); i++) {
for (int i = Action::manager().max(); i > 0; i--) {
std::string step_label_ = Action::manager().label(i);
@@ -1115,13 +1141,30 @@ void UserInterface::RenderPreview()
{
if (ImGui::BeginMenu(IMGUI_TITLE_PREVIEW))
{
glm::ivec2 p = FrameBuffer::getParametersFromResolution(output->resolution());
std::ostringstream info;
info << "Resolution " << output->width() << "x" << output->height();
if (p.x > -1)
info << " " << FrameBuffer::aspect_ratio_name[p.x] ;
ImGui::MenuItem(info.str().c_str(), nullptr, false, false);
// cannot change resolution when recording
if (rec == nullptr && p.y > -1) {
ImGui::SetNextItemWidth(IMGUI_RIGHT_ALIGN);
if (ImGui::Combo("Height", &p.y, FrameBuffer::resolution_name, IM_ARRAYSIZE(FrameBuffer::resolution_name) ) )
{
glm::vec3 res = FrameBuffer::getResolutionFromParameters(p.x, p.y);
Mixer::manager().session()->setResolution(res);
}
}
ImGui::Separator();
if ( ImGui::MenuItem( ICON_FA_WINDOW_RESTORE " Show output window") )
Rendering::manager().outputWindow().show();
if ( ImGui::MenuItem( ICON_FA_SHARE_SQUARE " Create Source") )
Mixer::manager().addSource( Mixer::manager().createSourceRender() );
if ( ImGui::MenuItem( ICON_FA_TIMES " Close") )
if ( ImGui::MenuItem( ICON_FA_TIMES " Close", CTRL_MOD "D") )
Settings::application.widget.preview = false;
ImGui::EndMenu();
@@ -1153,7 +1196,7 @@ void UserInterface::RenderPreview()
}
ImGui::PopStyleColor(1);
// select profile
ImGui::SetNextItemWidth(300);
ImGui::SetNextItemWidth(IMGUI_RIGHT_ALIGN);
ImGui::Combo("Codec", &Settings::application.record.profile, VideoRecorder::profile_name, IM_ARRAYSIZE(VideoRecorder::profile_name) );
}
@@ -1403,7 +1446,7 @@ void MediaController::Render()
{
ImGui::MenuItem( ICON_FA_EYE " Preview", nullptr, &Settings::application.widget.media_player_view);
if ( ImGui::MenuItem( ICON_FA_TIMES " Close") )
if ( ImGui::MenuItem( ICON_FA_TIMES " Close", CTRL_MOD "P") )
Settings::application.widget.media_player = false;
ImGui::EndMenu();
@@ -1956,7 +1999,7 @@ void Navigator::Render()
view_pannel_visible = previous_view == Settings::application.current_view;
}
if (ImGui::IsItemHovered())
about = "Mixing [F1]";
about = "Mixing [ F1 ]";
if (ImGui::Selectable( ICON_FA_OBJECT_UNGROUP , &selected_view[2], 0, iconsize))
{
if (ImGui::IsItemHovered())
@@ -1964,21 +2007,21 @@ void Navigator::Render()
view_pannel_visible = previous_view == Settings::application.current_view;
}
if (ImGui::IsItemHovered())
about = "Geometry [F2]";
about = "Geometry [ F2 ]";
if (ImGui::Selectable( ICON_FA_LAYER_GROUP, &selected_view[3], 0, iconsize))
{
Mixer::manager().setView(View::LAYER);
view_pannel_visible = previous_view == Settings::application.current_view;
}
if (ImGui::IsItemHovered())
about = "Layers [F3]";
if (ImGui::Selectable( ICON_FA_SIGN, &selected_view[4], 0, iconsize))
about = "Layers [ F3 ]";
if (ImGui::Selectable( ICON_FA_CHESS_BOARD, &selected_view[4], 0, iconsize))
{
Mixer::manager().setView(View::APPEARANCE);
view_pannel_visible = previous_view == Settings::application.current_view;
}
if (ImGui::IsItemHovered())
about = "Source apppearance [F4]";
about = "Texturing [ F4 ]";
ImGui::End();
@@ -2099,8 +2142,8 @@ void Navigator::RenderSourcePannel(Source *s)
// Source pannel
static ImGuiVisitor v;
s->accept(v);
// ensure change is applied
s->touch();
// ensure change is applied // TODO : touch() in visitor ? [avoid here as it forces useless update]
// s->touch();
// delete button
ImGui::Text(" ");
// Action on source
@@ -2116,7 +2159,7 @@ void Navigator::RenderSourcePannel(Source *s)
// ImGui::EndPopup();
// }
}
ImGui::End();
ImGui::End();
}
@@ -2240,7 +2283,8 @@ void Navigator::RenderNewPannel()
fileImportFileDialogs.pop_back();
fileDialogPending_ = false;
// create a source with this file
std::string label = open_filename.substr( open_filename.size() - MIN( 35, open_filename.size()) );
std::string label = SystemToolkit::transliterate( open_filename );
label = label.substr( label.size() - MIN( 35, label.size()) );
new_source_preview_.setSource( Mixer::manager().createSourceFile(open_filename), label);
}
}
@@ -2254,7 +2298,8 @@ void Navigator::RenderNewPannel()
{
std::string recentpath(*path);
if ( SystemToolkit::file_exists(recentpath)) {
std::string label = SystemToolkit::trunc_filename(recentpath, 35);
std::string label = SystemToolkit::transliterate( recentpath );
label = SystemToolkit::trunc_filename(label, 35);
if (ImGui::Selectable( label.c_str() )) {
new_source_preview_.setSource( Mixer::manager().createSourceFile(recentpath.c_str()), label);
}
@@ -2657,49 +2702,55 @@ void Navigator::RenderMainPannel()
ImGuiToolkit::ButtonSwitch( ICON_FA_HISTORY " History", &Settings::application.widget.history);
ImGuiToolkit::ButtonSwitch( ICON_FA_TACHOMETER_ALT " Metrics", &Settings::application.widget.stats);
// Settings application appearance
// Settings & application appearance
static bool show_config = false;
ImGui::Spacing();
ImGui::Text("Appearance");
ImGui::SetNextItemWidth(IMGUI_RIGHT_ALIGN);
if ( ImGui::DragFloat("Scale", &Settings::application.scale, 0.01, 0.5f, 2.0f, "%.1f"))
ImGui::GetIO().FontGlobalScale = Settings::application.scale;
// ImGui::SetNextItemWidth(IMGUI_RIGHT_ALIGN);
// if ( ImGui::Combo("Accent", &Settings::application.accent_color, "Blue\0Orange\0Grey\0\0"))
// ImGuiToolkit::SetAccentColor(static_cast<ImGuiToolkit::accent_color>(Settings::application.accent_color));
bool b = ImGui::RadioButton("Blue", &Settings::application.accent_color, 0); ImGui::SameLine();
bool o = ImGui::RadioButton("Orange", &Settings::application.accent_color, 1); ImGui::SameLine();
bool g = ImGui::RadioButton("Grey", &Settings::application.accent_color, 2);
if (b || o || g)
ImGuiToolkit::SetAccentColor(static_cast<ImGuiToolkit::accent_color>(Settings::application.accent_color));
static unsigned int vimixicon = Resource::getTextureImage("images/vimix_256x256.png");
static float height_about = 3.f * ImGui::GetTextLineHeightWithSpacing();
bool show_icon = ImGui::GetCursorPosY() + height_about + 128.f < height_ ;
bool show_about = ImGui::GetCursorPosY() + height_about < height_ ;
// Bottom aligned About buttons
if ( show_about) {
// Bottom aligned Logo
if ( show_icon ) {
ImGui::SetCursorPos(ImVec2(pannel_width_ / 2.f - 64.f, height_ -height_about - 128.f));
ImGui::Image((void*)(intptr_t)vimixicon, ImVec2(128, 128));
}
else {
ImGui::SetCursorPosY(height_ -height_about);
}
if (show_config)
{
ImGui::Text("System");
bool vsync = (Settings::application.render.vsync > 0);
ImGuiToolkit::ButtonSwitch( "Vertical synchronization", &vsync);
Settings::application.render.vsync = vsync ? 1 : 0;
ImGuiToolkit::ButtonSwitch( "Blit framebuffer", &Settings::application.render.blit);
bool multi = (Settings::application.render.multisampling > 0);
ImGuiToolkit::ButtonSwitch( "Antialiasing framebuffer", &multi);
Settings::application.render.multisampling = multi ? 3 : 0;
ImGuiToolkit::ButtonSwitch( "Hardware video decoding", &Settings::application.render.gpu_decoding);
ImGui::Spacing();
if ( ImGui::Button( ICON_FA_CROW " vimix", ImVec2(ImGui::GetContentRegionAvail().x, 0)) )
UserInterface::manager().show_vimix_config = true;
if ( ImGui::Button(" ImGui "))
UserInterface::manager().show_imgui_about = true;
ImGui::SameLine();
if ( ImGui::Button(" GStreamer "))
UserInterface::manager().show_gst_about = true;
ImGui::SameLine();
if ( ImGui::Button("OpenGL", ImVec2(ImGui::GetContentRegionAvail().x, 0)))
UserInterface::manager().show_opengl_about = true;
if (ImGui::Button( ICON_FA_POWER_OFF " Restart to apply", ImVec2(ImGui::GetContentRegionAvail().x - 50, 0)))
Rendering::manager().close();
}
else {
ImGui::Text("Appearance");
ImGui::SetNextItemWidth(IMGUI_RIGHT_ALIGN);
if ( ImGui::DragFloat("Scale", &Settings::application.scale, 0.01, 0.5f, 2.0f, "%.1f"))
ImGui::GetIO().FontGlobalScale = Settings::application.scale;
bool b = ImGui::RadioButton("Blue", &Settings::application.accent_color, 0); ImGui::SameLine();
bool o = ImGui::RadioButton("Orange", &Settings::application.accent_color, 1); ImGui::SameLine();
bool g = ImGui::RadioButton("Grey", &Settings::application.accent_color, 2);
if (b || o || g)
ImGuiToolkit::SetAccentColor(static_cast<ImGuiToolkit::accent_color>(Settings::application.accent_color));
}
// Bottom aligned Logo (if enougth room)
static unsigned int vimixicon = Resource::getTextureImage("images/vimix_256x256.png");
static float height_about = 1.6f * ImGui::GetTextLineHeightWithSpacing();
bool show_icon = ImGui::GetCursorPosY() + height_about + 128.f < height_ ;
if ( show_icon ) {
ImGui::SetCursorPos(ImVec2(pannel_width_ / 2.f - 64.f, height_ -height_about - 128.f));
ImGui::Image((void*)(intptr_t)vimixicon, ImVec2(128, 128));
}
else {
ImGui::SetCursorPosY(height_ -height_about);
}
// About & System config toggle
if ( ImGui::Button( ICON_FA_CROW " About vimix", ImVec2(ImGui::GetContentRegionAvail().x - 50, 0)) )
UserInterface::manager().show_vimix_about = true;
ImGui::SameLine();
ImGuiToolkit::IconToggle(13,5,12,5,&show_config);
}
ImGui::End();
@@ -2755,134 +2806,100 @@ void ShowSandbox(bool* p_open)
ImGui::Text("Testing sandox");
const guint64 duration = GST_SECOND * 6;
const guint64 step = GST_MSECOND * 20;
static guint64 t = 0;
// const guint64 duration = GST_SECOND * 6;
// const guint64 step = GST_MSECOND * 20;
// static guint64 t = 0;
// bool slider_pressed = ImGuiToolkit::TimelineSlider("timeline", &t, duration, step);
// static float *arr_lines = nullptr;
// static float *arr_histo = nullptr;
// static uint array_size = 200;
static float *arr_lines = nullptr;
static float *arr_histo = nullptr;
// static float arr[] = { 0.6f, 0.1f, 1.0f, 0.5f, 0.92f, 0.1f, 0.2f, 0.f, 1.f, 0.4f,
// 0.6f, 0.1f, 1.0f, 0.5f, 0.92f, 0.1f, 0.2f, 0.f, 1.f, 0.4f,
// 0.6f, 0.1f, 1.0f, 0.5f, 0.92f, 0.1f, 0.2f, 0.f, 1.f, 0.4f,
// 0.6f, 0.1f, 1.0f, 0.5f, 0.92f, 0.1f, 0.2f, 0.f, 1.f, 0.4f,
// 0.6f, 0.1f, 1.0f, 0.5f, 0.92f, 0.1f, 0.2f, 0.f, 1.f, 0.4f,
// 0.6f, 0.1f, 1.0f, 0.5f, 0.92f, 0.1f, 0.2f, 0.f, 1.f, 0.4f,
// 0.6f, 0.1f, 1.0f, 0.5f, 0.92f, 0.1f, 0.2f, 0.f, 1.f, 0.4f,
// 0.6f, 0.1f, 1.0f, 0.5f, 0.92f, 0.1f, 0.2f, 0.f, 1.f, 0.4f,
// 0.6f, 0.1f, 1.0f, 0.5f, 0.92f, 0.1f, 0.2f, 0.f, 1.f, 0.4f,
// 0.6f, 0.1f, 1.0f, 0.5f, 0.92f, 0.1f, 0.2f, 0.f, 1.f, 0.4f,
// 0.6f, 0.1f, 1.0f, 0.5f, 0.92f, 0.1f, 0.2f, 0.f, 1.f, 0.4f,
// 0.6f, 0.1f, 1.0f, 0.5f, 0.92f, 0.1f, 0.2f, 0.f, 1.f, 0.4f,
// 0.6f, 0.1f, 1.0f, 0.5f, 0.92f, 0.1f, 0.2f, 0.f, 1.f, 0.4f,
// 0.6f, 0.1f, 1.0f, 0.5f, 0.92f, 0.1f, 0.2f, 0.f, 1.f, 0.4f,
// 0.6f, 0.1f, 1.0f, 0.5f, 0.92f, 0.1f, 0.2f, 0.f, 1.f, 0.4f,
// 0.6f, 0.1f, 1.0f, 0.5f, 0.92f, 0.1f, 0.2f, 0.f, 1.f, 0.4f,
// 0.6f, 0.1f, 1.0f, 0.5f, 0.92f, 0.1f, 0.2f, 0.f, 1.f, 0.4f,
// 0.6f, 0.1f, 1.0f, 0.5f, 0.92f, 0.1f, 0.2f, 0.f, 1.f, 0.4f,
// 0.6f, 0.1f, 1.0f, 0.5f, 0.92f, 0.1f, 0.2f, 0.f, 1.f, 0.4f,
// 0.6f, 0.1f, 1.0f, 0.5f, 0.92f, 0.1f, 0.2f, 0.f, 1.f, 0.4f,
// 0.6f, 0.1f, 1.0f, 0.5f, 0.92f, 0.1f, 0.2f, 0.f, 1.f, 0.4f,
// 0.6f, 0.1f, 1.0f, 0.5f, 0.92f, 0.1f, 0.2f, 0.f, 1.f, 0.4f,
// 0.6f, 0.1f, 1.0f, 0.5f, 0.92f, 0.1f, 0.2f, 0.f, 1.f, 0.4f };
// if (arr_lines == nullptr) {
static uint array_size = 200;
// arr_lines = (float *) malloc(array_size * sizeof(float));
// arr_histo = (float *) malloc(array_size * sizeof(float));
// MediaPlayer *mp_ = nullptr;
// auto po = MediaPlayer::begin();
// if (po != MediaPlayer::end())
// mp_ = *po;
// if (mp_) {
// }
//// duration = mp_->duration();
//// step = mp_->frameDuration();
//// t = mp_->position();
// for (int i = 0; i < array_size; ++i) {
// arr_lines[i] = 1.f;
// arr_histo[i] = 0.f;
// }
// }
//// arr = mp_->timelineArray();
//// array_size = mp_->timelineArraySize();
if (arr_lines == nullptr) {
arr_lines = (float *) malloc(array_size * sizeof(float));
arr_histo = (float *) malloc(array_size * sizeof(float));
for (int i = 0; i < array_size; ++i) {
arr_lines[i] = 1.f;
arr_histo[i] = 0.f;
}
}
// scrolling sub-window
ImGui::BeginChild("##scrolling",
ImVec2(ImGui::GetContentRegionAvail().x, 250),
false, ImGuiWindowFlags_HorizontalScrollbar);
// // scrolling sub-window
// ImGui::BeginChild("##scrolling",
// ImVec2(ImGui::GetContentRegionAvail().x, 250),
// false, ImGuiWindowFlags_HorizontalScrollbar);
if (arr_lines != nullptr)
{
// if (arr_lines != nullptr)
// {
ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(1, 1));
ImGui::PushStyleVar(ImGuiStyleVar_FrameRounding, 1.f);
// ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(1, 1));
// ImGui::PushStyleVar(ImGuiStyleVar_FrameRounding, 1.f);
ImVec2 size = ImGui::CalcItemSize(ImVec2(-FLT_MIN, 0.0f), ImGui::CalcItemWidth(), 40);
size.x *= 1.f;
// ImVec2 size = ImGui::CalcItemSize(ImVec2(-FLT_MIN, 0.0f), ImGui::CalcItemWidth(), 40);
// size.x *= 1.f;
// // draw position when entering
// ImVec2 draw_pos = ImGui::GetCursorPos();
//// // draw position when entering
//// ImVec2 draw_pos = ImGui::GetCursorPos();
//// // capture user input
//// uint press_index = array_size-1;
//// float val = 0.f;
//// bool pressed = false;
////// // capture user input
////// uint press_index = array_size-1;
////// float val = 0.f;
////// bool pressed = false;
//// uint starting_index = press_index;
//// pressed = ImGuiToolkit::InvisibleDoubleSliderFloat("test", &press_index, &val, 0, array_size-1, size);
//// if (pressed)
//// {
//// for (int i = MIN(starting_index, press_index); i < MAX(starting_index, press_index); ++i)
//// arr[i] = val;
////// uint starting_index = press_index;
////// pressed = ImGuiToolkit::InvisibleDoubleSliderFloat("test", &press_index, &val, 0, array_size-1, size);
////// if (pressed)
////// {
////// for (int i = MIN(starting_index, press_index); i < MAX(starting_index, press_index); ++i)
////// arr[i] = val;
////// starting_index = press_index;
//////// starting_index = press_index;
////// }
//// float x = -1.f;
//// float y = -1.f;
//// bool clicked = ImGuiToolkit::InvisibleCoordinatesFloat("test", &x, &y, size);
//// if (clicked) {
//// Log::Info("clic %f %f in [%f %f]", x, y, size.x, size.y);
//// }
// float x = -1.f;
// float y = -1.f;
// bool clicked = ImGuiToolkit::InvisibleCoordinatesFloat("test", &x, &y, size);
// if (clicked) {
// Log::Info("clic %f %f in [%f %f]", x, y, size.x, size.y);
// }
//// // back to
//// ImGui::SetCursorPos(draw_pos);
//// // plot lines
//// ImGui::PlotLines("Lines", arr, array_size-1, 0, NULL, 0.0f, 1.0f, size);
// // back to
// ImGui::SetCursorPos(draw_pos);
// // plot lines
// ImGui::PlotLines("Lines", arr, array_size-1, 0, NULL, 0.0f, 1.0f, size);
////// size.y = 20;
////// ImGui::PlotHistogram("Hisfd", arr, array_size-1, 0, NULL, 0.0f, 1.0f, size);
// bool r = false;
// ImGuiToolkit::EditPlotHistoLines("Alpha", arr_histo, arr_lines, array_size, 0.f, 1.f, &r, size);
//// size.y = 20;
//// ImGui::PlotHistogram("Hisfd", arr, array_size-1, 0, NULL, 0.0f, 1.0f, size);
bool r = false;
ImGuiToolkit::EditPlotHistoLines("Alpha", arr_histo, arr_lines, array_size, 0.f, 1.f, &r, size);
// bool slider_pressed = ImGuiToolkit::TimelineSlider("timeline", &t, 0, duration, step, size.x);
bool slider_pressed = ImGuiToolkit::TimelineSlider("timeline", &t, 0, duration, step, size.x);
// ImGui::PopStyleVar(2);
ImGui::PopStyleVar(2);
// ImGui::Text("Timeline t %" GST_STIME_FORMAT "\n", GST_STIME_ARGS(t));
// ImGui::Text("Timeline Pressed %s", slider_pressed ? "on" : "off");
ImGui::Text("Timeline t %" GST_STIME_FORMAT "\n", GST_STIME_ARGS(t));
ImGui::Text("Timeline Pressed %s", slider_pressed ? "on" : "off");
// static int w = 0;
// ImGui::SetNextItemWidth(size.x);
// ImGui::SliderInt("##int", &w, 0, array_size-1);
static int w = 0;
ImGui::SetNextItemWidth(size.x);
ImGui::SliderInt("##int", &w, 0, array_size-1);
// }
}
// ImGui::EndChild();
ImGui::EndChild();
static char str0[128] = "àöäüèáû вторая строчка";
ImGui::InputText("input text", str0, IM_ARRAYSIZE(str0));
std::string tra = SystemToolkit::transliterate(std::string(str0));
ImGui::Text("Transliteration: '%s'", tra.c_str());
ImGui::End();
}
void ShowConfig(bool* p_open)
void UserInterface::RenderAbout(bool* p_open)
{
ImGui::SetNextWindowPos(ImVec2(1000, 20), ImGuiCond_FirstUseEver);
if (!ImGui::Begin("About " APP_NAME APP_TITLE, p_open, ImGuiWindowFlags_NoCollapse | ImGuiWindowFlags_AlwaysAutoResize))
@@ -2897,27 +2914,41 @@ void ShowConfig(bool* p_open)
ImGui::Separator();
ImGui::Text("vimix performs graphical mixing and blending of\nseveral movie clips and computer generated graphics,\nwith image processing effects in real-time.");
ImGui::Text("\nvimix is licensed under the GNU GPL version 3.\nCopyright 2019-2020 Bruno Herbelin.");
ImGuiToolkit::ButtonOpenUrl("https://brunoherbelin.github.io/vimix/");
ImGui::SameLine();
static bool show_config = false;
ImGui::SetNextItemWidth(-100.f);
ImGui::Text(" Details");
ImGui::SameLine();
ImGui::Spacing();
ImGuiToolkit::ButtonOpenUrl("https://brunoherbelin.github.io/vimix/", ImVec2(ImGui::GetContentRegionAvail().x, 0));
ImGui::Spacing();
ImGui::Text("\nvimix is built using the following libraries:");
ImGui::Columns(3, "abouts");
ImGui::Separator();
ImGui::Text("Dear ImGui");
ImGui::PushID("dearimguiabout");
if ( ImGui::Button("More info", ImVec2(ImGui::GetContentRegionAvail().x, 0)))
show_imgui_about = true;
ImGui::PopID();
ImGui::NextColumn();
ImGui::Text("GStreamer");
ImGui::PushID("gstreamerabout");
if ( ImGui::Button("More info", ImVec2(ImGui::GetContentRegionAvail().x, 0)))
show_gst_about = true;
ImGui::PopID();
ImGui::NextColumn();
ImGui::Text("OpenGL");
ImGui::PushID("openglabout");
if ( ImGui::Button("More info", ImVec2(ImGui::GetContentRegionAvail().x, 0)))
show_opengl_about = true;
ImGui::PopID();
ImGui::Columns(1);
ImGuiToolkit::IconToggle(10,0,11,0,&show_config);
if (show_config)
{
ImGui::Text("\nOpenGL options (enable all for optimal performance).");
ImGui::Checkbox("Blit framebuffer (fast draw to output)", &Settings::application.render.blit);
bool multi = (Settings::application.render.multisampling > 0);
ImGui::Checkbox("Antialiasing framebuffer (fast multisampling)", &multi);
Settings::application.render.multisampling = multi ? 3 : 0;
bool vsync = (Settings::application.render.vsync < 2);
ImGui::Checkbox("Sync refresh with monitor (v-sync 60Hz)", &vsync);
Settings::application.render.vsync = vsync ? 1 : 2;
ImGui::Text( ICON_FA_EXCLAMATION " Restart the application for change to take effect.");
}
ImGui::End();
}

View File

@@ -109,7 +109,7 @@ class UserInterface
bool ctrl_modifier_active;
bool alt_modifier_active;
bool shift_modifier_active;
bool show_vimix_config;
bool show_vimix_about;
bool show_imgui_about;
bool show_gst_about;
bool show_opengl_about;
@@ -168,6 +168,7 @@ protected:
void handleKeyboard();
void handleMouse();
void handleScreenshot();
void RenderAbout(bool* p_open);
};
#endif /* #define __UI_MANAGER_H_ */

1212
View.cpp

File diff suppressed because it is too large Load Diff

72
View.h
View File

@@ -29,9 +29,9 @@ public:
virtual void update (float dt);
virtual void draw ();
virtual void zoom (float) {}
virtual void zoom (float);
virtual void resize (int) {}
virtual int size () { return 0; }
virtual int size () { return 50; }
virtual void recenter();
virtual void centerSource(Source *) {}
@@ -71,16 +71,19 @@ public:
return Cursor();
}
// // test mouse over provided a point in screen coordinates and the picking point
// virtual Cursor over (Source*, glm::vec2, std::pair<Node *, glm::vec2>) {
// return Cursor();
// }
// test mouse over provided a point in screen coordinates
virtual Cursor over (glm::vec2) {
return Cursor();
}
// left-right [-1 1] and up-down [1 -1] action from arrow keys
virtual void arrow (glm::vec2) {}
// accessible scene
Scene scene;
// reordering scene when necessary
static bool need_deep_update_;
static uint need_deep_update_;
protected:
@@ -100,15 +103,15 @@ public:
void draw () override;
void update (float dt) override;
void zoom (float factor) override;
void resize (int) override;
int size () override;
void centerSource(Source *) override;
void select(glm::vec2, glm::vec2) override;
void selectAll() override;
std::pair<Node *, glm::vec2> pick(glm::vec2) override;
Cursor grab (Source *s, glm::vec2 from, glm::vec2 to, std::pair<Node *, glm::vec2>) override;
Cursor drag (glm::vec2, glm::vec2) override;
void arrow (glm::vec2) override;
void setAlpha (Source *s);
inline float limboScale() { return limbo_scale_; }
@@ -153,17 +156,16 @@ public:
void draw () override;
void update (float dt) override;
void zoom (float factor) override;
void resize (int) override;
int size () override;
std::pair<Node *, glm::vec2> pick(glm::vec2 P) override;
Cursor grab (Source *s, glm::vec2 from, glm::vec2 to, std::pair<Node *, glm::vec2> pick) override;
// Cursor over (Source *s, glm::vec2 pos, std::pair<Node *, glm::vec2> pick) override;
Cursor drag (glm::vec2, glm::vec2) override;
void terminate() override;
void arrow (glm::vec2) override;
private:
Surface *output_surface_;
Node *overlay_position_;
Node *overlay_position_cross_;
Node *overlay_rotation_;
@@ -173,6 +175,7 @@ private:
Node *overlay_scaling_;
Node *overlay_scaling_cross_;
Node *overlay_scaling_grid_;
Node *overlay_crop_;
bool show_context_menu_;
};
@@ -182,17 +185,19 @@ public:
LayerView();
void update (float dt) override;
void zoom (float factor) override;
void resize (int) override;
int size () override;
Cursor grab (Source *s, glm::vec2 from, glm::vec2 to, std::pair<Node *, glm::vec2> pick) override;
Cursor drag (glm::vec2, glm::vec2) override;
void arrow (glm::vec2) override;
float setDepth (Source *, float d = -1.f);
private:
float aspect_ratio;
Mesh *persp_layer_;
Mesh *persp_left_, *persp_right_;
Group *frame_;
};
class TransitionView : public View
@@ -207,6 +212,7 @@ public:
std::pair<Node *, glm::vec2> pick(glm::vec2 P) override;
Cursor grab (Source *s, glm::vec2 from, glm::vec2 to, std::pair<Node *, glm::vec2> pick) override;
void arrow (glm::vec2) override;
Cursor drag (glm::vec2, glm::vec2) override;
void attach(SessionSource *ts);
@@ -232,13 +238,15 @@ public:
void draw () override;
void update (float dt) override;
void zoom (float factor) override;
void resize (int) override;
int size () override;
std::pair<Node *, glm::vec2> pick(glm::vec2 P) override;
Cursor grab (Source *s, glm::vec2 from, glm::vec2 to, std::pair<Node *, glm::vec2> pick) override;
Cursor drag (glm::vec2, glm::vec2) override;
Cursor over (glm::vec2) override;
void arrow (glm::vec2) override;
void initiate() override;
void terminate() override;
private:
@@ -248,17 +256,21 @@ private:
Source *getEditOrCurrentSource();
void adjustBackground();
Surface *surfacepreview;
Surface *backgroundchecker_;
Frame *backgroundframe_;
Mesh *horizontal_line_;
Surface *preview_surface_;
class ImageShader *preview_shader_;
Surface *preview_checker_;
Frame *preview_frame_;
Surface *background_surface_;
Frame *background_frame_;
Mesh *horizontal_mark_;
bool show_horizontal_scale_;
Group *vertical_line_;
Mesh *vertical_mark_;
bool show_vertical_scale_;
Symbol *crop_horizontal_;
Symbol *crop_vertical_;
bool show_scale_;
Group *mask_node_;
Frame *mask_square_;
Mesh *mask_circle_;
Mesh *mask_horizontal_;
Group *mask_vertical_;
Symbol *overlay_position_;
Symbol *overlay_position_cross_;
Symbol *overlay_scaling_;
@@ -269,6 +281,16 @@ private:
Node *overlay_rotation_clock_;
Symbol *overlay_rotation_clock_hand_;
bool show_context_menu_;
// for mask shader draw: 0=cursor, 1=brush, 2=eraser, 3=crop_shape
int mask_cursor_paint_;
int mask_cursor_shape_;
Mesh *mask_cursor_circle_;
Mesh *mask_cursor_square_;
Mesh *mask_cursor_crop_;
glm::vec3 stored_mask_size_;
bool show_cursor_forced_;
};

View File

@@ -25,6 +25,7 @@ class Stream;
class MediaPlayer;
class Shader;
class ImageShader;
class MaskShader;
class ImageProcessingShader;
class Source;
class MediaSource;
@@ -64,6 +65,7 @@ public:
virtual void visit (MediaPlayer&) {}
virtual void visit (Shader&) {}
virtual void visit (ImageShader&) {}
virtual void visit (MaskShader&) {}
virtual void visit (ImageProcessingShader&) {}
// utility

View File

@@ -5,9 +5,9 @@
#define APP_TITLE " -- Video Live Mixer"
#define APP_SETTINGS "vimix.xml"
#define APP_VERSION_MAJOR 0
#define APP_VERSION_MINOR 4
#define APP_VERSION_MINOR 5
#define XML_VERSION_MAJOR 0
#define XML_VERSION_MINOR 1
#define XML_VERSION_MINOR 2
#define MAX_RECENT_HISTORY 20
#define MINI(a, b) (((a) < (b)) ? (a) : (b))
@@ -24,27 +24,40 @@
#define ROUND(val, factor) float( int( val * factor ) ) / factor;
#define SCENE_UNIT 5.f
#define SCENE_DEPTH 12.f
#define CIRCLE_SQUARE_DIST(x,y) ( (x*x + y*y) / (SCENE_UNIT * SCENE_UNIT * SCENE_UNIT * SCENE_UNIT) )
#define MIN_SCALE 0.01f
#define MAX_SCALE 10.f
#define CLAMP_SCALE(x) SIGN(x) * CLAMP( ABS(x), MIN_SCALE, MAX_SCALE)
#define SCENE_DEPTH 14.f
#define MIN_DEPTH 0.f
#define MAX_DEPTH 12.f
#define BACKGROUND_DEPTH 2.f
#define FOREGROUND_DEPTH 10.f
#define MIXING_DEFAULT_SCALE 2.4f
#define MIXING_MIN_SCALE 0.8f
#define MIXING_MAX_SCALE 7.0f
#define MIXING_LIMBO_SCALE 1.3f
#define MIXING_ICON_SCALE 0.15f, 0.15f, 1.f
#define GEOMETRY_DEFAULT_SCALE 1.2f
#define GEOMETRY_DEFAULT_SCALE 1.4f
#define GEOMETRY_MIN_SCALE 0.4f
#define GEOMETRY_MAX_SCALE 10.0f
#define LAYER_DEFAULT_SCALE 0.8f
#define GEOMETRY_MAX_SCALE 7.0f
#define LAYER_DEFAULT_SCALE 0.6f
#define LAYER_MIN_SCALE 0.4f
#define LAYER_MAX_SCALE 1.7f
#define LAYER_PERSPECTIVE 2.0f
#define APPEARANCE_DEFAULT_SCALE 2.f
#define APPEARANCE_MIN_SCALE 0.4f
#define APPEARANCE_MAX_SCALE 10.0f
#define APPEARANCE_MAX_SCALE 7.0f
#define BRUSH_MIN_SIZE 0.05f
#define BRUSH_MAX_SIZE 2.f
#define BRUSH_MIN_PRESS 0.005f
#define BRUSH_MAX_PRESS 1.f
#define SHAPE_MIN_BLUR 0.f
#define SHAPE_MAX_BLUR 1.f
#define TRANSITION_DEFAULT_SCALE 5.0f
#define TRANSITION_MIN_DURATION 0.2f
#define TRANSITION_MAX_DURATION 10.f
#define ARROWS_MOVEMENT_FACTOR 5.f
#define IMGUI_TITLE_MAINWINDOW ICON_FA_CIRCLE_NOTCH " vimix"
#define IMGUI_TITLE_MEDIAPLAYER ICON_FA_FILM " Player"
@@ -72,7 +85,10 @@
#define COLOR_TRANSITION_SOURCE 1.f, 0.5f, 1.f
#define COLOR_TRANSITION_LINES 0.9f, 0.9f, 0.9f
#define COLOR_APPEARANCE_SOURCE 0.9f, 0.9f, 0.1f
#define COLOR_APPEARANCE_MASK 0.1f, 0.9f, 0.9f
#define COLOR_APPEARANCE_MASK_DISABLE 0.3f, 0.6f, 0.6f
#define COLOR_FRAME 0.8f, 0.f, 0.8f
#define COLOR_FRAME_LIGHT 0.95f, 0.3f, 0.95f
#define COLOR_LIMBO_CIRCLE 0.16f, 0.16f, 0.16f
#define COLOR_SLIDER_CIRCLE 0.11f, 0.11f, 0.11f
#define COLOR_STASH_CIRCLE 0.06f, 0.06f, 0.06f

Binary file not shown.

After

Width:  |  Height:  |  Size: 592 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 772 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 210 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 846 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 404 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 582 KiB

Binary file not shown.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 31 KiB

After

Width:  |  Height:  |  Size: 31 KiB

View File

@@ -1,6 +1,4 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:osb="http://www.openswatchbook.org/uri/2009/osb"
xmlns:dc="http://purl.org/dc/elements/1.1/"
@@ -15,11 +13,11 @@
height="64"
id="svg3744"
sodipodi:version="0.32"
inkscape:version="0.92.4 (5da689c313, 2019-01-14)"
inkscape:version="1.0.1 (3bc2e813f5, 2020-09-07)"
version="1.0"
sodipodi:docname="v-mix.svg"
sodipodi:docname="vimix.svg"
inkscape:output_extension="org.inkscape.output.svg.inkscape"
inkscape:export-filename="/home/bhbn/Developments/v-mix/rsc/images/v-mix_256x256.png"
inkscape:export-filename="/home/bhbn/Developments/v-mix/rsc/images/vimix_256x256.png"
inkscape:export-xdpi="405.16815"
inkscape:export-ydpi="405.16815">
<sodipodi:namedview
@@ -29,9 +27,9 @@
borderopacity="1.0"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:zoom="24.671299"
inkscape:cx="36.638352"
inkscape:cy="31.887987"
inkscape:zoom="32"
inkscape:cx="34.523709"
inkscape:cy="21.609175"
inkscape:current-layer="layer1"
showgrid="false"
inkscape:document-units="px"
@@ -41,16 +39,17 @@
showborder="true"
objecttolerance="1"
guidetolerance="10000"
inkscape:window-width="2618"
inkscape:window-width="2890"
inkscape:window-height="1885"
inkscape:window-x="920"
inkscape:window-y="160"
inkscape:window-x="982"
inkscape:window-y="112"
inkscape:window-maximized="0"
fit-margin-top="0"
fit-margin-left="0"
fit-margin-right="0"
fit-margin-bottom="0"
inkscape:showpageshadow="false">
inkscape:showpageshadow="false"
inkscape:document-rotation="0">
<inkscape:grid
type="xygrid"
id="grid3754"
@@ -169,7 +168,7 @@
xlink:href="#linearGradient3237-580"
id="radialGradient855"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(4.0147937,-0.11912026,0.11328765,3.8182126,-0.22461479,-46.392657)"
gradientTransform="matrix(4.0147937,-0.11912026,0.11328765,3.8182126,-1.0246148,2.407343)"
cx="8"
cy="8"
fx="8"
@@ -196,12 +195,26 @@
<path
id="path4090"
d="m 32.8,-48.060406 c -17.255744,0 -31.2604062,14.004662 -31.2604062,31.260406 0,17.25574444 14.0046622,31.260406 31.2604062,31.260406 17.255744,0 31.260406,-14.00466156 31.260406,-31.260406 0,-17.255744 -14.004662,-31.260406 -31.260406,-31.260406 z m 0,3.907551 c 15.098776,0 27.352855,12.254079 27.352855,27.352855 0,15.0987764 -12.254079,27.352856 -27.352855,27.352856 -15.098776,0 -27.3528555,-12.2540796 -27.3528555,-27.352856 0,-15.098776 12.2540795,-27.352855 27.3528555,-27.352855 z"
style="display:inline;overflow:visible;visibility:visible;opacity:0.2;fill:#848484;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:4.34172344;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:3.5999999;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;enable-background:accumulate"
style="display:inline;overflow:visible;visibility:visible;opacity:0.2;fill:#848484;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:4.34172;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:3.6;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;enable-background:accumulate"
inkscape:connector-curvature="0" />
<path
style="display:inline;overflow:visible;visibility:visible;opacity:0.80100002;fill:url(#radialGradient855);fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:2.09425879;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0.64077669;marker:none;marker-start:none;marker-mid:none;marker-end:none;paint-order:stroke fill markers;enable-background:accumulate"
d="m 32.810524,-42.734828 -1.015246,0.02097 A 25.934385,25.934385 0 0 0 6.8756139,-16.048973 25.934385,25.934385 0 0 0 11.186212,-2.4795029 L 33.725083,-20.21064 v -1.535455 c 0,-3.229159 2.61689,-5.846052 5.846054,-5.846052 1.906945,0 3.585382,0.926722 4.652509,2.33884 h 1.19564 c 3.875281,0 7.016522,2.093915 7.016522,4.677681 l -7.016522,1.168373 v 5.848149 c 0,6.3779185 -4.259255,11.7523532 -10.085332,13.45829656 l 3.014273,8.15342884 c 0.05432,0.1490791 0.05251,0.2989217 0.02726,0.444695 A 25.934385,25.934385 0 0 0 58.732847,-17.043242 25.934385,25.934385 0 0 0 32.810524,-42.734828 Z m 6.760613,19.235127 c -0.968462,0 -1.753607,0.78442 -1.753607,1.753606 0,0.968457 0.785146,1.755704 1.753607,1.755704 0.96846,0 1.755703,-0.787247 1.755703,-1.755704 0,-0.969186 -0.787244,-1.753606 -1.755703,-1.753606 z M 31.799473,0.45296287 c -0.138877,0.004393 -0.273623,0.0209759 -0.413229,0.0209759 h -2.854855 l 2.800315,7.57868263 c 0.138751,0.3807921 -0.01302,0.7823496 -0.329324,1.0047577 a 25.934385,25.934385 0 0 0 2.294791,0.071319 25.934385,25.934385 0 0 0 1.675994,-0.090197 z M 17.737064,0.47393875 14.865429,1.9087078 A 25.934385,25.934385 0 0 0 27.807711,8.6336612 L 24.789245,0.47393875 Z"
id="path4096"
inkscape:connector-curvature="0" />
style="display:inline;overflow:visible;visibility:visible;opacity:0.801;fill:url(#radialGradient855);fill-opacity:1;fill-rule:nonzero;stroke:#1a1a1a;stroke-width:2.09426;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;paint-order:stroke fill markers;enable-background:accumulate"
d="m 35.888672,6.359375 c -0.303933,2.1085366 -2.081796,3.675579 -4.183594,3.6875 -2.080492,0.0106 -3.863017,-1.5066505 -4.21289,-3.5859375 C 14.819383,8.697554 5.7033554,19.888693 6.0761719,32.751953 c 0.1430268,4.836335 1.636139,9.536221 4.3105471,13.568359 L 32.925781,28.589844 v -1.535156 c 0,-3.229159 2.616539,-5.847657 5.845703,-5.847657 1.906945,0 3.585217,0.927726 4.652344,2.339844 h 1.195313 c 3.875281,0 7.017578,2.093968 7.017578,4.677734 l -7.017578,1.167969 v 5.847656 c 0,6.377919 -4.259861,11.753041 -10.085938,13.458985 l 3.015625,8.154297 c 0.05432,0.149079 0.106204,0.243515 0.205076,0.378518 C 49.721772,54.597233 58.034322,44.009915 57.933594,31.755859 57.813463,19.027519 48.473702,8.2678032 35.888672,6.359375 Z m 2.882812,18.941406 c -0.968462,0 -1.753906,0.78472 -1.753906,1.753907 0,0.968457 0.785445,1.755859 1.753906,1.755859 0.96846,0 1.75586,-0.787402 1.75586,-1.755859 0,-0.969187 -0.787401,-1.753907 -1.75586,-1.753907 z M 31,49.253906 c -0.138877,0.0044 -0.274456,0.01953 -0.414062,0.01953 h -2.855469 l 2.800781,7.580078 c 0.138751,0.380792 0.336318,0.763068 0.493205,1.047905 0.763561,0.0573 0.707955,0.03676 1.473592,0.02631 0.559417,-0.01186 1.118303,-0.04182 1.675781,-0.08984 z m -14.0625,0.01953 -2.873047,1.435546 c 3.582287,3.433627 8.074429,5.76748 12.943359,6.72461 l -3.019531,-8.160156 z"
transform="translate(0.8,-48.8)"
sodipodi:nodetypes="ccccccsscsccscccccssssscsccccccccccc" />
<path
style="opacity:0.80908332;fill:#acacac;fill-opacity:1;stroke:#1c1c1c;stroke-width:1.12343;stroke-linecap:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;paint-order:normal"
id="path859"
sodipodi:type="arc"
sodipodi:cx="32.47654"
sodipodi:cy="-43.181934"
sodipodi:rx="2.0615652"
sodipodi:ry="2.0901108"
sodipodi:start="0"
sodipodi:end="6.2616827"
sodipodi:arc-type="chord"
d="m 34.538105,-43.181934 a 2.0615652,2.0901108 0 0 1 -2.050483,2.09008 2.0615652,2.0901108 0 0 1 -2.072528,-2.067609 2.0615652,2.0901108 0 0 1 2.0282,-2.11231 2.0615652,2.0901108 0 0 1 2.094334,2.044899 z"
sodipodi:open="true" />
</g>
</svg>

Before

Width:  |  Height:  |  Size: 322 KiB

After

Width:  |  Height:  |  Size: 323 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 31 KiB

After

Width:  |  Height:  |  Size: 33 KiB

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 322 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 19 KiB

View File

@@ -0,0 +1,506 @@
ply
format ascii 1.0
comment Created by Blender 2.91.0 - www.blender.org
element vertex 250
property float x
property float y
property float z
element face 246
property list uchar uint vertex_indices
end_header
-0.042157 0.063218 0.000000
-0.041120 0.063272 0.000000
-0.041354 0.063272 0.000000
-0.040476 0.063272 0.000000
-0.039503 0.063272 0.000000
-0.038283 0.063272 0.000000
-0.036898 0.063272 0.000000
-0.035432 0.063272 0.000000
-0.033965 0.063272 0.000000
-0.032581 0.063272 0.000000
-0.031361 0.063272 0.000000
-0.030387 0.063272 0.000000
-0.029743 0.063272 0.000000
-0.029510 0.063272 0.000000
-0.028707 0.063218 0.000000
-0.042927 0.063061 0.000000
-0.027936 0.063061 0.000000
-0.043658 0.062807 0.000000
-0.027206 0.062807 0.000000
-0.044342 0.062464 0.000000
-0.026522 0.062464 0.000000
-0.044972 0.062039 0.000000
-0.025892 0.062039 0.000000
-0.045540 0.061539 0.000000
-0.025323 0.061539 0.000000
-0.046041 0.060970 0.000000
-0.024823 0.060970 0.000000
-0.046467 0.060341 0.000000
-0.024397 0.060341 0.000000
-0.046810 0.059657 0.000000
-0.024054 0.059657 0.000000
-0.047064 0.058926 0.000000
-0.023800 0.058926 0.000000
-0.047221 0.058155 0.000000
-0.023642 0.058155 0.000000
-0.047275 0.057352 0.000000
-0.023588 0.057352 0.000000
-0.047275 0.057158 0.000000
-0.023588 0.055760 0.000000
-0.047275 0.056621 0.000000
-0.047275 0.055810 0.000000
-0.047275 0.054794 0.000000
-0.023588 0.051358 0.000000
-0.047275 0.053640 0.000000
-0.047275 0.052418 0.000000
-0.047275 0.051196 0.000000
-0.023588 0.044709 0.000000
-0.047275 0.050043 0.000000
-0.047275 0.049026 0.000000
-0.047275 0.048215 0.000000
-0.047275 0.047678 0.000000
-0.047275 0.047484 0.000000
-0.057948 0.047430 0.000000
-0.057145 0.047484 0.000000
-0.015693 0.023802 0.000000
-0.014605 0.047484 0.000000
-0.015693 0.047484 0.000000
-0.011599 0.047484 0.000000
-0.007057 0.047484 0.000000
-0.001363 0.047484 0.000000
0.005097 0.047484 0.000000
0.011942 0.047484 0.000000
0.018787 0.047484 0.000000
0.025248 0.047484 0.000000
0.030941 0.047484 0.000000
0.035483 0.047484 0.000000
0.038490 0.047484 0.000000
0.039577 0.047484 0.000000
0.040648 0.047412 0.000000
-0.058719 0.047273 0.000000
0.041676 0.047202 0.000000
-0.059449 0.047019 0.000000
0.042650 0.046864 0.000000
-0.060133 0.046676 0.000000
0.043562 0.046406 0.000000
-0.060763 0.046251 0.000000
0.044402 0.045839 0.000000
-0.061332 0.045751 0.000000
0.045160 0.045172 0.000000
-0.061832 0.045182 0.000000
-0.062258 0.044553 0.000000
0.045827 0.044414 0.000000
-0.023588 0.036374 0.000000
-0.062601 0.043869 0.000000
0.046395 0.043574 0.000000
-0.062855 0.043138 0.000000
0.046852 0.042663 0.000000
-0.063013 0.042367 0.000000
0.047191 0.041689 0.000000
-0.063067 0.041564 0.000000
0.047401 0.040661 0.000000
-0.063067 0.041331 0.000000
-0.063067 0.040687 0.000000
-0.063067 0.039714 0.000000
0.047473 0.039590 0.000000
-0.063067 0.038494 0.000000
0.023786 0.023802 0.000000
0.047473 -0.023562 0.000000
-0.063067 0.037110 0.000000
-0.063067 0.035643 0.000000
-0.023588 0.026916 0.000000
-0.063067 0.034177 0.000000
-0.063067 0.032793 0.000000
-0.063067 0.031573 0.000000
-0.063067 0.030600 0.000000
-0.063067 0.029956 0.000000
-0.063067 0.029723 0.000000
-0.063013 0.028920 0.000000
-0.062855 0.028149 0.000000
-0.062601 0.027419 0.000000
-0.062258 0.026735 0.000000
-0.047275 0.023802 0.000000
-0.023588 0.016895 0.000000
-0.061832 0.026105 0.000000
-0.061332 0.025537 0.000000
-0.060763 0.025036 0.000000
-0.060133 0.024611 0.000000
-0.059449 0.024268 0.000000
-0.058719 0.024014 0.000000
-0.057948 0.023856 0.000000
-0.057145 0.023802 0.000000
-0.056951 0.023802 0.000000
-0.056414 0.023802 0.000000
-0.055603 0.023802 0.000000
-0.054586 0.023802 0.000000
-0.053432 0.023802 0.000000
-0.052210 0.023802 0.000000
-0.050988 0.023802 0.000000
-0.049834 0.023802 0.000000
-0.048817 0.023802 0.000000
-0.048006 0.023802 0.000000
-0.047469 0.023802 0.000000
-0.047275 -0.039350 0.000000
0.023786 -0.057111 0.000000
-0.023588 0.006875 0.000000
-0.023588 -0.002584 0.000000
-0.023588 -0.010919 0.000000
-0.023588 -0.017568 0.000000
-0.023588 -0.021970 0.000000
-0.023588 -0.023562 0.000000
0.015890 -0.023562 0.000000
0.015890 -0.047244 0.000000
0.057342 -0.023562 0.000000
0.058146 -0.023616 0.000000
0.058916 -0.023773 0.000000
0.059647 -0.024027 0.000000
0.060331 -0.024370 0.000000
0.060960 -0.024795 0.000000
0.061529 -0.025295 0.000000
0.062030 -0.025864 0.000000
0.062455 -0.026493 0.000000
0.062798 -0.027177 0.000000
0.063052 -0.027908 0.000000
0.063210 -0.028679 0.000000
0.063264 -0.029482 0.000000
0.063264 -0.029715 0.000000
0.063264 -0.030359 0.000000
0.063264 -0.031332 0.000000
0.063264 -0.032552 0.000000
0.063264 -0.033936 0.000000
0.063264 -0.035403 0.000000
0.063264 -0.036869 0.000000
0.063264 -0.038253 0.000000
0.063264 -0.039473 0.000000
-0.047203 -0.040421 0.000000
0.063264 -0.040446 0.000000
-0.046993 -0.041448 0.000000
0.047473 -0.047244 0.000000
0.063264 -0.041090 0.000000
0.063264 -0.041323 0.000000
0.063210 -0.042126 0.000000
-0.046655 -0.042422 0.000000
0.063052 -0.042897 0.000000
-0.046197 -0.043334 0.000000
0.062798 -0.043627 0.000000
-0.045630 -0.044173 0.000000
0.062455 -0.044311 0.000000
-0.044962 -0.044931 0.000000
0.062030 -0.044940 0.000000
-0.044204 -0.045599 0.000000
0.061529 -0.045509 0.000000
0.060960 -0.046010 0.000000
-0.043364 -0.046166 0.000000
0.060331 -0.046435 0.000000
-0.042453 -0.046623 0.000000
0.059647 -0.046778 0.000000
-0.041478 -0.046962 0.000000
0.058916 -0.047032 0.000000
-0.040451 -0.047172 0.000000
0.058146 -0.047190 0.000000
-0.039380 -0.047244 0.000000
0.057342 -0.047244 0.000000
-0.038292 -0.047244 0.000000
-0.035286 -0.047244 0.000000
-0.030744 -0.047244 0.000000
-0.025050 -0.047244 0.000000
-0.018590 -0.047244 0.000000
-0.011745 -0.047244 0.000000
-0.004900 -0.047244 0.000000
0.001561 -0.047244 0.000000
0.007254 -0.047244 0.000000
0.011796 -0.047244 0.000000
0.014803 -0.047244 0.000000
0.047473 -0.047438 0.000000
0.047473 -0.047975 0.000000
0.047473 -0.048785 0.000000
0.047473 -0.049802 0.000000
0.047473 -0.050955 0.000000
0.047473 -0.052177 0.000000
0.047473 -0.053399 0.000000
0.047473 -0.054553 0.000000
0.047473 -0.055569 0.000000
0.047473 -0.056380 0.000000
0.047473 -0.056917 0.000000
0.047473 -0.057111 0.000000
0.023840 -0.057914 0.000000
0.047419 -0.057914 0.000000
0.023997 -0.058685 0.000000
0.047261 -0.058685 0.000000
0.024251 -0.059415 0.000000
0.047007 -0.059415 0.000000
0.024594 -0.060099 0.000000
0.046664 -0.060099 0.000000
0.025020 -0.060728 0.000000
0.046238 -0.060728 0.000000
0.025521 -0.061297 0.000000
0.045738 -0.061297 0.000000
0.026089 -0.061798 0.000000
0.045169 -0.061798 0.000000
0.026719 -0.062223 0.000000
0.044539 -0.062223 0.000000
0.027403 -0.062566 0.000000
0.043855 -0.062566 0.000000
0.028134 -0.062820 0.000000
0.043125 -0.062820 0.000000
0.028904 -0.062978 0.000000
0.042354 -0.062978 0.000000
0.029707 -0.063032 0.000000
0.041551 -0.063032 0.000000
0.029940 -0.063032 0.000000
0.030585 -0.063032 0.000000
0.031558 -0.063032 0.000000
0.032778 -0.063032 0.000000
0.034162 -0.063032 0.000000
0.035629 -0.063032 0.000000
0.037096 -0.063032 0.000000
0.038480 -0.063032 0.000000
0.039700 -0.063032 0.000000
0.040674 -0.063032 0.000000
0.041318 -0.063032 0.000000
3 0 1 2
3 0 3 1
3 0 4 3
3 0 5 4
3 0 6 5
3 0 7 6
3 0 8 7
3 0 9 8
3 0 10 9
3 0 11 10
3 0 12 11
3 0 13 12
3 0 14 13
3 15 14 0
3 15 16 14
3 17 16 15
3 17 18 16
3 19 18 17
3 19 20 18
3 21 20 19
3 21 22 20
3 23 22 21
3 23 24 22
3 25 24 23
3 25 26 24
3 27 26 25
3 27 28 26
3 29 28 27
3 29 30 28
3 31 30 29
3 31 32 30
3 33 32 31
3 33 34 32
3 35 34 33
3 35 36 34
3 37 36 35
3 37 38 36
3 39 38 37
3 40 38 39
3 41 38 40
3 41 42 38
3 43 42 41
3 44 42 43
3 45 42 44
3 45 46 42
3 47 46 45
3 48 46 47
3 49 46 48
3 50 46 49
3 51 46 50
3 52 51 53
3 52 46 51
3 54 55 56
3 54 57 55
3 54 58 57
3 54 59 58
3 54 60 59
3 54 61 60
3 54 62 61
3 54 63 62
3 54 64 63
3 54 65 64
3 54 66 65
3 54 67 66
3 54 68 67
3 69 46 52
3 54 70 68
3 71 46 69
3 54 72 70
3 73 46 71
3 54 74 72
3 75 46 73
3 54 76 74
3 77 46 75
3 54 78 76
3 79 46 77
3 80 46 79
3 54 81 78
3 80 82 46
3 83 82 80
3 54 84 81
3 85 82 83
3 54 86 84
3 87 82 85
3 54 88 86
3 89 82 87
3 54 90 88
3 91 82 89
3 92 82 91
3 93 82 92
3 54 94 90
3 95 82 93
3 54 96 94
3 96 97 94
3 98 82 95
3 99 82 98
3 99 100 82
3 101 100 99
3 102 100 101
3 103 100 102
3 104 100 103
3 105 100 104
3 106 100 105
3 107 100 106
3 108 100 107
3 109 100 108
3 110 100 109
3 110 111 100
3 111 112 100
3 113 111 110
3 114 111 113
3 115 111 114
3 116 111 115
3 117 111 116
3 118 111 117
3 119 111 118
3 120 111 119
3 121 111 120
3 122 111 121
3 123 111 122
3 124 111 123
3 125 111 124
3 126 111 125
3 127 111 126
3 128 111 127
3 129 111 128
3 130 111 129
3 131 111 130
3 132 112 111
3 133 97 96
3 132 134 112
3 132 135 134
3 132 136 135
3 132 137 136
3 132 138 137
3 132 139 138
3 132 140 139
3 132 141 140
3 133 142 97
3 133 143 142
3 133 144 143
3 133 145 144
3 133 146 145
3 133 147 146
3 133 148 147
3 133 149 148
3 133 150 149
3 133 151 150
3 133 152 151
3 133 153 152
3 133 154 153
3 133 155 154
3 133 156 155
3 133 157 156
3 133 158 157
3 133 159 158
3 133 160 159
3 133 161 160
3 133 162 161
3 133 163 162
3 164 141 132
3 133 165 163
3 166 141 164
3 133 167 165
3 167 168 165
3 167 169 168
3 167 170 169
3 171 141 166
3 167 172 170
3 173 141 171
3 167 174 172
3 175 141 173
3 167 176 174
3 177 141 175
3 167 178 176
3 179 141 177
3 167 180 178
3 167 181 180
3 182 141 179
3 167 183 181
3 184 141 182
3 167 185 183
3 186 141 184
3 167 187 185
3 188 141 186
3 167 189 187
3 190 141 188
3 167 191 189
3 192 141 190
3 193 141 192
3 194 141 193
3 195 141 194
3 196 141 195
3 197 141 196
3 198 141 197
3 199 141 198
3 200 141 199
3 201 141 200
3 202 141 201
3 133 203 167
3 133 204 203
3 133 205 204
3 133 206 205
3 133 207 206
3 133 208 207
3 133 209 208
3 133 210 209
3 133 211 210
3 133 212 211
3 133 213 212
3 133 214 213
3 215 214 133
3 215 216 214
3 217 216 215
3 217 218 216
3 219 218 217
3 219 220 218
3 221 220 219
3 221 222 220
3 223 222 221
3 223 224 222
3 225 224 223
3 225 226 224
3 227 226 225
3 227 228 226
3 229 228 227
3 229 230 228
3 231 230 229
3 231 232 230
3 233 232 231
3 233 234 232
3 235 234 233
3 235 236 234
3 237 236 235
3 237 238 236
3 239 238 237
3 240 238 239
3 241 238 240
3 242 238 241
3 243 238 242
3 244 238 243
3 245 238 244
3 246 238 245
3 247 238 246
3 248 238 247
3 249 238 248

59
rsc/mesh/corner.ply Normal file
View File

@@ -0,0 +1,59 @@
ply
format ascii 1.0
comment Created by Blender 2.91.0 - www.blender.org
element vertex 21
property float x
property float y
property float z
property uchar red
property uchar green
property uchar blue
property uchar alpha
element face 24
property list uchar uint vertex_indices
end_header
-0.006000 0.200012 0.000000 255 255 255 255
-0.002199 0.014730 0.000000 255 255 255 255
-0.002199 0.200028 0.000000 255 255 255 255
0.000000 0.019503 0.000000 255 255 255 255
0.000000 0.200031 0.000000 255 255 255 255
0.000000 0.011329 0.000000 255 255 255 255
-0.001404 0.006999 0.000000 255 255 255 255
0.000000 -0.000000 0.000000 255 255 255 255
0.007305 -0.001503 0.000000 255 255 255 255
-0.001032 -0.001167 0.000000 255 255 255 255
0.014783 -0.002353 0.000000 255 255 255 255
0.011630 -0.000000 0.000000 255 255 255 255
0.004955 -0.006000 0.000000 255 255 255 255
-0.004236 -0.006000 0.000000 255 255 255 255
-0.006000 -0.006000 0.000000 255 255 255 255
-0.006000 -0.000126 0.000000 255 255 255 255
-0.006000 0.007802 0.000000 255 255 255 255
0.199994 -0.006001 0.000000 255 255 255 255
0.199997 -0.002353 0.000000 255 255 255 255
0.019554 -0.000000 0.000000 255 255 255 255
0.200000 0.000000 0.000000 255 255 255 255
3 0 1 2
3 2 3 4
3 1 5 3
3 6 7 5
3 8 7 9
3 10 11 8
3 8 12 10
3 13 9 14
3 9 15 14
3 6 16 15
3 17 10 12
3 18 19 10
3 0 16 1
3 2 1 3
3 1 6 5
3 6 9 7
3 8 11 7
3 10 19 11
3 8 13 12
3 13 8 9
3 9 6 15
3 6 1 16
3 17 18 10
3 18 20 19

506
rsc/mesh/icon_crop.ply Normal file
View File

@@ -0,0 +1,506 @@
ply
format ascii 1.0
comment Created by Blender 2.91.0 - www.blender.org
element vertex 250
property float x
property float y
property float z
element face 246
property list uchar uint vertex_indices
end_header
-0.042157 0.063218 0.000000
-0.041120 0.063272 0.000000
-0.041354 0.063272 0.000000
-0.040476 0.063272 0.000000
-0.039503 0.063272 0.000000
-0.038283 0.063272 0.000000
-0.036898 0.063272 0.000000
-0.035432 0.063272 0.000000
-0.033965 0.063272 0.000000
-0.032581 0.063272 0.000000
-0.031361 0.063272 0.000000
-0.030387 0.063272 0.000000
-0.029743 0.063272 0.000000
-0.029510 0.063272 0.000000
-0.028707 0.063218 0.000000
-0.042927 0.063061 0.000000
-0.027936 0.063061 0.000000
-0.043658 0.062807 0.000000
-0.027206 0.062807 0.000000
-0.044342 0.062464 0.000000
-0.026522 0.062464 0.000000
-0.044972 0.062039 0.000000
-0.025892 0.062039 0.000000
-0.045540 0.061539 0.000000
-0.025323 0.061539 0.000000
-0.046041 0.060970 0.000000
-0.024823 0.060970 0.000000
-0.046467 0.060341 0.000000
-0.024397 0.060341 0.000000
-0.046810 0.059657 0.000000
-0.024054 0.059657 0.000000
-0.047064 0.058926 0.000000
-0.023800 0.058926 0.000000
-0.047221 0.058155 0.000000
-0.023642 0.058155 0.000000
-0.047275 0.057352 0.000000
-0.023588 0.057352 0.000000
-0.047275 0.057158 0.000000
-0.023588 0.055760 0.000000
-0.047275 0.056621 0.000000
-0.047275 0.055810 0.000000
-0.047275 0.054794 0.000000
-0.023588 0.051358 0.000000
-0.047275 0.053640 0.000000
-0.047275 0.052418 0.000000
-0.047275 0.051196 0.000000
-0.023588 0.044709 0.000000
-0.047275 0.050043 0.000000
-0.047275 0.049026 0.000000
-0.047275 0.048215 0.000000
-0.047275 0.047678 0.000000
-0.047275 0.047484 0.000000
-0.057948 0.047430 0.000000
-0.057145 0.047484 0.000000
-0.015693 0.023802 0.000000
-0.014605 0.047484 0.000000
-0.015693 0.047484 0.000000
-0.011599 0.047484 0.000000
-0.007057 0.047484 0.000000
-0.001363 0.047484 0.000000
0.005097 0.047484 0.000000
0.011942 0.047484 0.000000
0.018787 0.047484 0.000000
0.025248 0.047484 0.000000
0.030941 0.047484 0.000000
0.035483 0.047484 0.000000
0.038490 0.047484 0.000000
0.039577 0.047484 0.000000
0.040648 0.047412 0.000000
-0.058719 0.047273 0.000000
0.041676 0.047202 0.000000
-0.059449 0.047019 0.000000
0.042650 0.046864 0.000000
-0.060133 0.046676 0.000000
0.043562 0.046406 0.000000
-0.060763 0.046251 0.000000
0.044402 0.045839 0.000000
-0.061332 0.045751 0.000000
0.045160 0.045172 0.000000
-0.061832 0.045182 0.000000
-0.062258 0.044553 0.000000
0.045827 0.044414 0.000000
-0.023588 0.036374 0.000000
-0.062601 0.043869 0.000000
0.046395 0.043574 0.000000
-0.062855 0.043138 0.000000
0.046852 0.042663 0.000000
-0.063013 0.042367 0.000000
0.047191 0.041689 0.000000
-0.063067 0.041564 0.000000
0.047401 0.040661 0.000000
-0.063067 0.041331 0.000000
-0.063067 0.040687 0.000000
-0.063067 0.039714 0.000000
0.047473 0.039590 0.000000
-0.063067 0.038494 0.000000
0.023786 0.023802 0.000000
0.047473 -0.023562 0.000000
-0.063067 0.037110 0.000000
-0.063067 0.035643 0.000000
-0.023588 0.026916 0.000000
-0.063067 0.034177 0.000000
-0.063067 0.032793 0.000000
-0.063067 0.031573 0.000000
-0.063067 0.030600 0.000000
-0.063067 0.029956 0.000000
-0.063067 0.029723 0.000000
-0.063013 0.028920 0.000000
-0.062855 0.028149 0.000000
-0.062601 0.027419 0.000000
-0.062258 0.026735 0.000000
-0.047275 0.023802 0.000000
-0.023588 0.016895 0.000000
-0.061832 0.026105 0.000000
-0.061332 0.025537 0.000000
-0.060763 0.025036 0.000000
-0.060133 0.024611 0.000000
-0.059449 0.024268 0.000000
-0.058719 0.024014 0.000000
-0.057948 0.023856 0.000000
-0.057145 0.023802 0.000000
-0.056951 0.023802 0.000000
-0.056414 0.023802 0.000000
-0.055603 0.023802 0.000000
-0.054586 0.023802 0.000000
-0.053432 0.023802 0.000000
-0.052210 0.023802 0.000000
-0.050988 0.023802 0.000000
-0.049834 0.023802 0.000000
-0.048817 0.023802 0.000000
-0.048006 0.023802 0.000000
-0.047469 0.023802 0.000000
-0.047275 -0.039350 0.000000
0.023786 -0.057111 0.000000
-0.023588 0.006875 0.000000
-0.023588 -0.002584 0.000000
-0.023588 -0.010919 0.000000
-0.023588 -0.017568 0.000000
-0.023588 -0.021970 0.000000
-0.023588 -0.023562 0.000000
0.015890 -0.023562 0.000000
0.015890 -0.047244 0.000000
0.057342 -0.023562 0.000000
0.058146 -0.023616 0.000000
0.058916 -0.023773 0.000000
0.059647 -0.024027 0.000000
0.060331 -0.024370 0.000000
0.060960 -0.024795 0.000000
0.061529 -0.025295 0.000000
0.062030 -0.025864 0.000000
0.062455 -0.026493 0.000000
0.062798 -0.027177 0.000000
0.063052 -0.027908 0.000000
0.063210 -0.028679 0.000000
0.063264 -0.029482 0.000000
0.063264 -0.029715 0.000000
0.063264 -0.030359 0.000000
0.063264 -0.031332 0.000000
0.063264 -0.032552 0.000000
0.063264 -0.033936 0.000000
0.063264 -0.035403 0.000000
0.063264 -0.036869 0.000000
0.063264 -0.038253 0.000000
0.063264 -0.039473 0.000000
-0.047203 -0.040421 0.000000
0.063264 -0.040446 0.000000
-0.046993 -0.041448 0.000000
0.047473 -0.047244 0.000000
0.063264 -0.041090 0.000000
0.063264 -0.041323 0.000000
0.063210 -0.042126 0.000000
-0.046655 -0.042422 0.000000
0.063052 -0.042897 0.000000
-0.046197 -0.043334 0.000000
0.062798 -0.043627 0.000000
-0.045630 -0.044173 0.000000
0.062455 -0.044311 0.000000
-0.044962 -0.044931 0.000000
0.062030 -0.044940 0.000000
-0.044204 -0.045599 0.000000
0.061529 -0.045509 0.000000
0.060960 -0.046010 0.000000
-0.043364 -0.046166 0.000000
0.060331 -0.046435 0.000000
-0.042453 -0.046623 0.000000
0.059647 -0.046778 0.000000
-0.041478 -0.046962 0.000000
0.058916 -0.047032 0.000000
-0.040451 -0.047172 0.000000
0.058146 -0.047190 0.000000
-0.039380 -0.047244 0.000000
0.057342 -0.047244 0.000000
-0.038292 -0.047244 0.000000
-0.035286 -0.047244 0.000000
-0.030744 -0.047244 0.000000
-0.025050 -0.047244 0.000000
-0.018590 -0.047244 0.000000
-0.011745 -0.047244 0.000000
-0.004900 -0.047244 0.000000
0.001561 -0.047244 0.000000
0.007254 -0.047244 0.000000
0.011796 -0.047244 0.000000
0.014803 -0.047244 0.000000
0.047473 -0.047438 0.000000
0.047473 -0.047975 0.000000
0.047473 -0.048785 0.000000
0.047473 -0.049802 0.000000
0.047473 -0.050955 0.000000
0.047473 -0.052177 0.000000
0.047473 -0.053399 0.000000
0.047473 -0.054553 0.000000
0.047473 -0.055569 0.000000
0.047473 -0.056380 0.000000
0.047473 -0.056917 0.000000
0.047473 -0.057111 0.000000
0.023840 -0.057914 0.000000
0.047419 -0.057914 0.000000
0.023997 -0.058685 0.000000
0.047261 -0.058685 0.000000
0.024251 -0.059415 0.000000
0.047007 -0.059415 0.000000
0.024594 -0.060099 0.000000
0.046664 -0.060099 0.000000
0.025020 -0.060728 0.000000
0.046238 -0.060728 0.000000
0.025521 -0.061297 0.000000
0.045738 -0.061297 0.000000
0.026089 -0.061798 0.000000
0.045169 -0.061798 0.000000
0.026719 -0.062223 0.000000
0.044539 -0.062223 0.000000
0.027403 -0.062566 0.000000
0.043855 -0.062566 0.000000
0.028134 -0.062820 0.000000
0.043125 -0.062820 0.000000
0.028904 -0.062978 0.000000
0.042354 -0.062978 0.000000
0.029707 -0.063032 0.000000
0.041551 -0.063032 0.000000
0.029940 -0.063032 0.000000
0.030585 -0.063032 0.000000
0.031558 -0.063032 0.000000
0.032778 -0.063032 0.000000
0.034162 -0.063032 0.000000
0.035629 -0.063032 0.000000
0.037096 -0.063032 0.000000
0.038480 -0.063032 0.000000
0.039700 -0.063032 0.000000
0.040674 -0.063032 0.000000
0.041318 -0.063032 0.000000
3 0 1 2
3 0 3 1
3 0 4 3
3 0 5 4
3 0 6 5
3 0 7 6
3 0 8 7
3 0 9 8
3 0 10 9
3 0 11 10
3 0 12 11
3 0 13 12
3 0 14 13
3 15 14 0
3 15 16 14
3 17 16 15
3 17 18 16
3 19 18 17
3 19 20 18
3 21 20 19
3 21 22 20
3 23 22 21
3 23 24 22
3 25 24 23
3 25 26 24
3 27 26 25
3 27 28 26
3 29 28 27
3 29 30 28
3 31 30 29
3 31 32 30
3 33 32 31
3 33 34 32
3 35 34 33
3 35 36 34
3 37 36 35
3 37 38 36
3 39 38 37
3 40 38 39
3 41 38 40
3 41 42 38
3 43 42 41
3 44 42 43
3 45 42 44
3 45 46 42
3 47 46 45
3 48 46 47
3 49 46 48
3 50 46 49
3 51 46 50
3 52 51 53
3 52 46 51
3 54 55 56
3 54 57 55
3 54 58 57
3 54 59 58
3 54 60 59
3 54 61 60
3 54 62 61
3 54 63 62
3 54 64 63
3 54 65 64
3 54 66 65
3 54 67 66
3 54 68 67
3 69 46 52
3 54 70 68
3 71 46 69
3 54 72 70
3 73 46 71
3 54 74 72
3 75 46 73
3 54 76 74
3 77 46 75
3 54 78 76
3 79 46 77
3 80 46 79
3 54 81 78
3 80 82 46
3 83 82 80
3 54 84 81
3 85 82 83
3 54 86 84
3 87 82 85
3 54 88 86
3 89 82 87
3 54 90 88
3 91 82 89
3 92 82 91
3 93 82 92
3 54 94 90
3 95 82 93
3 54 96 94
3 96 97 94
3 98 82 95
3 99 82 98
3 99 100 82
3 101 100 99
3 102 100 101
3 103 100 102
3 104 100 103
3 105 100 104
3 106 100 105
3 107 100 106
3 108 100 107
3 109 100 108
3 110 100 109
3 110 111 100
3 111 112 100
3 113 111 110
3 114 111 113
3 115 111 114
3 116 111 115
3 117 111 116
3 118 111 117
3 119 111 118
3 120 111 119
3 121 111 120
3 122 111 121
3 123 111 122
3 124 111 123
3 125 111 124
3 126 111 125
3 127 111 126
3 128 111 127
3 129 111 128
3 130 111 129
3 131 111 130
3 132 112 111
3 133 97 96
3 132 134 112
3 132 135 134
3 132 136 135
3 132 137 136
3 132 138 137
3 132 139 138
3 132 140 139
3 132 141 140
3 133 142 97
3 133 143 142
3 133 144 143
3 133 145 144
3 133 146 145
3 133 147 146
3 133 148 147
3 133 149 148
3 133 150 149
3 133 151 150
3 133 152 151
3 133 153 152
3 133 154 153
3 133 155 154
3 133 156 155
3 133 157 156
3 133 158 157
3 133 159 158
3 133 160 159
3 133 161 160
3 133 162 161
3 133 163 162
3 164 141 132
3 133 165 163
3 166 141 164
3 133 167 165
3 167 168 165
3 167 169 168
3 167 170 169
3 171 141 166
3 167 172 170
3 173 141 171
3 167 174 172
3 175 141 173
3 167 176 174
3 177 141 175
3 167 178 176
3 179 141 177
3 167 180 178
3 167 181 180
3 182 141 179
3 167 183 181
3 184 141 182
3 167 185 183
3 186 141 184
3 167 187 185
3 188 141 186
3 167 189 187
3 190 141 188
3 167 191 189
3 192 141 190
3 193 141 192
3 194 141 193
3 195 141 194
3 196 141 195
3 197 141 196
3 198 141 197
3 199 141 198
3 200 141 199
3 201 141 200
3 202 141 201
3 133 203 167
3 133 204 203
3 133 205 204
3 133 206 205
3 133 207 206
3 133 208 207
3 133 209 208
3 133 210 209
3 133 211 210
3 133 212 211
3 133 213 212
3 133 214 213
3 215 214 133
3 215 216 214
3 217 216 215
3 217 218 216
3 219 218 217
3 219 220 218
3 221 220 219
3 221 222 220
3 223 222 221
3 223 224 222
3 225 224 223
3 225 226 224
3 227 226 225
3 227 228 226
3 229 228 227
3 229 230 228
3 231 230 229
3 231 232 230
3 233 232 231
3 233 234 232
3 235 234 233
3 235 236 234
3 237 236 235
3 237 238 236
3 239 238 237
3 240 238 239
3 241 238 240
3 242 238 241
3 243 238 242
3 244 238 243
3 245 238 244
3 246 238 245
3 247 238 246
3 248 238 247
3 249 238 248

View File

@@ -0,0 +1,192 @@
ply
format ascii 1.0
comment Created by Blender 2.91.0 - www.blender.org
element vertex 81
property float x
property float y
property float z
element face 101
property list uchar uint vertex_indices
end_header
-1.005000 -2.010402 0.000000
-0.997299 -2.010402 0.000000
-1.016821 -2.006961 0.000000
-1.012701 -2.042907 0.000000
-1.012701 -2.010402 0.000000
-1.005000 -2.140421 0.000000
-1.012701 -2.140421 0.000000
-0.993243 -2.143901 0.000000
-5.016935 -6.134262 0.000000
-5.012702 -6.172815 0.000000
-5.012702 -6.140421 0.000000
-5.005000 -6.269996 0.000000
-5.012702 -6.269996 0.000000
-4.993124 -6.271469 0.000000
-0.993107 -2.007656 0.000000
-0.025000 -1.026536 0.000000
-0.040402 -1.029598 0.000000
-1.016843 -2.042907 0.000000
-4.997299 -6.140421 0.000000
-4.992839 -6.146410 0.000000
-1.016888 -2.130304 0.000000
-5.017002 -6.172815 0.000000
-5.016947 -6.272215 0.000000
-6.051421 -7.308137 0.000000
-6.029597 -7.308137 0.000000
-0.014928 -1.028372 0.000000
-0.023242 -1.023197 0.000000
-0.014320 -1.024299 0.000000
-5.005000 -6.205208 0.000000
-5.005000 -6.237602 0.000000
-4.997299 -6.237602 0.000000
-5.012702 -6.205208 0.000000
-5.017002 -6.205208 0.000000
-5.017002 -6.237602 0.000000
-5.012702 -6.237602 0.000000
-5.005000 -6.140421 0.000000
-4.997299 -6.172815 0.000000
-5.005000 -6.172815 0.000000
-4.997299 -6.205208 0.000000
-4.992999 -6.237602 0.000000
-4.992999 -6.205208 0.000000
-4.992999 -6.172815 0.000000
-4.997299 -6.269996 0.000000
-1.005000 -2.075412 0.000000
-1.005000 -2.107916 0.000000
-0.997299 -2.107916 0.000000
-1.012701 -2.075412 0.000000
-1.016843 -2.075412 0.000000
-1.016843 -2.107916 0.000000
-1.012701 -2.107916 0.000000
-0.997299 -2.042907 0.000000
-1.005000 -2.042907 0.000000
-0.997299 -2.075412 0.000000
-0.993157 -2.107916 0.000000
-0.993157 -2.075412 0.000000
-0.993157 -2.042907 0.000000
-0.997299 -2.140421 0.000000
-0.024245 -1.019051 0.000000
-0.029970 -1.019912 0.000000
-0.017730 -1.020603 0.000000
-0.033926 -1.023085 0.000000
-4.771169 -7.309363 0.000000
-6.041811 -7.295620 0.000000
-6.041811 -7.309363 0.000000
-4.771169 -7.295620 0.000000
-3.725413 -6.272977 0.000000
-5.004570 -6.259233 0.000000
-5.004570 -6.272977 0.000000
-3.725413 -6.259233 0.000000
-3.722498 -6.151754 0.000000
-5.003956 -6.129984 0.000000
-5.003956 -6.151754 0.000000
-3.722498 -6.129984 0.000000
0.262578 -2.147450 0.000000
-1.004861 -2.126240 0.000000
-1.004861 -2.147450 0.000000
0.262578 -2.126240 0.000000
0.268543 -2.021173 0.000000
-1.004861 -2.007429 0.000000
-1.004861 -2.021173 0.000000
0.268543 -2.007429 0.000000
3 0 1 2
3 2 3 4
3 5 6 7
3 8 9 10
3 11 12 13
3 14 15 16
3 2 17 3
3 18 19 20
3 8 21 9
3 22 23 24
3 25 26 15
3 25 27 26
3 28 29 30
3 28 31 29
3 32 33 34
3 35 36 18
3 35 37 36
3 28 30 38
3 38 39 40
3 38 30 39
3 30 13 39
3 36 38 40
3 36 37 38
3 37 28 38
3 18 41 19
3 18 36 41
3 36 40 41
3 34 12 11
3 34 33 12
3 33 22 12
3 29 34 11
3 29 31 34
3 31 32 34
3 30 42 13
3 30 29 42
3 29 11 42
3 9 31 28
3 9 21 31
3 21 32 31
3 10 37 35
3 10 9 37
3 9 28 37
3 43 44 45
3 43 46 44
3 47 48 49
3 0 50 1
3 0 51 50
3 43 45 52
3 52 53 54
3 52 45 53
3 45 7 53
3 50 52 54
3 50 51 52
3 51 43 52
3 1 55 14
3 1 50 55
3 50 54 55
3 49 6 5
3 49 48 6
3 48 20 6
3 44 49 5
3 44 46 49
3 46 47 49
3 45 56 7
3 45 44 56
3 44 5 56
3 3 46 43
3 3 17 46
3 17 47 46
3 4 51 0
3 4 3 51
3 3 43 51
3 1 14 16
3 16 2 1
3 2 4 0
3 6 20 19
3 19 7 6
3 7 56 5
3 12 22 24
3 24 13 12
3 13 42 11
3 20 8 18
3 8 10 35
3 35 18 8
3 26 57 58
3 26 27 57
3 27 59 57
3 15 60 16
3 15 26 60
3 26 58 60
3 14 25 15
3 61 62 63
3 61 64 62
3 65 66 67
3 65 68 66
3 69 70 71
3 69 72 70
3 73 74 75
3 73 76 74
3 77 78 79
3 77 80 78

File diff suppressed because it is too large Load Diff

View File

@@ -1,42 +1,40 @@
ply
format ascii 1.0
comment Created by Blender 2.82 (sub 7) - www.blender.org, source file: 'perspective_layer.blend'
element vertex 16
comment Created by Blender 2.91.0 - www.blender.org
element vertex 20
property float x
property float y
property float z
property uchar red
property uchar green
property uchar blue
property uchar alpha
element face 12
element face 10
property list uchar uint vertex_indices
end_header
-6.690000 -6.700000 0.000000 255 0 255 100
-1.010000 -1.000000 0.000000 255 0 255 100
-6.710000 -6.700000 0.000000 255 0 255 100
-0.990000 -1.000000 0.000000 255 0 255 100
-6.610000 -6.710000 0.000000 255 0 255 100
-6.500000 -6.700000 0.000000 255 0 255 100
-6.705731 -6.710000 0.000000 255 0 255 100
-6.510000 -6.710000 0.000000 255 0 255 100
-4.690000 -6.700000 0.000000 255 0 255 100
0.990000 -1.000000 0.000000 255 0 255 100
-4.710000 -6.700000 0.000000 255 0 255 100
1.010000 -1.000000 0.000000 255 0 255 100
-4.706754 -6.710000 0.000000 255 0 255 100
-4.910000 -6.710000 0.000000 255 0 255 100
-4.810000 -6.710000 0.000000 255 0 255 100
-4.900000 -6.700000 0.000000 255 0 255 100
1.001107 -2.119227 0.000000
-0.998893 -2.105483 0.000000
-0.998893 -2.119227 0.000000
1.001107 -2.105483 0.000000
-2.998893 -6.127666 0.000000
-4.998893 -6.113922 0.000000
-4.998893 -6.127666 0.000000
-2.998893 -6.113922 0.000000
-2.998893 -6.247665 0.000000
-4.998893 -6.233922 0.000000
-4.998893 -6.247665 0.000000
-2.998893 -6.233922 0.000000
-4.028101 -7.298446 0.000000
-6.029685 -7.284703 0.000000
-6.029685 -7.298446 0.000000
-4.028101 -7.284703 0.000000
1.001107 -2.008962 0.000000
-0.998893 -1.995219 0.000000
-0.998893 -2.008962 0.000000
1.001107 -1.995219 0.000000
3 0 1 2
3 0 3 1
3 2 4 0
3 4 5 0
3 2 6 4
3 4 5 6
3 4 7 5
3 8 9 10
3 8 11 9
3 10 12 8
3 10 13 14
3 10 14 12
3 10 15 13
3 12 13 14
3 12 15 13
3 16 17 18
3 16 19 17

View File

@@ -7,7 +7,7 @@ in vec2 vertexUV;
// from General Shader
uniform vec3 iResolution; // viewport image resolution (in pixels)
uniform mat4 iTransform; // UV image transformation
uniform mat4 iTransform; // image transformation
uniform vec4 color;
uniform vec4 uv;
@@ -25,13 +25,14 @@ void main()
vec4 textureColor = texture(iChannel0, texcoord.xy);
vec3 RGB = textureColor.rgb * vertexColor.rgb * color.rgb;
// alpha is a mix of texture alpha, vertex alpha, and uniform alpha affected by stippling
vec4 maskColor = texture(iChannel1, vertexUV);
float maskIntensity = (maskColor.r + maskColor.g + maskColor.b) / 3.0;
// read mask intensity as average of RGB
float maskIntensity = dot(texture(iChannel1, vertexUV).rgb, vec3(1.0/3.0));
// alpha is a mix of texture alpha, vertex alpha, and uniform alpha affected by stippling
float A = textureColor.a * vertexColor.a * color.a * maskIntensity;
A -= stipple * ( int(gl_FragCoord.x + gl_FragCoord.y) % 2 > 0 ? 0.05 : 0.95 );
A += textureColor.a * stipple * ( int(gl_FragCoord.x + gl_FragCoord.y) % 2 );
// output RGBA
FragColor = vec4(RGB, clamp(A, 0.0, 1.0) );
// FragColor = texture(iChannel1, vertexUV);
}

View File

@@ -25,8 +25,7 @@ void main()
vec3 RGB = textureColor.rgb * vertexColor.rgb * color.rgb;
// alpha is a mix of texture alpha, vertex alpha, and uniform alpha affected by stippling
vec4 maskColor = texture(iChannel1, vertexUV);
float maskIntensity = (maskColor.r + maskColor.g + maskColor.b) / 3.0;
float maskIntensity = dot(texture(iChannel1, vertexUV).rgb, vec3(1.0/3.0));
float A = textureColor.a * vertexColor.a * color.a * maskIntensity;
A -= stipple * ( int(gl_FragCoord.x + gl_FragCoord.y) % 2 > 0 ? 0.05 : 0.95 );

35
rsc/shaders/mask_box.fs Normal file
View File

@@ -0,0 +1,35 @@
#version 330 core
out vec4 FragColor;
in vec4 vertexColor;
in vec2 vertexUV;
// from General Shader
uniform vec3 iResolution; // viewport resolution (in pixels)
uniform mat4 iTransform; // image transformation
uniform vec4 color; // drawing color
uniform vec4 uv;
// Mask Shader
uniform vec2 size; // size of the mask area
uniform float blur; // percent of blur
float sdRoundBox( in vec2 p, in vec2 b, in float r )
{
vec2 q = abs(p)-b+r;
return min(max(q.x,q.y),0.0) + length(max(q,0.0)) - r;
}
void main()
{
vec2 uv = -1.0 + 2.0 * gl_FragCoord.xy / iResolution.xy;
uv.x *= iResolution.x / iResolution.y;
float d = sdRoundBox( uv, vec2(size.x * iResolution.x/iResolution.y, size.y), blur * 0.5 );
vec3 col = vec3(1.0 - sign(d));
col *= 1.0 - exp( -600.0/ (blur * 1000.f + 1.0) * abs(d));
FragColor = vec4( col, 1.0 );
}

111
rsc/shaders/mask_draw.fs Normal file
View File

@@ -0,0 +1,111 @@
#version 330 core
out vec4 FragColor;
in vec4 vertexColor;
in vec2 vertexUV;
// from General Shader
uniform vec3 iResolution; // viewport resolution (in pixels)
uniform mat4 iTransform; // image transformation
uniform vec4 color; // drawing color
uniform vec4 uv;
// Mask Shader
uniform sampler2D iChannel0; // base texture
uniform vec2 size; // size of the mask area
uniform float blur; // percent of blur
uniform vec4 cursor;
uniform vec3 brush;
uniform int option;
uniform int effect;
float sdBox( in vec2 p, in float b)
{
vec2 q = abs(p) - vec2(b);
float d = min( max(q.x, q.y), 0.0) + length(max(q,0.0));
return 1.0 - abs(d) * step(d, 0.0);
}
float sdCircle( in vec2 p, in float b)
{
return ( length( p ) / b );
}
const mat3 KERNEL = mat3( 0.0625, 0.125, 0.0625,
0.125, 0.25, 0.125,
0.0625, 0.125, 0.0625);
vec3 gaussian()
{
vec2 filter_step = 1.f / textureSize(iChannel0, 0);
int i = 0, j = 0;
vec3 sum = vec3(0.0);
for (i = 0; i<3; ++i)
for (j = 0; j<3; ++j)
sum += texture(iChannel0, vertexUV.xy + filter_step * vec2 (i-1, j-1) ).rgb * KERNEL[i][j];
return sum;
}
void main()
{
vec3 color = texture(iChannel0, vertexUV).rgb; // raw color
// clear
color += mix(vec3(0), vec3(1) - color, int(effect == 1));
// invert
color = mix(color, vec3(1) - color, int(effect == 2));
// step edge
color = mix(color, vec3(1.0 - step(dot(color, vec3(1.0/3.0)), 0.6)), int(effect == 3));
if ( option > 0 ) {
// fragment coordinates
vec2 uv = -1.0 + 2.0 * gl_FragCoord.xy / iResolution.xy;
// adjust coordinates to match scaling area
uv.x *= cursor.z ;
uv.y *= cursor.w ;
// cursor coordinates
vec2 cursor = vec2(cursor.x, - cursor.y);
// use distance function relative to length brush.x (size), depending on brush.z (shape):
// - brush.z = 0 : circle shape
// - brush.z = 1 : square shape
float d = (1.0 -brush.z) * sdCircle(cursor-uv, brush.x) + brush.z * sdBox(uv-cursor, brush.x);
// modify only the pixels inside the brush
if( d < 1.0 )
{
// blur the image incrementally each step
color = gaussian();
// mask intensity
float c = dot(color, vec3(1.0/3.0));
// depending on option:
// - option 1 : paint (add color)
// - option 2 : erase (substract color)
float p = c + (option > 1 ? d - 1.0 : 1.0 - d );
// new intensity is a mix betwen current intensity and painted intensity
c = (1.0 - brush.y) * c + (brush.y) * p;
// distribute value in RGB (will be averaged in image.fs)
// NB : this encodes the mask intensity over 3*8 bits
c *= 3.0;
color.r = clamp(c, 0.0, 1.0);
color.g = step(1.0, c) * (clamp(c, 1.0, 2.0) - 1.0);
color.b = step(2.0, c) * (clamp(c, 2.0, 3.0) - 2.0);
}
}
FragColor = vec4( clamp(color, 0.0, 1.0), 1.0);
}

View File

@@ -0,0 +1,63 @@
#version 330 core
out vec4 FragColor;
in vec4 vertexColor;
in vec2 vertexUV;
// from General Shader
uniform vec3 iResolution; // viewport resolution (in pixels)
uniform mat4 iTransform; // image transformation
uniform vec4 color; // drawing color
uniform vec4 uv;
// Mask Shader
uniform vec2 size; // size of the mask area
uniform float blur; // percent of blur
// See: http://www.iquilezles.org/www/articles/ellipsoids/ellipsoids.htm
float sdEllipsoid( in vec2 p, in vec2 r )
{
float k0 = length(p/r);
float k1 = length(p/(r*r));
return k0*(k0-1.0)/k1;
}
float sdEllipse( in vec2 p, in vec2 e )
{
p = abs( p );
if( e.x<e.y ) { p = p.yx; e = e.yx; }
vec2 r = e*e;
vec2 z = p/e;
vec2 n = r*z;
float g = dot(z,z) - 1.0;
float s0 = z.y - 1.0;
float s1 = (g<0.0) ? 0.0 : length( n )/r.y - 1.0;
float s = 0.0;
for( int i=0; i<64; i++ )
{
s = 0.5*(s0+s1);
vec2 ratio = n/(r.y*s+r);
g = dot(ratio,ratio) - 1.0;
if( g>0.0 ) s0=s; else s1=s;
}
vec2 q = p*r/(r.y*s+r);
return length( p-q ) * (((p.y-q.y)<0.0)?-1.0:1.0);
}
void main()
{
vec2 uv = -1.0 + 2.0 * gl_FragCoord.xy / iResolution.xy;
uv.x *= iResolution.x / iResolution.y;
float d = sdEllipse( uv, vec2(size.x * iResolution.x/iResolution.y, size.y) );
vec3 col = vec3(1.0- sign(d));
col *= 1.0 - exp( -600.0/ (blur * 1000.f + 1.0) * abs(d));
FragColor = vec4( col, 1.0 );
}

View File

@@ -0,0 +1,32 @@
#version 330 core
out vec4 FragColor;
in vec4 vertexColor;
in vec2 vertexUV;
// from General Shader
uniform vec3 iResolution; // viewport resolution (in pixels)
uniform mat4 iTransform; // image transformation
uniform vec4 color; // drawing color
uniform vec4 uv;
// Mask Shader
uniform vec2 size; // size of the mask area
uniform float blur; // percent of blur
float sdHorizontal( in vec2 p, in float y )
{
float d = step(0.0, y);
d = d * smoothstep(0.0, 2.0 * blur, y + p.y) + (1.0-d)*smoothstep(-2.0 * blur, 0.0, (-2.0 * blur) - (y + p.y));
return d;
}
void main()
{
vec2 uv = -1.0 + 2.0 * gl_FragCoord.xy / iResolution.xy;
float d = sdHorizontal( uv, size.y);
FragColor = vec4( vec3(d), 1.0 );
}

View File

@@ -0,0 +1,67 @@
#version 330 core
out vec4 FragColor;
in vec4 vertexColor;
in vec2 vertexUV;
// from General Shader
uniform vec3 iResolution; // viewport resolution (in pixels)
uniform mat4 iTransform; // image transformation
uniform vec4 color; // drawing color
uniform vec4 uv;
// Mask Shader
uniform vec2 size; // size of the mask area
uniform float blur; // percent of blur
float sdRoundSide( in vec2 p, in vec2 b, in float r )
{
vec2 q = vec2(-1.0, 1.0) * p - b + r;
return min(max(q.x,q.y),0.0) + length(max(q,0.0)) - r;
}
float sdHorizontal( in vec2 p, in float y )
{
float d = 0.0;
// if (y < 0.0) {
// d = smoothstep(-2.0 * blur, 0.0, (-2.0 * blur) - (y + p.y));
//// d = smoothstep(-2.0 * blur, 0.0, -y -blur -p.y); // centered blur
// }
// else {
// d = smoothstep(0.0, 2.0 * blur, y + p.y);
//// d = smoothstep(0.0, 2.0 * blur, y +blur +p.y); // centered blur
// }
d = step(0.0, y);
d = d * smoothstep(0.0, 2.0 * blur, y + p.y) + (1.0-d)*smoothstep(-2.0 * blur, 0.0, (-2.0 * blur) - (y + p.y));
return d;
}
void main()
{
vec2 uv = -1.0 + 2.0 * gl_FragCoord.xy / iResolution.xy;
uv.x *= iResolution.x / iResolution.y;
float d = sdHorizontal( uv, size.y);
vec3 col = vec3(d);
// col = vec3(sign(d));
// col *= 1.0 - exp( -600.0/ (blur * 1000.0 + 1.0) * abs(d));
// float d = sdRoundSide( uv, vec2(size.x * iResolution.x/iResolution.y, size.y), blur );
// vec3 col = vec3(1.0 - sign(d));
// float delta = 0.5 * length(min(size,1.0));
// col *= 1.0 - exp( -300.0/ (blur * 1000.0 * delta + 1.0) * abs(d));
FragColor = vec4( col, 1.0 );
}

54
rsc/shaders/mask_round.fs Normal file
View File

@@ -0,0 +1,54 @@
#version 330 core
out vec4 FragColor;
in vec4 vertexColor;
in vec2 vertexUV;
// from General Shader
uniform vec3 iResolution; // viewport resolution (in pixels)
uniform mat4 iTransform; // image transformation
uniform vec4 color; // drawing color
uniform vec4 uv;
// Mask Shader
uniform vec2 size; // size of the mask area
uniform float blur; // percent of blur
float udSegment( in vec2 p, in vec2 a, in vec2 b )
{
vec2 ba = b-a;
vec2 pa = p-a;
float h =clamp( dot(pa,ba)/dot(ba,ba), 0.0, 1.0 );
return length(pa-h*ba);
}
void main()
{
float ar = iResolution.x / iResolution.y;
vec2 uv = -1.0 + 2.0 * gl_FragCoord.xy / iResolution.xy;
uv.x *= ar;
float th = 0.0;
vec2 v1;
vec2 v2;
vec2 rect = size;
rect.x *= ar;
if(rect.x < rect.y) {
th = rect.x;
v1 = vec2(0.0, -rect.y + th) ;
v2 = vec2(0.0, rect.y - th) ;
}
else {
th = rect.y;
v1 = vec2(-rect.x + th, 0.0) ;
v2 = vec2( rect.x - th, 0.0) ;
}
float d = udSegment( uv, v1, v2 )- th;
vec3 col = vec3(1.0- sign(d));
col *= 1.0 - exp( -600.0/ (blur * 1000.0 + 1.0) * abs(d));
FragColor = vec4( col, 1.0 );
}

View File

@@ -0,0 +1,37 @@
#version 330 core
out vec4 FragColor;
in vec4 vertexColor;
in vec2 vertexUV;
// from General Shader
uniform vec3 iResolution; // viewport resolution (in pixels)
uniform mat4 iTransform; // image transformation
uniform vec4 color; // drawing color
uniform vec4 uv;
// Mask Shader
uniform vec2 size; // size of the mask area
uniform float blur; // percent of blur
float sdRoundSide( in vec2 p, in vec2 b, in float r )
{
vec2 q = vec2(1.0, -1.0) * p - b + r;
return min(max(q.x,q.y),0.0) + length(max(q,0.0)) - r;
}
void main()
{
vec2 uv = -1.0 + 2.0 * gl_FragCoord.xy / iResolution.xy;
uv.x *= iResolution.x / iResolution.y;
vec2 s = 2.0 - size;
float d = sdRoundSide( uv, vec2(s.x * iResolution.x/iResolution.y, s.y), blur );
vec3 col = vec3(1.0 - sign(d));
float delta = 0.5 * length(min(size, 1.0));
col *= 1.0 - exp( -200.0/ (blur * 1000.0 * delta + 1.0) * abs(d) );
FragColor = vec4( col, 1.0 );
}

View File

@@ -0,0 +1,32 @@
#version 330 core
out vec4 FragColor;
in vec4 vertexColor;
in vec2 vertexUV;
// from General Shader
uniform vec3 iResolution; // viewport resolution (in pixels)
uniform mat4 iTransform; // image transformation
uniform vec4 color; // drawing color
uniform vec4 uv;
// Mask Shader
uniform vec2 size; // size of the mask area
uniform float blur; // percent of blur
float sdVertical( in vec2 p, in float x )
{
float d = step(0.0, x);
d = d * smoothstep(0.0, 2.0 * blur, x + p.x) + (1.0-d)*smoothstep(-2.0 * blur, 0.0, (-2.0 * blur) - (x + p.x));
return d;
}
void main()
{
vec2 uv = -1.0 + 2.0 * gl_FragCoord.xy / iResolution.xy;
float d = sdVertical( uv, -size.x);
FragColor = vec4( vec3(d), 1.0 );
}

View File

@@ -1,6 +1,6 @@
name: vimix
base: core18
version: '0.4'
version: '0.5'
summary: Live video mixing
title: vimix
description: |
@@ -51,6 +51,7 @@ parts:
- libglfw3-dev
- libgstreamer1.0-dev
- libgstreamer-plugins-base1.0-dev
- libicu-dev
stage-packages:
- zenity
- libpng16-16

View File

@@ -22,6 +22,14 @@ XMLElement *tinyxml2::XMLElementFromGLM(XMLDocument *doc, glm::ivec2 vector)
return newelement;
}
XMLElement *tinyxml2::XMLElementFromGLM(XMLDocument *doc, glm::vec2 vector)
{
XMLElement *newelement = doc->NewElement( "vec2" );
newelement->SetAttribute("x", vector.x);
newelement->SetAttribute("y", vector.y);
return newelement;
}
XMLElement *tinyxml2::XMLElementFromGLM(XMLDocument *doc, glm::vec3 vector)
{
XMLElement *newelement = doc->NewElement( "vec3" );
@@ -62,6 +70,14 @@ void tinyxml2::XMLElementToGLM(XMLElement *elem, glm::ivec2 &vector)
elem->QueryIntAttribute("y", &vector.y);
}
void tinyxml2::XMLElementToGLM(XMLElement *elem, glm::vec2 &vector)
{
if ( !elem || std::string(elem->Name()).find("vec2") == std::string::npos )
return;
elem->QueryFloatAttribute("x", &vector.x); // If this fails, original value is left as-is
elem->QueryFloatAttribute("y", &vector.y);
}
void tinyxml2::XMLElementToGLM(XMLElement *elem, glm::vec3 &vector)
{
if ( !elem || std::string(elem->Name()).find("vec3") == std::string::npos )
@@ -102,7 +118,7 @@ void tinyxml2::XMLElementToGLM(XMLElement *elem, glm::mat4 &matrix)
}
XMLElement *tinyxml2::XMLElementEncodeArray(XMLDocument *doc, void *array, unsigned int arraysize)
XMLElement *tinyxml2::XMLElementEncodeArray(XMLDocument *doc, const void *array, uint arraysize)
{
// create <array> node
XMLElement *newelement = doc->NewElement( "array" );
@@ -141,63 +157,68 @@ XMLElement *tinyxml2::XMLElementEncodeArray(XMLDocument *doc, void *array, unsig
return newelement;
}
bool tinyxml2::XMLElementDecodeArray(XMLElement *elem, void *array, unsigned int arraysize)
bool tinyxml2::XMLElementDecodeArray(XMLElement *elem, void *array, uint arraysize)
{
bool ret = false;
// sanity check
if (array==nullptr || arraysize==0)
return ret;
// make sure we have the good type of XML node
if ( !elem || std::string(elem->Name()).compare("array") != 0 )
return ret;
// make sure the stored array is of the requested array size
unsigned int len = 0;
uint len = 0;
elem->QueryUnsignedAttribute("len", &len);
if ( arraysize != len )
return ret;
if (len == arraysize)
{
// read and decode the text field in <array>
gsize decoded_size = 0;
guchar *decoded_array = g_base64_decode(elem->GetText(), &decoded_size);
// read and decode the text field in <array>
gsize decoded_size = 0;
guchar *decoded_array = g_base64_decode(elem->GetText(), &decoded_size);
// if data is z-compressed (zbytes size is indicated)
uint zbytes = 0;
elem->QueryUnsignedAttribute("zbytes", &zbytes);
if ( zbytes > 0) {
// sanity check 1: decoded data size must match the buffer size
if ( decoded_array && zbytes == (uint) decoded_size ) {
// if data is z-compressed (zbytes size is indicated)
uint zbytes = 0;
elem->QueryUnsignedAttribute("zbytes", &zbytes);
if ( zbytes > 0) {
// sanity check 1: decoded data size must match the buffer size
if ( decoded_array && zbytes == (uint) decoded_size ) {
// allocate a temporary array for decompressing data
uLong uncompressed_size = len;
gchar *uncompressed_array = g_new(gchar, uncompressed_size);
// allocate a temporary array for decompressing data
uLong uncompressed_size = arraysize;
gchar *uncompressed_array = g_new(gchar, uncompressed_size);
// zlib uncompress ((Bytef *dest, uLongf *destLen, const Bytef *source, uLong sourceLen));
uncompress((Bytef *)uncompressed_array, &uncompressed_size,
(Bytef *)decoded_array, (uLong) zbytes) ;
// zlib uncompress ((Bytef *dest, uLongf *destLen, const Bytef *source, uLong sourceLen));
uncompress((Bytef *)uncompressed_array, &uncompressed_size,
(Bytef *)decoded_array, (uLong) zbytes) ;
// sanity check 2: decompressed data size must match array size
if ( uncompressed_array && arraysize == uncompressed_size ){
// sanity check 2: decompressed data size must match array size
if ( uncompressed_array && len == uncompressed_size ){
// copy to target array
memcpy(array, uncompressed_array, len);
// success
ret = true;
}
// free temp decompression buffer
g_free(uncompressed_array);
}
}
// data is not z-compressed
else {
// copy the decoded data
if ( decoded_array && len == decoded_size ) {
// copy to target array
memcpy(array, uncompressed_array, arraysize);
memcpy(array, decoded_array, len);
// success
ret = true;
}
// free temp decompression buffer
g_free(uncompressed_array);
}
}
// data is not z-compressed
else {
// copy the decoded data
if ( decoded_array && arraysize == decoded_size )
memcpy(array, decoded_array, arraysize);
// success
ret = true;
}
// free temporary array
g_free(decoded_array);
// free temporary array
g_free(decoded_array);
}
return ret;
}

View File

@@ -2,6 +2,10 @@
#define TINYXML2TOOLKIT_H
#include <string>
#ifdef __APPLE__
#include <sys/types.h>
#endif
#include <glm/glm.hpp>
namespace tinyxml2 {
@@ -10,17 +14,19 @@ class XMLDocument;
class XMLElement;
XMLElement *XMLElementFromGLM(XMLDocument *doc, glm::ivec2 vector);
XMLElement *XMLElementFromGLM(XMLDocument *doc, glm::vec2 vector);
XMLElement *XMLElementFromGLM(XMLDocument *doc, glm::vec3 vector);
XMLElement *XMLElementFromGLM(XMLDocument *doc, glm::vec4 vector);
XMLElement *XMLElementFromGLM(XMLDocument *doc, glm::mat4 matrix);
void XMLElementToGLM(XMLElement *elem, glm::ivec2 &vector);
void XMLElementToGLM(XMLElement *elem, glm::vec2 &vector);
void XMLElementToGLM(XMLElement *elem, glm::vec3 &vector);
void XMLElementToGLM(XMLElement *elem, glm::vec4 &vector);
void XMLElementToGLM(XMLElement *elem, glm::mat4 &matrix);
XMLElement *XMLElementEncodeArray(XMLDocument *doc, void *array, unsigned int arraysize);
bool XMLElementDecodeArray(XMLElement *elem, void *array, unsigned int arraysize);
XMLElement *XMLElementEncodeArray(XMLDocument *doc, const void *array, uint arraysize);
bool XMLElementDecodeArray(XMLElement *elem, void *array, uint arraysize);
bool XMLSaveDoc(tinyxml2::XMLDocument * const doc, std::string filename);
bool XMLResultError(int result);