Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
125 changes: 78 additions & 47 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,61 +1,69 @@
# fluidsim

Third semester project
![themo](image.png)

Third semester project.

## Leírás

A projekt egy 2D folyadék-szimulációs alkalmazás, amely a Navier–Stokes egyenleteken alapul. A felhasználó képes módosítani a szimuláció fizikai paramétereit, interakcióba lépni a folyadékkal, valamint elmenteni és betölteni a konfigurációkat.
A projekt egy 2D folyadék-szimulációs alkalmazás, amely [Jos Stam Real-Time Fluid Dynamics for Games](https://graphics.cs.cmu.edu/nsp/course/15-464/Fall09/papers/StamFluidforGames.pdf) c. papírján alapszik. A felhasználó képes módosítani a szimuláció fizikai paramétereit, interakcióba lépni a folyadékkal, valamint elmenteni és betölteni a konfigurációkat, illetve objektumokat.

## Használat & kezelés

Az ablaknak két fő része van:

### Sidebar

Egy oldalsó vagy alsó panel, amelyen a szimuláció paraméterei állíthatóak valós időben.

### Vizualizáció:
Két ablak van:

Egy canvas, amelyen szimuláció vizualizálva van.
#### Sidebar

A `JPanel` `paintComponent(Graphics g)` metódusa felel a renderelésért, amely a `visualization.drawMode` paramétertől függően a következőket rajzolja ki:
Egy vertikáis swing panel, amelyen a beállítások vannak.

- **Sűrűség:** Egy adott cella színe a sűrűség alapján van színkódolva.
- **Folyam Iránya:** Vektorokat rajzol a rácsra, amelyek szemléltetik a folyam irányát és sebességét.
- **Mindkettő:** A fenti két opciót egyszerre rajzolja ki.
#### Vizualizáció:

### Interakció
Egy OpenGL ablak, amelyen szimuláció vizualizálva van. Két vizualizációs beállítás van: sűrűség, és áramlássebesség. Ezen felül bekapcsolhatóak kis erővektorok négyzetrácsa, amely szemlélteti a folyadékra ható erők irányát.

A felhasználónak lehetősége van folyamokat csinálni az egér segítségével a vásznon (`MouseListener` és `MouseMotionListener` használatával).
## Interakció

**Erő hozzáadása**
A felhasználónak lehetősége van folyamokat csinálni az egér segítségével a vásznon. Az interakció a kurzor körül egy felhasználó által megadott sugárban elhelyezkedő cellákra vonatkozik.

Ha a felhasználó lenyomja a jobb egérgombot és húzza az egeret, a program erőt (sebességet) ad a folyadékhoz. Az erő iránya megegyezik az egér elmozdulásának irányával (az előző pozíciótól a jelenlegiig), nagysága pedig arányos az `interaction.forceAmount` értékkel.
**Erő hozzáadása** a bal oldal egérgomb lenyomásával és az egér húzásával elérhető. Az erő egybeesik a kurzor mozgásának irányával, nagysága pedig arányos annak sebességével.

**Folyadék hozzáadása**
**Folyadék hozzáadása** a mindeközbeni `shift` gomb lenyomásával lehetséges.

Ha a felhasználó lenyomja a bal egérgombot és húzza az egeret, a program "több folyadékot ad" a kurzor alatti cellákhoz (`interaction.densityAmount`-tal).
**Folyadék elvonása** a mindeközbeni `ctrl` gomb lenyomásával lehetséges.

## Mentés és betöltés

A szoftvernek biztosítania kell a 3. pontban részletezett összes paraméter mentését és betöltését **XML formátumban**.
Lehetőség van a felhasználó által módosítható paraméterek mentésére és betöltésére. Ezen felül léteznek felhasználó által nem módosítható paraméterek is, amelyek indításkor kerülnek beolvasásra - ez egy XML konfigurációs fájl, amelyet az első command line argument-nek lehet megadni.

**Mentés**

A felhasználó a `File > Save config...` menüből kiválaszthat egy célfájlt.
Az alkalmazás az aktuális paramétereket egy XML fájlba írja.
Például:
A felhasználó a `File > Save config` menüből kiválaszthat egy célfájlt. Egy konfigurációs fájl így néz ki:

```xml

<FluidSimConfig version="1.0">
<simulation gridResolution="128" timeStep="0.1" />
<physics viscosity="0.0001" diffusionRate="0.0" solverIterations="20" />
<interaction forceAmount="5.0" densityAmount="50.0" />
<visualization drawMode="BOTH" vectorScale="10.0" vectorSkip="4" />
</FluidSimConfig>
<?xml version="1.0" encoding="UTF-8"?><SimParams>
<simulation>
<iterations>26</iterations>
<viscosity>0.0043</viscosity>
<diffusion>0.0256</diffusion>
<vorticity>24.8</vorticity>
<dissipation>0.9944</dissipation>
<interactionRadius>200.0</interactionRadius>
<velocityView>true</velocityView>
<showArrows>true</showArrows>
</simulation>
<grid>
<width>1500</width>
<height>1000</height>
</grid>
<arrow density="0.1" maxLength="5.0" headLength="2.0" headAngle="22.5" velocityScale="2.0" colorR="255" colorG="255" colorB="255" colorA="255"/>
<nozzles>
<nozzle side="LEFT" position="0.5" radius="20.0" length="100.0" directionDegrees="0.0" forceMagnitude="200000.0" density="250.0"/>
<nozzle side="RIGHT" position="0.5" radius="20.0" length="100.0" directionDegrees="-179.99999499104396" forceMagnitude="200000.0" density="250.0"/>
</nozzles>
</SimParams>
```

A `simulation` tagek között elhelyezkedő elemek a felhasználó által frissíthető paraméterek, minden más nem.

**Betöltés**

A felhasználó egy menüből (pl. `File > Load config...`) kiválaszthat egy létező `.xml` konfigurációs fájlt.
Expand All @@ -65,24 +73,45 @@ Az alkalmazás beolvassa az XML-t, és frissíti a szimuláció paramétereit

## Szimuláció paraméterei

A felhasználónak képesnek kell lennie a szimuláció viselkedésének finomhangolására egy dedikált UI panelen (pl. `JSlider` vagy `JTextField` komponensekkel). Az összes paraméter-kulcs angol nyelvű.

| Kategória | Paraméter neve | Típus | Leírás |
| :----------- | :-------------------------- | :----- | :------------------------------------------------------------------------------------------------------------- |
| Szimuláció | `simulation.gridResolution` | int | A szimulációs rács felbontása, cellákban |
| | `simulation.timeStep` | double | Az egyes szimulációs lépések közötti idő ($dt$). Nagyobb érték gyorsabb, de instabilabb szimulációt eredményez |
| Fizika | `physics.viscosity` | double | A folyadék viszkozitása (belső súrlódása). Magasabb érték "sűrűbb", mézszerűbb folyadékot eredményez |
| | `physics.diffusionRate` | double | A sűrűség (festék) diffúziós rátája. Mennyire gyorsan terjed szét a festék a folyadékban |
| | `physics.solverIterations` | int | A nyomás-korrekciós (Poisson) egyenlet megoldójának iterációszáma. Magasabb érték pontosabb, de lassabb |
| Interakció | `interaction.forceAmount` | double | Az egér által a folyadékhoz adott erő (sebesség) nagysága |
| | `interaction.densityAmount` | double | Az egér által a folyadékhoz adott sűrűség (festék) mennyisége |
| Vizualizáció | `visualization.drawMode` | Enum | A megjelenítés módja (pl. `DENSITY_ONLY`, `VELOCITY_ONLY`, `BOTH`) |
| | `visualization.vectorScale` | double | A sebességvektorok megjelenítési hosszának skálázási faktora |
| | `visualization.vectorSkip` | int | Hány cellánként rajzoljon ki egy vektort (teljesítményoptimalizálás céljából) |
- `iterations: float`: diffegyenlet solver iterációinak száma (több = pontosabb eredmény, rosszabb teljesítmény)
- `viscosity: float`: folyadék belső ellenállása
- `diffusion: float`: diffúziós paraméter
- `vorticity: float`: turbulencia együttható
- `dissipation: float`: milyen gyorsan tűnik el a sűrűség
- `interactionRadius: float`: hány pixeles környezetben érintettek a cellák a kurzor körül
- `velocityView: bool`: sebességvektorok nagyságának kijelzése (sűrűség helyett)
- `showArrows: bool`: erővektorok megjelenítése

---
`grid`:

- `width: int`: ablak (és szimuláció) szélessége
- `height: int`: ablak (és szimuláció) magassága

### Algoritmus Leírása (Navier-Stokes)
`arrows`:

- `density: float`: a szélesség/magasság hányadrészén van nyíl
- `maxLength: float`: nyíl maximális hossza pixelekben
- `headLength: float`: nyíl fejének hossza
- `headAngle: float`: nyíl feje és teste között bezárt szög
- `colorR: int`, `colorG: int`, `colorB: int`, `colorA: int`: nyilak RGBA színe

`nozzles`: befúvók listája

`nozzle`:

- `side: LEFT|RIGHT|TOP|BOTTOM`: melyik falon helyezkedik el
- `position: float`: a fal hanyadrészén van (pl. 0.5 -> fele)
- `radius: float`: interakció sugara
- `length: float`: gyorsítás hossza
- `directionDegrees: float`: irány (fokokban)
- `forceMagnitude: float`: erő mértéke
- `density: float`: kibocsátott sűrűség mértéke

## Objektumok betöltése

A felhasználó be tud tölteni egy "falnak" szolgáló entitást az `Objects > Load object...` menüben. A formátum egy egyszerű PNG képfájl, amelynek méretei megegyeznek az ablak méreteivel, a fehér pixelek falnak számítanak, a feketék pedig nem.

## Algoritmus Leírása (Navier-Stokes)

A szimuláció a Navier–Stokes egyenleteket oldja meg.

Expand All @@ -108,3 +137,5 @@ Az algoritmus minden időlépésben a következő lépéseket hajtja végre:
3. Diffúzió (diffusion): a viszkozitás (sebességnél) vagy a diffúziós ráta (sűrűségnél) hatásának szimulálása. Ez a lépés "simítja" a mezőket, ahogy a folyadék belső súrlódása hat.

4. Nyomás korrekció (projection): a folyadék "összenyomhatatlanságának" biztosítása. Kiszámítja a nyomást, és korrigálja a sebességeket.

5. Vorticity confinement: a "swirl" effektus előállításáért felelős lépés.
17 changes: 17 additions & 0 deletions example-configs/main.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
<?xml version="1.0" encoding="UTF-8"?><SimParams>
<simulation>
<iterations>40</iterations>
<viscosity>0.0043</viscosity>
<diffusion>0.002</diffusion>
<vorticity>23.1</vorticity>
<dissipation>0.997</dissipation>
<interactionRadius>200.0</interactionRadius>
<velocityView>false</velocityView>
<showArrows>true</showArrows>
</simulation>
<grid>
<width>1000</width>
<height>1000</height>
</grid>
<arrow density="0.05" maxLength="30.0" headLength="5.0" headAngle="0.5" velocityScale="1.0" colorR="255" colorG="255" colorB="255" colorA="255"/>
</SimParams>
21 changes: 21 additions & 0 deletions example-configs/oppositebeams.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
<?xml version="1.0" encoding="UTF-8"?><SimParams>
<simulation>
<iterations>26</iterations>
<viscosity>0.0043</viscosity>
<diffusion>0.0256</diffusion>
<vorticity>24.8</vorticity>
<dissipation>0.9944</dissipation>
<interactionRadius>200.0</interactionRadius>
<velocityView>true</velocityView>
<showArrows>true</showArrows>
</simulation>
<grid>
<width>1500</width>
<height>1000</height>
</grid>
<arrow density="0.1" maxLength="5.0" headLength="2.0" headAngle="22.5" velocityScale="2.0" colorR="255" colorG="255" colorB="255" colorA="255"/>
<nozzles>
<nozzle side="LEFT" position="0.5" radius="20.0" length="100.0" directionDegrees="0.0" forceMagnitude="200000.0" density="250.0"/>
<nozzle side="RIGHT" position="0.5" radius="20.0" length="100.0" directionDegrees="-179.99999499104396" forceMagnitude="200000.0" density="250.0"/>
</nozzles>
</SimParams>
24 changes: 24 additions & 0 deletions example-configs/windtunnel.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
<?xml version="1.0" encoding="UTF-8"?><SimParams>
<simulation>
<iterations>25</iterations>
<viscosity>0.005</viscosity>
<diffusion>0.0256</diffusion>
<vorticity>25</vorticity>
<dissipation>0.9940</dissipation>
<interactionRadius>200.0</interactionRadius>
<velocityView>true</velocityView>
<showArrows>true</showArrows>
</simulation>
<grid>
<width>1000</width>
<height>1000</height>
</grid>
<arrow density="0.1" maxLength="5.0" headLength="2.0" headAngle="22.5" velocityScale="2.0" colorR="255" colorG="255" colorB="255" colorA="255"/>
<nozzles>
<nozzle side="LEFT" position="0.3" radius="20.0" length="100.0" directionDegrees="0.0" forceMagnitude="200000.0" density="250.0"/>
<nozzle side="LEFT" position="0.4" radius="20.0" length="100.0" directionDegrees="0.0" forceMagnitude="200000.0" density="250.0"/>
<nozzle side="LEFT" position="0.5" radius="20.0" length="100.0" directionDegrees="0.0" forceMagnitude="200000.0" density="250.0"/>
<nozzle side="LEFT" position="0.6" radius="20.0" length="100.0" directionDegrees="0.0" forceMagnitude="200000.0" density="250.0"/>
<nozzle side="LEFT" position="0.7" radius="20.0" length="100.0" directionDegrees="0.0" forceMagnitude="200000.0" density="250.0"/>
</nozzles>
</SimParams>
92 changes: 85 additions & 7 deletions pom.xml
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>

Expand All @@ -15,10 +16,21 @@
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.release>21</maven.compiler.release>
<exec.mainClass>dev.fluidsim.App</exec.mainClass>
<joml.version>1.10.5</joml.version>
<lwjgl.version>3.3.2</lwjgl.version>
<lwjgl.natives>natives-windows</lwjgl.natives>
<!-- <lwjgl.natives>natives-linux</lwjgl.natives> -->
</properties>

<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.lwjgl</groupId>
<artifactId>lwjgl-bom</artifactId>
<version>${lwjgl.version}</version>
<scope>import</scope>
<type>pom</type>
</dependency>
<dependency>
<groupId>org.junit</groupId>
<artifactId>junit-bom</artifactId>
Expand All @@ -30,12 +42,59 @@
</dependencyManagement>

<dependencies>
<!-- LWJGL Core -->
<dependency>
<groupId>org.lwjgl</groupId>
<artifactId>lwjgl</artifactId>
</dependency>
<dependency>
<groupId>org.lwjgl</groupId>
<artifactId>lwjgl-glfw</artifactId>
</dependency>
<dependency>
<groupId>org.lwjgl</groupId>
<artifactId>lwjgl-opengl</artifactId>
</dependency>
<dependency>
<groupId>org.lwjgl</groupId>
<artifactId>lwjgl-stb</artifactId>
</dependency>

<!-- LWJGL Natives -->
<dependency>
<groupId>org.lwjgl</groupId>
<artifactId>lwjgl</artifactId>
<classifier>${lwjgl.natives}</classifier>
</dependency>
<dependency>
<groupId>org.lwjgl</groupId>
<artifactId>lwjgl-glfw</artifactId>
<classifier>${lwjgl.natives}</classifier>
</dependency>
<dependency>
<groupId>org.lwjgl</groupId>
<artifactId>lwjgl-opengl</artifactId>
<classifier>${lwjgl.natives}</classifier>
</dependency>
<dependency>
<groupId>org.lwjgl</groupId>
<artifactId>lwjgl-stb</artifactId>
<classifier>${lwjgl.natives}</classifier>
</dependency>

<!-- JOML for math -->
<dependency>
<groupId>org.joml</groupId>
<artifactId>joml</artifactId>
<version>${joml.version}</version>
</dependency>

<!-- Test dependencies -->
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-api</artifactId>
<scope>test</scope>
</dependency>
<!-- Optionally: parameterized tests support -->
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-params</artifactId>
Expand All @@ -44,14 +103,17 @@
</dependencies>

<build>
<pluginManagement><!-- lock down plugins versions to avoid using Maven defaults (may be moved to parent pom) -->
<pluginManagement><!-- lock down plugins versions to avoid using Maven defaults (may be moved to
parent pom) -->
<plugins>
<!-- clean lifecycle, see https://maven.apache.org/ref/current/maven-core/lifecycles.html#clean_Lifecycle -->
<!-- clean lifecycle, see
https://maven.apache.org/ref/current/maven-core/lifecycles.html#clean_Lifecycle -->
<plugin>
<artifactId>maven-clean-plugin</artifactId>
<version>3.4.0</version>
</plugin>
<!-- default lifecycle, jar packaging: see https://maven.apache.org/ref/current/maven-core/default-bindings.html#Plugin_bindings_for_jar_packaging -->
<!-- default lifecycle, jar packaging: see
https://maven.apache.org/ref/current/maven-core/default-bindings.html#Plugin_bindings_for_jar_packaging -->
<plugin>
<artifactId>maven-resources-plugin</artifactId>
<version>3.3.1</version>
Expand All @@ -76,7 +138,8 @@
<artifactId>maven-deploy-plugin</artifactId>
<version>3.1.2</version>
</plugin>
<!-- site lifecycle, see https://maven.apache.org/ref/current/maven-core/lifecycles.html#site_Lifecycle -->
<!-- site lifecycle, see
https://maven.apache.org/ref/current/maven-core/lifecycles.html#site_Lifecycle -->
<plugin>
<artifactId>maven-site-plugin</artifactId>
<version>3.12.1</version>
Expand All @@ -87,5 +150,20 @@
</plugin>
</plugins>
</pluginManagement>
<plugins>
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<configuration>
<archive>
<manifest>
<mainClass>dev.fluidsim.App</mainClass>
</manifest>
</archive>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
</configuration>
</plugin>
</plugins>
</build>
</project>
</project>
Loading
Loading