Úloha 035: Simulace plasma

Cílem je vytvořit takzvaný efekt "Plasma", který má připomínat plápolající oheň nebo rozplývající se kouř.

App screenshot Plasma sample

Základ

Jako základ poslouží projekt 035plasma z repository grcis. Je připravena jednoduchá aplikace, ve které se používá třída Simulation obsahující triviální implementace všech důležitých metod: Simulate(), Visualize(), Reset() a reakce na události myši Mouse*().

V dané aplikaci uživatel může ovlivnit velikost výsledného obrázku (v pixelech), startovat a zastavovat simulaci, resetovat ji a ve všech režimech pomocí levého tlačítka myši kreslit do simulovaného pole.

Princip simulace

Základ metody je velice jednoduchý: v každém kroku se použije vážený součet na pixely/hodnoty kolem aktuálně počítaného pixelu/hodnoty a výsledek se ještě přenásobí konstantou <1, aby oheň/kouř pomalu mizel. Pozor na počítání na tom samém poli hodnot, z kterého berete zdrojové hodnoty. Vhodné je použít "staré" (tzn. právě zobrazené) pole pouze jako zdroj a výsledek zapisovat do nového pole, případně tato dvě pole střídat, aby se předešlo zbytečným alokacím.

V místech "zdroje" plamene se generují náhodné hodnoty a přičítají se k existujícímu poli.

Vylepšený výpočet

Může se používat netriviální pole normalizovaných vektorů (pole má stejnou velikost jako simulační pole). Při výpočtu kroku algoritmu se neberou konstantní váhy, ale například skalární součet vektoru z vektorového pole a vektoru směřujícího od aktuálního cílového do aktuálního zdrojového pixelu (zdrojové pixely ... 8 sousedních pixelů). Myslete ovšem na to, že je třeba váhy normalizovat, aby jejich součet byl 1.

Inspirace

Jako další zdroje informací můžete použít např.:
Simple Fire Effect by Adam Parusel,
Lode's Fire Effect Tutorial,
Fire by Hugo Elias,
Fire/flame effect (video),
Real-Time Fluid Dynamics for Games by Jos Stam

Technické detaily

Momentálně je v metodě Visualize() převod z 2D pole do šedivého RGB obrázku. Vaše základní implementace musí vytvářet výsledek nějak zajímavě zabarvený. Je více možností, jak toho dosáhnout, je na Vás, pro kterou se rozhodnete. Buď můžete dělat celý výpočet přímo na RGB hodnotách a plamen ohně generovat v barvách, barevné plameny se tedy budou míchat. Další možností je nechat skalární simulační pole a přepočítávat hodnotu intenzity pomocí tzv. "look-up" tabulky, tím se dá získávat daleko širší spektrum efektů, například ostře ohraničený plamen nebo plamen měnící barvu při "chladnutí" atd.
Samozřejmě se dají různé přístupy kombinovat (vícekanálový výpočet + každý kanál vlastní LUT + výsledná kombinace výsledku, atd.), fantazii se meze nekladou. Není nutno zůstávat u RGB hodnot, dá se využít i jiný barevný prostor, například HSV...

Interakce

V aplikaci je připraven základ pro interaktivní zásahy uživatele do simulovaného pole pomocí levého tlačítka myši. Můžete například zasahovat do simulovaného pole, definovat pole zdrojových pixelů nebo editovat pole směrových vektorů. Je to zcela na Vás, k dispozici máte obsluhu třech událostí: stisk levého tlačítka myši, uvolnění tlačítka a přesun ukazatele myši (drag).

Co předělat

Typicky budete muset předělat tyto metody:

  • Simulation.InitParams() - inicializace parametrů formuláře (volá se jenom jednou při startu aplikace).
  • Simulation.Simulate() - provede jeden simulační krok, pouze v paměti, zatím se nic nekreslí. Je na Vás, jestli se zde provede opravdu pouze jeden krok, či zda se nebudete řídit reálnou rychlostí počítače a neuděláte zde kroků více (K simulačních kroků na jeden vizualizační..).
  • Simulation.Visualize() - vizualizace simulace = převod do rastrového obrázku Bitmap. Doporučujeme v zájmu rychlosti použít "unsafe" režim a plnit obrázek pomocí pointerů (viz vzorová implementace). Pozor: vizualizace by neměla žádným způsobem měnit stav simulovaných polí, aplikace ji může volat asynchronně a opakovaně (např. v případě GUI interakce dokonce z jiného vlákna).
  • Simulation.Reset() - nepovinná (ale doporučená) metoda, reinicializuje simulovaný systém.
  • Simulation.Change() - nepovinná (ale doporučená) metoda, aplikace ji volá při změně textového pole Params:.
Při použití interakce též obsluhy událostí:
  • Simulation.MouseDown() - reakce na stisk levého tlačítka myši. Vrací true, jestliže je potřeba překreslit rastrový obrázek (viz Simulation.Visualize()).
  • Simulation.MouseUp() - reakce na uvolnění levého tlačítka myši. Vrací true, jestliže je potřeba překreslit rastrový obrázek (viz Simulation.Visualize()).
  • Simulation.MouseMove() - reakce na pohyb myši. Vrací true, jestliže je potřeba překreslit rastrový obrázek (viz Simulation.Visualize()).

Termín

Odevzdat do: 9. 12. 2018

Body

3b .. základní implementace barevné plazmy, konstantní směr výpočtu pro celý rozsah (například směr nahoru),
3b .. dodána možnost netriviálního vektorového pole, směr výpočtu může být pro každý pixel jiný, ovšem po celou dobu zůstává konstantní,
3b .. implementace s dynamickým vektorovým polem,
2b .. zdroje plamene nejsou jen pouhé generování obdélníku na spodku obrázku, ale nějak zajímavě rozmístěné, například hořící nápis atd.,
až 3b .. interakce uživatele pomocí myši,
(dohromady až 14 bodů) + bonusy

Projekt

Visual Studio projekt: 035plasma

Zdrojový soubor

Modifikujte a odevzdejte pouze soubor: Simulation.cs
Do funkce InitParams() napište své jméno!


Copyright (C) 2011-2018 J.Pelikán, last change: 2019-05-09 17:52:59 +0200 (Thu, 09 May 2019)