Úloha 087: Ohňostroj

Úkolem je implementovat real-time simulaci ohňostroje ve 3D. Ohňostroj obsahuje odpalovací rampy (Launchers), ze kterých se vystřelují rakety, které potom ve vzduchu vybuchují a dávají vznik svítícím částicím (Particles). Rakety i částice jsou pod vlivem konstantního gravitačního pole (g = 9.81 m/s2). Navzájem však reagovat vůbec nebudou.

Fireworks Screenshot

Základ

Jako základ poslouží projekt 087fireworks z repository grcis (GIT). Je připravena aplikace, která umí v reálném čase vykreslovat 3D scénu (ovládání systémem "Trackball"), mezi vykreslováním se volá simulace ohňostroje (Fireworks.Simulate()). Pro řízení Vaší simulace jsou připravena tlačítka Start / stop, Reset sim a Update sim. Při inicializaci/update simulace je možné použít uživatelem zadaný řetězec Param.

Pro případné interaktivní ovládání je v simulační třídě Fireworks připraveno několik obslužných funkcí, které se zavolají v případě, že danou událost neošetří "Trackball" (pozn.: ve funkci Form1.InitParams() si můžete určit, které tlačítko myši má Trackball používat /default: levé/, ostatní tlačítka můžete obsluhovat Vy).
Připravené obslužné funkce:

  • Mouse*() – obsluha událostí od myši
  • KeyHandle() – obsluha klávesnice (framework již konzumuje klávesu 'o')

Fyzika

Postačí implementovat jednoduchou Eulerovu simulaci v diskrétních časových intervalech (předpokládá se konstantní rychlost všech komponent simulace během krátkého simulovaného časového intervalu), na pohybující se tělesa (Particles) by měly působit alespoň tyto dvě síly:

  • gravitační síla – konstantní síla s vektorem směřujícím dolů, zrychlení g = 9.81 m/s2
  • odporová síla – odpor prostředí se směrem proti okamžité rychlosti tělesa, velikost odporu doporučuji doladit z lineární a kvadratické složky: |a| = K1 |v| + K2 |v|2, viz např. tato stránka

Technické detaily

Musíte implementovat funkčnost následujících komponent:

  • Launcher – odpalovací rampa vystřelující primární částice (rakety)
  • Particle – primární (raketa, vybuchuje) nebo sekundární částice (může též vybuchovat, typicky hoří/svítí po nějakou dobu a pak zanikne). Je možné implementovat vícestupňové výbuchy, změny barev, apod. Jedinou podmínkou je, aby byla simulace alespoň na první pohled fyzikálně věrohodná

Simulace se počítá v diskrétních časových okamžicích, jednou v každém zobrazovacím cyklu. Všechny simulované objekty (Fireworks, Launcher i Particle) mají pro tento účel deklarovanou funkci Simulate ( double time ). Objekty se musí přepočítat tak, aby jejich stav odpovídal požadovanému času time v sekundách.

Vykreslování

Univerzální systém (interface IRenderObject) se používá k vykreslování všech komponent simulovaného světa. Jednotlivé objekty mohou definovat body (GL_POINTS), úsečky (GL_LINES) a trojúhelníky (GL_TRIANGLES), pomocí kterých budou zobrazeny. Vykreslování probíhá odděleně pro každý ze tří kreslených grafických primitiv a je implementováno obecné dvoufázové plnění datových bufferů:
1. poprvé se zavolá metoda TriangleVertices() (TriangleIndices(), LineVertices(), LineIndices() nebo PointVertices()) bez zadání datového pointeru, aby se jen zjistila velikost vertex-bufferu (index-bufferu) v bytech
2. podruhé se již příslušné metody používají k vlastnímu naplnění dat, VBO buffer z grafické karty se přitom namapuje do operační paměti aplikace metodou GL.MapBuffer()

Globální simulační objekt Fireworks implementuje agregované vykreslování ve třech fázích, nejprve trojúhelníky (FillTriangleData()), potom úsečky (FillLineData()) a nakonec body ("point-sprites" .. FillPointData()). Stačí, když všechny Vaše simulační objekty budou korektně implementovat interface IRenderObject a nebudete muset do vykreslování více zasahovat. Samozřejmě při požadavcích na komplikovanější efekty, např. rozšíření sady shaderů (viz Form1.InitShaderRepository()), budete muset i do vykreslovacího kódu zasáhnout.

V simulaci ohňostroje jsou dva typy objektů, které mohou generovat kresbu: odpalovací rampy (Launcher) a rakety / částice (Particle). Globální simulační objekt Fireworks obsahuje seznamy odpalovacích ramp i částic, ze kterých se potom v metodě RenderScene() vše vykresluje. Systém je navržen pro použití shaderů a VBO bufferů, bez nich vykreslování nefunguje (VAO objekty potřeba nejsou, lze tedy program spustit i na středně starých grafických kartách).

Při modifikacích se inspirujte pilotními implementacemi tříd Launcher a Particle, které jsou obě potomkem třídy DefaultRenderObject. Je to pohodlné, protože stačí přeprogramovat jenom některé funkce – podle toho, zda potřebujete kreslit body, úsečky či trojúhelníky (nic Vám však nebrání používat při vykreslování jednoho objektu více typů grafických primitiv).

Věnujte pozornost sadě atributů vrcholů, které se do GPU posílají. Např. má smysl modifikovat barvu vrcholu u všech třech typů primitiv, velikost bodu (gl_PointSize) má smysl jenom pro bodové objekty. Formulář obsahuje několik přepínačů se zřejmým významem, jejich nastavení můžete pohodlně inicializovat v metodě Form1.InitParams(). Vykreslovací systém je založen na dvou jednoduchých shaderech (vertex.glsl a fragment.glsl), které s těmito přepínači spolupracují přes "uniform" proměnné. Pro inspiraci je zobrazovací kód obohacen o jednu texturu, která se definuje programově, viz Form1.GenerateTexture(). V případě potřeby si snadno můžete doplnit další textury, i když to pravděpodobně pro ohňostroj nebude nutné.

Termín

Odevzdat do: 28. 2. 2022

Body

Základ: 8 bodů (jednoduchá ale funkční simulace),
dalších až 14 bodů: bonus za zajímavá rozšíření (animace odpalovacích ramp, vícestupňové výbuchy, změny barev, interaktivní ovládání /myš, klávesnice/, pokročilejší shaderové efekty, apod.)

Projekt

Visual Studio projekt: 087fireworks

Zdrojový soubor

Modifikujte a odevzdejte soubor: Fireworks.cs (a případně soubory shaderů)
Do funkce InitParams() napište své jméno!


Copyright (C) 2015-2022 J.Pelikán, last change: 2022-02-02 01:03:41 +0100 (Wed, 02 Feb 2022)