├── CMakeLists.txt
├── LICENSE
├── README.md
├── include
├── Camera.hpp
├── DynamicSystemParser
│ ├── DynamicSystemParser.hpp
│ └── Impl
│ │ └── DynamicSystemParserImpl.hpp
├── DynamicSystemWrapper.hpp
├── DynamicSystems
│ ├── DynamicSystem.hpp
│ ├── Impl
│ │ ├── DynamicSystemImpl.hpp
│ │ └── DynamicSystemInternal.hpp
│ └── SystemsBase
│ │ ├── SystemsBase.hpp
│ │ └── SystemsBaseGetImpl.hpp
├── Locus.hpp
├── Model
│ ├── Impl
│ │ └── ModelImpl.hpp
│ └── Model.hpp
├── Parser
│ ├── Lexer.hpp
│ ├── Parser.hpp
│ ├── ParserException.hpp
│ └── ParserNodes.hpp
├── PointsViewQGLWidget.hpp
├── Preferences.hpp
├── ShaderController.hpp
├── StoppableTask.hpp
├── VideoEncoder.hpp
├── Window.hpp
└── WindowPreferences.hpp
├── materials
├── FragmentShader.fsh
├── GeometryShaderLines.gsh
├── GeometryShaderPoints.gsh
├── Resources.qrc
└── VertexShader.vsh
├── src
├── Camera.cpp
├── DynamicSystemParser
│ └── DynamicSystemParser.cpp
├── Locus.cpp
├── Parser
│ ├── Lexer.cpp
│ └── Parser.cpp
├── PointsViewQGLWidget.cpp
├── Preferences.cpp
├── ShaderController.cpp
├── VideoEncoder.cpp
├── Window.cpp
├── WindowPreferences.cpp
├── form.ui
├── formPreferences.ui
└── main.cpp
└── test
├── CMakeLists.txt
├── testAll.cpp
├── testParser.cpp
└── testSystems.cpp
/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | cmake_minimum_required(VERSION 3.15)
2 |
3 | set(CMAKE_INCLUDE_CURRENT_DIR ON)
4 |
5 | set(CMAKE_AUTOUIC ON)
6 | set(CMAKE_AUTOMOC ON)
7 | set(CMAKE_AUTORCC ON)
8 |
9 | set(CMAKE_CXX_STANDARD 17)
10 | set(CMAKE_CXX_STANDARD_REQUIRED ON)
11 |
12 | set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Ofast -pipe -Wall -Wextra")
13 | set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -D__STDC_CONSTANT_MACROS")
14 |
15 | project(DynamicSystems)
16 |
17 | include_directories(include/)
18 |
19 | find_package(Qt5Widgets REQUIRED)
20 | find_package(Qt5OpenGL REQUIRED)
21 | find_package(OpenGL REQUIRED)
22 | find_package(Threads REQUIRED)
23 |
24 |
25 | find_path(AVCODEC_INCLUDE_DIR libavcodec/avcodec.h)
26 | find_library(AVCODEC_LIBRARY avcodec)
27 |
28 | find_path(AVFORMAT_INCLUDE_DIR libavformat/avformat.h)
29 | find_library(AVFORMAT_LIBRARY avformat)
30 |
31 | find_path(AVUTIL_INCLUDE_DIR libavutil/avutil.h)
32 | find_library(AVUTIL_LIBRARY avutil)
33 |
34 | find_path(AVSWS_INCLUDE_DIR libswscale/swscale.h)
35 | find_library(AVSWS_LIBRARY swscale)
36 |
37 | add_executable(DynamicSystems
38 | src/main.cpp
39 | src/WindowPreferences.cpp
40 | src/Camera.cpp
41 | src/PointsViewQGLWidget.cpp
42 | src/Window.cpp
43 | src/Locus.cpp
44 | src/Preferences.cpp
45 | src/VideoEncoder.cpp
46 | src/ShaderController.cpp
47 | src/DynamicSystemParser/DynamicSystemParser.cpp
48 | src/Parser/Parser.cpp
49 | src/Parser/Lexer.cpp
50 | include/Preferences.hpp
51 | include/Camera.hpp
52 | include/WindowPreferences.hpp
53 | include/Model/Model.hpp
54 | include/Model/Impl/ModelImpl.hpp
55 | include/DynamicSystems/DynamicSystem.hpp
56 | include/DynamicSystems/SystemsBase/SystemsBase.hpp
57 | include/DynamicSystems/SystemsBase/SystemsBaseGetImpl.hpp
58 | include/DynamicSystems/Impl/DynamicSystemImpl.hpp
59 | include/DynamicSystems/Impl/DynamicSystemInternal.hpp
60 | include/DynamicSystemParser/DynamicSystemParser.hpp
61 | include/DynamicSystemParser/Impl/DynamicSystemParserImpl.hpp
62 | include/Window.hpp
63 | include/DynamicSystemWrapper.hpp
64 | include/PointsViewQGLWidget.hpp
65 | include/StoppableTask.hpp
66 | include/Locus.hpp
67 | include/VideoEncoder.hpp
68 | include/ShaderController.hpp
69 | include/Parser/Parser.hpp
70 | include/Parser/ParserException.hpp
71 | include/Parser/ParserNodes.hpp
72 | include/Parser/Lexer.hpp
73 | src/form.ui
74 | src/formPreferences.ui
75 | materials/Resources.qrc
76 | )
77 |
78 | qt5_use_modules(DynamicSystems Widgets OpenGL)
79 |
80 | target_include_directories(DynamicSystems PRIVATE
81 | ${AVCODEC_INCLUDE_DIR}
82 | ${AVFORMAT_INCLUDE_DIR}
83 | ${AVUTIL_INCLUDE_DIR}
84 | ${AVSWS_INCLUDE_DIR}
85 | )
86 |
87 | target_link_libraries(DynamicSystems
88 | ${QT_LIBRARIES}
89 | ${OPENGL_LIBRARIES}
90 | ${AVCODEC_LIBRARY}
91 | ${AVFORMAT_LIBRARY}
92 | ${AVUTIL_LIBRARY}
93 | ${AVSWS_LIBRARY}
94 | Threads::Threads
95 | )
96 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2020 vladnosiv
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Modeling and visualization of dynamic systems
2 |
3 | 
4 |
5 | ## Introduction
6 |
7 | There are first-order differential equation systems on coordinates, which describe the position of points in space over time. Our application simulates them, thus allowing a convenient exploration of this area.
8 |
9 | In particular, the application already contains 35 systems that simulate classic strange attractors.
10 |
11 | Examples of equation systems: [Lorenz Attractor](https://en.wikipedia.org/wiki/Lorenz_system) and [Rössler Attractor](https://en.wikipedia.org/wiki/R%C3%B6ssler_attractor)
12 |
13 | ## UI
14 |
15 | The interface is implemented using Qt5. It includes:
16 | * Model selection
17 | * Selection of constants characterizing the model
18 | * Detailed settings of modeling and visualization
19 | * Video recording capability
20 | * Possibility to pause and fast-forward time
21 |
22 | 
23 |
24 | ## Simulation
25 |
26 | Simulation is carried out using the fourth-order Runge-Kutta method, with a constant step. Written in the style of metaprogramming to achieve maximum performance.
27 |
28 | To support models that are not integrated into the application, a mathematical equation parser has been implemented, which supports standard operations (+ - * /), brackets, and basic mathematical functions (sin, cos, exp, log, etc.).
29 |
30 | No additional libraries are used for calculations.
31 |
32 | ## Visualization
33 |
34 | Visualization is performed using OpenGL and the Qt wrapper over it.
35 |
36 | The application takes several points around the initial position, calculates their trajectories, and then displays the points with some tail of their trajectories. Points calculated by the model are interpolated by the Catmull-Rom curve.
37 |
38 | Free movement is implemented.
39 |
40 | For convenience, it is possible to record video in avi format. This uses the libav library. You can also take screenshots.
41 |
42 | ## OS Support
43 |
44 | The application is supported by the following operating systems:
45 | * Linux
46 | * Windows
47 | * MacOS
48 |
49 | ## Installation Instructions
50 | Required library versions:
51 | * Qt5 — 5.10 and higher.
52 | * libav (libavcodec, libavformat, libavutil, libswscale) — 57 and higher (but it is better to have at least 58).
53 | * OpenGL — 3.3 and higher.
54 |
55 | Next are instructions for specific OSs.
56 |
57 |
58 |
59 | Linux (U)buntu
60 |
61 |
62 | * Installing Qt:
63 | ```
64 | sudo apt-get install qt5-default
65 | ```
66 |
67 | * Installing libav:
68 | ```
69 | sudo apt-get install libavcodec-dev libavformat-dev libswscale-dev
70 | ```
71 |
72 | * Updating OpenGL:
73 | * To check the version:
74 | ```
75 | glxinfo | grep "OpenGL version"
76 | ```
77 | * If the version is below 3.3, you need to update:
78 | ```
79 | sudo add-apt-repository ppa:oibaf/graphics-drivers
80 | sudo apt-get update
81 | sudo apt-get upgrade
82 | ```
83 |
84 |
85 |
86 |
87 |
88 | Windows
89 |
90 |
91 | * To get the necessary version of C++ (g++7 and above), download and install [MinGW](https://sourceforge.net/projects/mingw-w64/files/Multilib%20Toolchains%28Targetting%20Win32%20and%20Win64%29/ray_linn/gcc-9.x-with-ada/), and also add `/path/to/MinGW/bin/` to `PATH`.
92 |
93 | * Install [Cmake](https://cmake.org/download/). It should be added to `PATH` automatically.
94 |
95 | * Install Qt5, following the instructions [from here](https://doc.qt.io/archives/qt-4.8/install-win.html).
96 |
97 | * Download [libav](http://builds.libav.org/windows/nightly-gpl/libav-x86_64-w64-mingw32-20180108.7z) and unpack it in a convenient location for you. Then add `/path/to/libav/bin` and `/path/to/libav/include` to `PATH`.
98 |
99 |
100 |
101 | ## How to use?
102 |
103 | To visualize a model, one needs to:
104 |
105 | * Select the model to be simulated:
106 | * You can choose one of the 35 presented models
107 | * You can enter your own differential equations
108 | * Select the constants that characterize the model:
109 | * You can choose classical values
110 | * You can enter your own values
111 | * Set the necessary settings:
112 | * Camera settings:
113 | * Modeling settings:
114 | * Visualization settings:
115 |
116 | Controls:
117 | * `WASDQE` — move forward / left / backward / right / up / down
118 |
119 | * `F` — return to the original position
120 | * `R` — take a screenshot
121 |
122 | ## Examples
123 |
124 | 
125 |
126 | 
127 |
128 | 
129 |
130 | ## Links
131 |
132 | Channels:
133 | * [YouTube](https://www.youtube.com/channel/UCL6pzFtbNd7fZKhABJCvV8g?view_as=subscriber)
134 |
135 | * [Telegram](https://t.me/strangeattractors)
136 |
137 | ## About us
138 |
139 | The application is being developed as part of a project work at the HSE University in St. Petersburg.
140 |
141 | Authors: [Vladislav Nosivskoy](https://github.com/vladnosiv), [Roman Venediktov](https://github.com/e2e4b6b7), [Kirill Karnaukhov](https://github.com/kkarnauk)
142 |
--------------------------------------------------------------------------------
/include/Camera.hpp:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include
4 | #include
5 | #include
6 | #include
7 | #include
8 | #include
9 | #include
10 | #include
11 |
12 | #include "Preferences.hpp"
13 |
14 | namespace Camera {
15 |
16 | class Camera final {
17 | public:
18 | Camera();
19 | ~Camera() = default;
20 |
21 | Camera(const Camera &) = delete;
22 | Camera(Camera &&) = delete;
23 | Camera &operator=(const Camera &) = delete;
24 | Camera &operator=(Camera &&) = delete;
25 |
26 |
27 | void applyDeltaPosition(const QVector3D &delta);
28 | void recalculatePerspective(int width, int height);
29 | void recalculateTarget(const QPoint &newMousePosition, float mouseSensitivity);
30 |
31 | void setPosition(const QVector3D &position);
32 | void setTarget(const QVector3D &target);
33 |
34 | void moveForward(float force);
35 | void moveRight(float force);
36 | void moveUp(float force);
37 |
38 | void resetMousePosition(const QPoint &point);
39 |
40 | void setDefault();
41 |
42 | QMatrix4x4 getMatrix() const;
43 | QVector3D getPosition() const;
44 | QVector3D getTarget() const;
45 |
46 | private:
47 | constexpr static QVector3D worldUp = QVector3D(0, 1, 0);
48 |
49 | QVector3D cameraPosition;
50 | QVector3D cameraTarget;
51 |
52 | QVector3D cameraForward;
53 | QVector3D cameraUp;
54 | QVector3D cameraRight;
55 |
56 | QMatrix4x4 perspectiveMatrix;
57 |
58 | float pitch;
59 | float yaw;
60 | QPoint lastMousePosition;
61 |
62 | bool invalidState;
63 |
64 | void recalculateVectors();
65 | void normalizeAngles();
66 | };
67 |
68 | class KeyboardAndMouseController final : public QObject {
69 | public:
70 | KeyboardAndMouseController();
71 | ~KeyboardAndMouseController() = default;
72 |
73 | KeyboardAndMouseController(const KeyboardAndMouseController &) = delete;
74 | KeyboardAndMouseController(KeyboardAndMouseController &&) = delete;
75 | KeyboardAndMouseController &operator=(const KeyboardAndMouseController &) = delete;
76 | KeyboardAndMouseController &operator=(KeyboardAndMouseController &&) = delete;
77 |
78 |
79 | void applyKeyPressEvent(QKeyEvent *event);
80 | void applyKeyReleaseEvent(QKeyEvent *event);
81 | void applyMousePressEvent(QMouseEvent *event);
82 | void applyMouseMoveEvent(QMouseEvent *event);
83 |
84 | void recalculatePerspective(int width, int height);
85 |
86 | QMatrix4x4 getMatrix() const;
87 | QVector3D getPosition() const;
88 | QVector3D getTarget() const;
89 |
90 | void setPreferences(const Preferences::Preferences *prefs);
91 |
92 | private slots:
93 | void updateKeys();
94 |
95 | private:
96 | Q_OBJECT
97 |
98 | Camera camera;
99 | QSet keys;
100 | QTimer *timer;
101 |
102 | const Preferences::Preferences *prefs;
103 | };
104 |
105 | } //namespace Camera
106 |
--------------------------------------------------------------------------------
/include/DynamicSystemParser/DynamicSystemParser.hpp:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include
4 | #include