├── .travis.yml ├── CMakeLists.txt ├── LICENSE ├── README.md ├── Screenshot_20200628_211604.png ├── screenshots ├── Background.png ├── Background_distorted.png ├── Densities.png ├── Density_sources.png ├── Divergence.png ├── Pressures.png ├── Scene.png ├── Scene_dbg.png ├── Scene_v_probes.png ├── Scene_v_probes_vecs.png ├── Scene_v_vecs.png ├── Velocities.png ├── Velocities_readback.png ├── Velocity_sources.png └── boids_teaser.png ├── scripts ├── build ├── build_dependencies ├── clean_all └── run └── src ├── CMakeLists.txt ├── battle_sub.cpp ├── battle_sub.h ├── bindings ├── fluid_source_component_lua.hpp └── status_component_lua.hpp ├── camera_dynamics.cpp ├── camera_dynamics.h ├── common.h ├── components ├── emitter_component.cpp ├── emitter_component.hpp ├── fluid_probes_component.hpp ├── fluid_source_component.hpp ├── parent_component.hpp ├── physics_component.hpp ├── status_component.hpp └── visuals_component.hpp ├── contact_listener.cpp ├── contact_listener.h ├── drawable_generic.h ├── entity.cpp ├── entity.h ├── fluid_grid.cpp ├── fluid_grid.h ├── global_resources.cpp ├── global_resources.h ├── gui_adapter ├── fluid_source_component_config_gui_adapter.hpp └── status_component_config_gui_adapter.hpp ├── lua └── config.lua ├── lua_manager.hpp ├── lua_path.hpp ├── message_handler.hpp ├── resource_storage.cpp ├── resource_storage.h ├── shader_path.h ├── shaders ├── advect_shader.h ├── density_display_shader.h ├── density_sources_shader.h ├── fluid_final_composition_shader.h ├── glsl │ ├── advect1d_shader.frag │ ├── advect2d_shader.frag │ ├── density_display_shader.frag │ ├── density_sources_shader.frag │ ├── density_sources_shader.vert │ ├── fluid_final_composition_shader.frag │ ├── ground_distortion_shader.frag │ ├── jacobi1d_shader.frag │ ├── jacobi2d_shader.frag │ ├── main_display_shader.frag │ ├── source1d_shader.frag │ ├── source2d_shader.frag │ ├── texture_2d32f_render_2d32f_shader.frag │ ├── texture_base_shader.vert │ ├── texture_base_unit_shader.vert │ ├── velocity_display_shader.frag │ ├── velocity_divergence_shader.frag │ ├── velocity_gradient_substraction_shader.frag │ ├── velocity_sources_shader.frag │ └── velocity_sources_shader.vert ├── ground_distortion_shader.h ├── jacobi_shader.h ├── main_display_shader.h ├── source_shader.h ├── texture_2d32f_render_2d32f_shader.h ├── velocity_display_shader.h ├── velocity_divergence_shader.h ├── velocity_gradient_substraction_shader.h └── velocity_sources_shader.h ├── submarine.cpp ├── submarine.h ├── submarine_definition.h ├── submarine_factory.h ├── systems ├── boid_system.hpp ├── debug_render_system.cpp ├── debug_render_system.hpp ├── emitter_system.cpp ├── emitter_system.hpp ├── fluid_interaction_system.cpp ├── fluid_interaction_system.hpp ├── game_object_system.cpp └── game_object_system.hpp ├── timer.h └── world_def.h /.travis.yml: -------------------------------------------------------------------------------- 1 | dist: focal 2 | sudo: required 3 | language: cpp 4 | 5 | git: 6 | strategy: clone 7 | depth: 1 8 | quiet: false 9 | 10 | addons: 11 | apt: 12 | packages: 13 | - libsdl2-2.0-0 14 | - libsdl2-dev 15 | - libsdl2-gfx-dev 16 | - libsdl2-image-2.0-0 17 | - libsdl2-image-dev 18 | - libsdl2-mixer-2.0-0 19 | - libsdl2-net-2.0-0 20 | - libsdl2-net-dev 21 | - libsdl2-ttf-2.0-0 22 | - libsdl2-ttf-dev 23 | - liblua5.3-dev 24 | 25 | install: 26 | - ./scripts/build_dependencies 27 | - ./scripts/build 28 | 29 | script: echo "Success!" 30 | -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.1) 2 | 3 | project(BattleSub) 4 | 5 | if ("${CMAKE_CXX_COMPILER_ID}" MATCHES "MSVC") 6 | add_compile_options(-mtune=native -Wall -pedantic) 7 | else() 8 | add_compile_options(-mtune=native -Wall -Wextra -pedantic) 9 | endif() 10 | 11 | set(CMAKE_MODULE_PATH "${PROJECT_SOURCE_DIR}/3rdparty/modules" ${CMAKE_MODULE_PATH}) 12 | 13 | set(BOX2D_LIBRARY_LOCAL "${PROJECT_SOURCE_DIR}/install/lib/libbox2d.a") 14 | 15 | find_package(Threads) 16 | find_package(Lua) 17 | find_package(Corrade REQUIRED Main) 18 | find_package(Magnum REQUIRED 19 | DebugTools 20 | GL 21 | MeshTools 22 | Primitives 23 | SceneGraph 24 | Sdl2Application 25 | Shaders 26 | Trade) 27 | find_package(MagnumIntegration REQUIRED ImGui) 28 | 29 | set_directory_properties(PROPERTIES CORRADE_USE_PEDANTIC_FLAGS ON) 30 | 31 | set(LIB_NOISE_HEADERS 32 | ${PROJECT_SOURCE_DIR}/3rdparty/libnoise2d/src/noise.h 33 | ) 34 | 35 | add_subdirectory(./src) 36 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # BattleSub 2 | Will eventually become a two player 2D submarine game with some fluid dynamics. 3 | BattleSub is using Magnum Graphics, Box2D, EnTT, and ImGUI: 4 | 5 | [![Build Status](https://travis-ci.com/bfeldpw/battlesub.svg?branch=master)](https://travis-ci.com/bfeldpw/battlesub) 6 | [![Codacy Badge](https://app.codacy.com/project/badge/Grade/5aa2f9b18121497cbe9ec07c610a08bd)](https://www.codacy.com/gh/bfeldpw/battlesub/dashboard?utm_source=github.com&utm_medium=referral&utm_content=bfeldpw/battlesub&utm_campaign=Badge_Grade) 7 | [![Last commit](https://img.shields.io/github/last-commit/bfeldpw/battlesub) 8 | 9 | ## What happened 10 | Well, let me just spend some words on the commit messages. I wanted to use Lua for scripting and configuration purposes, which I did in other projects before. But then TravisCI errored, because of missing Lua. So I added Lua, changed its version for CI, changed Ubuntu version in CI, added missing headers and everything was fine, eventually, apart from - git. 11 | 12 | Ofcourse, there is a backup, but given BattleSubs current state and popularity, I do not see any reason to further fiddle around with git, trying to merge the backup including history with current changes. 13 | 14 | So now, since the history is gone, lets just add a little changelog here, beginning today (2022-05-13): 15 | 16 | ### Change Log 17 | **Upcoming: Let's go fishing...** 18 | Teaser 19 | ![alt text](screenshots/boids_teaser.png?raw=true)\ 20 | Update 2022-11-12: Boids implementation is going well. All rules have been implemented in a first version. The boids branch has been added to the github repo today. Final work on parameterisation and exposing parameters to Lua and the debug GUI are being done. 21 | 22 | **2022-09-12: Colorful densities**\ 23 | The density implementation was changed from 1 to 3 channels (RGB32 float textures) to enable color selection for densities. The configuration was partly (proof of concept) exported to Lua following a more flexible binding structure. 24 | 25 | **2022-09-06: Long live the particles, show the beauty**\ 26 | Physical particles and their lifetime have been reconfigured. New screenshots and explanations were added. 27 | 28 | **2022-05-13: Lua love:**\ 29 | Lua has been added to enable configuration via scripts 30 | 31 | ## Installation and Dependencies 32 | 33 | To build and install after cloning run 34 | ```bash 35 | cd scripts 36 | ./build_dependencies && ./build 37 | ``` 38 | from BattleSub directory. 39 | 40 | If successful, run BattleSub using `./run` or `///scripts/run` if in another directory. 41 | 42 | ### Dependencies 43 | 44 | You can always have a look at .travis.yml for a configuration that should work. In general, dependencies are: 45 | * SDL2 46 | * Lua 47 | 48 | Other dependencies will be installed and compiled when running "build_dependencies" (see above). 49 | 50 | ### Platforms 51 | 52 | While I tried to stay portable with all code and libraries, BattleSub currently only supports Linux, since I don't exactly know, how to develop for Windows. Every support is welcome, ofcourse. 53 | 54 | ## Credits 55 | 56 | Since other libraries are what drives a great part of this project, I think they should go first. I appreciate all the hard work done by publicy available libraries, such as [Magnum Graphics](https://github.com/mosra/magnum), [Box2D](https://github.com/erincatto/box2d), [EnTT](https://github.com/skypjack/entt), and [Dear ImGUI](https://github.com/ocornut/imgui), as well as other contributions I maybe forgot. 57 | 58 | Special thanks go to [Vladimír Vondruš](https://github.com/mosra) and supporters, not only for the aforementioned Magnum Graphics middleware, but also the fast response time on gitter.im on my questions. Not only have the dev(s) been answering my API-related questions, but have also been giving valuable hints on concepts for implementation of different aspects. 59 | 60 | ## Screenshots 61 | 62 | Final buffer composition with debug GUI: 63 | ![alt text](screenshots/Scene_dbg.png?raw=true) 64 | 65 | ### Velocity and Density sources 66 | Physical objects generate velocity sources as well as density sources in each frame. They can also be just generated without a physical object. While the velocity sources modify the vector field which will influence physical objects and fluid densities, the density sources themself will increase the density of the fluid grid cells. The following images show these two sources (velocity and density): 67 | 68 | ![alt text](screenshots/Velocity_sources.png?raw=true) 69 | 70 | ![alt text](screenshots/Density_sources.png?raw=true) 71 | 72 | ### Velocity field 73 | The velocity field a vector field. Here, direction is color coded while intensity displays the velocity magnitude. The velocity field is used to move itsself (self advection), to move the density field (advection), and to move the physical objects. Since physical objects are calculated on the CPU, the velocity field is subsampled and read back to CPU. A double buffered, threaded pixelbuffer is used via DMA to avoid blocking. Sub-sampling is done spatially as well as temporally. In each frame, a lower resolution stripe of the velocity field is read back. There are no visible artifacts on physics objects, since sudden changes do only appear for force/acceleration. Influence on objects velocities and positions is implicitely smoothened by integration of accelerations. 74 | ![alt text](screenshots/Velocities.png?raw=true) 75 | 76 | ### Densities 77 | The densities, generated by density sources, are influenced by the vector field. Here, they are a purely visual representation (which might be smoke for gases, water bubbles in fluids or different coloured fluids in other cases) only which refers to a particle density. 78 | ![alt text](screenshots/Densities.png?raw=true) 79 | 80 | ### Pressure field 81 | The pressure field is calculated with a numeric optimisation, i.e. iteratively. It originates from divergence and ensures, that grid cells are mass preserving. This finally leads to vortices. 82 | ![alt text](screenshots/Pressures.png?raw=true) 83 | ### Heightmap (Background) 84 | The heightmap is a background image that is procedurally generated by mainly using several octaves of different noise functions. 85 | ![alt text](screenshots/Background.png?raw=true) 86 | ### Heightmap distorted by velocity field 87 | The velocity field distorts the heightmap based on velocity direction and magnitude to simulate a visual waterflow. This is pure cosmetics, kind of the "rule of cool". 88 | ![alt text](screenshots/Background_distorted.png?raw=true) 89 | ### Velocity vectors (sub-sampled) 90 | The velocity field may also be displayed by vectors. It is based on the subsampled field that was read back to CPU. It is further subsampled for reduced density and thus, better visualisation. 91 | ![alt text](screenshots/Scene_v_vecs.png?raw=true) 92 | ### Velocity probes 93 | Physical objects are influenced by the subsampled velocity field that was read back to CPU. Velocity probes measure the field in several points and include normal vectors of the objects edges to finally calculate the velocities/forces acting on objects. The probes show the current relative velocity (radius) and field direction (radial line). 94 | ![alt text](screenshots/Scene_v_probes.png?raw=true) 95 | 96 | -------------------------------------------------------------------------------- /Screenshot_20200628_211604.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bfeldpw/battlesub/f5d52152917775fbd2305e8681a0b6cf097e0f63/Screenshot_20200628_211604.png -------------------------------------------------------------------------------- /screenshots/Background.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bfeldpw/battlesub/f5d52152917775fbd2305e8681a0b6cf097e0f63/screenshots/Background.png -------------------------------------------------------------------------------- /screenshots/Background_distorted.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bfeldpw/battlesub/f5d52152917775fbd2305e8681a0b6cf097e0f63/screenshots/Background_distorted.png -------------------------------------------------------------------------------- /screenshots/Densities.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bfeldpw/battlesub/f5d52152917775fbd2305e8681a0b6cf097e0f63/screenshots/Densities.png -------------------------------------------------------------------------------- /screenshots/Density_sources.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bfeldpw/battlesub/f5d52152917775fbd2305e8681a0b6cf097e0f63/screenshots/Density_sources.png -------------------------------------------------------------------------------- /screenshots/Divergence.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bfeldpw/battlesub/f5d52152917775fbd2305e8681a0b6cf097e0f63/screenshots/Divergence.png -------------------------------------------------------------------------------- /screenshots/Pressures.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bfeldpw/battlesub/f5d52152917775fbd2305e8681a0b6cf097e0f63/screenshots/Pressures.png -------------------------------------------------------------------------------- /screenshots/Scene.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bfeldpw/battlesub/f5d52152917775fbd2305e8681a0b6cf097e0f63/screenshots/Scene.png -------------------------------------------------------------------------------- /screenshots/Scene_dbg.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bfeldpw/battlesub/f5d52152917775fbd2305e8681a0b6cf097e0f63/screenshots/Scene_dbg.png -------------------------------------------------------------------------------- /screenshots/Scene_v_probes.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bfeldpw/battlesub/f5d52152917775fbd2305e8681a0b6cf097e0f63/screenshots/Scene_v_probes.png -------------------------------------------------------------------------------- /screenshots/Scene_v_probes_vecs.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bfeldpw/battlesub/f5d52152917775fbd2305e8681a0b6cf097e0f63/screenshots/Scene_v_probes_vecs.png -------------------------------------------------------------------------------- /screenshots/Scene_v_vecs.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bfeldpw/battlesub/f5d52152917775fbd2305e8681a0b6cf097e0f63/screenshots/Scene_v_vecs.png -------------------------------------------------------------------------------- /screenshots/Velocities.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bfeldpw/battlesub/f5d52152917775fbd2305e8681a0b6cf097e0f63/screenshots/Velocities.png -------------------------------------------------------------------------------- /screenshots/Velocities_readback.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bfeldpw/battlesub/f5d52152917775fbd2305e8681a0b6cf097e0f63/screenshots/Velocities_readback.png -------------------------------------------------------------------------------- /screenshots/Velocity_sources.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bfeldpw/battlesub/f5d52152917775fbd2305e8681a0b6cf097e0f63/screenshots/Velocity_sources.png -------------------------------------------------------------------------------- /screenshots/boids_teaser.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bfeldpw/battlesub/f5d52152917775fbd2305e8681a0b6cf097e0f63/screenshots/boids_teaser.png -------------------------------------------------------------------------------- /scripts/build: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | echo "> cd $(dirname "$0")/.." 4 | cd $(dirname "$0")/.. 5 | 6 | # Install BattleSub 7 | 8 | echo "> mkdir -p build" 9 | mkdir -p build 10 | echo "> cd build" 11 | cd build 12 | echo "> cmake .. -DCMAKE_PREFIX_PATH=../install -DCMAKE_INSTALL_PREFIX=../install -DCMAKE_BUILD_TYPE=RELEASE" 13 | cmake .. -DCMAKE_PREFIX_PATH=../install -DCMAKE_INSTALL_PREFIX=../install -DCMAKE_BUILD_TYPE=RELEASE -DCMAKE_EXPORT_COMPILE_COMMANDS=1 14 | make -j8 install 15 | -------------------------------------------------------------------------------- /scripts/build_dependencies: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | echo "> cd $(dirname "$0")/.." 4 | cd $(dirname "$0")/.. 5 | 6 | echo "> mkdir -p install" 7 | mkdir -p install 8 | 9 | echo "> mkdir -p 3rdparty" 10 | mkdir -p 3rdparty 11 | 12 | echo "> cd 3rdparty" 13 | cd 3rdparty 14 | 15 | echo "> git config --global advice.detachedHead false" 16 | git config --global advice.detachedHead false 17 | 18 | echo "> git clone --branch v1.2.1 --depth 1 https://github.com/planeworld/libnoise2d.git" 19 | git clone --branch v1.2.1 --depth 1 https://github.com/planeworld/libnoise2d.git 20 | 21 | echo "> git clone --branch v2.4.1 --depth 1 https://github.com/erincatto/box2d.git" 22 | git clone --branch v2.4.1 --depth 1 https://github.com/erincatto/box2d.git 23 | 24 | echo "> git clone --branch v3.10.3 --depth 1 https://github.com/skypjack/entt.git" 25 | git clone --branch v3.10.3 --depth 1 https://github.com/skypjack/entt.git 26 | 27 | echo "> git clone --branch v2020.06 --depth 1 https://github.com/mosra/corrade.git" 28 | git clone --branch v2020.06 --depth 1 https://github.com/mosra/corrade.git 29 | 30 | echo "> git clone --branch v2020.06 --depth 1 https://github.com/mosra/magnum.git" 31 | git clone --branch v2020.06 --depth 1 https://github.com/mosra/magnum.git 32 | 33 | echo "> git clone --branch v1.79 --depth 1 https://github.com/ocornut/imgui.git" 34 | git clone --branch v1.79 --depth 1 https://github.com/ocornut/imgui.git 35 | 36 | echo "> git clone --branch v2020.06 --depth 1 https://github.com/mosra/magnum-integration.git" 37 | git clone --branch v2020.06 --depth 1 https://github.com/mosra/magnum-integration.git 38 | 39 | 40 | # Install libnoise2d 41 | 42 | echo "> cd libnoise2d" 43 | cd libnoise2d 44 | echo "> mkdir -p build" 45 | mkdir -p build 46 | echo "> cd build" 47 | cd build 48 | echo "> cmake .. -DCMAKE_INSTALL_PREFIX=../../../install -DUSE_XXHASH=ON -DCMAKE_BUILD_TYPE=RELEASE" 49 | cmake .. -DCMAKE_INSTALL_PREFIX=../../../install -DUSE_XXHASH=ON -DCMAKE_BUILD_TYPE=RELEASE 50 | echo "> make -j8 install" 51 | make -j8 install 52 | echo "> cd ../.." 53 | cd ../.. 54 | 55 | # Install box2d 56 | 57 | echo "> cd box2d" 58 | cd box2d 59 | echo "> mkdir -p build" 60 | mkdir -p build 61 | echo "> cd build" 62 | cd build 63 | echo "> cmake .. -DCMAKE_INSTALL_PREFIX=../../../install -DBOX2D_BUILD_TESTBED=OFF -DBOX2D_BUILD_UNIT_TESTS=OFF -DCMAKE_BUILD_TYPE=RELEASE" 64 | cmake .. -DCMAKE_INSTALL_PREFIX=../../../install -DBOX2D_BUILD_TESTBED=OFF -DBOX2D_BUILD_UNIT_TESTS=OFF -DCMAKE_BUILD_TYPE=RELEASE 65 | echo "> make -j8 install" 66 | make -j8 install 67 | echo "> cd ../.." 68 | cd ../.. 69 | 70 | # Install entt 71 | 72 | echo "> cd entt" 73 | cd entt 74 | # build directory already exists 75 | #echo "> mkdir -p build" 76 | #mkdir -p build 77 | echo "> cd build" 78 | cd build 79 | echo "> cmake .. -DCMAKE_INSTALL_PREFIX=../../../install -DBUILD_GMOCK=OFF -DBUILD_TESTING=OFF -DINSTALL_GTEST=OFF -DCMAKE_BUILD_TYPE=RELEASE" 80 | cmake .. -DCMAKE_INSTALL_PREFIX=../../../install -DBUILD_GMOCK=OFF -DBUILD_TESTING=OFF -DINSTALL_GTEST=OFF -DCMAKE_BUILD_TYPE=RELEASE 81 | echo "> make -j8 install" 82 | make -j8 install 83 | echo "> cd ../.." 84 | cd ../.. 85 | 86 | # Install corrade 87 | 88 | echo "> cd corrade" 89 | cd corrade 90 | echo "> mkdir -p build" 91 | mkdir -p build 92 | echo "> cd build" 93 | cd build 94 | echo "> cmake .. -DCMAKE_PREFIX_PATH=../../../install -DCMAKE_INSTALL_PREFIX=../../../install -DCMAKE_BUILD_TYPE=RELEASE -DBUILD_DEPRECATED=OFF" 95 | cmake .. -DCMAKE_PREFIX_PATH=../../../install -DCMAKE_INSTALL_PREFIX=../../../install -DCMAKE_BUILD_TYPE=RELEASE -DBUILD_DEPRECATED=OFF 96 | echo "> make -j8 install" 97 | make -j8 install 98 | echo "> cd ../.." 99 | cd ../.. 100 | 101 | # Install magnum 102 | 103 | echo "> cd magnum" 104 | cd magnum 105 | echo "> mkdir -p build" 106 | mkdir -p build 107 | echo "> cd build" 108 | cd build 109 | echo "> cmake .. -DCMAKE_PREFIX_PATH=../../../install -DCMAKE_INSTALL_PREFIX=../../../install -DCMAKE_BUILD_TYPE=RELEASE -DBUILD_DEPRECATED=OFF -DWITH_DEBUGTOOLS=ON -DWITH_SDL2APPLICATION=ON" 110 | cmake .. -DCMAKE_PREFIX_PATH=../../../install -DCMAKE_INSTALL_PREFIX=../../../install -DCMAKE_BUILD_TYPE=RELEASE -DBUILD_DEPRECATED=OFF -DWITH_DEBUGTOOLS=ON -DWITH_SDL2APPLICATION=ON 111 | echo "> make -j8 install" 112 | make -j8 install 113 | echo "> cd ../.." 114 | cd ../.. 115 | 116 | # Install imgui 117 | 118 | echo "> cd imgui" 119 | cd imgui 120 | echo "> cp *.h ../../install/include/" 121 | cp *.h ../../install/include/ 122 | echo "> cp *.cpp ../../install/include/" 123 | cp *.cpp ../../install/include/ 124 | echo "> cd .." 125 | cd .. 126 | 127 | # Install magnum-integration 128 | 129 | echo "> cd magnum-integration" 130 | cd magnum-integration 131 | echo "> mkdir -p build" 132 | mkdir -p build 133 | echo "> cd build" 134 | cd build 135 | echo "> cmake .. -DCMAKE_PREFIX_PATH=../../../install -DCMAKE_INSTALL_PREFIX=../../../install -DCMAKE_BUILD_TYPE=RELEASE -DWITH_IMGUI=ON -Dimgui_DIR=../../install" 136 | cmake .. -DCMAKE_PREFIX_PATH=../../../install -DCMAKE_INSTALL_PREFIX=../../../install -DCMAKE_BUILD_TYPE=RELEASE -DWITH_IMGUI=ON -Dimgui_DIR=../../install 137 | echo "> make -j8 install" 138 | make -j8 install 139 | echo "> cd ../.." 140 | cd ../.. 141 | 142 | # Add modules 143 | echo "> mkdir -p modules" 144 | mkdir -p modules 145 | echo "> cp magnum-integration/modules/* modules/" 146 | cp magnum-integration/modules/* modules/ 147 | echo "> cd .." 148 | cd .. 149 | 150 | # Install sol release 151 | cd install/include/ 152 | wget https://github.com/ThePhD/sol2/releases/download/v3.3.0/sol.hpp 153 | mkdir sol 154 | cd sol 155 | wget https://github.com/ThePhD/sol2/releases/download/v3.3.0/config.hpp 156 | wget https://github.com/ThePhD/sol2/releases/download/v3.3.0/forward.hpp 157 | cd ../../.. 158 | -------------------------------------------------------------------------------- /scripts/clean_all: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | cd $(dirname "$0")/.. 4 | 5 | rm -rf 3rdparty build install 6 | -------------------------------------------------------------------------------- /scripts/run: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | cd "$(dirname "$0")"/.. 4 | 5 | PKGDIR=./install 6 | export PATH=$PKGDIR/bin:/usr/bin/:$PATH 7 | export LD_LIBRARY_PATH=$PKGDIR/lib:$LD_LIBRARY_PATH 8 | 9 | ./install/bin/battle_sub 10 | -------------------------------------------------------------------------------- /src/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | set(HEADERS 2 | bindings/fluid_source_component_lua.hpp 3 | bindings/status_component_lua.hpp 4 | components/emitter_component.hpp 5 | components/fluid_probes_component.hpp 6 | components/fluid_source_component.hpp 7 | components/parent_component.hpp 8 | components/physics_component.hpp 9 | components/status_component.hpp 10 | components/visuals_component.hpp 11 | gui_adapter/fluid_source_component_config_gui_adapter.hpp 12 | gui_adapter/status_component_config_gui_adapter.hpp 13 | shaders/advect_shader.h 14 | shaders/density_display_shader.h 15 | shaders/density_sources_shader.h 16 | shaders/fluid_final_composition_shader.h 17 | shaders/jacobi_shader.h 18 | shaders/main_display_shader.h 19 | shaders/source_shader.h 20 | shaders/texture_2d32f_render_2d32f_shader.h 21 | shaders/velocity_display_shader.h 22 | shaders/velocity_divergence_shader.h 23 | shaders/velocity_gradient_substraction_shader.h 24 | shaders/velocity_sources_shader.h 25 | systems/boid_system.hpp 26 | systems/debug_render_system.hpp 27 | systems/emitter_system.hpp 28 | systems/fluid_interaction_system.hpp 29 | systems/game_object_system.hpp 30 | battle_sub.h 31 | camera_dynamics.h 32 | common.h 33 | contact_listener.h 34 | drawable_generic.h 35 | fluid_grid.h 36 | global_resources.h 37 | lua_manager.hpp 38 | lua_path.hpp 39 | message_handler.hpp 40 | resource_storage.h 41 | shader_path.h 42 | submarine.h 43 | submarine_definition.h 44 | timer.h 45 | world_def.h 46 | ) 47 | 48 | set(LIB_NOISE_LIBRARY 49 | ${PROJECT_SOURCE_DIR}/3rdparty/libnoise2d/build/src/libnoise2d.so 50 | ) 51 | 52 | set(SOURCES 53 | ${ImGui_INCLUDE_DIR}/imgui.cpp 54 | components/emitter_component.cpp 55 | systems/debug_render_system.cpp 56 | systems/emitter_system.cpp 57 | systems/fluid_interaction_system.cpp 58 | systems/game_object_system.cpp 59 | battle_sub.cpp 60 | camera_dynamics.cpp 61 | contact_listener.cpp 62 | fluid_grid.cpp 63 | global_resources.cpp 64 | resource_storage.cpp 65 | submarine.cpp 66 | ) 67 | 68 | add_executable(battle_sub ${LIB_NOISE_HEADERS} ${HEADERS} ${SOURCES}) 69 | 70 | target_include_directories(battle_sub PRIVATE "${PROJECT_SOURCE_DIR}/src/") 71 | target_include_directories(battle_sub PRIVATE "${PROJECT_SOURCE_DIR}/src/bindings/") 72 | target_include_directories(battle_sub PRIVATE "${PROJECT_SOURCE_DIR}/src/components/") 73 | target_include_directories(battle_sub PRIVATE "${PROJECT_SOURCE_DIR}/src/gui_adapter/") 74 | target_include_directories(battle_sub PRIVATE "${PROJECT_SOURCE_DIR}/src/shaders/") 75 | target_include_directories(battle_sub PRIVATE "${PROJECT_SOURCE_DIR}/src/systems/") 76 | target_include_directories(battle_sub PRIVATE ${LUA_INCLUDE_DIR}) 77 | target_include_directories(battle_sub PRIVATE ${MAGNUM_INCLUDE_DIR}) 78 | target_include_directories(battle_sub PRIVATE ${ImGui_INCLUDE_DIR}) 79 | target_include_directories(battle_sub PRIVATE "${PROJECT_SOURCE_DIR}/3rdparty/box2d/include/box2d") 80 | target_include_directories(battle_sub PRIVATE "${PROJECT_SOURCE_DIR}/3rdparty/libnoise2d/src/") 81 | 82 | target_link_libraries(battle_sub PRIVATE 83 | Threads::Threads 84 | OpenGL::GL 85 | Corrade::Main 86 | Magnum::Application 87 | Magnum::DebugTools 88 | Magnum::GL 89 | Magnum::Magnum 90 | Magnum::MeshTools 91 | Magnum::Primitives 92 | Magnum::SceneGraph 93 | Magnum::Shaders 94 | MagnumIntegration::ImGui 95 | ${LUA_LIBRARIES} 96 | ${BOX2D_LIBRARY_LOCAL} 97 | ${LIB_NOISE_LIBRARY} 98 | ) 99 | 100 | set_property(TARGET battle_sub PROPERTY CXX_STANDARD 17) 101 | 102 | install(TARGETS battle_sub DESTINATION bin) 103 | install(DIRECTORY "${PROJECT_SOURCE_DIR}/src/shaders/glsl/" DESTINATION "${PROJECT_SOURCE_DIR}/install/share/shaders/") 104 | install(DIRECTORY "${PROJECT_SOURCE_DIR}/src/lua/" DESTINATION "${PROJECT_SOURCE_DIR}/install/share/lua/") 105 | -------------------------------------------------------------------------------- /src/battle_sub.h: -------------------------------------------------------------------------------- 1 | #ifndef BATTLE_SUB_H 2 | #define BATTLE_SUB_H 3 | 4 | #include 5 | #include 6 | 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | #include "camera_dynamics.h" 13 | #include "common.h" 14 | #include "contact_listener.h" 15 | #include "fluid_grid.h" 16 | #include "game_object_system.hpp" 17 | #include "main_display_shader.h" 18 | #include "submarine.h" 19 | #include "timer.h" 20 | 21 | 22 | namespace BattleSub 23 | { 24 | 25 | class BattleSub : public Platform::Application 26 | { 27 | 28 | public: 29 | 30 | explicit BattleSub(const Arguments& arguments); 31 | BattleSub() = delete; 32 | ~BattleSub(); 33 | 34 | private: 35 | 36 | void drawEvent() override; 37 | void keyPressEvent(KeyEvent& Event) override; 38 | void keyReleaseEvent(KeyEvent& Event) override; 39 | void mouseMoveEvent(MouseMoveEvent& Event) override; 40 | void mousePressEvent(MouseEvent& Event) override; 41 | void mouseReleaseEvent(MouseEvent& Event) override; 42 | void viewportEvent(ViewportEvent& Evend) override; 43 | 44 | void cleanupAndExit(); 45 | void updateCameraDynamics(); 46 | void updateGameObjects(); 47 | void updateUI(const double _GPUTime); 48 | void updateWorld(); 49 | 50 | void setupECS(); 51 | void setupLua(const std::string& _f); 52 | void setupWindow(); 53 | void setupFrameBuffersMainScreen(); 54 | void setupMainDisplayMesh(); 55 | void setupCameras(); 56 | void setupGameObjects(); 57 | 58 | void showTooltip(const std::string& Tooltip); 59 | 60 | ImGuiIntegration::Context ImGUI_{NoCreate}; 61 | Timer SimTime_; 62 | 63 | //--- ECS ---// 64 | entt::registry Reg_; 65 | 66 | //--- World ---// 67 | int WindowResolutionX_ = 1600; 68 | int WindowResolutionY_ = 900; 69 | float Frequency_ = 60.0f; 70 | int NrOfObjectsCPU_ = 0; 71 | 72 | //--- Framebuffer related ---// 73 | GL::Framebuffer FBOMainDisplay_{NoCreate}; 74 | GL::Mesh MeshMainDisplay_{NoCreate}; 75 | GL::Texture2D TexMainDisplay_{NoCreate}; 76 | MainDisplayShader ShaderMainDisplay_{NoCreate}; 77 | 78 | //--- Controls ---// 79 | std::unordered_map KeyPressedMap; 80 | Vector2i MouseDelta_; 81 | bool IsDebugDisplayed_ = false; 82 | bool IsExitTriggered_ = false; 83 | bool IsMainMenuDisplayed_ = false; 84 | bool IsPaused_ = false; 85 | bool IsStepForward_ = false; 86 | bool IsSplitscreen_ = false; 87 | bool IsTooltipsEnabled_ = true; 88 | struct 89 | { 90 | bool IsVelocityProbesEnabled = false; 91 | bool IsVelocityVectorsEnabled = false; 92 | } DebugRender_; 93 | 94 | //-- UI --// 95 | ImGuiStyle* UIStyle_{nullptr}; 96 | ImGuiStyle UIStyleSubStats_; 97 | ImGuiStyle UIStyleDefault_; 98 | 99 | Object2D* CameraObjectCurrentPlayer_{nullptr}; 100 | Object2D* CameraObjectOtherPlayer_{nullptr}; 101 | Object2D* CameraObjectPlayer1_; 102 | Object2D* CameraObjectPlayer2_; 103 | Object2D* CameraObjectBoundaries_; 104 | SceneGraph::Camera2D* CameraCurrentPlayer_{nullptr}; 105 | SceneGraph::Camera2D* CameraOtherPlayer_{nullptr}; 106 | SceneGraph::Camera2D* CameraPlayer1_; 107 | SceneGraph::Camera2D* CameraPlayer2_; 108 | SceneGraph::Camera2D* CameraBoundaries_; 109 | 110 | FluidBufferE FluidBuffer_{FluidBufferE::FINAL_COMPOSITION}; 111 | float DensityDistortion_ = 50.0f; 112 | float ScalarFieldDisplayScale_ = 1.0f; 113 | float VelocityDisplayScale_ = 20.0f; 114 | bool VelocityDisplayShowOnlyMagnitude_ = false; 115 | float VelocitySourceBackprojection_ = 0.08f; 116 | 117 | Submarine* PlayerSub_ = nullptr; 118 | Submarine* PlayerSub2_ = nullptr; 119 | 120 | float VisRes_ = 5.0f; // Visual Resolution in pixels per meter 121 | CameraDynamics Cam1MoveAheadX_; 122 | CameraDynamics Cam1MoveAheadY_; 123 | CameraDynamics Cam1Zoom_; 124 | CameraDynamics Cam2MoveAheadX_; 125 | CameraDynamics Cam2MoveAheadY_; 126 | CameraDynamics Cam2Zoom_; 127 | bool Cam1MoveAheadIsAuto_ = true; 128 | bool DevCam_ = false; 129 | 130 | }; 131 | 132 | } 133 | 134 | #endif // BATTLE_SUB_H 135 | -------------------------------------------------------------------------------- /src/bindings/fluid_source_component_lua.hpp: -------------------------------------------------------------------------------- 1 | #ifndef FLUID_SOURCE_COMPONENT_LUA_HPP 2 | #define FLUID_SOURCE_COMPONENT_LUA_HPP 3 | 4 | #include 5 | 6 | #include "fluid_source_component.hpp" 7 | #include "lua_manager.hpp" 8 | 9 | class FluidSourceComponentLua 10 | { 11 | public: 12 | 13 | explicit FluidSourceComponentLua(entt::registry& _Reg) : Reg_(_Reg) {} 14 | FluidSourceComponentLua() = delete; 15 | 16 | void read(const std::string& _s) 17 | { 18 | auto& Lua = Reg_.ctx().at(); 19 | Conf_.DensityBackProjection_ = Lua.get(Lua.State_[_s]["fluid_source_component"]["density_back_projection"]); 20 | Conf_.DensityDynamicR_ = Lua.get(Lua.State_[_s]["fluid_source_component"]["density_dynamic_r"]); 21 | Conf_.DensityDynamicG_ = Lua.get(Lua.State_[_s]["fluid_source_component"]["density_dynamic_g"]); 22 | Conf_.DensityDynamicB_ = Lua.get(Lua.State_[_s]["fluid_source_component"]["density_dynamic_b"]); 23 | Conf_.DensityStaticR_ = Lua.get(Lua.State_[_s]["fluid_source_component"]["density_static_r"]); 24 | Conf_.DensityStaticG_ = Lua.get(Lua.State_[_s]["fluid_source_component"]["density_static_g"]); 25 | Conf_.DensityStaticB_ = Lua.get(Lua.State_[_s]["fluid_source_component"]["density_static_b"]); 26 | Conf_.VelocityBackProjection_ = Lua.get(Lua.State_[_s]["fluid_source_component"]["velocity_back_projection"]); 27 | } 28 | 29 | const FluidSourceComponent& get() const 30 | { 31 | return Conf_; 32 | } 33 | 34 | void set(const FluidSourceComponent& _c) 35 | { 36 | Conf_ = _c; 37 | } 38 | 39 | private: 40 | 41 | entt::registry& Reg_; 42 | 43 | FluidSourceComponent Conf_; 44 | }; 45 | 46 | #endif // FLUID_SOURCE_COMPONENT_LUA_HPP 47 | -------------------------------------------------------------------------------- /src/bindings/status_component_lua.hpp: -------------------------------------------------------------------------------- 1 | #ifndef STATUS_COMPONENT_LUA_HPP 2 | #define STATUS_COMPONENT_LUA_HPP 3 | 4 | #include 5 | 6 | #include "status_component.hpp" 7 | #include "lua_manager.hpp" 8 | 9 | class StatusComponentLua 10 | { 11 | public: 12 | 13 | explicit StatusComponentLua(entt::registry& _Reg) : Reg_(_Reg) {} 14 | StatusComponentLua() = delete; 15 | 16 | void read(const std::string& _s) 17 | { 18 | auto& Lua = Reg_.ctx().at(); 19 | Conf_.AgeMax_ = Lua.get(Lua.State_[_s]["status_component"]["age_max"]); 20 | Conf_.SinkDuration_ = Lua.get(Lua.State_[_s]["status_component"]["sink_duration"]); 21 | } 22 | 23 | const StatusComponent& get() const 24 | { 25 | return Conf_; 26 | } 27 | 28 | void set(const StatusComponent& _c) 29 | { 30 | Conf_ = _c; 31 | } 32 | 33 | private: 34 | 35 | entt::registry& Reg_; 36 | 37 | StatusComponent Conf_; 38 | }; 39 | 40 | #endif // STATUS_COMPONENT_LUA_HPP 41 | -------------------------------------------------------------------------------- /src/camera_dynamics.cpp: -------------------------------------------------------------------------------- 1 | #include "camera_dynamics.h" 2 | 3 | void CameraDynamics::increaseByMultiplication(const float f) 4 | { 5 | if (!IsAuto) 6 | { 7 | Auto = 0.0f; 8 | Base *= f; 9 | } 10 | } 11 | 12 | void CameraDynamics::interpolate(float Target) 13 | { 14 | Target *= Strength; 15 | if (IsAuto) 16 | { 17 | constexpr float Epsilon = 0.001f; 18 | 19 | if (Target != Target_) 20 | { 21 | Phase_ = Speed; 22 | Target_ = Target; 23 | } 24 | else 25 | { 26 | Phase_ += Speed; 27 | } 28 | To_.point() = Target; 29 | To_.inTangent() = 0.0f; 30 | To_.outTangent() = 0.0f; 31 | 32 | // Test for values near zero to fix oscillations 33 | if (std::abs(Target- Last0_) < Epsilon && Target < Epsilon) 34 | { 35 | Last0_ = Target; 36 | Last1_ = Target; 37 | From_.point() = Target; 38 | From_.inTangent() = 0.0f; 39 | From_.outTangent() = 0.0f; 40 | } 41 | else 42 | { 43 | From_.point() = Last0_; 44 | From_.inTangent() = (Last0_ - Last1_) / Speed; 45 | From_.outTangent() = (Last0_ - Last1_) / Speed; 46 | Auto = Magnum::Math::splerp(From_, To_, Phase_); 47 | Last1_ = Last0_; 48 | Last0_ = Auto; 49 | } 50 | 51 | Values.push_front(Base+Auto); 52 | if (Values.size() > 600) Values.pop_back(); 53 | } 54 | else 55 | { 56 | Auto = 0.0f; 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /src/camera_dynamics.h: -------------------------------------------------------------------------------- 1 | #ifndef CAMERA_DYNAMICS_H 2 | #define CAMERA_DYNAMICS_H 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | using namespace Magnum; 9 | 10 | class CameraDynamics 11 | { 12 | 13 | public: 14 | 15 | void increaseByMultiplication(const float f); 16 | void interpolate(float Target); 17 | 18 | float Value() {return Base+Auto;} 19 | 20 | float Auto = 0.0f; 21 | float Base = 1.0f; 22 | float Speed = 0.1f; 23 | float Strength = 0.1f; 24 | bool IsAuto = true; 25 | 26 | // The following deque is only for debug visualisation (i.e. to see if splines work) 27 | std::deque Values; 28 | 29 | private: 30 | 31 | float Last0_ = 0.0f; 32 | float Last1_ = 0.0f; 33 | float Target_ = 0.0f; 34 | float Phase_ = 1.0f; 35 | 36 | template using Pt = Magnum::Math::CubicHermite1D; 37 | 38 | Pt From_; 39 | Pt To_; 40 | }; 41 | 42 | #endif // CAMERA_DYNAMICS_H 43 | -------------------------------------------------------------------------------- /src/common.h: -------------------------------------------------------------------------------- 1 | #ifndef COMMON_H 2 | #define COMMON_H 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | using namespace Magnum; 14 | 15 | typedef SceneGraph::Object Object2D; 16 | typedef SceneGraph::Scene Scene2D; 17 | 18 | #endif // COMMON_H 19 | -------------------------------------------------------------------------------- /src/components/emitter_component.cpp: -------------------------------------------------------------------------------- 1 | #include "emitter_component.hpp" 2 | 3 | std::mt19937 EmitterComponent::Generator_; 4 | -------------------------------------------------------------------------------- /src/components/emitter_component.hpp: -------------------------------------------------------------------------------- 1 | #ifndef EMITTER_COMPONENT_HPP 2 | #define EMITTER_COMPONENT_HPP 3 | 4 | #include 5 | 6 | #include "status_component.hpp" 7 | 8 | struct EmitterComponent 9 | { 10 | static std::mt19937 Generator_; 11 | 12 | GameObjectTypeE Type_ = GameObjectTypeE::DEBRIS_LANDSCAPE; 13 | float Angle_ = 0.0f; 14 | float AngleStdDev_ = 0.0f; 15 | float Frequency_ = 0.0f; 16 | int Counter_ = 0; 17 | int Number_ = 1; 18 | float OriginX_ = 0.0f; 19 | float OriginY_ = 0.0f; 20 | float Scale_ = 1.0f; 21 | float ScaleStdDev_ = 0.0f; 22 | float Velocity_ = 1.0f; 23 | float VelocityStdDev_ = 0.0f; 24 | float VelocityWeight_ = 1.0f; 25 | }; 26 | 27 | #endif // EMITTER_COMPONENT_HPP 28 | -------------------------------------------------------------------------------- /src/components/fluid_probes_component.hpp: -------------------------------------------------------------------------------- 1 | #ifndef FLUID_PROBES_COMPONENT_HPP 2 | #define FLUID_PROBES_COMPONENT_HPP 3 | 4 | struct FluidProbeComponent 5 | { 6 | float M_ = 0.1f; 7 | float X_ = 0.0f; 8 | float Y_ = 0.0f; 9 | }; 10 | 11 | template 12 | struct FluidProbesComponent 13 | { 14 | int N_ = 0; 15 | float M_ = 0.1f; 16 | 17 | float X_[N]; 18 | float Y_[N]; 19 | float NormX_[N]; 20 | float NormY_[N]; 21 | 22 | }; 23 | 24 | #endif // FLUID_PROBES_COMPONENT_HPP 25 | -------------------------------------------------------------------------------- /src/components/fluid_source_component.hpp: -------------------------------------------------------------------------------- 1 | #ifndef FLUID_SOURCE_COMPONENT_HPP 2 | #define FLUID_SOURCE_COMPONENT_HPP 3 | 4 | enum class FluidSourceShapeE : int 5 | { 6 | POINT, 7 | LINE, 8 | RECT 9 | }; 10 | 11 | struct FluidSourceComponent 12 | { 13 | FluidSourceShapeE DensityShape_ = FluidSourceShapeE::POINT; 14 | float DensityBackProjection_ = 0.1f; // Linear Backprojection in seconds 15 | float DensitySourceSize_ = 1.0f; 16 | float DensityDynamicR_ = 1.0f; 17 | float DensityDynamicG_ = 1.0f; 18 | float DensityDynamicB_ = 1.0f; 19 | float DensityStaticR_ = 0.8f; 20 | float DensityStaticG_ = 0.0f; 21 | float DensityStaticB_ = 1.0f; 22 | 23 | FluidSourceShapeE VelocityShape_ = FluidSourceShapeE::POINT; 24 | float VelocityX_[4] = {1.0f, 1.0f, 1.0f, 1.0f}; 25 | float VelocityY_[4] = {1.0f, 1.0f, 1.0f, 1.0f}; 26 | float VelocitySourceSize_ = 1.0f; 27 | float VelocityBackProjection_ = 0.3f; // Linear Backprojection in seconds 28 | float VelocityWeight_ = 1.0f; 29 | }; 30 | 31 | #endif // FLUID_SOURCE_COMPONENT_HPP 32 | -------------------------------------------------------------------------------- /src/components/parent_component.hpp: -------------------------------------------------------------------------------- 1 | #ifndef PARENT_COMPONENT 2 | #define PARENT_COMPONENT 3 | 4 | #include 5 | 6 | #include 7 | 8 | struct ParentComponent 9 | { 10 | std::any Parent_; 11 | }; 12 | 13 | #endif // PARENT_COMPONENT 14 | -------------------------------------------------------------------------------- /src/components/physics_component.hpp: -------------------------------------------------------------------------------- 1 | #ifndef PHYSICS_COMPONENT_HPP 2 | #define PHYSICS_COMPONENT_HPP 3 | 4 | #include 5 | 6 | struct PhysicsComponent 7 | { 8 | b2Body* Body_ = nullptr; 9 | }; 10 | 11 | #endif // PHYSICS_COMPONENT_HPP 12 | -------------------------------------------------------------------------------- /src/components/status_component.hpp: -------------------------------------------------------------------------------- 1 | #ifndef STATUS_COMPONENT 2 | #define STATUS_COMPONENT 3 | 4 | #include "timer.h" 5 | 6 | enum class GameObjectTypeE : int 7 | { 8 | BOID, 9 | DEBRIS_LANDSCAPE, 10 | DEBRIS_SUBMARINE, 11 | LANDSCAPE, 12 | PROJECTILE, 13 | SUBMARINE_HULL, 14 | SUBMARINE_RUDDER, 15 | DEFAULT 16 | }; 17 | 18 | struct StatusComponent 19 | { 20 | GameObjectTypeE Type_ = GameObjectTypeE::DEFAULT; 21 | Timer Age_; 22 | int AgeMax_{-1}; // seconds, -1 = inf. 23 | int SinkDuration_{5}; // seconds 24 | bool IsSinking_{false}; 25 | bool IsSunk_{false}; 26 | bool IsToBeDeleted_{false}; 27 | }; 28 | 29 | #endif // STATUS_COMPONENT 30 | -------------------------------------------------------------------------------- /src/components/visuals_component.hpp: -------------------------------------------------------------------------------- 1 | #ifndef VISUALS_COMPONENT 2 | #define VISUALS_COMPONENT 3 | 4 | #include 5 | #include 6 | 7 | #include "drawable_generic.h" 8 | 9 | typedef std::vector MeshesType; 10 | 11 | struct VisualsComponent 12 | { 13 | MeshesType* Meshes_ = nullptr; 14 | Shaders::Flat2D* Shader_ = nullptr; 15 | Object2D* Visuals_ = nullptr; 16 | Scene2D* Scene_ = nullptr; 17 | DrawableGeneric* Drawable_ = nullptr; 18 | SceneGraph::DrawableGroup2D* DrawableGrp_ = nullptr; 19 | }; 20 | 21 | #endif // VISUALS_COMPONENT 22 | -------------------------------------------------------------------------------- /src/contact_listener.cpp: -------------------------------------------------------------------------------- 1 | #include "contact_listener.h" 2 | 3 | #include 4 | #include 5 | 6 | #include "emitter_component.hpp" 7 | #include "global_resources.h" 8 | #include "parent_component.hpp" 9 | #include "status_component.hpp" 10 | #include "submarine.h" 11 | 12 | void ContactListener::PreSolve(b2Contact* Contact, const b2Manifold* OldManifold) 13 | { 14 | b2PointState State1[2], State2[2]; 15 | b2GetPointStates(State1, State2, OldManifold, Contact->GetManifold()); 16 | 17 | bool IsValidContact = false; 18 | if (Contact->GetManifold()->pointCount == 1) 19 | { 20 | if (State2[0] == b2_addState) IsValidContact = true; 21 | } 22 | if (Contact->GetManifold()->pointCount == 2) 23 | { 24 | if ((State2[0] == b2_addState) || (State2[1] == b2_addState)) 25 | IsValidContact = true; 26 | } 27 | 28 | // Only emit debris if new collision occurred 29 | if (IsValidContact) 30 | { 31 | auto EntityA = *(reinterpret_cast(Contact->GetFixtureA()->GetBody()->GetUserData().pointer)); 32 | auto EntityB = *(reinterpret_cast(Contact->GetFixtureB()->GetBody()->GetUserData().pointer)); 33 | auto& StatusA = Reg_.get(EntityA); 34 | auto& StatusB = Reg_.get(EntityB); 35 | b2Body* BodyA = Reg_.get(EntityA).Body_; 36 | b2Body* BodyB = Reg_.get(EntityB).Body_; 37 | 38 | this->testGameObjectTypes(Contact, EntityA, EntityB, BodyA, BodyB); 39 | this->testGameObjectTypes(Contact, EntityB, EntityA, BodyB, BodyA); 40 | 41 | // else if (ObjA->getType() == GameObjectTypeE::SUBMARINE_HULL || 42 | // ObjA->getType() == GameObjectTypeE::SUBMARINE_RUDDER) 43 | // { 44 | // if (ObjB->getType() == GameObjectTypeE::PROJECTILE) 45 | // { 46 | // Body = Contact->GetFixtureB()->GetBody(); 47 | // if (Body != nullptr) 48 | // { 49 | // b2WorldManifold WorldManifold; 50 | // Contact->GetWorldManifold(&WorldManifold); 51 | // { 52 | // b2Vec2 POC = WorldManifold.points[0]; 53 | // b2Vec2 Velocity = Body->GetLinearVelocityFromWorldPoint(POC); 54 | 55 | // float AngleVel = std::atan2(Velocity.y, Velocity.x); 56 | // (AngleVel > 0.0f) ? AngleVel -= b2_pi : AngleVel += b2_pi; 57 | // float Angle = std::atan2(WorldManifold.normal.y, WorldManifold.normal.x) - AngleVel; 58 | // if (Angle > -0.7f && Angle < 0.7f) 59 | // { 60 | // IsContactKept = false; 61 | // std::any_cast(ObjA->getParent())->impact(2.0f); 62 | // } 63 | // } 64 | // } 65 | // DebrisType = GameObjectTypeE::DEBRIS_SUBMARINE; 66 | // } 67 | // } 68 | } 69 | } 70 | 71 | void ContactListener::emitLandscapeDebris(b2Contact* const _Contact, b2Body* const _Body1, b2Body* const _Body2) 72 | { 73 | b2Body* Body = _Body2; 74 | b2WorldManifold WorldManifold; 75 | _Contact->GetWorldManifold(&WorldManifold); 76 | 77 | b2Vec2 POC = WorldManifold.points[0]; 78 | b2Vec2 Velocity = Body->GetLinearVelocityFromWorldPoint(POC); 79 | float Mass = Body->GetMass(); 80 | 81 | float Angle = 2.0f * std::atan2(WorldManifold.normal.y, WorldManifold.normal.x) - 82 | (std::atan2(Velocity.y, Velocity.x)+b2_pi); 83 | 84 | auto Emitter = Reg_.create(); 85 | auto& EmComp = Reg_.emplace(Emitter); 86 | EmComp.Type_ = GameObjectTypeE::DEBRIS_LANDSCAPE; 87 | EmComp.Angle_ = Angle; 88 | EmComp.AngleStdDev_ = 1.0f; 89 | EmComp.Frequency_ = 1.0f; 90 | EmComp.Number_ = 20; 91 | EmComp.OriginX_ = POC.x+WorldManifold.normal.x*0.2f; 92 | EmComp.OriginY_ = POC.y+WorldManifold.normal.y*0.2f; 93 | EmComp.Scale_= 5.0; 94 | EmComp.ScaleStdDev_ = 2.5; 95 | EmComp.Velocity_ = 30.0f; 96 | EmComp.VelocityStdDev_ = 20.0f; 97 | EmComp.VelocityWeight_ = 0.0f; 98 | } 99 | 100 | void ContactListener::emitSubmarineDebris(b2Contact* const _Contact, 101 | b2Body* const _Body1, 102 | b2Body* const _Body2, 103 | const GameObjectTypeE _TypeOther) 104 | { 105 | constexpr float SCALE_SIZE_MAX = 2.0f; 106 | 107 | b2Body* Body = _Body1; 108 | b2WorldManifold WorldManifold; 109 | _Contact->GetWorldManifold(&WorldManifold); 110 | 111 | b2Vec2 POC = WorldManifold.points[0]; 112 | 113 | b2Vec2 Impulse(0.0f, 0.0f); 114 | b2Vec2 Velocity(0.0f, 0.0f); 115 | switch (_TypeOther) 116 | { 117 | case GameObjectTypeE::LANDSCAPE: 118 | Velocity = _Body1->GetLinearVelocityFromWorldPoint(POC); 119 | Impulse = _Body1->GetMass() * Velocity; 120 | 121 | break; 122 | case GameObjectTypeE::PROJECTILE: 123 | Velocity = (_Body2->GetLinearVelocityFromWorldPoint(POC)- 124 | _Body1->GetLinearVelocityFromWorldPoint(POC)); 125 | Impulse = _Body2->GetMass() * Velocity; 126 | break; 127 | case GameObjectTypeE::SUBMARINE_HULL: 128 | case GameObjectTypeE::SUBMARINE_RUDDER: 129 | Velocity = (_Body2->GetLinearVelocityFromWorldPoint(POC)- 130 | _Body1->GetLinearVelocityFromWorldPoint(POC)); 131 | Impulse = _Body2->GetMass() * Velocity; 132 | break; 133 | default: break; 134 | } 135 | 136 | float Scale = std::min(Impulse.Length()*1e-2f, SCALE_SIZE_MAX); 137 | 138 | float Angle = 2.0f * std::atan2(WorldManifold.normal.y, WorldManifold.normal.x) - 139 | (std::atan2(Velocity.y, Velocity.x)+b2_pi); 140 | 141 | if (_TypeOther == GameObjectTypeE::PROJECTILE || 142 | _TypeOther == GameObjectTypeE::SUBMARINE_HULL) 143 | { 144 | auto Emitter = Reg_.create(); 145 | auto& EmComp = Reg_.emplace(Emitter); 146 | EmComp.Type_ = GameObjectTypeE::DEBRIS_SUBMARINE; 147 | EmComp.Angle_ = Angle; 148 | EmComp.AngleStdDev_ = 1.0f; 149 | EmComp.Frequency_ = 1.0f; 150 | EmComp.Number_ = 10; 151 | EmComp.OriginX_ = POC.x+WorldManifold.normal.x*0.2f; 152 | EmComp.OriginY_ = POC.y+WorldManifold.normal.y*0.2f; 153 | EmComp.Scale_= Scale; 154 | EmComp.ScaleStdDev_ = Scale; 155 | EmComp.Velocity_ = Velocity.Length()*0.1f+5.0f; 156 | EmComp.VelocityStdDev_ = Velocity.Length()*0.1f; 157 | EmComp.VelocityWeight_ = 0.1f; 158 | } 159 | } 160 | 161 | void ContactListener::testGameObjectTypes(b2Contact* const _Contact, entt::entity _Entity1, entt::entity _Entity2, 162 | b2Body* const _Body1, b2Body* const _Body2) 163 | { 164 | auto& Status1 = Reg_.get(_Entity1); 165 | auto& Status2 = Reg_.get(_Entity2); 166 | 167 | if (Status1.Type_== GameObjectTypeE::LANDSCAPE) 168 | { 169 | if (Status2.Type_== GameObjectTypeE::PROJECTILE) 170 | { 171 | this->emitLandscapeDebris(_Contact, _Body1, _Body2); 172 | _Contact->SetEnabled(false); 173 | _Body2->SetLinearVelocity({0.0f, 0.0f}); 174 | Status2.IsSinking_ = true; 175 | Status2.IsSunk_ = true; 176 | } 177 | else if (Status2.Type_ == GameObjectTypeE::SUBMARINE_HULL || 178 | Status2.Type_ == GameObjectTypeE::SUBMARINE_RUDDER) 179 | 180 | { 181 | // this->emitLandscapeDebris(_Contact, _Body1, _Body2); 182 | // this->emitSubmarineDebris(_Contact, _Body2, _Body1, GameObjectTypeE::LANDSCAPE); 183 | } 184 | } 185 | else if (Status1.Type_ == GameObjectTypeE::PROJECTILE) 186 | { 187 | if (Status2.Type_ == GameObjectTypeE::SUBMARINE_HULL || 188 | Status2.Type_ == GameObjectTypeE::SUBMARINE_RUDDER) 189 | { 190 | this->emitSubmarineDebris(_Contact, _Body2, _Body1, GameObjectTypeE::SUBMARINE_HULL); 191 | _Contact->SetEnabled(false); 192 | _Body1->SetLinearVelocity({0.0f, 0.0f}); 193 | 194 | std::any_cast(Reg_.get(_Entity2).Parent_)->impact(2.0f); 195 | 196 | Status1.IsSinking_ = true; 197 | Status1.IsSunk_ = true; 198 | } 199 | } 200 | else if (Status1.Type_ == GameObjectTypeE::SUBMARINE_HULL || 201 | Status1.Type_ == GameObjectTypeE::SUBMARINE_RUDDER) 202 | { 203 | if (Status2.Type_ == GameObjectTypeE::SUBMARINE_HULL || 204 | Status2.Type_ == GameObjectTypeE::SUBMARINE_RUDDER) 205 | { 206 | // this->emitSubmarineDebris(_Contact, _Body1, _Body2, GameObjectTypeE::SUBMARINE_HULL); 207 | // this->emitSubmarineDebris(_Contact, _Body2, _Body1, GameObjectTypeE::SUBMARINE_HULL); 208 | } 209 | } 210 | } 211 | -------------------------------------------------------------------------------- /src/contact_listener.h: -------------------------------------------------------------------------------- 1 | #ifndef CONTACT_LISTENER_H 2 | #define CONTACT_LISTENER_H 3 | 4 | #include 5 | #include 6 | 7 | #include "status_component.hpp" 8 | 9 | class ContactListener : public b2ContactListener 10 | { 11 | 12 | public: 13 | 14 | explicit ContactListener(entt::registry& _Reg) : Reg_{_Reg} {} 15 | 16 | void PreSolve(b2Contact* Contact, const b2Manifold* OldManifold) override; 17 | 18 | private: 19 | 20 | void emitLandscapeDebris(b2Contact* const _Contact, 21 | b2Body* const _Body1, 22 | b2Body* const _Body2); 23 | void emitSubmarineDebris(b2Contact* const _Contact, 24 | b2Body* const _Body1, 25 | b2Body* const _Body2, 26 | const GameObjectTypeE _TypeOther); 27 | void testGameObjectTypes(b2Contact* const _Contact, 28 | entt::entity _Entity1, 29 | entt::entity _Entity2, 30 | b2Body* const _Body1, 31 | b2Body* const _Body2); 32 | 33 | entt::registry& Reg_; 34 | 35 | }; 36 | 37 | #endif // CONTACT_LISTENER_H 38 | -------------------------------------------------------------------------------- /src/drawable_generic.h: -------------------------------------------------------------------------------- 1 | #ifndef DRAWABLE_GENERIC_H 2 | #define DRAWABLE_GENERIC_H 3 | 4 | #include 5 | 6 | #include "common.h" 7 | 8 | class DrawableGeneric: public SceneGraph::Drawable2D 9 | { 10 | 11 | public: 12 | 13 | explicit DrawableGeneric(Object2D* Obj, 14 | GL::Mesh* Mesh, 15 | Shaders::Flat2D* Shader, 16 | const Color4& Color, 17 | SceneGraph::DrawableGroup2D* Drawables) : 18 | SceneGraph::Drawable2D{*Obj, Drawables}, Mesh_(Mesh), Shader_(Shader), Color_{Color} {} 19 | 20 | void setColor(const Color4 Color) {Color_ = Color;} 21 | 22 | private: 23 | 24 | void draw(const Matrix3& TransformationMatrix, SceneGraph::Camera2D& Camera) override 25 | { 26 | assert(Mesh_ != nullptr); 27 | assert(Shader_ != nullptr); 28 | Shader_ 29 | ->setTransformationProjectionMatrix(Camera.projectionMatrix()*TransformationMatrix) 30 | .setColor(Color_) 31 | .draw(*Mesh_); 32 | } 33 | 34 | GL::Mesh* Mesh_; 35 | Shaders::Flat2D* Shader_; 36 | Color4 Color_; 37 | 38 | }; 39 | 40 | #endif // DRAWABLE_GENERIC_H 41 | -------------------------------------------------------------------------------- /src/entity.cpp: -------------------------------------------------------------------------------- 1 | #include "entity.h" 2 | 3 | EntityIDType Entity::s_IDMax = 0; 4 | -------------------------------------------------------------------------------- /src/entity.h: -------------------------------------------------------------------------------- 1 | #ifndef ENTITY_H 2 | #define ENTITY_H 3 | 4 | typedef int EntityIDType; 5 | 6 | class Entity 7 | { 8 | public: 9 | 10 | Entity() : ID(s_IDMax++) {} 11 | 12 | EntityIDType ID = 0; 13 | 14 | 15 | private: 16 | 17 | static EntityIDType s_IDMax; 18 | 19 | }; 20 | 21 | #endif // ENTITY_H 22 | -------------------------------------------------------------------------------- /src/fluid_grid.h: -------------------------------------------------------------------------------- 1 | #ifndef FLUID_GRID_H 2 | #define FLUID_GRID_H 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | #include 9 | #include 10 | #include 11 | 12 | #include "advect_shader.h" 13 | #include "density_display_shader.h" 14 | #include "density_sources_shader.h" 15 | #include "drawable_generic.h" 16 | #include "fluid_final_composition_shader.h" 17 | #include "global_resources.h" 18 | #include "ground_distortion_shader.h" 19 | #include "jacobi_shader.h" 20 | #include "source_shader.h" 21 | #include "texture_2d32f_render_2d32f_shader.h" 22 | #include "velocity_display_shader.h" 23 | #include "velocity_divergence_shader.h" 24 | #include "velocity_gradient_substraction_shader.h" 25 | #include "velocity_sources_shader.h" 26 | #include "world_def.h" 27 | 28 | using namespace Magnum; 29 | 30 | enum class FluidBufferE : int 31 | { 32 | BOUNDARIES = 0, 33 | DENSITY_SOURCES = 1, 34 | DENSITY_BASE = 2, 35 | VELOCITY_SOURCES = 3, 36 | VELOCITIES_FRONT = 4, 37 | VELOCITIES_BACK = 5, 38 | VELOCITIES_LOW_RES = 6, 39 | VELOCITY_DIVERGENCE = 7, 40 | PRESSURE_FRONT = 8, 41 | PRESSURE_BACK = 9, 42 | DENSITY_DIFFUSION_FRONT = 10, 43 | DENSITY_DIFFUSION_BACK = 11, 44 | GROUND_DISTORTED = 12, 45 | FINAL_COMPOSITION = 13 46 | }; 47 | 48 | class FluidGrid 49 | { 50 | public: 51 | 52 | class Config 53 | { 54 | public: 55 | 56 | enum class Param : int 57 | { 58 | ITERATIONS_DENSITY_DIFFUSION, 59 | VELOCITY_ADVECTION_FACTOR 60 | }; 61 | 62 | int IterationsDensityDiffusion = 2; 63 | int IterationsVelocityDiffusion = 5; 64 | int IterationsPressureEquation = 20; 65 | float VelocityAdvectionFactor = 0.9f; 66 | float UpdateFrequency = 30.0f; // [Hz] 67 | 68 | bool onChange(Param _p); 69 | 70 | private: 71 | 72 | int IterationsDensityDiffusion_ = 2; 73 | float VelocityAdvectionFactor_ = 0.9f; 74 | 75 | } Conf; 76 | 77 | // Fluid Grid constants to be accessed from outside, too 78 | static constexpr float FLUID_FREQUENCY = 30.0f; 79 | static constexpr float FLUID_TIMESTEP = 1.0f/FLUID_FREQUENCY; 80 | static constexpr int VELOCITY_READBACK_SUBSAMPLE = 2; 81 | static constexpr int VELOCITY_READBACK_SUBSAMPLE_XY = 3; 82 | 83 | typedef std::array> VELOCITY_READBACK_SUBSAMPLE_XY)> VelocityReadbackDataType; 84 | 85 | explicit FluidGrid(entt::registry& _Reg) : Reg_(_Reg) {} 86 | FluidGrid() = delete; 87 | 88 | void loadConfig(); 89 | 90 | Vector2 getVelocity(const float _x, const float _y) const; 91 | const VelocityReadbackDataType& getVelocityReadback() const {return VelReadback_;}; 92 | 93 | FluidGrid& addDensityPt(const float _x, const float _y, const float _r, const float _g, const float _b); 94 | FluidGrid& addDensityLn(const float _x0, const float _y0, 95 | const float _x1, const float _y1, 96 | const float _r, const float _g, const float _b); 97 | FluidGrid& addVelocity(const float x, const float y, const float Vx, const float Vy, 98 | const float w = 1.0f); 99 | FluidGrid& addVelocity(const float x0, const float y0, const float Vx0, const float Vy0, 100 | const float x1, const float y1, const float Vx1, const float Vy1, 101 | const float w = 1.0f); 102 | FluidGrid& setDensityDistortion(const float f) {ShaderGroundDistortion_.setDistortion(f); return *this;} 103 | FluidGrid& setConfig(const Config& _Config) {Conf = _Config; return *this;} 104 | FluidGrid& setIterationsDensityDiffusion(const int n) 105 | { 106 | // Conf.IterationsDensityDiffusion_ = n; 107 | // ShaderJacobi1d_.setAlpha(getDiffusionAlpha()); 108 | return *this; 109 | } 110 | FluidGrid& setScalarFieldDisplayScale(const float f) {ShaderDensityDisplay_.setScale(f); return *this;} 111 | FluidGrid& setVelocityDisplayScale(const float f) {ShaderVelocityDisplay_.setScale(f); return *this;} 112 | FluidGrid& setVelocityDisplayShowOnlyMagnitude(const bool b) {ShaderVelocityDisplay_.setShowOnlyMagnitude(b); return *this;} 113 | FluidGrid& setDensityBase(std::vector* const DensityBase); 114 | 115 | void bindBoundaryMap(); 116 | void display(const Matrix3 CameraProjection, 117 | const FluidBufferE Buffer = FluidBufferE::FINAL_COMPOSITION); 118 | void init(); 119 | void process(const double); 120 | 121 | private: 122 | 123 | entt::registry& Reg_; 124 | 125 | static constexpr int VELOCITY_READBACK_FRACTION_SIZE = 3; 126 | typedef std::array> 127 | (VELOCITY_READBACK_SUBSAMPLE_XY+ 128 | VELOCITY_READBACK_FRACTION_SIZE))> VelocityReadbackFractionDataType; 129 | static constexpr Magnum::Range2Di ViewportFull{{0, 0}, {FLUID_GRID_SIZE_X, FLUID_GRID_SIZE_Y}}; 130 | static constexpr Magnum::Range2Di ViewportTop{{0, 0}, {FLUID_GRID_SIZE_X, FLUID_GRID_SIZE_Y>>1}}; 131 | static constexpr Magnum::Range2Di ViewportBottom{{0, FLUID_GRID_SIZE_Y>>1}, {FLUID_GRID_SIZE_X, FLUID_GRID_SIZE_Y}}; 132 | const Magnum::Range2Di* ViewportCurrent = &ViewportTop; 133 | const Magnum::Range2Di* ViewportNext = &ViewportBottom; 134 | 135 | float getPressureEquationAlpha() 136 | { 137 | // float Res = float(FLUID_GRID_SIZE_X) / WORLD_SIZE_DEFAULT_X; 138 | float Res = WORLD_SIZE_DEFAULT_X / FLUID_GRID_SIZE_X; 139 | // return -Res*Res; 140 | return 2.0f; 141 | } 142 | float getDiffusionAlpha() 143 | { 144 | float Res = float(FLUID_GRID_SIZE_X) / WORLD_SIZE_DEFAULT_X; 145 | // float Res = WORLD_SIZE_DEFAULT_X / FLUID_GRID_SIZE_X; 146 | return Res*Res / Conf.IterationsDensityDiffusion * FLUID_FREQUENCY; 147 | } 148 | void readbackVelocities(const int _Fraction, const int _SubDivisionBase2); 149 | 150 | void advectDensities(); 151 | void advectVelocities(); 152 | void diffuseDensities(); 153 | void calculateDivergence(); 154 | void calculatePressure(); 155 | void substractPressureGradient(); 156 | void diffuseVelocities(); 157 | void renderDensitySources(); 158 | void renderVelocitySources(); 159 | 160 | // int IterationsDensityDiffusion_ = 5; 161 | 162 | VelocityReadbackDataType VelReadback_; 163 | 164 | GL::BufferImage2D* PBOVelocityFront_{nullptr}; 165 | GL::BufferImage2D* PBOVelocityBack_{nullptr}; 166 | GL::BufferImage2D PBOVelocity0_{NoCreate}; 167 | GL::BufferImage2D PBOVelocity1_{NoCreate}; 168 | GL::Framebuffer* FBODensitiesBack_{nullptr}; 169 | GL::Framebuffer* FBODensitiesFront_{nullptr}; 170 | GL::Framebuffer* FBOPressureBack_{nullptr}; 171 | GL::Framebuffer* FBOPressureFront_{nullptr}; 172 | GL::Framebuffer* FBOVelocitiesBack_{nullptr}; 173 | GL::Framebuffer* FBOVelocitiesFront_{nullptr}; 174 | GL::Framebuffer FBOBoundaries_{NoCreate}; 175 | GL::Framebuffer FBODensitySources_{NoCreate}; 176 | GL::Framebuffer FBODensities0_{NoCreate}; 177 | GL::Framebuffer FBODensities1_{NoCreate}; 178 | GL::Framebuffer FBOFluidFinalComposition_{NoCreate}; 179 | GL::Framebuffer FBOGroundDistorted_{NoCreate}; 180 | GL::Framebuffer FBOPressure0_{NoCreate}; 181 | GL::Framebuffer FBOPressure1_{NoCreate}; 182 | GL::Framebuffer FBOVelocitySources_{NoCreate}; 183 | GL::Framebuffer FBOVelocities0_{NoCreate}; 184 | GL::Framebuffer FBOVelocities1_{NoCreate}; 185 | GL::Framebuffer FBOVelocitiesLowRes_{NoCreate}; 186 | GL::Framebuffer FBOVelocityDivergence_{NoCreate}; 187 | 188 | AdvectShader ShaderAdvect1d_{NoCreate}; 189 | AdvectShader ShaderAdvect2d_{NoCreate}; 190 | DensityDisplayShader ShaderDensityDisplay_{NoCreate}; 191 | DensitySourcesShader ShaderDensitySources_{NoCreate}; 192 | GroundDistortionShader ShaderGroundDistortion_{NoCreate}; 193 | FluidFinalCompositionShader ShaderFluidFinalComposition_{NoCreate}; 194 | JacobiShader ShaderJacobi1d_{NoCreate}; 195 | JacobiShader ShaderJacobi2d_{NoCreate}; 196 | SourceShader ShaderSource1d_{NoCreate}; 197 | SourceShader ShaderSource2d_{NoCreate}; 198 | Texture2D32FRender2D32FShader ShaderVelocityLowRes_{NoCreate}; 199 | VelocityDisplayShader ShaderVelocityDisplay_{NoCreate}; 200 | VelocityDivergenceShader ShaderVelocityDivergence_{NoCreate}; 201 | VelocityGradientSubstractionShader ShaderVelocityGradientSubstraction_{NoCreate}; 202 | VelocitySourcesShader ShaderVelocitySources_{NoCreate}; 203 | 204 | GL::Mesh MeshFluidGridBuffer_{NoCreate}; 205 | 206 | GL::Texture2D* TexVelocitiesBack_{nullptr}; 207 | GL::Texture2D* TexVelocitiesFront_{nullptr}; 208 | GL::Texture2D* TexDensitiesBack_{nullptr}; 209 | GL::Texture2D* TexDensitiesFront_{nullptr}; 210 | GL::Texture2D* TexPressureBack_{nullptr}; 211 | GL::Texture2D* TexPressureFront_{nullptr}; 212 | GL::Texture2D TexBoundaries_{NoCreate}; 213 | GL::Texture2D TexDensityBase_{NoCreate}; // Heightmap 214 | GL::Texture2D TexDensitySources_{NoCreate}; // Density sources 215 | GL::Texture2D TexDensities0_{NoCreate}; // Density buffer 216 | GL::Texture2D TexDensities1_{NoCreate}; // Density buffer 217 | GL::Texture2D TexFluidFinalComposition_{NoCreate}; 218 | GL::Texture2D TexGroundDistorted_{NoCreate}; 219 | GL::Texture2D TexPressure0_{NoCreate}; 220 | GL::Texture2D TexPressure1_{NoCreate}; 221 | GL::Texture2D TexVelocitySources_{NoCreate}; // Velocity sources 222 | GL::Texture2D TexVelocities0_{NoCreate}; // Velocities back buffer 223 | GL::Texture2D TexVelocities1_{NoCreate}; // Velocities front buffer 224 | GL::Texture2D TexVelocityDivergence_{NoCreate}; 225 | GL::Texture2D TexVelocitiesLowRes_{NoCreate}; 226 | 227 | std::vector* DensityBase_{nullptr}; 228 | std::vector DensitySourcesPoints_; 229 | std::vector DensitySourcesLines_; 230 | std::vector VelocitySourcesPoints_; 231 | std::vector VelocitySourcesLines_; 232 | 233 | }; 234 | 235 | #endif // FLUID_GRID_H 236 | -------------------------------------------------------------------------------- /src/global_resources.cpp: -------------------------------------------------------------------------------- 1 | #include "global_resources.h" 2 | 3 | ResourceStorage GlobalResources::Get; 4 | -------------------------------------------------------------------------------- /src/global_resources.h: -------------------------------------------------------------------------------- 1 | #ifndef GLOBAL_RESOURCES_H 2 | #define GLOBAL_RESOURCES_H 3 | 4 | #include "resource_storage.h" 5 | 6 | struct GlobalResources 7 | { 8 | 9 | static ResourceStorage Get; 10 | 11 | }; 12 | 13 | #endif // GLOBAL_RESOURCES_H 14 | -------------------------------------------------------------------------------- /src/gui_adapter/fluid_source_component_config_gui_adapter.hpp: -------------------------------------------------------------------------------- 1 | #ifndef FLUID_SOURCE_COMPONENT_CONFIG_GUI_ADAPTER_HPP 2 | #define FLUID_SOURCE_COMPONENT_CONFIG_GUI_ADAPTER_HPP 3 | 4 | #include 5 | 6 | #include 7 | #include 8 | 9 | #include "fluid_source_component.hpp" 10 | 11 | class FluidSourceComponentConfigGuiAdapter 12 | { 13 | public: 14 | 15 | explicit FluidSourceComponentConfigGuiAdapter(const std::string& _s) : s_(_s) {} 16 | FluidSourceComponentConfigGuiAdapter() = delete; 17 | 18 | bool place() 19 | { 20 | ImGui::Text((s_+" Densities").c_str()); 21 | bool r{false}; 22 | float ColDyn[3]; 23 | ColDyn[0] = Conf_.DensityDynamicR_; 24 | ColDyn[1] = Conf_.DensityDynamicG_; 25 | ColDyn[2] = Conf_.DensityDynamicB_; 26 | float ColStat[3]; 27 | ColStat[0] = Conf_.DensityStaticR_; 28 | ColStat[1] = Conf_.DensityStaticG_; 29 | ColStat[2] = Conf_.DensityStaticB_; 30 | if (ImGui::ColorEdit3("Dynamic", ColDyn)) 31 | { 32 | Conf_.DensityDynamicR_ = ColDyn[0]; 33 | Conf_.DensityDynamicG_ = ColDyn[1]; 34 | Conf_.DensityDynamicB_ = ColDyn[2]; 35 | r = true; 36 | } 37 | if (ImGui::ColorEdit3("Static", ColStat)) 38 | { 39 | Conf_.DensityStaticR_ = ColStat[0]; 40 | Conf_.DensityStaticG_ = ColStat[1]; 41 | Conf_.DensityStaticB_ = ColStat[2]; 42 | r = true; 43 | } 44 | return r; 45 | } 46 | 47 | const FluidSourceComponent& get() const 48 | { 49 | return Conf_; 50 | } 51 | 52 | void set(const FluidSourceComponent& _c) 53 | { 54 | Conf_ = _c; 55 | } 56 | 57 | private: 58 | 59 | FluidSourceComponent Conf_; 60 | std::string s_; 61 | 62 | }; 63 | 64 | #endif // FLUID_SOURCE_COMPONENT_CONFIG_GUI_ADAPTER_HPP 65 | -------------------------------------------------------------------------------- /src/gui_adapter/status_component_config_gui_adapter.hpp: -------------------------------------------------------------------------------- 1 | #ifndef STATUS_COMPONENT_CONFIG_GUI_ADAPTER_HPP 2 | #define STATUS_COMPONENT_CONFIG_GUI_ADAPTER_HPP 3 | 4 | #include 5 | 6 | #include 7 | #include 8 | 9 | #include "status_component.hpp" 10 | 11 | class StatusComponentConfigGuiAdapter 12 | { 13 | public: 14 | 15 | explicit StatusComponentConfigGuiAdapter(const std::string& _s) : s_(_s) {} 16 | StatusComponentConfigGuiAdapter() = delete; 17 | 18 | bool place() 19 | { 20 | bool r{false}; 21 | 22 | ImGui::Text((s_+" Config").c_str()); 23 | if (ImGui::SliderInt("Max Age (s)", &Conf_.AgeMax_, -1, 100)) 24 | r = true; 25 | if (ImGui::SliderInt("Sink Duration (s)", &Conf_.SinkDuration_, 0, 100)) 26 | r = true; 27 | 28 | return r; 29 | } 30 | 31 | const StatusComponent& get() const 32 | { 33 | return Conf_; 34 | } 35 | 36 | void set(const StatusComponent& _c) 37 | { 38 | Conf_ = _c; 39 | } 40 | 41 | private: 42 | 43 | StatusComponent Conf_; 44 | std::string s_; 45 | 46 | }; 47 | 48 | #endif // STATUS_COMPONENT_CONFIG_GUI_ADAPTER_HPP 49 | -------------------------------------------------------------------------------- /src/lua/config.lua: -------------------------------------------------------------------------------- 1 | -- Fluid dynamics configuration 2 | fluid_dynamics = { 3 | iterations_density_diffusion = 2, 4 | iterations_velocity_diffusion = 5, 5 | iterations_pressure_equation = 20, 6 | velocity_advection_factor = 0.9, 7 | update_frequency = 30.0 8 | } 9 | 10 | display = { 11 | fluid_visual = 1.0 12 | } 13 | 14 | -- Configuration of debris components 15 | debris = { 16 | 17 | status_component = { 18 | age_max = 20, 19 | sink_duration = 5 20 | }, 21 | 22 | fluid_source_component = { 23 | density_back_projection = 1.0/fluid_dynamics.update_frequency, 24 | density_dynamic_r = 0.2, 25 | density_dynamic_g = 0.3, 26 | density_dynamic_b = 1.0, 27 | density_static_r = 1.0, 28 | density_static_g = 2.0, 29 | density_static_b = 5.0, 30 | velocity_back_projection = 1.0/fluid_dynamics.update_frequency 31 | } 32 | } 33 | 34 | -- Configuration of projectile components 35 | projectile = { 36 | 37 | status_component = { 38 | age_max = 5, 39 | sink_duration = 5 40 | }, 41 | 42 | fluid_source_component = { 43 | density_back_projection = 1.0/fluid_dynamics.update_frequency, 44 | density_dynamic_r = 1.0, 45 | density_dynamic_g = 1.0, 46 | density_dynamic_b = 0.5, 47 | density_static_r = 100.0, 48 | density_static_g = 20.0, 49 | density_static_b = 20.0, 50 | velocity_back_projection = 1.0/fluid_dynamics.update_frequency 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /src/lua_manager.hpp: -------------------------------------------------------------------------------- 1 | #ifndef LUA_MANAGER_HPP 2 | #define LUA_MANAGER_HPP 3 | 4 | #include 5 | 6 | #include "lua_path.hpp" 7 | #include "message_handler.hpp" 8 | 9 | #define SOL_ALL_SAFETIES_ON 1 10 | #include // Needed for sol, seemed to be forgotten 11 | #include "sol.hpp" 12 | 13 | #include 14 | 15 | class LuaManager 16 | { 17 | public: 18 | 19 | explicit LuaManager(entt::registry& _Reg) : Reg_(_Reg) 20 | { 21 | State_.open_libraries(sol::lib::base); 22 | } 23 | LuaManager() = delete; 24 | 25 | bool loadFile(const std::string& _f) 26 | { 27 | sol::protected_function_result r = State_.safe_script_file(LUA_PATH+_f); 28 | if (r.valid()) 29 | { 30 | Reg_.ctx().at().report("lua", "Loading "+_f+" successful", MessageHandler::INFO); 31 | return true; 32 | } 33 | else 34 | { 35 | sol::error e = r; 36 | Reg_.ctx().at().report("lua","Loading "+_f+" failed: "+e.what()); 37 | return false; 38 | } 39 | } 40 | 41 | template 42 | T get(const sol::optional& _r, T _Default = 0) 43 | { 44 | if (_r) 45 | { 46 | return _r.value(); 47 | } 48 | else 49 | { 50 | Reg_.ctx().at().report("lua", "Lua error aquiring value."); 51 | return _Default; 52 | } 53 | } 54 | 55 | sol::state State_; 56 | 57 | private: 58 | 59 | entt::registry& Reg_; 60 | }; 61 | 62 | #endif // LUA_MANAGER_HPP 63 | -------------------------------------------------------------------------------- /src/lua_path.hpp: -------------------------------------------------------------------------------- 1 | #ifndef LUA_PATH_HPP 2 | #define LUA_PATH_HPP 3 | 4 | static const char* LUA_PATH = "./install/share/lua/"; 5 | 6 | #endif 7 | -------------------------------------------------------------------------------- /src/message_handler.hpp: -------------------------------------------------------------------------------- 1 | #ifndef MESSAGE_HANDLER_H 2 | #define MESSAGE_HANDLER_H 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | // Only compile debug blocks in debug mode 14 | #ifdef NDEBUG 15 | #define DBLK(x) 16 | #else 17 | #define DBLK(x) x 18 | #endif 19 | 20 | class MessageHandler 21 | { 22 | 23 | public: 24 | 25 | typedef enum 26 | { 27 | ERROR = 0, 28 | WARNING = 1, 29 | INFO = 2, 30 | DEBUG_L1 = 3, 31 | DEBUG_L2 = 4, 32 | DEBUG_L3 = 5 33 | } ReportLevelType; 34 | 35 | bool checkError() 36 | { 37 | return ErrorFlag.exchange(false); 38 | } 39 | 40 | void registerSource(const std::string& _Source, const std::string& _DisplayName) 41 | { 42 | SourceMap_.insert({_Source, _DisplayName}); 43 | } 44 | 45 | void report(const std::string& _Source, const std::string& _Message, const ReportLevelType _Level = ERROR) 46 | { 47 | auto t = std::chrono::system_clock::to_time_t(std::chrono::system_clock::now()); 48 | 49 | std::stringstream Message; 50 | std::string L; 51 | 52 | switch (_Level) 53 | { 54 | case ERROR: 55 | L = "[ E ]"; 56 | break; 57 | case WARNING: 58 | L = "[ W ]"; 59 | break; 60 | case INFO: 61 | L = "[ I ]"; 62 | break; 63 | case DEBUG_L1: 64 | case DEBUG_L2: 65 | case DEBUG_L3: 66 | L = "[ D" + std::to_string(_Level-2) + " ]"; 67 | break; 68 | default: 69 | L = "[ ? ]"; 70 | 71 | } 72 | if (_Level <= Level_) 73 | { 74 | if (IsColored_) 75 | { 76 | if (_Level == 0) 77 | { 78 | Message << "\033[31m"; 79 | } 80 | else if (_Level == 1) 81 | { 82 | Message << "\033[33m"; 83 | } 84 | else if (_Level == 2) 85 | { 86 | Message << "\033[32m"; 87 | } 88 | } 89 | Message << std::put_time(std::localtime(&t), "%Y-%m-%d %X") << " "; 90 | 91 | if (SourceMap_.count(_Source) == 1) 92 | { 93 | Message << L << "[ " << SourceMap_[_Source] << " ] " << _Message; 94 | } 95 | else 96 | { 97 | Message << L << "[ " << _Source << ": source not found ] " << _Message; 98 | } 99 | if (IsColored_ && (_Level == 0 || _Level == 1) || _Level == 2) 100 | { 101 | Message << "\033[0m"; 102 | } 103 | if (_Level == 0) 104 | { 105 | std::cerr << Message.str() << std::endl; 106 | ErrorFlag = true; 107 | } 108 | else 109 | std::cout << Message.str() << std::endl; 110 | } 111 | } 112 | 113 | void reportRaw(const std::string& _Message, const ReportLevelType _Level = INFO) 114 | { 115 | if (_Level <= Level_) 116 | { 117 | std::cout << _Message; 118 | } 119 | } 120 | 121 | void setColored(bool _IsColored) {IsColored_ = _IsColored;} 122 | void setLevel(ReportLevelType _Level) {Level_ = _Level;} 123 | 124 | private: 125 | 126 | std::atomic_bool ErrorFlag{false}; 127 | std::atomic Level_{DEBUG_L3}; 128 | 129 | bool IsColored_{true}; 130 | // Map source identifiers to display names 131 | std::unordered_map SourceMap_; 132 | 133 | }; 134 | 135 | #endif // MESSAGE_HANDLER_H 136 | -------------------------------------------------------------------------------- /src/resource_storage.cpp: -------------------------------------------------------------------------------- 1 | #include "resource_storage.h" 2 | 3 | #include 4 | #include 5 | 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | 15 | #include "common.h" 16 | #include "message_handler.hpp" 17 | #include "noise.h" 18 | #include "timer.h" 19 | #include "world_def.h" 20 | 21 | void ResourceStorage::init() 22 | { 23 | this->initBoids(); 24 | this->initDebris(); 25 | this->initHeightMap(); 26 | this->initLandscape(); 27 | this->initProjectile(); 28 | this->initSubmarine(); 29 | 30 | Shader_ = new Shaders::Flat2D{}; 31 | 32 | IsInitialised = true; 33 | } 34 | 35 | void ResourceStorage::release() 36 | { 37 | if (IsInitialised) 38 | { 39 | for (auto i=0u; iconvertGeometryPhysicsToGraphics(ShapeG), GL::BufferUsage::StaticDraw); 102 | MeshBoid.setCount(ShapeG.size()) 103 | .setPrimitive(GL::MeshPrimitive::TriangleFan) 104 | .addVertexBuffer(std::move(Buffer), 0, Shaders::VertexColor2D::Position{}); 105 | Meshes_[int(GameObjectTypeE::BOID)].push_back(std::move(MeshBoid)); 106 | } 107 | 108 | void ResourceStorage::initDebris() 109 | { 110 | constexpr float DEBRIS_SIZE_AVG = 0.05; 111 | 112 | ShapeType ShapeG; // Shape for graphics differs from physics shape (circle) 113 | 114 | for (auto i=0.0f; i<2.0f*3.14159f; i+=2.0f*3.14159f/5.0f) 115 | { 116 | ShapeG.push_back({DEBRIS_SIZE_AVG*std::cos(i), 117 | DEBRIS_SIZE_AVG*std::sin(i)}); 118 | } 119 | 120 | auto& ShapesLandscape = Shapes_[int(GameObjectTypeE::DEBRIS_LANDSCAPE)]; 121 | auto& ShapesSubmarine = Shapes_[int(GameObjectTypeE::DEBRIS_SUBMARINE)]; 122 | 123 | b2FixtureDef Fixture; 124 | Fixture.density = 2.5f; 125 | Fixture.friction = 0.02f; // Use low value, since we are using a circle for performance reasons 126 | Fixture.restitution = 0.2f; 127 | Fixture.isSensor = false; 128 | 129 | // Physics shape (circle), always 3 values here 130 | // - center x 131 | // - center y 132 | // - radius 133 | // - dummy 134 | ShapeType ShapeP{{0.0f, 0.0f}, {DEBRIS_SIZE_AVG, 0.0f}}; 135 | 136 | ShapesLandscape.ShapeDefs.push_back(ShapeP); 137 | ShapesLandscape.FixtureDefs.push_back(Fixture); 138 | ShapesLandscape.Type = ShapeEnumType::CIRCLE; 139 | ShapesSubmarine.ShapeDefs.push_back(std::move(ShapeP)); 140 | ShapesSubmarine.FixtureDefs.push_back(std::move(Fixture)); 141 | ShapesSubmarine.Type = ShapeEnumType::CIRCLE; 142 | 143 | GL::Mesh MeshLandscape; 144 | GL::Mesh MeshSubmarine; 145 | GL::Buffer Buffer; 146 | Buffer.setData(this->convertGeometryPhysicsToGraphics(ShapeG), GL::BufferUsage::StaticDraw); 147 | MeshLandscape.setCount(ShapeG.size()) 148 | .setPrimitive(GL::MeshPrimitive::TriangleFan) 149 | .addVertexBuffer(Buffer, 0, Shaders::VertexColor2D::Position{}); 150 | MeshSubmarine.setCount(ShapeG.size()) 151 | .setPrimitive(GL::MeshPrimitive::TriangleFan) 152 | .addVertexBuffer(std::move(Buffer), 0, Shaders::VertexColor2D::Position{}); 153 | Meshes_[int(GameObjectTypeE::DEBRIS_LANDSCAPE)].push_back(std::move(MeshLandscape)); 154 | Meshes_[int(GameObjectTypeE::DEBRIS_SUBMARINE)].push_back(std::move(MeshSubmarine)); 155 | } 156 | 157 | void ResourceStorage::initHeightMap() 158 | { 159 | noise::module::RidgedMulti HeightmapRidge; 160 | noise::module::Perlin HeightmapBillow; 161 | noise::module::Add Average; 162 | noise::module::Turbulence FinalTerrain; 163 | noise::module::Exponent Exponent; 164 | noise::module::Clamp Plateus; 165 | 166 | { 167 | double FrequencyRidged = 0.001; 168 | double LacunarityRidged = 1.7931; 169 | 170 | HeightmapRidge.SetFrequency(FrequencyRidged); 171 | HeightmapRidge.SetLacunarity(LacunarityRidged); 172 | // HeightmapRidge.SetPersistence(0.5371); 173 | HeightmapRidge.SetNoiseQuality(noise::QUALITY_BEST); 174 | HeightmapRidge.SetNoiseType(noise::TYPE_VALUE); 175 | 176 | 177 | int OctaveCount = ceil(log2(1.0/FrequencyRidged)/log2(LacunarityRidged)); 178 | if (OctaveCount < 1) OctaveCount = 1; 179 | 180 | HeightmapRidge.SetOctaveCount(OctaveCount); 181 | HeightmapRidge.SetSeed(7); 182 | } 183 | { 184 | double Frequency = 0.01; 185 | double Lacunarity = 1.9731; 186 | 187 | HeightmapBillow.SetFrequency(Frequency); 188 | HeightmapBillow.SetLacunarity(Lacunarity); 189 | HeightmapBillow.SetPersistence(0.5371); 190 | HeightmapBillow.SetNoiseQuality(noise::QUALITY_BEST); 191 | HeightmapBillow.SetNoiseType(noise::TYPE_VALUE); 192 | 193 | int OctaveCount = ceil(log2(1.0/Frequency)/log2(Lacunarity)); 194 | if (OctaveCount < 1) OctaveCount = 1; 195 | 196 | HeightmapBillow.SetOctaveCount(OctaveCount); 197 | HeightmapBillow.SetSeed(13); 198 | } 199 | Average.SetSourceModule(0, HeightmapRidge); 200 | Average.SetSourceModule(1, HeightmapBillow); 201 | FinalTerrain.SetSourceModule(0, Average); 202 | FinalTerrain.SetFrequency(0.005); 203 | FinalTerrain.SetPower(500.0); 204 | 205 | Exponent.SetExponent(2.0); 206 | Exponent.SetSourceModule(0, FinalTerrain); 207 | 208 | Plateus.SetBounds(-1.0, 0.6); 209 | Plateus.SetSourceModule(0, Exponent); 210 | 211 | // Fill heightmap, use multithreading 212 | HeightMap_.resize(FLUID_GRID_ARRAY_SIZE); 213 | 214 | auto NoOfThreads = std::thread::hardware_concurrency(); 215 | 216 | // GlobalMessageHandler.report("Building height map."); 217 | // DBLK( 218 | // GlobalMessageHandler.reportDebug("Number of threads: " + std::to_string(NoOfThreads)); 219 | // Timer HeightMapTimer; 220 | // HeightMapTimer.start(); 221 | // ) 222 | 223 | std::vector Workers; 224 | for (auto i=0u; i=0.6) v*=2.0; 236 | HeightMap_[(y << FLUID_GRID_SIZE_X_BITS) + x] = v; 237 | } 238 | } 239 | } 240 | )); 241 | } 242 | for (auto i=0u; iresize(FLUID_GRID_ARRAY_SIZE); 264 | HeightMapPlateausFront_->resize(FLUID_GRID_ARRAY_SIZE); 265 | 266 | for (auto y=0u; y ValueMax) ValueMax = Value; 310 | // } 311 | // } 312 | // (*HeightMapPlateausFront_)[y*FLUID_GRID_SIZE_X+x] = ValueMax; 313 | // } 314 | // } 315 | // std::swap(HeightMapPlateausFront_, HeightMapPlateausBack_); 316 | // } 317 | // //--- Kind of Marching Squares ---// 318 | // std::swap(HeightMapPlateausFront_, HeightMapPlateausBack_); 319 | // for (auto y=1u; y 1) (*HeightMapPlateausFront_)[y*FLUID_GRID_SIZE_X+x] = 0.0; 333 | // else (*HeightMapPlateausFront_)[y*FLUID_GRID_SIZE_X+x] = 1.0; 334 | // } 335 | // } 336 | 337 | for (auto y=0u; y=-h-b; i-=1.0f) 382 | { 383 | ShapeRight.push_back({w - a * float(Boundary.GetValue(double(w), double(i))), i}); 384 | } 385 | ShapeRight.push_back({w+b, -h-b}); 386 | 387 | // Left 388 | ShapeType ShapeLeft; 389 | ShapeLeft.push_back({-w-b, -h-b}); 390 | for (auto i=-h-b; i<=h+b; i+=1.0f) 391 | { 392 | ShapeLeft.push_back({-w + a * float(Boundary.GetValue(double(-w), double(i))), i}); 393 | } 394 | ShapeLeft.push_back({-w-b, h+b}); 395 | 396 | // Bottom 397 | ShapeType ShapeBottom; 398 | ShapeBottom.push_back({w+b, -h-b}); 399 | for (auto i=w+b; i>=-w-b; i-=1.0f) 400 | { 401 | ShapeBottom.push_back({i, -h + a * float(Boundary.GetValue(double(i), double(-h)))}); 402 | } 403 | ShapeBottom.push_back({-w-b, -h-b}); 404 | 405 | auto& Shapes = Shapes_[int(GameObjectTypeE::LANDSCAPE)]; 406 | 407 | b2FixtureDef Fixture; 408 | Fixture.density = 1.0f; 409 | Fixture.friction = 0.9f; 410 | Fixture.restitution = 0.2f; 411 | Fixture.isSensor = false; 412 | 413 | Shapes.ShapeDefs.push_back(std::move(ShapeTop)); 414 | Shapes.FixtureDefs.push_back(Fixture); 415 | Shapes.Type = ShapeEnumType::CHAIN; 416 | { 417 | ShapeType TmpShape; 418 | for (auto i=1u; iconvertGeometryPhysicsToGraphics(TmpShape), GL::BufferUsage::StaticDraw); 431 | Mesh.setCount(TmpShape.size()) 432 | .setPrimitive(GL::MeshPrimitive::Triangles) 433 | .addVertexBuffer(std::move(Buffer), 0, Shaders::VertexColor2D::Position{}); 434 | Meshes_[int(GameObjectTypeE::LANDSCAPE)].push_back(std::move(Mesh)); 435 | } 436 | Shapes.ShapeDefs.push_back(ShapeRight); 437 | Shapes.FixtureDefs.push_back(std::move(Fixture)); 438 | { 439 | ShapeType TmpShape; 440 | for (auto i=1u; iconvertGeometryPhysicsToGraphics(TmpShape), GL::BufferUsage::StaticDraw); 453 | Mesh.setCount(TmpShape.size()) 454 | .setPrimitive(GL::MeshPrimitive::Triangles) 455 | .addVertexBuffer(std::move(Buffer), 0, Shaders::VertexColor2D::Position{}); 456 | Meshes_[int(GameObjectTypeE::LANDSCAPE)].push_back(std::move(Mesh)); 457 | } 458 | Shapes.ShapeDefs.push_back(std::move(ShapeLeft)); 459 | Shapes.FixtureDefs.push_back(Fixture); 460 | { 461 | ShapeType TmpShape; 462 | for (auto i=1u; iconvertGeometryPhysicsToGraphics(TmpShape), GL::BufferUsage::StaticDraw); 475 | Mesh.setCount(TmpShape.size()) 476 | .setPrimitive(GL::MeshPrimitive::Triangles) 477 | .addVertexBuffer(std::move(Buffer), 0, Shaders::VertexColor2D::Position{}); 478 | Meshes_[int(GameObjectTypeE::LANDSCAPE)].push_back(std::move(Mesh)); 479 | } 480 | Shapes.ShapeDefs.push_back(std::move(ShapeBottom)); 481 | Shapes.FixtureDefs.push_back(std::move(Fixture)); 482 | { 483 | ShapeType TmpShape; 484 | for (auto i=1u; iconvertGeometryPhysicsToGraphics(TmpShape), GL::BufferUsage::StaticDraw); 497 | Mesh.setCount(TmpShape.size()) 498 | .setPrimitive(GL::MeshPrimitive::Triangles) 499 | .addVertexBuffer(std::move(Buffer), 0, Shaders::VertexColor2D::Position{}); 500 | Meshes_[int(GameObjectTypeE::LANDSCAPE)].push_back(std::move(Mesh)); 501 | } 502 | 503 | // DBLK( 504 | // GlobalMessageHandler.reportDebug("Boundary octave count: " + std::to_string(OctaveCount), MessageHandler::DEBUG_L1); 505 | // GlobalMessageHandler.reportDebug("Boundary vertex count: " + std::to_string(Shapes.ShapeDefs.back().size()), MessageHandler::DEBUG_L1); 506 | // ) 507 | } 508 | { 509 | Boundary.SetFrequency(0.008); 510 | ShapeType Shape; 511 | for (auto i=0.0f; i<2.0f*b2_pi; i+=2.0f*b2_pi/100.0f) 512 | { 513 | auto Value = 5.0f * float(Boundary.GetValue(100.0 * std::cos(double(i)), 100.0 * std::sin(double(i)))); 514 | 515 | Shape.push_back({(5.0f-Value)*std::cos(i), (5.0f-Value)*std::sin(i)+10.0f}); 516 | } 517 | auto& Shapes = Shapes_[int(GameObjectTypeE::LANDSCAPE)]; 518 | 519 | b2FixtureDef Fixture; 520 | Fixture.density = 1.0f; 521 | Fixture.friction = 0.8f; 522 | Fixture.restitution = 0.0f; 523 | Fixture.isSensor = false; 524 | 525 | Shapes.ShapeDefs.push_back(std::move(Shape)); 526 | Shapes.FixtureDefs.push_back(std::move(Fixture)); 527 | Shapes.Type = ShapeEnumType::CHAIN; 528 | 529 | GL::Mesh Mesh; 530 | GL::Buffer Buffer; 531 | Buffer.setData(this->convertGeometryPhysicsToGraphics(Shapes.ShapeDefs.back()), GL::BufferUsage::StaticDraw); 532 | Mesh.setCount(Shapes.ShapeDefs.back().size()) 533 | .setPrimitive(GL::MeshPrimitive::TriangleFan) 534 | .addVertexBuffer(std::move(Buffer), 0, Shaders::VertexColor2D::Position{}); 535 | Meshes_[int(GameObjectTypeE::LANDSCAPE)].push_back(std::move(Mesh)); 536 | } 537 | { 538 | Boundary.SetFrequency(0.008); 539 | ShapeType Shape; 540 | for (auto i=0.0f; i<2.0f*b2_pi; i+=2.0f*b2_pi/100.0f) 541 | { 542 | auto Value = 50.0f * float(Boundary.GetValue(100.0 * std::cos(double(i)), 100.0 * std::sin(double(i)))); 543 | 544 | Shape.push_back({(5.0f-Value)*std::cos(i)-20.0f, (5.0f-Value)*std::sin(i)-50.0f}); 545 | } 546 | auto& Shapes = Shapes_[int(GameObjectTypeE::LANDSCAPE)]; 547 | 548 | b2FixtureDef Fixture; 549 | Fixture.density = 1.0f; 550 | Fixture.friction = 0.8f; 551 | Fixture.restitution = 0.0f; 552 | Fixture.isSensor = false; 553 | 554 | Shapes.ShapeDefs.push_back(std::move(Shape)); 555 | Shapes.FixtureDefs.push_back(std::move(Fixture)); 556 | Shapes.Type = ShapeEnumType::CHAIN; 557 | 558 | GL::Mesh Mesh; 559 | GL::Buffer Buffer; 560 | Buffer.setData(this->convertGeometryPhysicsToGraphics(Shapes.ShapeDefs.back()), GL::BufferUsage::StaticDraw); 561 | Mesh.setCount(Shapes.ShapeDefs.back().size()) 562 | .setPrimitive(GL::MeshPrimitive::TriangleFan) 563 | .addVertexBuffer(std::move(Buffer), 0, Shaders::VertexColor2D::Position{}); 564 | Meshes_[int(GameObjectTypeE::LANDSCAPE)].push_back(std::move(Mesh)); 565 | } 566 | } 567 | 568 | void ResourceStorage::initProjectile() 569 | { 570 | ShapeType Shape; 571 | 572 | Shape.push_back({-0.02f, 0.0f}); 573 | Shape.push_back({ 0.02f, 0.0f}); 574 | Shape.push_back({ 0.02f, 0.05f}); 575 | Shape.push_back({ 0.0f, 0.15f}); 576 | Shape.push_back({-0.02f, 0.05f}); 577 | 578 | auto& Shapes = Shapes_[int(GameObjectTypeE::PROJECTILE)]; 579 | 580 | b2FixtureDef Fixture; 581 | Fixture.density = 800.0f; // Roughly the density of steel 582 | Fixture.friction = 0.5f; 583 | Fixture.restitution = 0.0f; 584 | Fixture.isSensor = false; 585 | 586 | // b2Filter Filter; 587 | // Filter.maskBits = 0; 588 | // Fixture.filter = Filter; 589 | 590 | Shapes.ShapeDefs.push_back(std::move(Shape)); 591 | Shapes.FixtureDefs.push_back(std::move(Fixture)); 592 | 593 | GL::Mesh Mesh; 594 | GL::Buffer Buffer; 595 | Buffer.setData(this->convertGeometryPhysicsToGraphics(Shapes.ShapeDefs.back()), GL::BufferUsage::StaticDraw); 596 | Mesh.setCount(Shapes.ShapeDefs.back().size()) 597 | .setPrimitive(GL::MeshPrimitive::TriangleFan) 598 | .addVertexBuffer(std::move(Buffer), 0, Shaders::VertexColor2D::Position{}); 599 | Meshes_[int(GameObjectTypeE::PROJECTILE)].push_back(std::move(Mesh)); 600 | } 601 | 602 | void ResourceStorage::initSubmarine() 603 | { 604 | { 605 | // Hull front 606 | ShapeType Shape; 607 | 608 | Shape.push_back({-1.8f, -5.0f}); 609 | Shape.push_back({ 1.8f, -5.0f}); 610 | Shape.push_back({ 2.0f, 6.0f}); 611 | Shape.push_back({ 1.5f, 8.0f}); 612 | Shape.push_back({ 0.5f, 9.0f}); 613 | Shape.push_back({-0.5f, 9.0f}); 614 | Shape.push_back({-1.5f, 8.0f}); 615 | Shape.push_back({-2.0f, 6.0f}); 616 | 617 | auto& Shapes = Shapes_[int(GameObjectTypeE::SUBMARINE_HULL)]; 618 | 619 | b2FixtureDef Fixture; 620 | Fixture.density = 400.0f; // Half of the hull consist of steel (roughly 800kg/m³) 621 | Fixture.friction = 0.2f; 622 | Fixture.restitution = 0.3f; 623 | Fixture.isSensor = false; 624 | 625 | Shapes.ShapeDefs.push_back(std::move(Shape)); 626 | Shapes.FixtureDefs.push_back(std::move(Fixture)); 627 | 628 | GL::Mesh Mesh; 629 | GL::Buffer Buffer; 630 | Buffer.setData( 631 | this->convertGeometryPhysicsToGraphics(Shapes.ShapeDefs.back()), 632 | GL::BufferUsage::StaticDraw 633 | ); 634 | Mesh.setCount(Shapes.ShapeDefs.back().size()) 635 | .setPrimitive(GL::MeshPrimitive::TriangleFan) 636 | .addVertexBuffer(std::move(Buffer), 0, Shaders::VertexColor2D::Position{}); 637 | Meshes_[int(GameObjectTypeE::SUBMARINE_HULL)].push_back(std::move(Mesh)); 638 | } 639 | { 640 | // Hull back 641 | ShapeType Shape; 642 | 643 | Shape.push_back({-1.5f, -7.0f}); 644 | Shape.push_back({ 1.5f, -7.0f}); 645 | Shape.push_back({ 1.8f, -5.0f}); 646 | Shape.push_back({-1.8f, -5.0f}); 647 | 648 | auto& Shapes = Shapes_[int(GameObjectTypeE::SUBMARINE_HULL)]; 649 | 650 | b2FixtureDef Fixture; 651 | Fixture.density = 600.0f; // Half of the hull consist of steel (roughly 800kg/m³) + engine 652 | Fixture.friction = 0.2f; 653 | Fixture.restitution = 0.3f; 654 | Fixture.isSensor = false; 655 | 656 | Shapes.ShapeDefs.push_back(std::move(Shape)); 657 | Shapes.FixtureDefs.push_back(std::move(Fixture)); 658 | 659 | GL::Mesh Mesh; 660 | GL::Buffer Buffer; 661 | Buffer.setData( 662 | this->convertGeometryPhysicsToGraphics(Shapes.ShapeDefs.back()), 663 | GL::BufferUsage::StaticDraw 664 | ); 665 | Mesh.setCount(Shapes.ShapeDefs.back().size()) 666 | .setPrimitive(GL::MeshPrimitive::TriangleFan) 667 | .addVertexBuffer(std::move(Buffer), 0, Shaders::VertexColor2D::Position{}); 668 | Meshes_[int(GameObjectTypeE::SUBMARINE_HULL)].push_back(std::move(Mesh)); 669 | } 670 | { 671 | // Rudder 672 | ShapeType Shape; 673 | 674 | Shape.push_back({-0.1f, -1.0f}); 675 | Shape.push_back({ 0.1f, -1.0f}); 676 | Shape.push_back({ 0.1f, 1.0f}); 677 | Shape.push_back({-0.1f, 1.0f}); 678 | 679 | auto& Shapes = Shapes_[int(GameObjectTypeE::SUBMARINE_RUDDER)]; 680 | 681 | b2FixtureDef Fixture; 682 | Fixture.density = 800.0f; 683 | Fixture.friction = 0.2f; 684 | Fixture.restitution = 0.3f; 685 | Fixture.isSensor = false; 686 | 687 | Shapes.ShapeDefs.push_back(std::move(Shape)); 688 | Shapes.FixtureDefs.push_back(std::move(Fixture)); 689 | 690 | GL::Mesh Mesh; 691 | GL::Buffer Buffer; 692 | Buffer.setData(this->convertGeometryPhysicsToGraphics(Shapes.ShapeDefs.back()), GL::BufferUsage::StaticDraw); 693 | Mesh.setCount(Shapes.ShapeDefs.back().size()) 694 | .setPrimitive(GL::MeshPrimitive::TriangleFan) 695 | .addVertexBuffer(std::move(Buffer), 0, Shaders::VertexColor2D::Position{}); 696 | Meshes_[int(GameObjectTypeE::SUBMARINE_RUDDER)].push_back(std::move(Mesh)); 697 | } 698 | 699 | // PluginManager::Manager SceneManager; 700 | // Containers::Pointer Importer = SceneManager.loadAndInstantiate("AnySceneImporter"); 701 | // 702 | // 703 | // if (!Importer) GlobalErrorHandler.reportError("Couldn't instantiate importer plugin AnySceneImporter."); 704 | // 705 | // std::string Filename = "submarine2.obj"; 706 | // if (!Importer->openFile(Filename)) 707 | // { 708 | // GlobalErrorHandler.reportError("Couldn't open file "+ Filename); 709 | // } 710 | // else 711 | // { 712 | // GlobalMessageHandler.report("Successfully opened file "+ Filename); 713 | // } 714 | // 715 | // Containers::Array Meshes; 716 | // Meshes = Containers::Array{Importer->mesh3DCount()}; 717 | // for(UnsignedInt i = 0; i != Importer->mesh3DCount(); ++i) 718 | // { 719 | // std::cout << "Importing mesh" << i << Importer->mesh3DName(i) << std::endl; 720 | // 721 | // Containers::Optional MeshData = Importer->mesh3D(i); 722 | // if(!MeshData || !MeshData->hasNormals() || MeshData->primitive() != MeshPrimitive::Triangles) 723 | // { 724 | // std::cout << "Cannot load the mesh, skipping" << std::endl; 725 | // } 726 | // 727 | // /* Compile the mesh */ 728 | // Meshes[i] = MeshTools::compile(*MeshData); 729 | // Meshes_[int(GameObjectTypeE::SUBMARINE_HULL)].push_back(std::move(Meshes[i])); 730 | // } 731 | 732 | } 733 | 734 | std::vector ResourceStorage::convertGeometryPhysicsToGraphics(const std::vector& Verts) 735 | { 736 | std::vector Tmp; 737 | 738 | for (auto Vec : Verts) 739 | { 740 | Tmp.push_back({Vec.x, Vec.y}); 741 | } 742 | return Tmp; // Note: No std::move needed, might even prevent copy elision 743 | } 744 | -------------------------------------------------------------------------------- /src/resource_storage.h: -------------------------------------------------------------------------------- 1 | #ifndef RESOURCE_STORAGE_H 2 | #define RESOURCE_STORAGE_H 3 | 4 | #include 5 | 6 | #include 7 | 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | #include "common.h" 14 | #include "physics_component.hpp" 15 | #include "status_component.hpp" 16 | #include "visuals_component.hpp" 17 | #include "world_def.h" 18 | 19 | enum class DrawableGroupsTypeE : int 20 | { 21 | BOIDS=0, 22 | WEAPON=1, 23 | DEFAULT=2 24 | }; 25 | 26 | enum class ShapeEnumType : int 27 | { 28 | CIRCLE, 29 | CHAIN, 30 | POLYGON 31 | }; 32 | 33 | typedef std::vector ShapeType; 34 | typedef struct 35 | { 36 | std::vector ShapeDefs; 37 | std::vector FixtureDefs; 38 | ShapeEnumType Type = ShapeEnumType::POLYGON; 39 | 40 | } ShapesType; 41 | 42 | class ResourceStorage 43 | { 44 | public: 45 | 46 | ~ResourceStorage() {this->release();} 47 | 48 | void init(); 49 | void release(); 50 | 51 | b2World* getWorld() {return &World_;} 52 | 53 | SceneGraph::DrawableGroup2D* getDrawables(DrawableGroupsTypeE t) {assert(IsInitialised == true); return Drawables_[int(t)];}; 54 | Shaders::Flat2D* getShader() {assert(IsInitialised == true); return Shader_;} 55 | Scene2D* getScene() {assert(IsInitialised == true); return Scene_;} 56 | 57 | ShapesType* getShapes(GameObjectTypeE t) {assert(IsInitialised == true); return &(Shapes_[int(t)]);} 58 | MeshesType* getMeshes(GameObjectTypeE t) {assert(IsInitialised == true); return &(Meshes_[int(t)]);} 59 | 60 | std::vector* getHeightMap() {return &HeightMap_;} 61 | 62 | private: 63 | 64 | void initBoids(); 65 | void initDebris(); 66 | void initHeightMap(); 67 | void initLandscape(); 68 | void initProjectile(); 69 | void initSubmarine(); 70 | 71 | bool IsInitialised = false; 72 | 73 | b2World World_{{0.0f, 0.0f}}; 74 | 75 | Scene2D* Scene_ = new Scene2D; 76 | Shaders::Flat2D* Shader_ = nullptr; 77 | 78 | std::array Drawables_{new SceneGraph::DrawableGroup2D, 79 | new SceneGraph::DrawableGroup2D, 80 | new SceneGraph::DrawableGroup2D}; 81 | std::array Meshes_; 82 | std::array Shapes_; 83 | 84 | std::vector HeightMap_; 85 | std::vector* HeightMapPlateausFront_; 86 | std::vector* HeightMapPlateausBack_; 87 | std::vector HeightMapPlateaus0_; 88 | std::vector HeightMapPlateaus1_; 89 | 90 | std::vector convertGeometryPhysicsToGraphics(const std::vector& Verts); 91 | }; 92 | 93 | #endif // RESOURCE_STORAGE_H 94 | -------------------------------------------------------------------------------- /src/shader_path.h: -------------------------------------------------------------------------------- 1 | #ifndef SHADER_PATH_H 2 | #define SHADER_PATH_H 3 | 4 | static const char* SHADER_PATH = "./install/share/shaders/"; 5 | 6 | #endif 7 | -------------------------------------------------------------------------------- /src/shaders/advect_shader.h: -------------------------------------------------------------------------------- 1 | #ifndef ADVECT_SHADER_H 2 | #define ADVECT_SHADER_H 3 | 4 | #include 5 | 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | 14 | #include "shader_path.h" 15 | 16 | using namespace Magnum; 17 | 18 | enum class AdvectShaderVersionE : int 19 | { 20 | SCALAR = 0, 21 | VECTOR = 1 22 | }; 23 | 24 | class AdvectShader : public GL::AbstractShaderProgram 25 | { 26 | 27 | public: 28 | 29 | typedef GL::Attribute<0, Vector2> Position; 30 | typedef GL::Attribute<1, Vector2> TextureCoordinates; 31 | 32 | explicit AdvectShader(NoCreateT): GL::AbstractShaderProgram{NoCreate} {} 33 | 34 | explicit AdvectShader(const AdvectShaderVersionE _ShaderVersion) 35 | { 36 | MAGNUM_ASSERT_GL_VERSION_SUPPORTED(GL::Version::GL330); 37 | 38 | GL::Shader Vert{GL::Version::GL330, GL::Shader::Type::Vertex}; 39 | GL::Shader Frag{GL::Version::GL330, GL::Shader::Type::Fragment}; 40 | 41 | Vert.addFile(Path_+"texture_base_shader.vert"); 42 | if (_ShaderVersion == AdvectShaderVersionE::SCALAR) 43 | Frag.addFile(Path_+"advect1d_shader.frag"); 44 | else 45 | Frag.addFile(Path_+"advect2d_shader.frag"); 46 | 47 | CORRADE_INTERNAL_ASSERT_OUTPUT(GL::Shader::compile({Vert, Frag})); 48 | 49 | attachShaders({Vert, Frag}); 50 | 51 | CORRADE_INTERNAL_ASSERT_OUTPUT(link()); 52 | 53 | setUniform(uniformLocation("u_tex_buffer"), TexUnitBuffer); 54 | setUniform(uniformLocation("u_tex_velocities"), TexUnitVelocities); 55 | AdvectionFactorUniform_ = uniformLocation("u_advection_factor"); 56 | DeltaTUniform_ = uniformLocation("u_dt"); 57 | GridResolutionUniform_ = uniformLocation("u_grid_res"); 58 | TransformationUniform_ = uniformLocation("u_matrix"); 59 | 60 | setUniform(AdvectionFactorUniform_, 100.0f); 61 | setUniform(DeltaTUniform_, 1.0f/60.0f); 62 | setUniform(GridResolutionUniform_, 0.25f); 63 | } 64 | 65 | AdvectShader& setAdvectionFactor(const Float f) 66 | { 67 | setUniform(AdvectionFactorUniform_, f); 68 | return *this; 69 | } 70 | 71 | AdvectShader& setDeltaT(const Float dt) 72 | { 73 | setUniform(DeltaTUniform_, dt); 74 | return *this; 75 | } 76 | 77 | AdvectShader& setGridRes(const Float r) 78 | { 79 | setUniform(GridResolutionUniform_, r); 80 | return *this; 81 | } 82 | 83 | AdvectShader& setTransformation(const Matrix3& t) 84 | { 85 | setUniform(TransformationUniform_, t); 86 | return *this; 87 | } 88 | 89 | AdvectShader& bindTextures(GL::Texture2D& TexBuffer, 90 | GL::Texture2D& TexVelocities) 91 | { 92 | TexBuffer.bind(TexUnitBuffer); 93 | TexVelocities.bind(TexUnitVelocities); 94 | return *this; 95 | } 96 | 97 | private: 98 | 99 | enum: Int 100 | { 101 | TexUnitBuffer = 0, 102 | TexUnitVelocities = 1 103 | }; 104 | 105 | std::string Path_{SHADER_PATH}; 106 | 107 | Float AdvectionFactorUniform_; 108 | Float DeltaTUniform_; 109 | Float GridResolutionUniform_; 110 | Int TransformationUniform_; 111 | }; 112 | 113 | #endif // ADVECT_SHADER_H 114 | -------------------------------------------------------------------------------- /src/shaders/density_display_shader.h: -------------------------------------------------------------------------------- 1 | #ifndef DENSITY_DISPLAY_SHADER_H 2 | #define DENSITY_DISPLAY_SHADER_H 3 | 4 | #include 5 | 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | 14 | #include "shader_path.h" 15 | 16 | using namespace Magnum; 17 | 18 | class DensityDisplayShader : public GL::AbstractShaderProgram 19 | { 20 | 21 | public: 22 | 23 | typedef GL::Attribute<0, Vector2> Position; 24 | typedef GL::Attribute<1, Vector2> TextureCoordinates; 25 | 26 | explicit DensityDisplayShader(NoCreateT): GL::AbstractShaderProgram{NoCreate} {} 27 | 28 | explicit DensityDisplayShader() 29 | { 30 | MAGNUM_ASSERT_GL_VERSION_SUPPORTED(GL::Version::GL330); 31 | 32 | GL::Shader Vert{GL::Version::GL330, GL::Shader::Type::Vertex}; 33 | GL::Shader Frag{GL::Version::GL330, GL::Shader::Type::Fragment}; 34 | 35 | Vert.addFile(Path_+"texture_base_shader.vert"); 36 | Frag.addFile(Path_+"density_display_shader.frag"); 37 | 38 | CORRADE_INTERNAL_ASSERT_OUTPUT(GL::Shader::compile({Vert, Frag})); 39 | 40 | attachShaders({Vert, Frag}); 41 | 42 | CORRADE_INTERNAL_ASSERT_OUTPUT(link()); 43 | 44 | setUniform(uniformLocation("u_texture"), TextureUnit); 45 | ScaleUniform_ = uniformLocation("u_scale"); 46 | TransformationMatrixUniform_ = uniformLocation("u_matrix"); 47 | } 48 | 49 | DensityDisplayShader& setScale(const Float s) 50 | { 51 | setUniform(ScaleUniform_, s); 52 | return *this; 53 | } 54 | 55 | DensityDisplayShader& setTransformation(const Matrix3& t) 56 | { 57 | setUniform(TransformationMatrixUniform_, t); 58 | return *this; 59 | } 60 | 61 | DensityDisplayShader& bindTexture(GL::Texture2D& Texture) 62 | { 63 | Texture.bind(TextureUnit); 64 | return *this; 65 | } 66 | 67 | private: 68 | 69 | enum: Int { TextureUnit = 0 }; 70 | 71 | std::string Path_{SHADER_PATH}; 72 | 73 | Int TransformationMatrixUniform_; 74 | Float ScaleUniform_ = 1.0f; 75 | 76 | }; 77 | 78 | #endif // DENSITY_DISPLAY_SHADER_H 79 | -------------------------------------------------------------------------------- /src/shaders/density_sources_shader.h: -------------------------------------------------------------------------------- 1 | #ifndef DENSITY_SOURCES_SHADER_H 2 | #define DENSITY_SOURCES_SHADER_H 3 | 4 | #include 5 | 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | #include "shader_path.h" 14 | 15 | using namespace Magnum; 16 | 17 | class DensitySourcesShader : public GL::AbstractShaderProgram 18 | { 19 | 20 | public: 21 | 22 | typedef GL::Attribute<0, Vector2> Position; 23 | typedef GL::Attribute<1, Vector3> AmountRGB; 24 | 25 | explicit DensitySourcesShader(NoCreateT): GL::AbstractShaderProgram{NoCreate} {} 26 | 27 | explicit DensitySourcesShader() 28 | { 29 | MAGNUM_ASSERT_GL_VERSION_SUPPORTED(GL::Version::GL330); 30 | 31 | GL::Shader Vert{GL::Version::GL330, GL::Shader::Type::Vertex}; 32 | GL::Shader Frag{GL::Version::GL330, GL::Shader::Type::Fragment}; 33 | 34 | Vert.addFile(Path_+"density_sources_shader.vert"); 35 | Frag.addFile(Path_+"density_sources_shader.frag"); 36 | 37 | CORRADE_INTERNAL_ASSERT_OUTPUT(GL::Shader::compile({Vert, Frag})); 38 | 39 | attachShaders({Vert, Frag}); 40 | 41 | CORRADE_INTERNAL_ASSERT_OUTPUT(link()); 42 | 43 | TransformationMatrixUniform_ = uniformLocation("u_matrix"); 44 | } 45 | 46 | DensitySourcesShader& setTransformation(const Matrix3& t) 47 | { 48 | setUniform(TransformationMatrixUniform_, t); 49 | return *this; 50 | } 51 | 52 | private: 53 | 54 | std::string Path_{SHADER_PATH}; 55 | Int TransformationMatrixUniform_; 56 | 57 | }; 58 | 59 | #endif // DENSITY_SOURCES_SHADER_H 60 | -------------------------------------------------------------------------------- /src/shaders/fluid_final_composition_shader.h: -------------------------------------------------------------------------------- 1 | #ifndef FLUID_FINAL_COMPOSITION_SHADER_H 2 | #define FLUID_FINAL_COMPOSITION_SHADER_H 3 | 4 | #include 5 | 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | 14 | #include "shader_path.h" 15 | 16 | using namespace Magnum; 17 | 18 | class FluidFinalCompositionShader : public GL::AbstractShaderProgram 19 | { 20 | 21 | public: 22 | 23 | typedef GL::Attribute<0, Vector2> Position; 24 | typedef GL::Attribute<1, Vector2> TextureCoordinates; 25 | 26 | explicit FluidFinalCompositionShader(NoCreateT): GL::AbstractShaderProgram{NoCreate} {} 27 | 28 | explicit FluidFinalCompositionShader() 29 | { 30 | MAGNUM_ASSERT_GL_VERSION_SUPPORTED(GL::Version::GL330); 31 | 32 | GL::Shader Vert{GL::Version::GL330, GL::Shader::Type::Vertex}; 33 | GL::Shader Frag{GL::Version::GL330, GL::Shader::Type::Fragment}; 34 | 35 | Vert.addFile(Path_+"texture_base_shader.vert"); 36 | Frag.addFile(Path_+"fluid_final_composition_shader.frag"); 37 | 38 | CORRADE_INTERNAL_ASSERT_OUTPUT(GL::Shader::compile({Vert, Frag})); 39 | 40 | attachShaders({Vert, Frag}); 41 | 42 | CORRADE_INTERNAL_ASSERT_OUTPUT(link()); 43 | 44 | setUniform(uniformLocation("u_tex_density_base"), TexUnitDensityBase); 45 | setUniform(uniformLocation("u_tex_density_buffer"), TexUnitDensityBuffer); 46 | setUniform(uniformLocation("u_tex_ground_distorted"), TexUnitGroundDistorted); 47 | setUniform(uniformLocation("u_tex_velocities"), TexUnitVelocities); 48 | TransformationUniform_ = uniformLocation("u_matrix"); 49 | } 50 | 51 | FluidFinalCompositionShader& setTransformation(const Matrix3& t) 52 | { 53 | setUniform(TransformationUniform_, t); 54 | return *this; 55 | } 56 | 57 | FluidFinalCompositionShader& bindTextures(GL::Texture2D& TexDensityBase, 58 | GL::Texture2D& TexDensityBuffer, 59 | GL::Texture2D& TexGroundDistorted, 60 | GL::Texture2D& TexVelocities) 61 | { 62 | TexDensityBase.bind(TexUnitDensityBase); 63 | TexDensityBuffer.bind(TexUnitDensityBuffer); 64 | TexGroundDistorted.bind(TexUnitGroundDistorted); 65 | TexVelocities.bind(TexUnitVelocities); 66 | return *this; 67 | } 68 | 69 | private: 70 | 71 | enum: Int 72 | { 73 | TexUnitDensityBase = 0, 74 | TexUnitDensityBuffer = 1, 75 | TexUnitGroundDistorted = 2, 76 | TexUnitVelocities = 3 77 | }; 78 | 79 | std::string Path_{SHADER_PATH}; 80 | 81 | Int TransformationUniform_; 82 | }; 83 | 84 | #endif // FLUID_FINAL_COMPOSITON_SHADER_H 85 | -------------------------------------------------------------------------------- /src/shaders/glsl/advect1d_shader.frag: -------------------------------------------------------------------------------- 1 | uniform sampler2D u_tex_buffer; 2 | uniform sampler2D u_tex_velocities; 3 | 4 | uniform float u_advection_factor; 5 | uniform float u_dt; 6 | uniform float u_grid_res; 7 | 8 | in vec2 v_tex; 9 | 10 | out vec3 frag_value; 11 | 12 | void main() 13 | { 14 | vec2 vel = u_advection_factor*texelFetch(u_tex_velocities, ivec2(gl_FragCoord.xy), 0).xy; 15 | vec2 pos = gl_FragCoord.xy - u_grid_res * u_dt * vel; 16 | 17 | // Neighbour indices 18 | vec4 n; 19 | n.xy = floor(pos-0.5)+0.5; 20 | n.zw = n.xy+1.0; 21 | 22 | // Neighbour values 23 | vec3 v_tl = texelFetch(u_tex_buffer, ivec2(n.xy), 0).rgb; // top left 24 | vec3 v_tr = texelFetch(u_tex_buffer, ivec2(n.zy), 0).rgb; // top right 25 | vec3 v_bl = texelFetch(u_tex_buffer, ivec2(n.xw), 0).rgb; // bottom left 26 | vec3 v_br = texelFetch(u_tex_buffer, ivec2(n.zw), 0).rgb; // bottom right 27 | 28 | vec2 f = pos - n.xy; 29 | 30 | frag_value = mix(mix(v_tl, v_tr, f.x), mix(v_bl, v_br, f.x), f.y); 31 | } 32 | -------------------------------------------------------------------------------- /src/shaders/glsl/advect2d_shader.frag: -------------------------------------------------------------------------------- 1 | uniform sampler2D u_tex_buffer; 2 | uniform sampler2D u_tex_velocities; 3 | 4 | uniform float u_advection_factor; 5 | uniform float u_dt; 6 | uniform float u_grid_res; 7 | 8 | in vec2 v_tex; 9 | 10 | out vec2 frag_value; 11 | 12 | void main() 13 | { 14 | vec2 vel = u_advection_factor*texelFetch(u_tex_velocities, ivec2(gl_FragCoord.xy), 0).xy; 15 | vec2 pos = gl_FragCoord.xy - u_grid_res * u_dt * vel; 16 | 17 | // Neighbour indices 18 | vec4 n; 19 | n.xy = floor(pos-0.5)+0.5; 20 | n.zw = n.xy+1.0; 21 | 22 | // Neighbour values 23 | vec2 v_tl = texelFetch(u_tex_buffer, ivec2(n.xy), 0).xy; // top left 24 | vec2 v_tr = texelFetch(u_tex_buffer, ivec2(n.zy), 0).xy; // top right 25 | vec2 v_bl = texelFetch(u_tex_buffer, ivec2(n.xw), 0).xy; // bottom left 26 | vec2 v_br = texelFetch(u_tex_buffer, ivec2(n.zw), 0).xy; // bottom right 27 | 28 | vec2 f = pos - n.xy; 29 | 30 | frag_value = mix(mix(v_tl, v_tr, f.x), mix(v_bl, v_br, f.x), f.y); 31 | // frag_value = texelFetch(u_tex_velocities, ivec2(pos), 0).xy; 32 | } 33 | -------------------------------------------------------------------------------- /src/shaders/glsl/density_display_shader.frag: -------------------------------------------------------------------------------- 1 | uniform sampler2D u_texture; 2 | 3 | uniform float u_scale; 4 | 5 | in vec2 v_tex; 6 | 7 | out vec4 fragmentColor; 8 | 9 | void main() 10 | { 11 | // float value = float(texture(u_texture, v_tex)); 12 | // fragmentColor.rgb = u_scale*vec3(value*0.01, value*0.3, value); 13 | vec4 value = texture(u_texture, v_tex) * u_scale; 14 | 15 | fragmentColor.r = value.r; 16 | fragmentColor.g = value.g; 17 | fragmentColor.b = value.b; 18 | fragmentColor.a = 1.0; 19 | } 20 | -------------------------------------------------------------------------------- /src/shaders/glsl/density_sources_shader.frag: -------------------------------------------------------------------------------- 1 | in vec3 v_amount; 2 | 3 | out vec3 fragmentColor; 4 | 5 | void main() 6 | { 7 | fragmentColor = v_amount; 8 | // fragmentColor.rga = vec3(1.0, 0.0, 0.0); 9 | } 10 | -------------------------------------------------------------------------------- /src/shaders/glsl/density_sources_shader.vert: -------------------------------------------------------------------------------- 1 | layout(location = 0) in vec2 pos; 2 | layout(location = 1) in vec3 amount; 3 | 4 | out vec3 v_amount; 5 | 6 | uniform mat3 u_matrix; 7 | 8 | void main() 9 | { 10 | v_amount = amount; 11 | gl_Position.xyw = u_matrix*vec3(pos, 1.0); 12 | } 13 | -------------------------------------------------------------------------------- /src/shaders/glsl/fluid_final_composition_shader.frag: -------------------------------------------------------------------------------- 1 | uniform sampler2D u_tex_density_base; 2 | uniform sampler2D u_tex_density_buffer; 3 | uniform sampler2D u_tex_ground_distorted; 4 | uniform sampler2D u_tex_velocities; 5 | 6 | out vec3 frag_col; 7 | 8 | void main() 9 | { 10 | float g_b = texelFetch(u_tex_density_base, ivec2(gl_FragCoord.xy), 0).x; 11 | float g_d = texelFetch(u_tex_ground_distorted, ivec2(gl_FragCoord.xy), 0).x; 12 | float v = length(texelFetch(u_tex_velocities, ivec2(gl_FragCoord.xy),0)); 13 | vec3 d = texelFetch(u_tex_density_buffer, ivec2(gl_FragCoord.xy), 0).rgb; 14 | frag_col.r = 0.05*g_b + 0.1*g_d + 0.025 * clamp(0.1*v, 0.0, 2.0) + 0.2*clamp(0.05*d.r, 0.0, 10.0); 15 | frag_col.g = 0.05*g_b + 0.1*g_d + 0.025 * clamp(0.1*v, 0.0, 2.0) + 0.2*clamp(0.05*d.g, 0.0, 10.0); 16 | frag_col.b = 0.3*g_b + 0.6*g_d + 0.025 * clamp(0.1*v, 0.0, 2.0) + 0.2*clamp(0.05*d.b, 0.0, 10.0); 17 | } 18 | -------------------------------------------------------------------------------- /src/shaders/glsl/ground_distortion_shader.frag: -------------------------------------------------------------------------------- 1 | uniform sampler2D u_tex_ground; 2 | uniform sampler2D u_tex_velocities; 3 | 4 | uniform float u_distortion; 5 | uniform float u_dt; 6 | uniform float u_grid_res; 7 | uniform float u_time; 8 | 9 | in vec2 v_tex; 10 | 11 | out float frag_col; 12 | 13 | void main() 14 | { 15 | vec2 vel = texelFetch(u_tex_velocities, ivec2(gl_FragCoord.xy), 0).xy; 16 | float vel_v = length(vel); 17 | vec2 dir = normalize(vel); 18 | // vec2 grad = vel + texelFetch(u_tex_velocities, ivec2(gl_FragCoord.xy-2*dir), 0).xy; 19 | // vec2 amp = 2.0*dir*(1.0+sign(vel_v - 1.5)) + vel; 20 | vec2 amp = 3.0*dir+vel;//dir * (1.0+vel_v); 21 | vec2 arg = 0.01*dir*gl_FragCoord.xy; 22 | vec2 pos = gl_FragCoord.xy - u_grid_res * u_dt * u_distortion * 23 | (amp * sin(arg)); 24 | 25 | // Neighbour indices 26 | vec4 n; 27 | n.xy = floor(pos-0.5)+0.5; 28 | n.zw = n.xy+1.0; 29 | 30 | // Neighbour values 31 | float v_tl = texelFetch(u_tex_ground, ivec2(n.xy), 0).x; // top left 32 | float v_tr = texelFetch(u_tex_ground, ivec2(n.zy), 0).x; // top right 33 | float v_bl = texelFetch(u_tex_ground, ivec2(n.xw), 0).x; // bottom left 34 | float v_br = texelFetch(u_tex_ground, ivec2(n.zw), 0).x; // bottom right 35 | 36 | vec2 f = pos - n.xy; 37 | 38 | frag_col = mix(mix(v_tl, v_tr, f.x), mix(v_bl, v_br, f.x), f.y); 39 | } 40 | -------------------------------------------------------------------------------- /src/shaders/glsl/jacobi1d_shader.frag: -------------------------------------------------------------------------------- 1 | // Solves Ax = b 2 | uniform sampler2D u_tex_x; 3 | uniform sampler2D u_tex_b; 4 | 5 | uniform float u_alpha; 6 | uniform float u_r_beta; 7 | uniform float u_diffusion_rate; 8 | 9 | in vec2 v_tex; 10 | 11 | out vec3 frag_value; 12 | 13 | void main() 14 | { 15 | const ivec3 o = ivec3(-1,0,1); 16 | 17 | // float r_beta = 1.0/(u_diffusion_rate*4.0); 18 | 19 | ivec2 i_w = ivec2(gl_FragCoord.xy)+o.xy; 20 | ivec2 i_n = ivec2(gl_FragCoord.xy)+o.yz; 21 | ivec2 i_s = ivec2(gl_FragCoord.xy)+o.yx; 22 | ivec2 i_e = ivec2(gl_FragCoord.xy)+o.zy; 23 | 24 | // frag_value = (u_alpha * texelFetch(u_tex_b, ivec2(gl_FragCoord.xy), 0).x + 25 | frag_value = (u_alpha * texelFetch(u_tex_b, ivec2(gl_FragCoord.xy), 0).rgb + 26 | u_diffusion_rate * texelFetch(u_tex_x, i_e, 0).rgb + 27 | u_diffusion_rate * texelFetch(u_tex_x, i_w, 0).rgb + 28 | u_diffusion_rate * texelFetch(u_tex_x, i_s, 0).rgb + 29 | u_diffusion_rate * texelFetch(u_tex_x, i_n, 0).rgb 30 | ) * u_r_beta; 31 | } 32 | -------------------------------------------------------------------------------- /src/shaders/glsl/jacobi2d_shader.frag: -------------------------------------------------------------------------------- 1 | // Solves Ax = b 2 | uniform sampler2D u_tex_x; 3 | uniform sampler2D u_tex_b; 4 | 5 | uniform float u_alpha; 6 | uniform float u_r_beta; 7 | uniform float u_diffusion_rate; 8 | 9 | in vec2 v_tex; 10 | 11 | out vec2 frag_value; 12 | 13 | void main() 14 | { 15 | const ivec3 o = ivec3(-1,0,1); 16 | 17 | ivec2 i_w = ivec2(gl_FragCoord.xy)+o.xy; 18 | ivec2 i_n = ivec2(gl_FragCoord.xy)+o.yz; 19 | ivec2 i_s = ivec2(gl_FragCoord.xy)+o.yx; 20 | ivec2 i_e = ivec2(gl_FragCoord.xy)+o.zy; 21 | 22 | frag_value = (u_alpha * texelFetch(u_tex_b, ivec2(gl_FragCoord.xy), 0).xy + 23 | u_diffusion_rate * texelFetch(u_tex_x, i_e, 0).xy + 24 | u_diffusion_rate * texelFetch(u_tex_x, i_w, 0).xy + 25 | u_diffusion_rate * texelFetch(u_tex_x, i_s, 0).xy + 26 | u_diffusion_rate * texelFetch(u_tex_x, i_n, 0).xy 27 | ) * u_r_beta; 28 | } 29 | -------------------------------------------------------------------------------- /src/shaders/glsl/main_display_shader.frag: -------------------------------------------------------------------------------- 1 | uniform sampler2D u_texture; 2 | 3 | in vec2 v_tex; 4 | 5 | out vec4 frag_color; 6 | 7 | void main() 8 | { 9 | frag_color = texture(u_texture, v_tex); 10 | } 11 | -------------------------------------------------------------------------------- /src/shaders/glsl/source1d_shader.frag: -------------------------------------------------------------------------------- 1 | uniform sampler2D u_tex_buffer; 2 | uniform sampler2D u_tex_sources; 3 | 4 | in vec2 v_tex; 5 | 6 | out vec3 frag_value; 7 | 8 | void main() 9 | { 10 | frag_value = (texelFetch(u_tex_buffer, ivec2(gl_FragCoord.xy), 0).rgb + 11 | texelFetch(u_tex_sources, ivec2(gl_FragCoord.xy), 0).rgb)*0.99; 12 | } 13 | -------------------------------------------------------------------------------- /src/shaders/glsl/source2d_shader.frag: -------------------------------------------------------------------------------- 1 | uniform sampler2D u_tex_buffer; 2 | uniform sampler2D u_tex_sources; 3 | 4 | in vec2 v_tex; 5 | 6 | out vec2 frag_value; 7 | 8 | void main() 9 | { 10 | vec2 v_src = texelFetch(u_tex_sources, ivec2(gl_FragCoord.xy), 0).xy; 11 | vec2 v_buf = texelFetch(u_tex_buffer, ivec2(gl_FragCoord.xy), 0).xy; 12 | 13 | vec2 v_buf_unit = normalize(v_buf+vec2(-0.1, 0.1)); 14 | vec2 v_prj = dot(v_src, v_buf_unit)*v_buf_unit; 15 | 16 | frag_value = v_buf.xy+(v_src.xy-v_prj.xy)*0.9999; 17 | } 18 | -------------------------------------------------------------------------------- /src/shaders/glsl/texture_2d32f_render_2d32f_shader.frag: -------------------------------------------------------------------------------- 1 | uniform sampler2D u_texture; 2 | 3 | in vec2 v_tex; 4 | 5 | out vec2 frag_col; 6 | 7 | void main() 8 | { 9 | frag_col.xy = texture(u_texture, v_tex).xy; 10 | } 11 | -------------------------------------------------------------------------------- /src/shaders/glsl/texture_base_shader.vert: -------------------------------------------------------------------------------- 1 | layout(location = 0) in vec2 pos; 2 | layout(location = 1) in vec2 tex; 3 | 4 | out vec2 v_tex; 5 | 6 | uniform mat3 u_matrix; 7 | 8 | void main() 9 | { 10 | v_tex = tex; 11 | gl_Position.xyw = u_matrix*vec3(pos, 1.0); 12 | } 13 | -------------------------------------------------------------------------------- /src/shaders/glsl/texture_base_unit_shader.vert: -------------------------------------------------------------------------------- 1 | uniform float u_tex_scale_x; 2 | uniform float u_tex_scale_y; 3 | 4 | out vec2 v_tex; 5 | 6 | const vec2 pos[3] = vec2[] 7 | ( 8 | vec2(-1.0, -1.0), 9 | vec2( 3.0, -1.0), 10 | vec2(-1.0, 3.0) 11 | ); 12 | 13 | const vec2 tex[3] = vec2[] 14 | ( 15 | vec2(0.0, 0.0), 16 | vec2(2.0, 0.0), 17 | vec2(0.0, 2.0) 18 | ); 19 | 20 | void main() 21 | { 22 | v_tex = vec2(u_tex_scale_x*tex[gl_VertexID].x, 23 | u_tex_scale_y*tex[gl_VertexID].y); 24 | gl_Position = vec4(pos[gl_VertexID], 0.0, 1.0); 25 | } 26 | -------------------------------------------------------------------------------- /src/shaders/glsl/velocity_display_shader.frag: -------------------------------------------------------------------------------- 1 | uniform sampler2D u_texture; 2 | 3 | uniform bool u_show_only_magnitude; 4 | uniform float u_scale; 5 | 6 | in vec2 v_tex; 7 | 8 | out vec4 frag_col; 9 | 10 | void main() 11 | { 12 | // Scale velocity to interval [0, 1/scale], e.g. scale = 0.05 => [0, 20] m/s 13 | float x = texture(u_texture, v_tex).r; 14 | float y = texture(u_texture, v_tex).g; 15 | 16 | // Show only magnitude of velocity 17 | if (u_show_only_magnitude) 18 | { 19 | vec2 vec = vec2(x,y) * u_scale; 20 | frag_col = vec4(length(vec), length(vec), length(vec), 1.0); 21 | } 22 | // Or show colour-coded direction and magnitude 23 | else 24 | { 25 | // Very simply colour coding for direction (not orientation) 26 | float scale_sqr = u_scale * u_scale; 27 | float b = x*y; 28 | frag_col.rgba = vec4(u_scale*abs(x), 29 | u_scale*abs(y), 30 | scale_sqr*b, 31 | 1.0); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/shaders/glsl/velocity_divergence_shader.frag: -------------------------------------------------------------------------------- 1 | uniform sampler2D u_tex_velocity_buffer; 2 | 3 | in vec2 v_tex; 4 | out float div; 5 | 6 | void main() 7 | { 8 | const ivec3 o = ivec3(-1,0,1); 9 | ivec2 i_w = ivec2(gl_FragCoord.xy)+o.xy; 10 | ivec2 i_n = ivec2(gl_FragCoord.xy)+o.yz; 11 | ivec2 i_s = ivec2(gl_FragCoord.xy)+o.yx; 12 | ivec2 i_e = ivec2(gl_FragCoord.xy)+o.zy; 13 | 14 | float east = texelFetch(u_tex_velocity_buffer, i_e, 0).x; 15 | float west = texelFetch(u_tex_velocity_buffer, i_w, 0).x; 16 | float south = texelFetch(u_tex_velocity_buffer, i_s, 0).y; 17 | float north = texelFetch(u_tex_velocity_buffer, i_n, 0).y; 18 | 19 | div = -((east - west) + (north - south)); 20 | } 21 | -------------------------------------------------------------------------------- /src/shaders/glsl/velocity_gradient_substraction_shader.frag: -------------------------------------------------------------------------------- 1 | uniform sampler2D u_tex_velocity_buffer; 2 | uniform sampler2D u_tex_velocity_divergence_buffer; 3 | 4 | in vec2 v_tex; 5 | out vec2 v_vel; 6 | 7 | void main() 8 | { 9 | const ivec3 o = ivec3(-1,0,1); 10 | ivec2 i_west = ivec2(gl_FragCoord.xy)+o.xy; 11 | ivec2 i_north = ivec2(gl_FragCoord.xy)+o.yz; 12 | ivec2 i_south = ivec2(gl_FragCoord.xy)+o.yx; 13 | ivec2 i_east = ivec2(gl_FragCoord.xy)+o.zy; 14 | 15 | float east = texelFetch(u_tex_velocity_divergence_buffer, i_east, 0).x; 16 | float west = texelFetch(u_tex_velocity_divergence_buffer, i_west, 0).x; 17 | float south = texelFetch(u_tex_velocity_divergence_buffer, i_south, 0).x; 18 | float north = texelFetch(u_tex_velocity_divergence_buffer, i_north, 0).x; 19 | vec2 vel_buffer = texelFetch(u_tex_velocity_buffer, ivec2(gl_FragCoord.xy), 0).xy; 20 | 21 | // v_vel = vel_buffer; 22 | v_vel = vel_buffer - vec2((east - west), (north - south)); 23 | // v_vel = vec2((west - east), (north - south)); 24 | } 25 | -------------------------------------------------------------------------------- /src/shaders/glsl/velocity_sources_shader.frag: -------------------------------------------------------------------------------- 1 | in vec2 v_vel; 2 | in float v_weight; 3 | 4 | out vec3 fragmentColor; 5 | 6 | void main() 7 | { 8 | fragmentColor.xy = v_vel; 9 | fragmentColor.z = v_weight; 10 | } 11 | -------------------------------------------------------------------------------- /src/shaders/glsl/velocity_sources_shader.vert: -------------------------------------------------------------------------------- 1 | layout(location = 0) in vec2 pos; 2 | layout(location = 1) in vec2 vel; 3 | layout(location = 2) in float weight; 4 | 5 | out vec2 v_vel; 6 | out float v_weight; 7 | 8 | uniform mat3 u_matrix; 9 | 10 | void main() 11 | { 12 | v_vel = vel; 13 | v_weight = weight; 14 | gl_Position.xyw = u_matrix*vec3(pos, 1.0); 15 | } 16 | -------------------------------------------------------------------------------- /src/shaders/ground_distortion_shader.h: -------------------------------------------------------------------------------- 1 | #ifndef GROUND_DISTORTION_SHADER_H 2 | #define GROUND_DISTORTION_SHADER_H 3 | 4 | #include 5 | 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | 14 | #include "shader_path.h" 15 | 16 | using namespace Magnum; 17 | 18 | class GroundDistortionShader: public GL::AbstractShaderProgram 19 | { 20 | 21 | public: 22 | 23 | typedef GL::Attribute<0, Vector2> Position; 24 | typedef GL::Attribute<1, Vector2> TextureCoordinates; 25 | 26 | explicit GroundDistortionShader(NoCreateT): GL::AbstractShaderProgram{NoCreate} {} 27 | 28 | explicit GroundDistortionShader() 29 | { 30 | MAGNUM_ASSERT_GL_VERSION_SUPPORTED(GL::Version::GL330); 31 | 32 | GL::Shader Vert{GL::Version::GL330, GL::Shader::Type::Vertex}; 33 | GL::Shader Frag{GL::Version::GL330, GL::Shader::Type::Fragment}; 34 | 35 | Vert.addFile(Path_+"texture_base_shader.vert"); 36 | Frag.addFile(Path_+"ground_distortion_shader.frag"); 37 | 38 | CORRADE_INTERNAL_ASSERT_OUTPUT(GL::Shader::compile({Vert, Frag})); 39 | 40 | attachShaders({Vert, Frag}); 41 | 42 | CORRADE_INTERNAL_ASSERT_OUTPUT(link()); 43 | 44 | setUniform(uniformLocation("u_tex_ground"), TexUnitGround); 45 | setUniform(uniformLocation("u_tex_velocities"), TexUnitVelocities); 46 | DistortionUniform_ = uniformLocation("u_distortion"); 47 | DeltaTUniform_ = uniformLocation("u_dt"); 48 | GridResolutionUniform_ = uniformLocation("u_grid_res"); 49 | TimeUniform_ = uniformLocation("u_time"); 50 | TransformationUniform_ = uniformLocation("u_matrix"); 51 | 52 | setUniform(DistortionUniform_, 100.0f); 53 | setUniform(DeltaTUniform_, 1.0f/60.0f); 54 | setUniform(GridResolutionUniform_, 2.0f); 55 | setUniform(TimeUniform_, 0.0f); 56 | } 57 | 58 | GroundDistortionShader& setDistortion(const Float f) 59 | { 60 | setUniform(DistortionUniform_, f); 61 | return *this; 62 | } 63 | 64 | GroundDistortionShader& setDeltaT(const Float dt) 65 | { 66 | setUniform(DeltaTUniform_, dt); 67 | return *this; 68 | } 69 | 70 | GroundDistortionShader& setGridRes(const Float r) 71 | { 72 | setUniform(GridResolutionUniform_, r); 73 | return *this; 74 | } 75 | 76 | GroundDistortionShader& setTime(const Float t) 77 | { 78 | setUniform(TimeUniform_, t); 79 | return *this; 80 | } 81 | 82 | GroundDistortionShader& setTransformation(const Matrix3& t) 83 | { 84 | setUniform(TransformationUniform_, t); 85 | return *this; 86 | } 87 | 88 | GroundDistortionShader& bindTextures(GL::Texture2D& TexGround, 89 | GL::Texture2D& TexVelocities) 90 | { 91 | TexGround.bind(TexUnitGround); 92 | TexVelocities.bind(TexUnitVelocities); 93 | return *this; 94 | } 95 | 96 | private: 97 | 98 | enum: Int 99 | { 100 | TexUnitGround = 0, 101 | TexUnitVelocities = 1 102 | }; 103 | 104 | std::string Path_{SHADER_PATH}; 105 | 106 | Float DistortionUniform_; 107 | Float DeltaTUniform_; 108 | Float GridResolutionUniform_; 109 | Float TimeUniform_; 110 | Int TransformationUniform_; 111 | }; 112 | 113 | #endif // GROUND_DISTORTION_SHADER_H 114 | -------------------------------------------------------------------------------- /src/shaders/jacobi_shader.h: -------------------------------------------------------------------------------- 1 | #ifndef JACOBI_SHADER_H 2 | #define JACOBI_SHADER_H 3 | 4 | #include 5 | 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | 14 | #include "shader_path.h" 15 | 16 | using namespace Magnum; 17 | 18 | enum class JacobiShaderVersionE : int 19 | { 20 | SCALAR = 0, 21 | VECTOR = 1 22 | }; 23 | 24 | class JacobiShader : public GL::AbstractShaderProgram 25 | { 26 | 27 | public: 28 | 29 | typedef GL::Attribute<0, Vector2> Position; 30 | typedef GL::Attribute<1, Vector2> TextureCoordinates; 31 | 32 | explicit JacobiShader(NoCreateT): GL::AbstractShaderProgram{NoCreate} {} 33 | 34 | explicit JacobiShader(const JacobiShaderVersionE _ShaderVersion) 35 | { 36 | MAGNUM_ASSERT_GL_VERSION_SUPPORTED(GL::Version::GL330); 37 | 38 | GL::Shader Vert{GL::Version::GL330, GL::Shader::Type::Vertex}; 39 | GL::Shader Frag{GL::Version::GL330, GL::Shader::Type::Fragment}; 40 | 41 | Vert.addFile(Path_+"texture_base_shader.vert"); 42 | if (_ShaderVersion == JacobiShaderVersionE::SCALAR) 43 | Frag.addFile(Path_+"jacobi1d_shader.frag"); 44 | else 45 | Frag.addFile(Path_+"jacobi2d_shader.frag"); 46 | 47 | CORRADE_INTERNAL_ASSERT_OUTPUT(GL::Shader::compile({Vert, Frag})); 48 | 49 | attachShaders({Vert, Frag}); 50 | 51 | CORRADE_INTERNAL_ASSERT_OUTPUT(link()); 52 | 53 | setUniform(uniformLocation("u_tex_x"), TexUnitX); 54 | setUniform(uniformLocation("u_tex_b"), TexUnitB); 55 | AlphaUniform_ = uniformLocation("u_alpha"); 56 | RBetaUniform_ = uniformLocation("u_r_beta"); 57 | DiffusionRateUniform_ = uniformLocation("u_diffusion_rate"); 58 | TransformationUniform_ = uniformLocation("u_matrix"); 59 | 60 | setUniform(AlphaUniform_, 1.0f); 61 | setUniform(RBetaUniform_, 1.0f/4.0f); 62 | setUniform(DiffusionRateUniform_, 1.0f); 63 | } 64 | 65 | JacobiShader& setAlpha(const Float a) 66 | { 67 | setUniform(AlphaUniform_, a); 68 | return *this; 69 | } 70 | 71 | JacobiShader& setRBeta(const Float b) 72 | { 73 | setUniform(RBetaUniform_, b); 74 | return *this; 75 | } 76 | 77 | JacobiShader& setDiffusionRate(const Float d) 78 | { 79 | setUniform(DiffusionRateUniform_, d); 80 | return *this; 81 | } 82 | 83 | JacobiShader& setTransformation(const Matrix3& t) 84 | { 85 | setUniform(TransformationUniform_, t); 86 | return *this; 87 | } 88 | 89 | JacobiShader& bindTextures(GL::Texture2D& TexX, GL::Texture2D& TexB) 90 | { 91 | TexX.bind(TexUnitX); 92 | TexB.bind(TexUnitB); 93 | return *this; 94 | } 95 | 96 | private: 97 | 98 | enum: Int 99 | { 100 | TexUnitX = 0, 101 | TexUnitB = 1 102 | }; 103 | 104 | std::string Path_{SHADER_PATH}; 105 | 106 | Float AlphaUniform_; 107 | Float RBetaUniform_; 108 | Float DiffusionRateUniform_; 109 | Int TransformationUniform_; 110 | }; 111 | 112 | #endif // JACOBI_SHADER_H 113 | -------------------------------------------------------------------------------- /src/shaders/main_display_shader.h: -------------------------------------------------------------------------------- 1 | #ifndef MAIN_DISPLAY_SHADER_H 2 | #define MAIN_DISPLAY_SHADER_H 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | #include "shader_path.h" 12 | 13 | using namespace Magnum; 14 | 15 | class MainDisplayShader : public GL::AbstractShaderProgram 16 | { 17 | 18 | public: 19 | 20 | explicit MainDisplayShader(NoCreateT): GL::AbstractShaderProgram{NoCreate} {} 21 | 22 | explicit MainDisplayShader() 23 | { 24 | MAGNUM_ASSERT_GL_VERSION_SUPPORTED(GL::Version::GL330); 25 | 26 | GL::Shader Vert{GL::Version::GL330, GL::Shader::Type::Vertex}; 27 | GL::Shader Frag{GL::Version::GL330, GL::Shader::Type::Fragment}; 28 | 29 | Vert.addFile(Path_+"texture_base_unit_shader.vert"); 30 | Frag.addFile(Path_+"main_display_shader.frag"); 31 | 32 | CORRADE_INTERNAL_ASSERT_OUTPUT(GL::Shader::compile({Vert, Frag})); 33 | 34 | attachShaders({Vert, Frag}); 35 | 36 | CORRADE_INTERNAL_ASSERT_OUTPUT(link()); 37 | 38 | TexScaleUniformX_ = uniformLocation("u_tex_scale_x"); 39 | TexScaleUniformY_ = uniformLocation("u_tex_scale_y"); 40 | 41 | setUniform(uniformLocation("u_texture"), TextureUnit); 42 | setUniform(TexScaleUniformX_, 1.0f); 43 | } 44 | 45 | MainDisplayShader& setTexScale(const float TexScaleX, const float TexScaleY) 46 | { 47 | setUniform(TexScaleUniformX_, TexScaleX); 48 | setUniform(TexScaleUniformY_, TexScaleY); 49 | return *this; 50 | } 51 | 52 | MainDisplayShader& bindTexture(GL::Texture2D& Texture) 53 | { 54 | Texture.bind(TextureUnit); 55 | return *this; 56 | } 57 | 58 | private: 59 | 60 | enum: Int { TextureUnit = 0 }; 61 | 62 | Float TexScaleUniformX_ = 1.0f; 63 | Float TexScaleUniformY_ = 1.0f; 64 | 65 | std::string Path_{SHADER_PATH}; 66 | }; 67 | 68 | #endif // MAIN_DISPLAY_SHADER_H 69 | -------------------------------------------------------------------------------- /src/shaders/source_shader.h: -------------------------------------------------------------------------------- 1 | #ifndef SOURCE_SHADER_H 2 | #define SOURCE_SHADER_H 3 | 4 | #include 5 | 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | 14 | #include "shader_path.h" 15 | 16 | using namespace Magnum; 17 | 18 | enum class SourceShaderVersionE : int 19 | { 20 | SCALAR = 0, 21 | VECTOR = 1 22 | }; 23 | 24 | class SourceShader : public GL::AbstractShaderProgram 25 | { 26 | 27 | public: 28 | 29 | typedef GL::Attribute<0, Vector2> Position; 30 | typedef GL::Attribute<1, Vector2> TextureCoordinates; 31 | 32 | explicit SourceShader(NoCreateT): GL::AbstractShaderProgram{NoCreate} {} 33 | 34 | explicit SourceShader(const SourceShaderVersionE _ShaderVersion) 35 | { 36 | MAGNUM_ASSERT_GL_VERSION_SUPPORTED(GL::Version::GL330); 37 | 38 | GL::Shader Vert{GL::Version::GL330, GL::Shader::Type::Vertex}; 39 | GL::Shader Frag{GL::Version::GL330, GL::Shader::Type::Fragment}; 40 | 41 | Vert.addFile(Path_+"texture_base_shader.vert"); 42 | if (_ShaderVersion == SourceShaderVersionE::SCALAR) 43 | Frag.addFile(Path_+"source1d_shader.frag"); 44 | else 45 | Frag.addFile(Path_+"source2d_shader.frag"); 46 | 47 | CORRADE_INTERNAL_ASSERT_OUTPUT(GL::Shader::compile({Vert, Frag})); 48 | 49 | attachShaders({Vert, Frag}); 50 | 51 | CORRADE_INTERNAL_ASSERT_OUTPUT(link()); 52 | 53 | setUniform(uniformLocation("u_tex_buffer"), TexUnitBuffer); 54 | setUniform(uniformLocation("u_tex_sources"), TexUnitSources); 55 | TransformationUniform_ = uniformLocation("u_matrix"); 56 | } 57 | 58 | SourceShader& setTransformation(const Matrix3& t) 59 | { 60 | setUniform(TransformationUniform_, t); 61 | return *this; 62 | } 63 | 64 | SourceShader& bindTextures(GL::Texture2D& TexBuffer, 65 | GL::Texture2D& TexSources) 66 | { 67 | TexBuffer.bind(TexUnitBuffer); 68 | TexSources.bind(TexUnitSources); 69 | return *this; 70 | } 71 | 72 | private: 73 | 74 | enum: Int 75 | { 76 | TexUnitBuffer = 0, 77 | TexUnitSources = 1 78 | }; 79 | 80 | std::string Path_{SHADER_PATH}; 81 | 82 | Int TransformationUniform_; 83 | }; 84 | 85 | #endif // SOURCE_SHADER_H 86 | -------------------------------------------------------------------------------- /src/shaders/texture_2d32f_render_2d32f_shader.h: -------------------------------------------------------------------------------- 1 | #ifndef TEXTURE_2D32F_RENDER_2D32F_SHADER_H 2 | #define TEXTURE_2D32F_RENDER_2D32F_SHADER_H 3 | 4 | #include 5 | 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | 14 | #include "shader_path.h" 15 | 16 | using namespace Magnum; 17 | 18 | class Texture2D32FRender2D32FShader: public GL::AbstractShaderProgram 19 | { 20 | 21 | public: 22 | 23 | typedef GL::Attribute<0, Vector2> Position; 24 | typedef GL::Attribute<1, Vector2> TextureCoordinates; 25 | 26 | explicit Texture2D32FRender2D32FShader(NoCreateT): GL::AbstractShaderProgram{NoCreate} {} 27 | 28 | explicit Texture2D32FRender2D32FShader() 29 | { 30 | MAGNUM_ASSERT_GL_VERSION_SUPPORTED(GL::Version::GL330); 31 | 32 | GL::Shader Vert{GL::Version::GL330, GL::Shader::Type::Vertex}; 33 | GL::Shader Frag{GL::Version::GL330, GL::Shader::Type::Fragment}; 34 | 35 | Vert.addFile(Path_+"texture_base_shader.vert"); 36 | Frag.addFile(Path_+"texture_2d32f_render_2d32f_shader.frag"); 37 | 38 | CORRADE_INTERNAL_ASSERT_OUTPUT(GL::Shader::compile({Vert, Frag})); 39 | 40 | attachShaders({Vert, Frag}); 41 | 42 | CORRADE_INTERNAL_ASSERT_OUTPUT(link()); 43 | 44 | setUniform(uniformLocation("u_texture"), TextureUnit); 45 | TransformationMatrixUniform_ = uniformLocation("u_matrix"); 46 | } 47 | 48 | Texture2D32FRender2D32FShader& setTransformation(const Matrix3& t) 49 | { 50 | setUniform(TransformationMatrixUniform_, t); 51 | return *this; 52 | } 53 | 54 | Texture2D32FRender2D32FShader& bindTexture(GL::Texture2D& Texture) 55 | { 56 | Texture.bind(TextureUnit); 57 | return *this; 58 | } 59 | 60 | private: 61 | 62 | enum: Int { TextureUnit = 0 }; 63 | 64 | std::string Path_{SHADER_PATH}; 65 | 66 | Int TransformationMatrixUniform_; 67 | }; 68 | 69 | #endif // TEXTURE_2D32F_RENDER_2D32F_SHADER_H 70 | -------------------------------------------------------------------------------- /src/shaders/velocity_display_shader.h: -------------------------------------------------------------------------------- 1 | #ifndef VELOCITY_DISPLAY_SHADER_H 2 | #define VELOCITY_DISPLAY_SHADER_H 3 | 4 | #include 5 | 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | 14 | #include "shader_path.h" 15 | 16 | using namespace Magnum; 17 | 18 | class VelocityDisplayShader : public GL::AbstractShaderProgram 19 | { 20 | 21 | public: 22 | 23 | typedef GL::Attribute<0, Vector2> Position; 24 | typedef GL::Attribute<1, Vector2> TextureCoordinates; 25 | 26 | explicit VelocityDisplayShader(NoCreateT): GL::AbstractShaderProgram{NoCreate} {} 27 | 28 | explicit VelocityDisplayShader() 29 | { 30 | MAGNUM_ASSERT_GL_VERSION_SUPPORTED(GL::Version::GL330); 31 | 32 | GL::Shader Vert{GL::Version::GL330, GL::Shader::Type::Vertex}; 33 | GL::Shader Frag{GL::Version::GL330, GL::Shader::Type::Fragment}; 34 | 35 | Vert.addFile(Path_+"texture_base_shader.vert"); 36 | Frag.addFile(Path_+"velocity_display_shader.frag"); 37 | 38 | CORRADE_INTERNAL_ASSERT_OUTPUT(GL::Shader::compile({Vert, Frag})); 39 | 40 | attachShaders({Vert, Frag}); 41 | 42 | CORRADE_INTERNAL_ASSERT_OUTPUT(link()); 43 | 44 | setUniform(uniformLocation("u_texture"), TextureUnit); 45 | ScaleUniform_ = uniformLocation("u_scale"); 46 | ShowOnlyMagnitudeUniform_ = uniformLocation("u_show_only_magnitude"); 47 | TransformationMatrixUniform_ = uniformLocation("u_matrix"); 48 | } 49 | 50 | VelocityDisplayShader& setScale(const Float s) 51 | { 52 | setUniform(ScaleUniform_, s); 53 | return *this; 54 | } 55 | 56 | VelocityDisplayShader& setShowOnlyMagnitude(const bool b) 57 | { 58 | setUniform(ShowOnlyMagnitudeUniform_, b); 59 | return *this; 60 | } 61 | 62 | VelocityDisplayShader& setTransformation(const Matrix3& t) 63 | { 64 | setUniform(TransformationMatrixUniform_, t); 65 | return *this; 66 | } 67 | 68 | VelocityDisplayShader& bindTexture(GL::Texture2D& Texture) 69 | { 70 | Texture.bind(TextureUnit); 71 | return *this; 72 | } 73 | 74 | private: 75 | 76 | enum: Int { TextureUnit = 0 }; 77 | 78 | std::string Path_{SHADER_PATH}; 79 | 80 | Int TransformationMatrixUniform_; 81 | Float ScaleUniform_ = 1.0f; 82 | GLboolean ShowOnlyMagnitudeUniform_ = false; 83 | }; 84 | 85 | #endif // VELOCITY_DISPLAY_SHADER_H 86 | -------------------------------------------------------------------------------- /src/shaders/velocity_divergence_shader.h: -------------------------------------------------------------------------------- 1 | #ifndef VELOCITY_DIVERGENCE_SHADER_H 2 | #define VELOCITY_DIVERGENCE_SHADER_H 3 | 4 | #include 5 | 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | 14 | #include "shader_path.h" 15 | 16 | using namespace Magnum; 17 | 18 | class VelocityDivergenceShader : public GL::AbstractShaderProgram 19 | { 20 | 21 | public: 22 | 23 | typedef GL::Attribute<0, Vector2> Position; 24 | typedef GL::Attribute<1, Vector2> TextureCoordinates; 25 | 26 | explicit VelocityDivergenceShader(NoCreateT): GL::AbstractShaderProgram{NoCreate} {} 27 | 28 | explicit VelocityDivergenceShader() 29 | { 30 | MAGNUM_ASSERT_GL_VERSION_SUPPORTED(GL::Version::GL330); 31 | 32 | GL::Shader Vert{GL::Version::GL330, GL::Shader::Type::Vertex}; 33 | GL::Shader Frag{GL::Version::GL330, GL::Shader::Type::Fragment}; 34 | 35 | Vert.addFile(Path_+"texture_base_shader.vert"); 36 | Frag.addFile(Path_+"velocity_divergence_shader.frag"); 37 | 38 | CORRADE_INTERNAL_ASSERT_OUTPUT(GL::Shader::compile({Vert, Frag})); 39 | 40 | attachShaders({Vert, Frag}); 41 | 42 | CORRADE_INTERNAL_ASSERT_OUTPUT(link()); 43 | 44 | setUniform(uniformLocation("u_tex_velocity_buffer"), TexUnitVelocityBuffer); 45 | TransformationUniform_ = uniformLocation("u_matrix"); 46 | } 47 | 48 | VelocityDivergenceShader& setTransformation(const Matrix3& t) 49 | { 50 | setUniform(TransformationUniform_, t); 51 | return *this; 52 | } 53 | 54 | VelocityDivergenceShader& bindTexture(GL::Texture2D& TexVelocityBuffer) 55 | { 56 | TexVelocityBuffer.bind(TexUnitVelocityBuffer); 57 | return *this; 58 | } 59 | 60 | private: 61 | 62 | enum: Int 63 | { 64 | TexUnitVelocityBuffer = 0 65 | }; 66 | 67 | std::string Path_{SHADER_PATH}; 68 | 69 | Int TransformationUniform_; 70 | }; 71 | 72 | #endif // VELOCITY_DIVERGENCE_SHADER_H 73 | -------------------------------------------------------------------------------- /src/shaders/velocity_gradient_substraction_shader.h: -------------------------------------------------------------------------------- 1 | #ifndef VELOCITY_GRADIENT_SUBSTRACTION_SHADER_H 2 | #define VELOCITY_GRADIENT_SUBSTRACTION_SHADER_H 3 | 4 | #include 5 | 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | 14 | #include "shader_path.h" 15 | 16 | using namespace Magnum; 17 | 18 | class VelocityGradientSubstractionShader : public GL::AbstractShaderProgram 19 | { 20 | 21 | public: 22 | 23 | typedef GL::Attribute<0, Vector2> Position; 24 | typedef GL::Attribute<1, Vector2> TextureCoordinates; 25 | 26 | explicit VelocityGradientSubstractionShader(NoCreateT): GL::AbstractShaderProgram{NoCreate} {} 27 | 28 | explicit VelocityGradientSubstractionShader() 29 | { 30 | MAGNUM_ASSERT_GL_VERSION_SUPPORTED(GL::Version::GL330); 31 | 32 | GL::Shader Vert{GL::Version::GL330, GL::Shader::Type::Vertex}; 33 | GL::Shader Frag{GL::Version::GL330, GL::Shader::Type::Fragment}; 34 | 35 | Vert.addFile(Path_+"texture_base_shader.vert"); 36 | Frag.addFile(Path_+"velocity_gradient_substraction_shader.frag"); 37 | 38 | CORRADE_INTERNAL_ASSERT_OUTPUT(GL::Shader::compile({Vert, Frag})); 39 | 40 | attachShaders({Vert, Frag}); 41 | 42 | CORRADE_INTERNAL_ASSERT_OUTPUT(link()); 43 | 44 | setUniform(uniformLocation("u_tex_velocity_buffer"), TexUnitVelocityBuffer); 45 | setUniform(uniformLocation("u_tex_velocity_divergence_buffer"), TexUnitVelocityDivergenceBuffer); 46 | TransformationUniform_ = uniformLocation("u_matrix"); 47 | } 48 | 49 | VelocityGradientSubstractionShader& setTransformation(const Matrix3& t) 50 | { 51 | setUniform(TransformationUniform_, t); 52 | return *this; 53 | } 54 | 55 | VelocityGradientSubstractionShader& bindTextures(GL::Texture2D& TexVelocityBuffer, 56 | GL::Texture2D& TexVelocityDivergenceBuffer) 57 | { 58 | TexVelocityBuffer.bind(TexUnitVelocityBuffer); 59 | TexVelocityDivergenceBuffer.bind(TexUnitVelocityDivergenceBuffer); 60 | return *this; 61 | } 62 | 63 | private: 64 | 65 | enum: Int 66 | { 67 | TexUnitVelocityBuffer = 0, 68 | TexUnitVelocityDivergenceBuffer = 1 69 | }; 70 | 71 | std::string Path_{SHADER_PATH}; 72 | 73 | Int TransformationUniform_; 74 | }; 75 | 76 | #endif // VELOCITY_GRADIENT_SUBSTRACTION_SHADER_H 77 | -------------------------------------------------------------------------------- /src/shaders/velocity_sources_shader.h: -------------------------------------------------------------------------------- 1 | #ifndef VELOCITY_SOURCES_SHADER_H 2 | #define VELOCITY_SOURCES_SHADER_H 3 | 4 | #include 5 | 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | #include "shader_path.h" 14 | 15 | using namespace Magnum; 16 | 17 | class VelocitySourcesShader : public GL::AbstractShaderProgram 18 | { 19 | 20 | public: 21 | 22 | typedef GL::Attribute<0, Vector2> Position; 23 | typedef GL::Attribute<1, Vector2> Velocity; 24 | typedef GL::Attribute<2, Float> Weight; 25 | 26 | explicit VelocitySourcesShader(NoCreateT): GL::AbstractShaderProgram{NoCreate} {} 27 | 28 | explicit VelocitySourcesShader() 29 | { 30 | MAGNUM_ASSERT_GL_VERSION_SUPPORTED(GL::Version::GL330); 31 | 32 | GL::Shader Vert{GL::Version::GL330, GL::Shader::Type::Vertex}; 33 | GL::Shader Frag{GL::Version::GL330, GL::Shader::Type::Fragment}; 34 | 35 | Vert.addFile(Path_+"velocity_sources_shader.vert"); 36 | Frag.addFile(Path_+"velocity_sources_shader.frag"); 37 | 38 | CORRADE_INTERNAL_ASSERT_OUTPUT(GL::Shader::compile({Vert, Frag})); 39 | 40 | attachShaders({Vert, Frag}); 41 | 42 | CORRADE_INTERNAL_ASSERT_OUTPUT(link()); 43 | 44 | TransformationMatrixUniform_ = uniformLocation("u_matrix"); 45 | } 46 | 47 | VelocitySourcesShader& setTransformation(const Matrix3& t) 48 | { 49 | setUniform(TransformationMatrixUniform_, t); 50 | return *this; 51 | } 52 | 53 | private: 54 | 55 | std::string Path_{SHADER_PATH}; 56 | 57 | Int TransformationMatrixUniform_; 58 | 59 | }; 60 | 61 | #endif // VELOCITY_SOURCES_SHADER_H 62 | -------------------------------------------------------------------------------- /src/submarine.cpp: -------------------------------------------------------------------------------- 1 | #include "submarine.h" 2 | 3 | #include "fluid_interaction_system.hpp" 4 | #include "fluid_probes_component.hpp" 5 | #include "fluid_source_component.hpp" 6 | #include "message_handler.hpp" 7 | 8 | void Submarine::create(entt::registry& _Reg, const float PosX, const float PosY, const float Angle) 9 | { 10 | { 11 | b2BodyDef BodyDef; 12 | BodyDef.type = b2_dynamicBody; 13 | BodyDef.enabled = true; 14 | BodyDef.position.Set(PosX, PosY); 15 | BodyDef.angle = Angle; 16 | BodyDef.angularDamping = 0.0f; 17 | BodyDef.linearDamping = 0.0f; 18 | 19 | Hull = _Reg.create(); 20 | _Reg.ctx().at().create(Hull, this, GameObjectTypeE::SUBMARINE_HULL, 5, DrawableGroupsTypeE::DEFAULT, 21 | {0.1f, 0.1f, 0.2f, 1.0f}, BodyDef); 22 | DBLK( 23 | _Reg.ctx().at().report("sub", "created submarine hull", MessageHandler::DEBUG_L1); 24 | _Reg.ctx().at().report("sub", " - mass: "+std::to_string(_Reg.get(Hull).Body_->GetMass()), MessageHandler::DEBUG_L1); 25 | ) 26 | 27 | auto& FldProbesComp = _Reg.emplace>(Hull); 28 | _Reg.ctx().at().addFluidProbe<8>(FldProbesComp, 8, 300.0f, 0, -1.7f, -7.2f, -1.0f, -1.0f); 29 | _Reg.ctx().at().addFluidProbe<8>(FldProbesComp, 1, 1.7f, -7.2f, 1.0f, -1.0f); 30 | _Reg.ctx().at().addFluidProbe<8>(FldProbesComp, 2, 2.1f, 0.5f, 1.0f, 0.0f); 31 | _Reg.ctx().at().addFluidProbe<8>(FldProbesComp, 3, 1.7f, 8.2f, 1.0f, 1.0f); 32 | _Reg.ctx().at().addFluidProbe<8>(FldProbesComp, 4, 0.7f, 9.2f, 0.0f, 1.0f); 33 | _Reg.ctx().at().addFluidProbe<8>(FldProbesComp, 5, -0.7f, 9.2f, 0.0f, 1.0f); 34 | _Reg.ctx().at().addFluidProbe<8>(FldProbesComp, 6, -1.7f, 8.2f, -1.0f, 1.0f); 35 | _Reg.ctx().at().addFluidProbe<8>(FldProbesComp, 7, -2.1f, 0.5f, -1.0f, 0.0f); 36 | 37 | b2BodyDef BodyDefRudder; 38 | BodyDefRudder.type = b2_dynamicBody; 39 | BodyDefRudder.enabled = true; 40 | BodyDefRudder.position.Set(PosX+8.0f*std::sin(Angle), PosY-8.0f*std::cos(Angle)); 41 | BodyDefRudder.angle = Angle; 42 | // BodyDefRudder.angularDamping = 0.8f; 43 | // BodyDefRudder.linearDamping = 0.2f; 44 | BodyDefRudder.angularDamping = 0.0f; 45 | BodyDefRudder.linearDamping = 0.0f; 46 | 47 | Rudder = _Reg.create(); 48 | _Reg.ctx().at().create(Rudder, this, GameObjectTypeE::SUBMARINE_RUDDER, 5, DrawableGroupsTypeE::DEFAULT, 49 | {0.1f, 0.1f, 0.2f, 1.0f}, BodyDefRudder); 50 | DBLK( 51 | _Reg.ctx().at().report("sub", "created submarine rudder", MessageHandler::DEBUG_L1); 52 | _Reg.ctx().at().report("sub", " - mass: "+std::to_string(_Reg.get(Rudder).Body_->GetMass()), MessageHandler::DEBUG_L1); 53 | ) 54 | auto& FldProbesCompRudder = _Reg.emplace>(Rudder); 55 | _Reg.ctx().at().addFluidProbe<8>(FldProbesCompRudder, 2, 50.0f, 0, -0.1f, -1.0f, -1.0f, 0.0f); 56 | _Reg.ctx().at().addFluidProbe<8>(FldProbesCompRudder, 1, 0.1f, -1.0f, 1.0f, 0.0f); 57 | 58 | // auto Joint = _Reg.create(); 59 | { 60 | // auto Parent = _Reg.emplace(Joint); 61 | // auto Physics = _Reg.emplace(Joint); 62 | b2RevoluteJointDef jointDef; 63 | jointDef.lowerAngle = -0.25f * b2_pi; // -45 degrees 64 | jointDef.upperAngle = 0.25f * b2_pi; // 45 degrees 65 | jointDef.enableLimit = true; 66 | jointDef.bodyA = _Reg.get(Hull).Body_; 67 | jointDef.localAnchorA = {0.0f, -6.0f}; 68 | jointDef.bodyB = _Reg.get(Rudder).Body_; 69 | jointDef.localAnchorB = {0.0f, 1.0f}; 70 | jointDef.maxMotorTorque = 100000.0f; 71 | jointDef.motorSpeed = 0.0f; 72 | jointDef.enableMotor = true; 73 | jointDef.collideConnected = false; 74 | RudderJoint = static_cast(GlobalResources::Get.getWorld()->CreateJoint(&jointDef)); 75 | } 76 | 77 | _Reg.ctx().at().report("sub", "Created submarine. ", MessageHandler::INFO); 78 | } 79 | } 80 | 81 | void Submarine::fire(entt::registry& _Reg) 82 | { 83 | b2Body* const Body = _Reg.get(Hull).Body_; 84 | assert(Body != nullptr); 85 | 86 | float GunPos = 1.0f; 87 | 88 | GunSide == GUN_LEFT ? GunPos = -1.0f : GunPos = 1.0f; 89 | 90 | if (GunRateTimer.split() > 0.1) 91 | { 92 | auto Bullet = _Reg.create(); 93 | 94 | b2BodyDef BodyDef; 95 | BodyDef.type = b2_dynamicBody; 96 | BodyDef.enabled = true; 97 | BodyDef.position.Set(Body->GetPosition().x + 98 | Body->GetWorldVector({GunPos, 8.75f}).x, 99 | Body->GetPosition().y + 100 | Body->GetWorldVector({GunPos, 8.75f}).y); 101 | BodyDef.angle = Body->GetAngle(); 102 | BodyDef.angularDamping = 5.0f; 103 | BodyDef.linearDamping = 0.0f; 104 | BodyDef.bullet = true; 105 | _Reg.ctx().at().create(Bullet, this, GameObjectTypeE::PROJECTILE, 106 | StatusCompLua_.get().AgeMax_, DrawableGroupsTypeE::WEAPON, 107 | {0.7f, 0.5f, 0.3f, 1.0f}, BodyDef); 108 | 109 | auto& FldProbesComp = _Reg.emplace(Bullet); 110 | _Reg.ctx().at().addFluidProbe(FldProbesComp, 0.1f, 0.0f, 0.06f); 111 | 112 | auto& FldSrcComp = _Reg.emplace(Bullet); 113 | FldSrcComp = FldSrcCompLua_.get(); 114 | FldSrcComp.VelocityWeight_ = 1.0f; 115 | 116 | b2Filter Filter; 117 | Filter.categoryBits = 0x0004; 118 | // Filter.maskBits = 0xFFFD; 119 | b2Body* const BulletBody = _Reg.get(Bullet).Body_; 120 | BulletBody->GetFixtureList()->SetFilterData(Filter); 121 | BulletBody->ApplyLinearImpulse(BulletBody->GetWorldVector({0.0f,5.0e2f}), 122 | BulletBody->GetWorldPoint({0.0f, 0.0f}), true); 123 | Body->ApplyLinearImpulse(Body->GetWorldVector({0.0f,-1.0e4f}), 124 | Body->GetWorldPoint({GunPos, 8.0f}), true); 125 | 126 | GunSide ^= true; // Just toggle 127 | GunRateTimer.restart(); 128 | } 129 | } 130 | 131 | void Submarine::loadConfig() 132 | { 133 | FldSrcCompLua_.read("projectile"); 134 | StatusCompLua_.read("projectile"); 135 | } 136 | 137 | void Submarine::update(entt::registry& _Reg) 138 | { 139 | b2Body* const HullBody = _Reg.get(Hull).Body_; 140 | assert(HullBody != nullptr); 141 | 142 | HullBody->ApplyForceToCenter(HullBody->GetWorldVector({0.0f, Throttle_}), true); 143 | // std::cout << HullBody->GetLinearVelocity().Length()*3.6f << std::endl; 144 | } 145 | -------------------------------------------------------------------------------- /src/submarine.h: -------------------------------------------------------------------------------- 1 | #ifndef SUBMARINE_H 2 | #define SUBMARINE_H 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | #include "fluid_source_component_lua.hpp" 9 | #include "game_object_system.hpp" 10 | #include "status_component_lua.hpp" 11 | #include "timer.h" 12 | 13 | class Submarine 14 | { 15 | public: 16 | 17 | // GameObject Hull; 18 | // GameObject Rudder; 19 | entt::entity Hull; 20 | entt::entity Rudder; 21 | 22 | explicit Submarine(entt::registry& _Reg) : Reg_(_Reg), 23 | FldSrcCompLua_(_Reg), 24 | StatusCompLua_(_Reg) 25 | { 26 | GunRateTimer.start(); 27 | } 28 | Submarine() = delete; 29 | 30 | Submarine& setPose(float PosX, float PosY, float Angle=0.0f) 31 | { 32 | if (IsInitialised) 33 | { 34 | // Hull.getBody()->SetTransform({PosX, PosY}, Angle); 35 | // Rudder.getBody()->SetTransform({PosX*std::cos(Angle), (PosY-15.0f)*std::sin(Angle)}, Angle); 36 | } 37 | else 38 | { 39 | b2BodyDef Bodydef; 40 | Bodydef.position = {PosX, PosY}; 41 | Bodydef.angle = Angle; 42 | } 43 | return *this; 44 | } 45 | 46 | float getThrottle() const {return Throttle_;} 47 | float getHullIntegrity() const {return HullIntegrity_;} 48 | void impact(const float Strength) 49 | { 50 | HullIntegrity_ -= Strength; 51 | if (HullIntegrity_ < 0.0f) HullIntegrity_ = 0.0f; 52 | } 53 | 54 | void create(entt::registry& _Reg, const float PosX, const float PosY, const float Angle); 55 | void fire(entt::registry& _Reg); 56 | void loadConfig(); 57 | 58 | void fullStop() 59 | { 60 | Throttle_ = 0.0f; 61 | } 62 | void rudderLeft() 63 | { 64 | RudderJoint->SetMotorSpeed(-1.0f); 65 | Rudder_ = -10.0f; 66 | } 67 | void rudderRight() 68 | { 69 | RudderJoint->SetMotorSpeed(1.0f); 70 | Rudder_ = 10.0f; 71 | } 72 | void rudderStop() 73 | { 74 | RudderJoint->SetMotorSpeed(0.0f); 75 | Rudder_ = 0.0f; 76 | } 77 | void throttleForward() 78 | { 79 | if (Throttle_ < 60000.0f) Throttle_ += 2000.0f; 80 | } 81 | void throttleReverse() 82 | { 83 | if (Throttle_ > -60000.0f) Throttle_ -= 2000.0f; 84 | } 85 | 86 | void update(entt::registry& _Reg); 87 | 88 | private: 89 | 90 | entt::registry& Reg_; 91 | 92 | constexpr static bool GUN_LEFT=false; 93 | constexpr static bool GUN_RIGHT=true; 94 | bool GunSide = GUN_LEFT; 95 | Timer GunRateTimer; 96 | 97 | b2RevoluteJoint* RudderJoint = nullptr; 98 | 99 | bool IsInitialised = false; 100 | 101 | float Rudder_ = 0.0f; 102 | float Throttle_ = 0.0f; 103 | 104 | float HullIntegrity_ = 100.0f; 105 | 106 | FluidSourceComponentLua FldSrcCompLua_; 107 | StatusComponentLua StatusCompLua_; 108 | }; 109 | 110 | #endif // SUBMARINE_H 111 | -------------------------------------------------------------------------------- /src/submarine_definition.h: -------------------------------------------------------------------------------- 1 | #ifndef SUBMARINE_DEFINITION_H 2 | #define SUBMARINE_DEFINITION_H 3 | 4 | struct SubmarineDefintion 5 | { 6 | float Angle = 0.0f; 7 | float PosX = 0.0f; 8 | float PosY = 0.0f; 9 | }; 10 | 11 | #endif // SUBMARINE_DEFINITION_H 12 | -------------------------------------------------------------------------------- /src/submarine_factory.h: -------------------------------------------------------------------------------- 1 | #ifndef SUBMARINE_FACTORY_H 2 | #define SUBMARINE_FACTORY_H 3 | 4 | #include "entity.h" 5 | #include "submarine.h" 6 | 7 | constexpr int POOL_SIZE_SUBS = 5; 8 | 9 | typedef EntityFactory SubmarineFactory; 10 | 11 | #endif // SUBMARINE_FACTORY_H 12 | -------------------------------------------------------------------------------- /src/systems/boid_system.hpp: -------------------------------------------------------------------------------- 1 | #ifndef BOID_SYSTEM_HPP 2 | #define BOID_SYSTEM_HPP 3 | 4 | #include 5 | #include 6 | 7 | #include 8 | 9 | #include "fluid_interaction_system.hpp" 10 | #include "fluid_probes_component.hpp" 11 | #include "fluid_source_component.hpp" 12 | #include "game_object_system.hpp" 13 | #include "message_handler.hpp" 14 | #include "status_component.hpp" 15 | #include "physics_component.hpp" 16 | #include "visuals_component.hpp" 17 | 18 | struct BoidComponent 19 | { 20 | float Test_; 21 | }; 22 | 23 | struct BoidSystemConfig 24 | { 25 | int n{999}; 26 | int CellGridX{32}; 27 | int CellGridY{16}; 28 | }; 29 | 30 | class BoidSystem 31 | { 32 | public: 33 | 34 | explicit BoidSystem(entt::registry& Reg) : Reg_(Reg) {} 35 | BoidSystem() = delete; 36 | 37 | void init() 38 | { 39 | std::normal_distribution DistPos(0.0, 10.0f); 40 | 41 | for (auto i=0; i < Conf_.n; ++i) 42 | { 43 | auto Boid = Reg_.create(); 44 | Magnum::Math::Color3 Col = {0.3f, 0.3f, 0.1f}; 45 | b2BodyDef BodyDef; 46 | BodyDef.type = b2_dynamicBody; 47 | BodyDef.enabled = true; 48 | BodyDef.angularDamping = 1.0f; 49 | BodyDef.linearDamping = 0.0f; 50 | BodyDef.position.Set(200.f+DistPos(Generator_), 20.f+DistPos(Generator_)); 51 | Reg_.ctx().at().create(Boid, this, GameObjectTypeE::BOID, -1, 52 | DrawableGroupsTypeE::BOIDS, Col, BodyDef); 53 | Reg_.emplace(Boid); 54 | Reg_.emplace(Boid); 55 | 56 | auto& FldProbesComp = Reg_.emplace(Boid); 57 | Reg_.ctx().at().addFluidProbe(FldProbesComp, 0.001f, 0.0f, 0.0f); 58 | 59 | 60 | auto& Vis = Reg_.get(Boid); 61 | auto Scale = 0.5f+DistPos(Generator_)*0.01f; 62 | Vis.Visuals_->setScaling({Scale, Scale}); 63 | } 64 | Reg_.ctx().at().report("bds", "Populated world with "+std::to_string(Conf_.n)+" fish", MessageHandler::INFO); 65 | } 66 | 67 | void update() 68 | { 69 | std::normal_distribution DistPos(0.0, 0.05); 70 | 71 | // Update cells 72 | Reg_.view().each( 73 | [&,this](auto _e, auto& _BoidComp, auto& _PhysComp) 74 | { 75 | _PhysComp.Body_->ApplyTorque(DistPos(Generator_), true); 76 | _PhysComp.Body_->ApplyForceToCenter({_PhysComp.Body_->GetWorldVector({0.f, 0.5f})}, true); 77 | auto p = _PhysComp.Body_->GetPosition(); 78 | // std::cout << (int(p.x+256.f) / 16 + int(p.y+128.f) / 16 * 16) << std::endl; 79 | // Cells_.insert({22, _e}); 80 | }); 81 | } 82 | 83 | private: 84 | 85 | entt::registry& Reg_; 86 | 87 | BoidSystemConfig Conf_; 88 | 89 | std::mt19937 Generator_; 90 | 91 | // Definition of a spatial grid for boids behaviour. A rough 92 | // approximation should be enough, so the number of boids per 93 | // cell is restricted. This simplifies the data structure and 94 | // shouldn't have too much of an impact for the algorithm. 95 | std::array Grid_; 96 | }; 97 | 98 | #endif // BOID_SYSTEM_HPP 99 | -------------------------------------------------------------------------------- /src/systems/debug_render_system.cpp: -------------------------------------------------------------------------------- 1 | #include "debug_render_system.hpp" 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | #include "fluid_grid.h" 9 | #include "fluid_probes_component.hpp" 10 | #include "physics_component.hpp" 11 | 12 | DebugRenderSystem::DebugRenderSystem(entt::registry& _Reg) : 13 | Reg_(_Reg), 14 | MeshCircle_(MeshTools::compile(Primitives::circle2DSolid(16))), 15 | MeshLine_(MeshTools::compile(Primitives::line2D())) 16 | {} 17 | 18 | void DebugRenderSystem::renderVelocityProbes(const Matrix3& _ProjectionMatrix) 19 | { 20 | const auto& Fluid = Reg_.ctx().at(); 21 | Reg_.view().each( 22 | [&](const auto& _ProbeComp, const auto& _PhysComp) 23 | { 24 | Matrix3 MatTransformation; 25 | Matrix3 MatRotation; 26 | b2Body* Body = _PhysComp.Body_; 27 | 28 | auto ProbePos = Body->GetWorldPoint({_ProbeComp.X_, _ProbeComp.Y_}); 29 | auto VelF = Fluid.getVelocity(ProbePos.x, ProbePos.y); 30 | auto VelB = Body->GetLinearVelocityFromLocalPoint({_ProbeComp.X_, _ProbeComp.Y_}); 31 | b2Vec2 Vel = {VelF.x() - VelB.x, VelF.y() - VelB.y}; 32 | 33 | MatTransformation = Matrix3::translation({ProbePos.x, ProbePos.y})* 34 | Matrix3::scaling({0.1f+Vel.Length()*0.2f, 0.1f+Vel.Length()*0.2f}); 35 | MatRotation = Matrix3::rotation(Magnum::Rad(std::atan2(VelF.y(), VelF.x()))); 36 | 37 | Shader_.setTransformationProjectionMatrix(_ProjectionMatrix*MatTransformation) 38 | .setColor({1.0f, 0.0f, 0.0f, 0.2f}) 39 | .draw(MeshCircle_); 40 | Shader_.setTransformationProjectionMatrix(_ProjectionMatrix*MatTransformation*MatRotation) 41 | .setColor({1.0f, 0.0f, 0.0f, 0.5f}) 42 | .draw(MeshLine_); 43 | }); 44 | Reg_.view, PhysicsComponent>().each([&](const auto& _ProbesComp, const auto& _PhysComp) 45 | { 46 | for (int i=0; i<_ProbesComp.N_; ++i) 47 | { 48 | Matrix3 MatTransformation; 49 | Matrix3 MatRotation; 50 | b2Body* Body = _PhysComp.Body_; 51 | 52 | auto ProbePos = Body->GetWorldPoint({_ProbesComp.X_[i], _ProbesComp.Y_[i]}); 53 | auto VelF = Fluid.getVelocity(ProbePos.x, ProbePos.y); 54 | auto VelB = Body->GetLinearVelocityFromLocalPoint({_ProbesComp.X_[i], _ProbesComp.Y_[i]}); 55 | auto NormB = Body->GetWorldVector({_ProbesComp.NormX_[i], _ProbesComp.NormY_[i]}); 56 | b2Vec2 VelR = {VelF.x() - VelB.x, VelF.y() - VelB.y}; 57 | b2Vec2 Vel = b2Dot(VelR, NormB)*NormB; 58 | 59 | MatTransformation = Matrix3::translation({ProbePos.x, ProbePos.y})* 60 | Matrix3::scaling({0.1f+Vel.Length()*0.2f, 0.1f+Vel.Length()*0.2f}); 61 | MatRotation = Matrix3::rotation(Magnum::Rad(std::atan2(VelF.y(), VelF.x()))); 62 | 63 | Shader_.setTransformationProjectionMatrix(_ProjectionMatrix*MatTransformation) 64 | .setColor({1.0f, 0.0f, 0.0f, 0.2f}) 65 | .draw(MeshCircle_); 66 | Shader_.setTransformationProjectionMatrix(_ProjectionMatrix*MatTransformation*MatRotation) 67 | .setColor({1.0f, 0.0f, 0.0f, 0.5f}) 68 | .draw(MeshLine_); 69 | } 70 | }); 71 | } 72 | 73 | void DebugRenderSystem::renderVelocityVectors(const Matrix3& _ProjectionMatrix) 74 | { 75 | GL::Mesh Mesh; 76 | GL::Buffer Buffer; 77 | 78 | constexpr auto GRID_X = FLUID_GRID_SIZE_X >> FluidGrid::VELOCITY_READBACK_SUBSAMPLE; 79 | constexpr auto GRID_Y = FLUID_GRID_SIZE_Y >> FluidGrid::VELOCITY_READBACK_SUBSAMPLE; 80 | constexpr auto CELL_X = WORLD_SIZE_DEFAULT_X/GRID_X; 81 | constexpr auto CELL_Y = WORLD_SIZE_DEFAULT_Y/GRID_Y; 82 | 83 | const auto& Fluid = Reg_.ctx().at(); 84 | 85 | for (auto y=0; y 5 | 6 | #include 7 | #include 8 | #include 9 | 10 | #include "fluid_grid.h" 11 | 12 | using namespace Magnum; 13 | 14 | class DebugRenderSystem 15 | { 16 | 17 | public: 18 | 19 | explicit DebugRenderSystem(entt::registry& _Reg); 20 | DebugRenderSystem() = delete; 21 | 22 | void renderVelocityProbes(const Matrix3& _ProjectionMatrix); 23 | void renderVelocityVectors(const Matrix3& _ProjectionMatrix); 24 | 25 | private: 26 | 27 | entt::registry& Reg_; 28 | 29 | static constexpr int VEL_VEC_ARRAY_SIZE = (FLUID_GRID_ARRAY_SIZE >> (FluidGrid::VELOCITY_READBACK_SUBSAMPLE_XY-1)); 30 | // static constexpr int VEL_VEC_ARRAY_SIZE = (FLUID_GRID_ARRAY_SIZE >> (FluidGrid::VELOCITY_READBACK_SUBSAMPLE_XY)); 31 | typedef std::array VelocityVectorFieldDataType; 32 | 33 | VelocityVectorFieldDataType VelocityVectors_; 34 | 35 | GL::Mesh MeshCircle_; 36 | GL::Mesh MeshLine_; 37 | Shaders::Flat2D Shader_; 38 | 39 | }; 40 | 41 | #endif // DEBUG_RENDER_SYSTEM_HPP 42 | -------------------------------------------------------------------------------- /src/systems/emitter_system.cpp: -------------------------------------------------------------------------------- 1 | #include "emitter_system.hpp" 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include "bindings/fluid_source_component_lua.hpp" 8 | #include "fluid_interaction_system.hpp" 9 | #include "fluid_probes_component.hpp" 10 | #include "fluid_source_component.hpp" 11 | 12 | #include "game_object_system.hpp" 13 | #include "status_component.hpp" 14 | 15 | void EmitterSystem::emit() 16 | { 17 | Reg_.view().each([this](auto& _EmComp) 18 | { 19 | std::normal_distribution DistAngle(_EmComp.Angle_, _EmComp.AngleStdDev_); 20 | std::normal_distribution DistScale(_EmComp.Scale_, _EmComp.ScaleStdDev_); 21 | std::normal_distribution DistColor(1.0, 0.2); 22 | 23 | for (auto i=0; i<_EmComp.Number_; ++i) 24 | { 25 | auto Debris = Reg_.create(); 26 | 27 | // Magnum::Math::Color3 Col = {0.05f, 0.05f, 0.1f}; 28 | auto ColorGrade = DistColor(_EmComp.Generator_); 29 | Magnum::Math::Color3 Col = {0.5f*ColorGrade, 0.5f*ColorGrade, 1.0f*ColorGrade}; 30 | if (_EmComp.Type_ == GameObjectTypeE::DEBRIS_SUBMARINE) 31 | { 32 | Col = {0.1f, 0.1f, 0.2f}; 33 | } 34 | 35 | b2BodyDef BodyDef; 36 | BodyDef.type = b2_dynamicBody; 37 | BodyDef.enabled = true; 38 | BodyDef.angularDamping = 1.0f; 39 | BodyDef.linearDamping = 0.0f; 40 | BodyDef.position.Set(_EmComp.OriginX_+i*0.01f, _EmComp.OriginY_); 41 | BodyDef.linearVelocity.Set(std::cos(DistAngle(_EmComp.Generator_))* 42 | (_EmComp.Velocity_+_EmComp.VelocityStdDev_), 43 | std::sin(DistAngle(_EmComp.Generator_))* 44 | (_EmComp.Velocity_+_EmComp.VelocityStdDev_)); 45 | BodyDef.angularVelocity = 0.5f*DistAngle(_EmComp.Generator_); 46 | Reg_.ctx().at().create(Debris, this, _EmComp.Type_, StatusCompLua_.get().AgeMax_, 47 | DrawableGroupsTypeE::WEAPON, Col, BodyDef); 48 | 49 | auto& FldProbesComp = Reg_.emplace(Debris); 50 | Reg_.ctx().at().addFluidProbe(FldProbesComp, 0.001f, 0.0f, 0.0f); 51 | 52 | auto& FldSrcComp = Reg_.emplace(Debris); 53 | FldSrcComp = FldSrcCompLua_.get(); 54 | FldSrcComp.VelocityWeight_ = _EmComp.VelocityWeight_; 55 | 56 | //--- Adjust physics body for non-self collisions ---// 57 | auto& PhysComp = Reg_.get(Debris); 58 | 59 | auto& StatusComp = Reg_.get(Debris); 60 | StatusComp.SinkDuration_ = StatusCompLua_.get().SinkDuration_; 61 | 62 | b2Filter Filter; 63 | Filter.categoryBits = 0x0002; 64 | Filter.maskBits = 0xFFF9; 65 | PhysComp.Body_->GetFixtureList()->SetFilterData(Filter); 66 | 67 | //--- Adjust visuals for varying size ---// 68 | auto& VisComp = Reg_.get(Debris); 69 | 70 | auto Size = DistScale(_EmComp.Generator_); 71 | auto Asymmetry = 0.5f; 72 | if (_EmComp.Type_ == GameObjectTypeE::DEBRIS_SUBMARINE) 73 | { 74 | Size *= 0.75f; 75 | Asymmetry = 1.5f; 76 | } 77 | VisComp.Visuals_->setScaling({Size, Size+Asymmetry*DistScale(_EmComp.Generator_)}); 78 | } 79 | _EmComp.Counter_ += _EmComp.Number_; 80 | if (_EmComp.Counter_ > _EmComp.Number_) 81 | { 82 | auto e = entt::to_entity(Reg_, _EmComp); 83 | Reg_.destroy(e); 84 | } 85 | }); 86 | } 87 | 88 | void EmitterSystem::loadConfigDebris() 89 | { 90 | FldSrcCompLua_.read("debris"); 91 | StatusCompLua_.read("debris"); 92 | } 93 | -------------------------------------------------------------------------------- /src/systems/emitter_system.hpp: -------------------------------------------------------------------------------- 1 | #ifndef EMITTER_SYSTEM_HPP 2 | #define EMITTER_SYSTEM_HPP 3 | 4 | #include 5 | 6 | #include "emitter_component.hpp" 7 | #include "fluid_source_component.hpp" 8 | #include "fluid_source_component_lua.hpp" 9 | #include "status_component.hpp" 10 | #include "status_component_lua.hpp" 11 | 12 | class EmitterSystem 13 | { 14 | 15 | public: 16 | 17 | explicit EmitterSystem(entt::registry& _Reg) : Reg_(_Reg), 18 | FldSrcCompLua_(_Reg), 19 | StatusCompLua_(_Reg){} 20 | EmitterSystem() = delete; 21 | 22 | const FluidSourceComponent& getConfigDebrisFluidSource() const {return FldSrcCompLua_.get();} 23 | const StatusComponent& getConfigDebrisStatus() const {return StatusCompLua_.get();} 24 | 25 | void emit(); 26 | void loadConfigDebris(); 27 | void setConfigDebrisFluidSource(const FluidSourceComponent& _c) {FldSrcCompLua_.set(_c);} 28 | void setConfigDebrisStatus(const StatusComponent& _c) {StatusCompLua_.set(_c);} 29 | 30 | private: 31 | 32 | entt::registry& Reg_; 33 | 34 | FluidSourceComponentLua FldSrcCompLua_; 35 | StatusComponentLua StatusCompLua_; 36 | 37 | }; 38 | 39 | #endif // EMITTER_SYSTEM_HPP 40 | -------------------------------------------------------------------------------- /src/systems/fluid_interaction_system.cpp: -------------------------------------------------------------------------------- 1 | #include "fluid_interaction_system.hpp" 2 | 3 | #include "fluid_grid.h" 4 | #include "fluid_source_component.hpp" 5 | #include "physics_component.hpp" 6 | 7 | void FluidInteractionSystem::addFluidProbe(FluidProbeComponent& _Probe, const float _M, const float _X, const float _Y) 8 | { 9 | _Probe.M_ = _M; 10 | _Probe.X_ = _X; 11 | _Probe.Y_ = _Y; 12 | } 13 | 14 | void FluidInteractionSystem::addSources() 15 | { 16 | auto& Fluid = Reg_.ctx().at(); 17 | Reg_.view().each([&](const auto& _PhysComp, const auto& _FluidComp) 18 | { 19 | auto Pos = _PhysComp.Body_->GetPosition(); 20 | auto Vel = _PhysComp.Body_->GetLinearVelocity(); 21 | auto VelBP = _FluidComp.VelocityBackProjection_; 22 | auto DenBP = _FluidComp.DensityBackProjection_; 23 | auto R = (_FluidComp.DensityStaticR_ + _FluidComp.DensityDynamicR_*Vel.Length()); 24 | auto G = (_FluidComp.DensityStaticG_ + _FluidComp.DensityDynamicG_*Vel.Length()); 25 | auto B = (_FluidComp.DensityStaticB_ + _FluidComp.DensityDynamicB_*Vel.Length()); 26 | 27 | Fluid.addDensityLn(Pos.x, Pos.y, 28 | Pos.x-Vel.x*DenBP, Pos.y-Vel.y*DenBP, 29 | R, G, B) 30 | .addVelocity(Pos.x, Pos.y, Vel.x, Vel.y, 31 | Pos.x-Vel.x*VelBP, 32 | Pos.y-Vel.y*VelBP, 33 | Vel.x, Vel.y, 34 | _FluidComp.VelocityWeight_); 35 | }); 36 | } 37 | 38 | void FluidInteractionSystem::applyForces() 39 | { 40 | auto& Fluid = Reg_.ctx().at(); 41 | Reg_.view().each( 42 | [&](const auto& _ProbeComp, const auto& _PhysComp) 43 | { 44 | 45 | const float f = _ProbeComp.M_*60.0f; 46 | 47 | b2Body* Body = _PhysComp.Body_; 48 | 49 | auto ProbePos = Body->GetWorldPoint({_ProbeComp.X_, _ProbeComp.Y_}); 50 | auto VelF = Fluid.getVelocity(ProbePos.x, ProbePos.y); 51 | auto VelB = Body->GetLinearVelocityFromLocalPoint({_ProbeComp.X_, _ProbeComp.Y_}); 52 | b2Vec2 Vel = {VelF.x() - VelB.x, VelF.y() - VelB.y}; 53 | 54 | _PhysComp.Body_->ApplyForce({Vel.x*f, Vel.y*f}, ProbePos, true); 55 | }); 56 | Reg_.view, PhysicsComponent>().each( 57 | [&](const auto& _ProbesComp, const auto& _PhysComp) 58 | { 59 | 60 | for (int i=0; i<_ProbesComp.N_; ++i) 61 | { 62 | 63 | const float f = _ProbesComp.M_/_ProbesComp.N_*60.0f; 64 | 65 | b2Body* Body = _PhysComp.Body_; 66 | 67 | auto ProbePos = Body->GetWorldPoint({_ProbesComp.X_[i], _ProbesComp.Y_[i]}); 68 | auto VelF = Fluid.getVelocity(ProbePos.x, ProbePos.y); 69 | auto VelB = Body->GetLinearVelocityFromLocalPoint({_ProbesComp.X_[i], _ProbesComp.Y_[i]}); 70 | auto NormB = Body->GetWorldVector({_ProbesComp.NormX_[i], _ProbesComp.NormY_[i]}); 71 | b2Vec2 VelR = {VelF.x() - VelB.x, VelF.y() - VelB.y}; 72 | b2Vec2 Vel = b2Dot(VelR, NormB)*NormB; 73 | 74 | _PhysComp.Body_->ApplyForce({Vel.x*f, Vel.y*f}, ProbePos, true); 75 | } 76 | }); 77 | } 78 | -------------------------------------------------------------------------------- /src/systems/fluid_interaction_system.hpp: -------------------------------------------------------------------------------- 1 | #ifndef FLUID_INTERACTION_SYSTEM_HPP 2 | #define FLUID_INTERACTION_SYSTEM_HPP 3 | 4 | #include 5 | 6 | #include "fluid_grid.h" 7 | #include "fluid_probes_component.hpp" 8 | 9 | class FluidInteractionSystem 10 | { 11 | 12 | public: 13 | 14 | explicit FluidInteractionSystem(entt::registry& _Reg) : Reg_(_Reg) {} 15 | FluidInteractionSystem() = delete; 16 | 17 | void addFluidProbe(FluidProbeComponent& _Probe, const float _M, const float _X, const float _Y); 18 | 19 | template 20 | void addFluidProbe(FluidProbesComponent& _Probe, const int _N, const float _M, const int _I, 21 | const float _X, const float _Y, 22 | const float _NormX, const float _NormY, const bool Normalize = true); 23 | template 24 | void addFluidProbe(FluidProbesComponent& _Probe, const int _I, 25 | const float _X, const float _Y, 26 | const float _NormX, const float _NormY, const bool Normalize = true); 27 | void addSources(); 28 | void applyForces(); 29 | 30 | 31 | private: 32 | 33 | entt::registry& Reg_; 34 | 35 | }; 36 | 37 | template 38 | void FluidInteractionSystem::addFluidProbe(FluidProbesComponent& _Probe, const int _N, const float _M, const int _I, 39 | const float _X, const float _Y, 40 | const float _NormX, const float _NormY, const bool Normalize) 41 | { 42 | _Probe.N_ = _N; 43 | _Probe.M_ = _M; 44 | this->addFluidProbe(_Probe, _I, _X, _Y, _NormX, _NormY, Normalize); 45 | } 46 | 47 | template 48 | void FluidInteractionSystem::addFluidProbe(FluidProbesComponent& _Probe, const int _I, 49 | const float _X, const float _Y, 50 | const float _NormX, const float _NormY, const bool Normalize) 51 | { 52 | assert(_I < N); 53 | _Probe.X_[_I] = _X; 54 | _Probe.Y_[_I] = _Y; 55 | if (Normalize) 56 | { 57 | float Length = std::sqrt(_NormX*_NormX + _NormY*_NormY); 58 | if (Length > 0.0f) 59 | { 60 | float InvLength = 1.0f/Length; 61 | _Probe.NormX_[_I] = _NormX * InvLength; 62 | _Probe.NormY_[_I] = _NormY * InvLength; 63 | } 64 | } 65 | else 66 | { 67 | _Probe.NormX_[_I] = _NormX; 68 | _Probe.NormY_[_I] = _NormY; 69 | } 70 | } 71 | 72 | #endif // FLUID_INTERACTION_SYSTEM_HPP 73 | -------------------------------------------------------------------------------- /src/systems/game_object_system.cpp: -------------------------------------------------------------------------------- 1 | #include "game_object_system.hpp" 2 | 3 | #include "parent_component.hpp" 4 | 5 | void GameObjectSystem::create(entt::entity e, std::any _Parent, const GameObjectTypeE _GameObjectType, 6 | const int _AgeMax, 7 | const DrawableGroupsTypeE _DrawableGroupsType, Color4 _Col, 8 | const b2BodyDef& _BodyDef) 9 | { 10 | auto& Parent = Reg_.emplace(e); 11 | auto& Physics = Reg_.emplace(e); 12 | auto& Status = Reg_.emplace(e); 13 | auto& Visuals = Reg_.emplace(e); 14 | 15 | Parent.Parent_ = _Parent; 16 | 17 | Physics.Body_ = GlobalResources::Get.getWorld()->CreateBody(&_BodyDef); 18 | 19 | if (EntityIDs.CountFree_ > 0) 20 | { 21 | EntityIDs.IDs_[EntityIDs.FreeIDs_[EntityIDs.CountFree_-1]] = entt::id_type(e); 22 | 23 | EntityIDs.IDMap_[id(e)] = EntityIDs.FreeIDs_[EntityIDs.CountFree_-1]; 24 | Physics.Body_->GetUserData().pointer = reinterpret_cast(&EntityIDs.IDs_[EntityIDs.FreeIDs_[EntityIDs.CountFree_-1]]); 25 | EntityIDs.CountFree_--; 26 | } 27 | else 28 | { 29 | EntityIDs.IDs_[EntityIDs.Count_] = entt::id_type(e); 30 | EntityIDs.IDMap_[id(e)] = EntityIDs.Count_; 31 | Physics.Body_->GetUserData().pointer = reinterpret_cast(&EntityIDs.IDs_[EntityIDs.Count_++]); 32 | } 33 | 34 | DBLK(printInternalEntityLists();) 35 | 36 | this->createShapes(Physics.Body_, GlobalResources::Get.getShapes(_GameObjectType)); 37 | 38 | Status.Age_.restart(); 39 | Status.AgeMax_ = _AgeMax; 40 | Status.Type_ = _GameObjectType; 41 | 42 | Visuals.DrawableGrp_ = GlobalResources::Get.getDrawables(_DrawableGroupsType); 43 | Visuals.Meshes_ = GlobalResources::Get.getMeshes(_GameObjectType); 44 | Visuals.Scene_ = GlobalResources::Get.getScene(); 45 | Visuals.Shader_ = GlobalResources::Get.getShader(); 46 | assert(Visuals.DrawableGrp_ != nullptr); 47 | assert(Visuals.Meshes_ != nullptr); 48 | assert(Visuals.Scene_ != nullptr); 49 | assert(Visuals.Shader_ != nullptr); 50 | Visuals.Visuals_ = new Object2D(Visuals.Scene_); 51 | 52 | Visuals.Visuals_->setTranslation({Physics.Body_->GetPosition().x, Physics.Body_->GetPosition().y}) 53 | .setRotation(Complex::rotation(Rad(Physics.Body_->GetAngle()))); 54 | 55 | for (auto i=0u; isize(); ++i) 56 | { 57 | Visuals.Drawable_ = new DrawableGeneric(Visuals.Visuals_, &((*Visuals.Meshes_)[i]), 58 | Visuals.Shader_, _Col, 59 | Visuals.DrawableGrp_); 60 | } 61 | } 62 | 63 | void GameObjectSystem::createShapes(b2Body* Body, ShapesType* Shapes) 64 | { 65 | for (auto i=0u; iShapeDefs.size(); ++i) 66 | { 67 | // Shape has to be defined here, since CreateFixture needs a 68 | // valid Shape (Box2D internal cloning is done within 69 | // CreateFixture while Fixture is just a structure). 70 | switch(Shapes->Type) 71 | { 72 | case ShapeEnumType::CIRCLE: 73 | { 74 | b2CircleShape Circle; 75 | Circle.m_p.Set(Shapes->ShapeDefs[i][0].x, Shapes->ShapeDefs[i][0].y); 76 | Circle.m_radius = Shapes->ShapeDefs[i][1].x; 77 | Shapes->FixtureDefs[i].shape = &Circle; 78 | Body->CreateFixture(&(Shapes->FixtureDefs[i])); 79 | break; 80 | } 81 | case ShapeEnumType::CHAIN: 82 | { 83 | b2ChainShape Chain; 84 | Chain.CreateLoop(Shapes->ShapeDefs[i].data(), Shapes->ShapeDefs[i].size()); 85 | Shapes->FixtureDefs[i].shape = &Chain; 86 | Body->CreateFixture(&(Shapes->FixtureDefs[i])); 87 | break; 88 | } 89 | case ShapeEnumType::POLYGON: 90 | { 91 | b2PolygonShape Shp; 92 | Shp.Set(Shapes->ShapeDefs[i].data(), Shapes->ShapeDefs[i].size()); 93 | Shapes->FixtureDefs[i].shape = &Shp; 94 | Body->CreateFixture(&(Shapes->FixtureDefs[i])); 95 | } 96 | } 97 | } 98 | } 99 | 100 | void GameObjectSystem::updateStatus() 101 | { 102 | Reg_.view().each( 103 | [this](auto& _PhysComp, auto& _StatusComp, auto& _VisComp) 104 | { 105 | if (_StatusComp.Type_ == GameObjectTypeE::PROJECTILE || 106 | _StatusComp.Type_ == GameObjectTypeE::DEBRIS_LANDSCAPE || 107 | _StatusComp.Type_ == GameObjectTypeE::DEBRIS_SUBMARINE) 108 | 109 | { 110 | if (!_StatusComp.IsSinking_ && _StatusComp.AgeMax_ != -1 && 111 | _StatusComp.Age_.time() > _StatusComp.AgeMax_) 112 | { 113 | _StatusComp.IsSinking_ = true; 114 | _StatusComp.Age_.restart(); 115 | } 116 | if (_StatusComp.IsSinking_) 117 | { 118 | auto Scale = 1.0f/(1.0f+float(_StatusComp.Age_.time())*0.01f); 119 | _VisComp.Visuals_->scale({Scale, Scale}); 120 | 121 | if (_StatusComp.Age_.time() > _StatusComp.SinkDuration_) 122 | { 123 | _StatusComp.IsSunk_ = true; 124 | } 125 | if (_StatusComp.IsSunk_) 126 | { 127 | _PhysComp.Body_->SetEnabled(false); 128 | } 129 | if (_StatusComp.IsSunk_ && _VisComp.Visuals_->scaling().x() < 1.0f) 130 | { 131 | _StatusComp.IsToBeDeleted_=true; 132 | } 133 | } 134 | } 135 | 136 | if (_StatusComp.IsToBeDeleted_) 137 | { 138 | // Destroy physics data, Box2D will handle everything from here 139 | GlobalResources::Get.getWorld()->DestroyBody(_PhysComp.Body_); 140 | 141 | // Destroy graphics data, Magnum will handle everything from here 142 | // (including drawables) 143 | if (_VisComp.Visuals_ != nullptr) 144 | { 145 | delete _VisComp.Visuals_; 146 | _VisComp.Visuals_ = nullptr; 147 | } 148 | auto e = *reinterpret_cast(_PhysComp.Body_->GetUserData().pointer); 149 | 150 | EntityIDs.CountFree_++; 151 | EntityIDs.FreeIDs_[EntityIDs.CountFree_-1] = EntityIDs.IDMap_[id(e)]; 152 | 153 | DBLK(printInternalEntityLists();) 154 | 155 | Reg_.destroy(e); 156 | } 157 | }); 158 | } 159 | 160 | void GameObjectSystem::updateVisuals() 161 | { 162 | Reg_.view().each([](auto& _PhysComp, auto& _VisComp) 163 | { 164 | b2Body* const Body = _PhysComp.Body_; 165 | Object2D* const Visuals = _VisComp.Visuals_; 166 | 167 | if (Body->IsEnabled() && Body->GetType() != b2_staticBody) 168 | { 169 | Visuals->setTranslation({Body->GetPosition().x, Body->GetPosition().y}) 170 | .setRotation(Complex::rotation(Rad(Body->GetAngle()))); 171 | } 172 | }); 173 | } 174 | 175 | 176 | DBLK( 177 | void GameObjectSystem::printInternalEntityLists() const 178 | { 179 | auto& Msg = Reg_.ctx().at(); 180 | Msg.reportRaw("ID: ", MessageHandler::DEBUG_L2); 181 | for (auto i=0; i 5 | 6 | #include 7 | #include 8 | #include 9 | 10 | #include "drawable_generic.h" 11 | #include "global_resources.h" 12 | #include "message_handler.hpp" 13 | #include "physics_component.hpp" 14 | #include "status_component.hpp" 15 | #include "visuals_component.hpp" 16 | 17 | 18 | class GameObjectSystem 19 | { 20 | public: 21 | 22 | explicit GameObjectSystem(entt::registry& Reg) : Reg_(Reg) {} 23 | GameObjectSystem() = delete; 24 | 25 | void create(entt::entity e, std::any _Parent, const GameObjectTypeE _GameObjectType, 26 | const int _AgeMax, 27 | const DrawableGroupsTypeE _DrawableGroupsType, Color4 _Col, 28 | const b2BodyDef& _BodyDef); 29 | 30 | void createShapes(b2Body* Body, ShapesType* Shapes); 31 | void updateStatus(); 32 | void updateVisuals(); 33 | 34 | private: 35 | 36 | entt::registry& Reg_; 37 | 38 | // A static memory storage for entities is needed in order to have a 39 | // consistent storage for SetUserData of Box2D. AFAIK, there is no 40 | // way to get a persistent memory address from entt::registry. Hence, 41 | // an intermediate structure is needed to allow for user data if using 42 | // only entities. 43 | struct 44 | { 45 | std::array IDs_; 46 | std::array IDMap_; 47 | std::array FreeIDs_; 48 | int Count_ = 0; 49 | int CountFree_ = 0; 50 | } EntityIDs; 51 | 52 | entt::id_type id(entt::entity _e) {return entt::to_entity(_e);} 53 | DBLK( 54 | void printInternalEntityLists() const; 55 | ) 56 | }; 57 | 58 | #endif // GAME_OBJECT_FACTORY_H 59 | -------------------------------------------------------------------------------- /src/timer.h: -------------------------------------------------------------------------------- 1 | #ifndef TIMER_H 2 | #define TIMER_H 3 | 4 | #include 5 | 6 | using namespace std::chrono; 7 | using HiResClock = high_resolution_clock; 8 | 9 | class Timer 10 | { 11 | public: 12 | Timer() {this->start();} 13 | void start() {Start = HiResClock::now();} 14 | void stop() {Stop = HiResClock::now();} 15 | void restart() {stop(); start();} 16 | double elapsed() {return duration(Stop-Start).count();} 17 | double split() {return duration(HiResClock::now() - Start).count();} 18 | double time() {return duration(HiResClock::now() - Start).count();} 19 | 20 | private: 21 | 22 | HiResClock::time_point Start; 23 | HiResClock::time_point Stop; 24 | }; 25 | 26 | #endif // TIMER_H 27 | -------------------------------------------------------------------------------- /src/world_def.h: -------------------------------------------------------------------------------- 1 | #ifndef WORLD_DEF_H 2 | #define WORLD_DEF_H 3 | 4 | #include 5 | 6 | constexpr float WORLD_SIZE_DEFAULT_X = 512.0f; 7 | constexpr float WORLD_SIZE_DEFAULT_Y = 256.0f; 8 | 9 | constexpr int WINDOW_RESOLUTION_MAX_X = 4096; 10 | constexpr int WINDOW_RESOLUTION_MAX_Y = 2048; 11 | 12 | using namespace Magnum; 13 | 14 | constexpr GL::SamplerFilter FLUID_GRID_DIFFUSION_FILTER = GL::SamplerFilter::Linear; 15 | constexpr GL::SamplerMipmap FLUID_GRID_DIFFUSION_FILTER_MIP_MAP = GL::SamplerMipmap::Linear; 16 | 17 | constexpr int FLUID_GRID_SIZE_X_BITS = 11; 18 | constexpr int FLUID_GRID_SIZE_X = 1 << FLUID_GRID_SIZE_X_BITS; 19 | constexpr int FLUID_GRID_SIZE_Y = 1 << (FLUID_GRID_SIZE_X_BITS-1); 20 | constexpr int FLUID_GRID_ARRAY_SIZE = FLUID_GRID_SIZE_X * FLUID_GRID_SIZE_Y; 21 | 22 | #endif // WORLD_DEF_H 23 | --------------------------------------------------------------------------------