This post contains a Matlab example to see how  trajectory of the Lorenz attractor is evolving as time flow and the Lorenz attractor is shown below.






Below is the M file used to generate the above picture.


%% Imlements the Lorenz System ODE

%   dx/dt = sigma*(y-x)

%   dy/dt = x*(rho-z)-y

%   dz/dt = xy-beta*z



clear all;


%% Settings for Lorenz system

global sigma rho beta


% Standard constants for the Lorenz Attractor

sigma = 10;

rho = 28;

beta = 8/3;


tmax = 1000;


start_point = [1.0 1.0 1.0];


%% Function declaration

%[t,y] = ode45(@mylorenz,[0 1000], [1.0 1.0 1.0]);


f = @(t,y) [sigma*(y(2) - y(1)); -y(1)*y(3) + rho*y(1) - y(2); y(1)*y(2) - beta*y(3)];


% To plot a trajectory in the phase plane starting at a point (a1, a2) at 

%   time t=0 for increasing values of t going from 0 to 4 type

[ts,ys] = ode45(f,[0,tmax],start_point);


syms t y1 y2 y3

F = f(t,[y1;y2;y3])


[y1s,y2s,y3s] = solve(F(1),F(2),F(3),y1,y2,y3)


plot3(y1s(1),y2s(1),y3s(1),'*', y1s(2),y2s(2),y3s(2),'>', y1s(3),y2s(3),y3s(3),'o');

strCrit1 = ['(',num2str(double(y1s(1))),',',num2str(double(y2s(1))),',',num2str(double(y3s(1))),')'];

strCrit2 = ['(',num2str(double(y1s(2))),',',num2str(double(y2s(2))),',',num2str(double(y3s(2))),')'];

strCrit3 = ['(',num2str(double(y1s(3))),',',num2str(double(y2s(3))),',',num2str(double(y3s(3))),')'];

%legend(strCrit1,strCrit2,strCrit3,'Location','northoutside','Orientation','horizontal')

legend(strCrit1,strCrit2,strCrit3);


[t,y] = ode45(@mylorenz,[0 tmax], start_point);


h = animatedline;

h.Color = [0 0 1];


%# initialize point

spot = line('XData',y(1,1), 'YData',y(1,2), 'ZData',y(1,3), ...

        'Color','r', 'marker','.', 'MarkerSize',50);

    

for k = 1:length(t)

    addpoints(h,y(k,1),y(k,2),y(k,3));

    set(spot,'XData',y(k,1), 'YData',y(k,2), 'ZData',y(k,3))    %# update X/Y data

    str = ['Time: ',num2str(k)];

    %set(hTxt,'String',str);         %# update time tick

    title(['Time ',str,' Ticks'])

    drawnow

    if ~ishandle(h), return; end             %# end running in case you close the figure

end


grid on;



And another m file: mylorenz.m


% mylorenz.m

%

% Imlements the Lorenz System ODE

%   dx/dt = sigma*(y-x)

%   dy/dt = x*(rho-z)-y

%   dz/dt = xy-beta*z

%

% Inputs:

%   t - Time variable: not used here because our equation

%       is independent of time, or 'autonomous'.

%   x - Independent variable: has 3 dimensions

% Output:

%   dx - First derivative: the rate of change of the three dimension

%        values over time, given the values of each dimension


function dy = mylorenz(t,y)


global sigma rho beta


% Standard constants for the Lorenz Attractor

%sigma = 10;

%rho = 28;

%beta = 8/3;


% I like to initialize my arrays

dy = [0; 0; 0];

%dy = zeros(3,1);


dy(1) = sigma*(y(2) - y(1));

dy(2) = -y(1)*y(3) + rho*y(1) - y(2);

dy(3) = y(1)*y(2) - beta*y(3);



Posted by kevino
,

In here, I will update several tips which helped me to create games using the Unreal Engine 4.


Tip List:


1. Split a FBX file with many animation takes into multiple fbx files and import those FBX files.

2. To be continued ...



1. Split a FBX file with many takes into multiple fbx files and import those FBX files.


Split FBX


If you need to import FBX animations, you need to seperate a single FBX with a long take into multiple fbx files because Unreal Engine 4 seems to not support that( Please correct me if I am wrong). To do that, refer to the following link.


http://wiki.etc.cmu.edu/unity3d/index.php/Importing_and_Exporting_Models_(Maya)


Caution: Don't forget to set the timeline slider to the specified animation as depicted below







Importing FBXs


Firstly, import a base FBX file with no animation to get static mesh and skeleton info.

Then import split FBX files in UEditor. In the import dialog, make sure to set skeleton to one which was taken in importing base FBX.



2. To be added ...

Posted by kevino
,

OpenCV tips

프로그래밍/OpenCV 2014. 3. 31. 20:56

Here are some useful tips which helped me a lot in programming with OpenCV and I recorded those here because I don't want to spend my time again to find such rare tips.


List


1. Problem which drawing primitives such as line, ellipse, text with certain NON-White scalar color on image of type cv::Mat produce only WHITE colored traces (RGB(255,255,255)). 


Recommendation: Firstly, check whether the input image type is CV_8UC4. If so, then converted the input to CV_8UC4 using cvtColor(). Look below example.


cvtColor(image, image, CV_RGBA2BGR);

Whole story can be founded here.


2. To be added later...


   

Posted by kevino
,

Useful commands used in Windows commands shell


As Unix script language is actually quit powerful to do manipulate text, files/directories and so on, on Windows machine, there are many ways to do the same jobs. Here some useful examples which can be used in normal Windows .bat or .cmd and are also quit helpful in many option menus supported in Visual Studio. For example, before actual compilation of a project, someone may want to copy or create resources necessary to build binary to certain location or add a time stamp string to many source code files. For this purpose, we can add custom commands in Pre-build Event options of Visual Studio property setting window. 


So hope these examples show you a guidance on that. Again this information were taken from various link which I cannot remember correctly.



1. Searching files having specific extension in its file name in current folder


for %%f in (*.java *.cmd) do echo  %%f


2. Searching files with .java extension recursively  


dir /b /s /a-d | findstr /i ".java$


3. Find and delete files with certain name recursivly

 i) In batch file,

    for /f "usebackq" %%i in (`dir /s /b ^| find "Makefile"`) do echo %%i

 ii) In command line,

    for /f "usebackq" %i in (`dir /s /b ^| find "Makefile"`) do echo %i


 ** Note: replace "echo" with "del" to delete file instead of echoing file name.


4. Create array containing file names with full path located in specific folder. Note: In Windows there seems a limitation in assigning array from command line with use of pipe. So this is different trial to do that.

setlocal enabledelayedexpansion enableextensions

set LIST=

for %%x in (javaSourceFolder\*.java) do set LIST= %%x

set LIST=%LIST:~1%


5. Compiling all java files located at specific folder

---- Assuming %LIST% having file list with full path  ---

for %%f in (%LIST%) do (

 "$(JDK_ROOT)\bin\javac.exe" -d $(IntDir)$(JavaOutputDir) -classpath $(IntDir)$(JavaOutputDir) -classpath $(AndroidSdkApiDir)/android.jar %%f

)


6. QT

When you need to decide which build configuration among 32bit and 64bit, don't forget to keep using only one configuration. For example, if you develop qt application using Visual Studio C/C++ 20xx and want to use command prompt to build it, you need to choose build environment among 32bit, 64bit and 64bit_opengl. Once you pick one among them, DON'T FORGET to call proper bat file for Visual Studio compilation setup.


If you want 32bit QT application, run below command after opening QT command prompt

call "C:\Program Files (x86)\Microsoft Visual Studio 11.0\VC\bin\vcvarsall.bat" x86


If you want 64bit QT application, run below command after opening QT command prompt

call "C:\Program Files (x86)\Microsoft Visual Studio 11.0\VC\bin\vcvarsall.bat" x64


7. later...


Posted by kevino
,

MODBUS is a communication protocol over a variety of  networks such as RS232 and Ethernet which was designed by Modicon.

It has been used widely since last several ten years and FreeMODBUS is a free implementation of this popular MODBUS protocol. 


Recently I wanted to have a tool to share data between some embedded devices over serial connection or ethernet and heard MODBUS can be a starting point for such purpose. So this is the outcome.


This MBServer ( a sample MODBUS TCP server) supports Qt5 but for now no GUI. Later I will put some GUI on it to talk with devices which can support MODBUS. For someone with interests on this can find source tree in the following link.  


https://github.com/seetime/freeMBServer/


How to build:


You need to have Cmake to generate Visual studio C++ project file.


First download source file and enter the root folder


cd <MBServer_root_dir>

mkdir build

cd build

cmake ..


With the project file generated, open it in Visual studio IDE and build and run.

 

For test, I used a MODBUS Diagnostick tool such as Modsak.  



Conclusion.


If someone need to develop application to talk with remote device over serial or Ethernet, MODBUS can be a option for such. This post could be helpful for someone searching or wanting to develop a basic MODBUS server tool. 


Posted by kevino
,

This article is written to show how CMake can be used to build OpenCL related application.

The sample code used here was grabbed from here and its main job is to apply simple Gaussian blur filter on test input image and saving output into a file. For better understanding about how OpenCL code works for Gaussian blur filtering, refer to the above link. I just wanted to build it on my machine to know how OpenCL application work so all credit on the source code should be given to Anteru which can be reached via https://anteru.net/2012/11/05/2022/.



Tested environment


1. Windows 7 with AMD OpenCL SDK

2. Windows 7 with Intel OpenCL SDK

3. MAC OSX 10.7


Below is CMakeLists.txt file used in this project.


CMakeLists.txt


As you can see, it is simple and no description on kernel CL source code because exe file will seek and compile it on run time. Please note that exe file should be located in the same folder with main source code to be able to read test input image and kernel CL code file.


For ones seeking zip file, use this file.

Anteru-opencltutorial.7z




Posted by kevino
,

QEMU can be very useful tool in developing wide range of software from simple application to even linux kernel itself for arm based embedded system. Here is to show how developing and debugging simple application for virtual arm based platform with QEMU is actually easy to people who are lazy so hate to move his/her finger to turn on real board and for poor people who do not have any real hardware.


Note: This post assume Host system is fairly new Ubuntu machine(For my case, its ubuntu 12.04 64bit)


Below is list for bullet items which this post focus.


1. How to build simple c application with a assembly library which can be callable in c function.

2. How to run the executable in Qemu

3. Debugging it with gdb



Phase 0. TOOL Setup


Before delving into programming, we need to check all necessary tools ready. Please refer to below command to install all of them. 


First install linaro image tools.


host$ sudo apt-get install linaro-image-tools


To get qemu to work with, there are two ways to building from source code and using apt-get but here I used apt-get as like below.


host$ sudo add-apt-repository ppa:linaro-maintainers/tools
host$ sudo apt-get update
host$ sudo apt-get install qemu-user-static qemu-system

To be able to compile c and assembly, we need to install crosstool chain for arm.


host$ sudo apt-get install gcc-arm-linux-gnueabi


Phase 1. Creating a simple application made up of c and assembly combination 


I wrote some articles in this site how to create CMake project so here I would like to show only source code without detailed explanation about it and why it is needed.


There are 4 files required in the project. 

1. main.c                                          # main c source code including main()

2. square.s                                       # assembly file containing functions callable in main() 

3. CMakeLists.txt                               # main cmake project file

4. toolchain-for-qemuarm.cmake          # cmake module used for cross compilation for arm target system


So just create below all 4 files in a $(EXAMPLE) directory.


main.c


square.s


CMakeLists.txt



toolchain-for-qemuarm.cmake


Note: Here I used gcc toolchain from Freescale site but you may use other popular toolchain also.


One you have those file, it is easy to build binary which will be run on qemu.


host$ mkdir build; cd build

host$ cmake -DCMAKE_TOOLCHAIN_FILE=../toolchain-for-qemuarm.cmake ..


Now you can check arm executable created correctly

host$ arm-linux-gnueabi-readelf ./program -a | more

ELF Header: Magic: 7f 45 4c 46 01 01 01 00 00 00 00 00 00 00 00 00 Class: ELF32 Data: 2's complement, little endian Version: 1 (current) OS/ABI: UNIX - System V ABI Version: 0 Type: EXEC (Executable file) Machine: ARM Version: 0x1 Entry point address: 0x8538 Start of program headers: 52 (bytes into file) Start of section headers: 3592 (bytes into file) Flags: 0x5000002, has entry point, Version5 EABI

For source codes, download this. 

cassemtest.tar.gz



Phase 2. Test with QEmu

The built program depends on external libary called ld-linux.so.3 and this is arm side shared libary. So qemu need to know where to find correct shared library for this arm friendly executable. In below, I informed /usr/arm-linux-gnueabi which was created when I installed cross-toolchain mentioned in phase 0. ( FYI, when I used one included in freescale toolchain, system got corrupted for uncertain reason)

host$ qemu-arm-static -L /usr/arm-linux-gnueabi ./program

sum(1, 100) = 101 Hello, ARM World!

The printed message above shows that program ran as intended.


Phase 3. Debugging with Qemu + gdb

With gdb, user can debug application in source level. I already gave option "SET(CMAKE_BUILD_TYPE debug)" to include debug symbol in the executable by including one line in CMakeList.txt so the executable should contain symbol table in itself.

host$ qemu-arm-static -g 1234 -L /usr/arm-linux-gnueabi ./program


With -g 1234 option in the above command, qemu is waiting for gdb connection via port 1234 of localhost.

host$ sudo apt-get install gdb-multiarch

host$ gdb-multiarch

...

(gdb) file program

Reading symbols from /home/<user>/work/qemu/linaro/examples/cassemtest/build/program...done.

(gdb) target remote localhost:1234

Remote debugging using localhost:1234 [New Remote target] warning: Unable to find dynamic linker breakpoint function. GDB will be unable to debug shared library initializers and track explicitly loaded dynamic code. [Switching to Remote target] 0xf67dfc40 in ?? ()

(gdb) b main

Breakpoint 1 at 0x85f0: file /home/<user>/work/qemu/linaro/examples/cassemtest/main.c, line 8.

(gdb) c

Continuing. warning: Could not load shared library symbols for 2 libraries, e.g. /lib/libc.so.6. Use the "info sharedlibrary" command to see the complete listing. Do you need "set solib-search-path" or "set sysroot"? Breakpoint 1, main () at /home/<user>/work/qemu/linaro/examples/cassemtest/main.c:8 8 int a=1, b =100;


Conclusion


So far showed how simple application debugging with qemu can be done and hope this post will help app development for embedded system under qemu sandbox which will throw away any worry to break system due to SW bug.

   



Posted by kevino
,

On Mac, it was hard to find out how to capture web camera input to me and this is to share what i found in dealing with gstreamer to capture live webcam input on my Macbook running OS X 10.7.5.



To use GStreamer, the necessary package should be installed and the following link shows how to install it.


http://docs.gstreamer.com/display/GstSDK/Installing+on+Mac+OS+X


Before running gst-launch, few more steps are needed because the path containing the gst binaries may not be included in PATH env variable. I recommend that few symbolic links to gst binaries be created in /usr/bin/ path.

For example, at command line, run below command to create those files.


$ sudo ln -s /Library/Frameworks/GStreamer.framework/Versions/Current/bin/gst-launch-0.10 /usr/bin/gst-launch

$ sudo ln -s /Library/Frameworks/GStreamer.framework/Versions/Current/bin/gst-inspect-0.10 /usr/bin/gst-inspect


Now we can test whether gstreamer is working properly.


Example 1: Testing with pre-made video source in gstreamer and displaying it in a window.


$ gst-launch videotestsrc ! osxvideosink


Example 2: Displaying webcam input in a window


$ gst-launch autovideosrc ! osxvideosink



Example 3: Grabbing one frame from webcam and saving it as jpeg


$ gst-launch -v -e autovideosrc num-buffers=1 ! jpegenc ! filesink location=capture1.jpeg


So far, all examples above are shown as command line use case.

Before completing this post, here come a sample c source code with cmake script which will ease developing user application for one's own use. The source file is taken from gstreamer tutorial page at http://docs.gstreamer.com/pages/viewpage.action?pageId=327735 so if details about it is required, then you can check it also in the link.


This project source was tested with my macbook.



gst-example-prj.tar.7z


 

Posted by kevino
,

이번 글은 리눅스 커널 3.6버전 부터 공식적으로 지원하는 device tree 에 관련된 몇가지 유용한 정보를 담고 있다.


우선 device tree에 대한 것을 최대한 간단히 설명하면 하드웨어를 기술하는 데이터 구조라고 www.devicetree.org에 나와 있는데 좀더 자세한 내용은 그쪽 사이트를 참조하도록 하고 여기에서는 개인적으로 이해하고 있는 내용을 그때 그때 추가해놓았다. 사실 devicetree는 방대한 개념이어서 이것을 모두 설명하기는 힘드니 필요할때마다 여기에 추가해서 갱신하고자 한다.


첫째, device tree는 범용적으로 하드웨어를 기술할 수 있는 데이터 구조만을 정의해놓아서 수만 수천가지의 장치에 대해 모두 동일하게 작성한다는 것이 불가능하기에 그때 그때 상황에 맞추어서 작가가 나름의 구조를 고안해서 작성하게 된다. 그래서 플랫폼마다 독자적인 개성을 가진 구조를 가지게 되고 그것을 접해보지 못한 작가가 만들어 놓은 device tree script(이하 dts )를 그대로 이용하려는 경우 적용이 불가능하게 되는 경우도 생겨서 이런 것들을 지원하려다 보면 부득이하게 새로운 구조라든지 device tree compiler(이하 dtc)에서 지원하는 새로운 키워드라든지 문구를 새로 만들기도 한다. 


beaglebone black(이하 BBB)에서도 마찬가지로 인터넷에서 떠돌아다니는 dts를 받아다 기본적으로 설치되어 있는 dtc로 컴파일하려하면 컴파일 오류를 만들어 내는 경우가 있을 수 있다. 이런 경우에는 기본설치된 dtc가 해당 dts에서 지원하는 문법을 지원하지 못하기에 발생하는 문제인데 이런 경우는 새로운 dtc 소스를 받아다가 몇몇 패치를 적용해서 만들어진 dtc를 이용하면 문제가 해결된다. 아래 방법을 보였는데 필요한 경우 원소스를 밝히니 참고하기 바란다.



우선 BBB에서 동작하는 dts가 필요한데 여기서는 다음링크에 있는 dts를 참고하기로 한다.


http://hipstercircuits.com/capture-input-events-via-gpio-on-beaglebone-black/


/dts-v1/;
/plugin/;

/ {
    compatible = "ti,beaglebone", "ti,beaglebone-black";

    /* identification */
    part-number = "BB-GPIO-KEYS";
    version = "00A0";

    fragment@0 {
        target = <&am33xx_pinmux>;
        __overlay__ {
            end_stop_pins: pinmux_end_stop_pins{
                pinctrl-single,pins = <
                    0x090 0x37 // P8_7  = End stop X1  = GPIO2_2
                    0x070 0x37 // P9_11 = End stop Y1  = GPIO0_30
                    0x074 0x37 // P9_13 = End stop Z1  = GPIO0_31
                    0x158 0x37 // P9_18 = End stop Z2  = GPIO0_4
                    0x1AC 0x37 // P9_25 = End stop Y2  = GPIO3_21
                    0x180 0x37 // P9_26 = End stop X2  = GPIO0_14
                >;
            };
        };
    };

    fragment@1 {
        target = <&ocp>;
        __overlay__ {            
            #address-cells = <1>;
            #size-cells = <1>;                            

            gpio_keys {
                compatible = "gpio-keys";
                pinctrl-names = "default";
                pinctrl-0 = <&end_stop_pins>;
                #address-cells = <1>;
                #size-cells = <0>;

                switch_x1 {
                    label = "End-stop-X1";
                    debounce_interval = <50>;
                    linux,code = <1>;
                    gpios = <&gpio3 2 0x5>;
                    gpio-key,wakeup;
                };                
                switch_x2 {
                    label = "End-stop-X2";
                    debounce_interval = <50>;
                    linux,code = <2>;
                    gpios = <&gpio1 14 0x5>;
                    gpio-key,wakeup;
                };
                switch_y1 {
                    label = "End-stop-Y1";
                    debounce_interval = <50>;
                    linux,code = <3>;
                    gpios = <&gpio1 30 0x5>;
                    gpio-key,wakeup;
                };                
                switch_y2 {
                    label = "End-stop-Y2";
                    debounce_interval = <50>;
                    linux,code = <4>;
                    gpios = <&gpio4 21 0x5>;
                    gpio-key,wakeup;
                };                
                switch_z1 {
                    label = "End-stop-Z1";
                    debounce_interval = <50>;
                    linux,code = <5>;
                    gpios = <&gpio1 31 0x5>;
                    gpio-key,wakeup;
                };                
                switch_z2 {
                    label = "End-stop-Z2";
                    debounce_interval = <50>;
                    linux,code = <6>;
                    gpios = <&gpio1 4 0x5>;
                    gpio-key,wakeup;
                };                
            };
        };
    };
};


위의 dts를 보면 두번째줄 /plugin/문구가 있는데 이것을 기본설치된 dtc로 컴파일하면 오류가 나면서 실패하게 된다. 이를 해결하기 위해서는 다음과 같이 패치된 dtc를 이용해야 한다.(출처:http://derekmolloy.ie/beaglebone/beaglebone-gpio-programming-on-arm-embedded-linux/)


$ git clone git://www.jdl.com/software/dtc.git
$ cd dtc
$ git checkout 27cdc1b16f86f970c3c049795d4e71ad531cca3d
$ wget https://github.com/beagleboard/meta-beagleboard/raw/master/common-bsp/recipes-kernel/dtc/dtc/0001-dtc-Dynamic-symbols-fixup-support.patch
$ patch -p1 < 0001-dtc-Dynamic-symbols-fixup-support.patch
$ make

위의 결과로 만들어진 dtc로 컴파일 하면 위의 dts가 정상적으로 컴파일될수 있다. 여기서 만들어진 dtbo를 리눅스 커널에 적재하려면 위의 언급된 사이트에 기술된 내용대로 하면 된다. 물론 위의 dts는 기본 BBB와 별도의 키입력용으로 만들어진 확장 보드를 동작시키기 위한 파일로 기본 BBB만 가지고는 실행할수 있는 있되 기능동작확인은 되지 않는 점을 밝혀둔다.



Posted by kevino
,

In Qt5, writing Cmake project for building Qt5 opengl app with optional shader seems to be little complicated comparing to previous Qt version(i.e Qt v5.0.2) and took time to figure out how to configure all necessary things. After many hours on this issue, I found one configuration to make possible to building Qt5 opengl app with Cmake and this post is to describe what I did with helps from various internet sources which will be listed below accordingly.


First thing to tell is preconditions before writing sources.


Precondition


1. OS: MS Windows 7

2. Qt version and toolkit: prebuilt Qt 5.1.0 msvc2010_opengl

3. Visual studio 2010

4. Windows SDK should be installed properly. : ie) c:\Program Files (x86)\Microsoft SDKs\Windows\v7.0A\Lib\

5. CMake 2.8.11


If your system is different with the above precondition, CMakeLists.txt should be changed properly. Refer to the example CMakeLists.txt in this post. You can get a hint about how to edit.


Now it is time to introduce source code for building a simple Qt5 opengl shader app. 


Because main purpose to write up this post is to show how to create CMakeLists.txt to compile existing source codes, just copy and create all 3 files referring to this link:  http://qt-project.org/doc/qt-5.0/qtgui/openglwindow.html


And last file CMakeLists.txt.


CMakeLists.txt


Now we have all files to build up Qt5 shader app showing rotating triangle and time to run cmake to create visual studio project file for this app. If you are lucky to complete compilation and launching this app, then you will see a rotating triangle with help of Opengl shader in a window.



One last thing I want to note is that CMAKE_PREFIX_PATH in CMakeLists.txt MUST include proper paths in order to succeed compilation. As you can see in the above example, there are two paths are included.

First path is the location to find all neccessary Qt5 tools and must be same with the path in below picture. Below picture shows Qt Options dialog box in Visual studio 2010 through "Qt5" -> "Qt5 options" which is enabled if you installed visual studio addin for Qt5





Second path in CMAKE_PREFIX_PATH is required to compile with OpenGL library: glu32.lib and opengl32.lib. These files are included in Windows SDK so make sure this before starting compilation and also don't forget to include TARGET_LINK_LIBRARIES in the above example. Otherwise, opengl libraries will not be included in the project file generated by cmake.


Added 2013-09-23.


You may notice below error message on compilation.

Error message=> module machine type 'x64' conflicts with target machine type 'X86'


This error message happens when you create visual studio project file for 32 bit binary and try to compile against 64 bit library. The default behavior of running "cmake .." on 64 bit machine usually generates 32 bit project instead of 64 bit project file so this may cause compilation error.


Solution. Try to generate 64 bit visual studio project file using below command and compile binary with it.

cmake -G "Visual Studio 11 Win64" ..


Below is source code for your convenience.


qt5shader.7z


Posted by kevino
,