úloha 058: Kuličky - jednoduchá 3D fyzikální simulace

Úkolem je implementovat jednoduchou fyzikální simulaci ve 3D. Kuličky pohybující se v homogenním gravitačním poli a odrážející se od průhledných stěn a od sebe navzájem.

Marbles demo

Koncepce

Bude potřeba promyslet a doimplementovat následující komponenty:

  • reprezentace 3D světa - množinu kuliček (v základní variantě pevný počet kuliček), jejich aktuální polohy, rychlosti, poloměry, barvy, .. + stěny "akvária" omezujícího pohyb kuliček (v základní variantě stačí pět obdélníků)
  • detekce kolizí - algoritmus detekující v daném okamžiku kolize mezi všemi objekty ve scéně. V našem případě půjde o detekci kolizí mezi všemi kuličkami (O(N2) testů) a mezi kuličkami a pevnými stěnami (M*N testů). N je počet kuliček, M počet pevných stěn scény
  • simulace mechaniky - homogenní gravitační pole + jednoduché chování při nárazu dvou kuliček nebo při odrazu od stěny (v jednoduché variantě stačí zanedbávat tření a otáčení kuliček a implementovat jenom tlumený pružný ráz)
  • zobrazování - v každém snímku se nakreslí aktuální stav světa. Lepšího vzhledu lze dosáhnout pomocí shaderů nebo třeba i textur..

Základ

Základem poslouží projekt 058marbles z repository grcis (GIT). Je připravena aplikace se základem pro realtime simulaci na CPU a zobrazování pomocí OpenGL.
Pro implementaci potřebných algoritmů budete modifikovat předem založené třídy (všechny naleznete ve zdrojovém souboru Marbles.cs):

  • MarblesWorld - reprezentace a simulace světa, nejdůležitější metody: Reset( string param ) pro [re-]inicializaci simulace a Simulate( double time ) počítající simulaci světa do daného časového okamžiku. Návratovou hodnotou je objekt obsahující data pro rendering, viz níže.
  • MarblesRenderData - reprezentace dat pro renderer, každá instance vznikne uvnitř metody MarblesWorld.Simulate() a později již není jakkoli modifikována nebo recyklována. Po upotřebení (vykreslení) se zahodí.
  • MarblesRenderer - provádí rendering scény podle připravených dat. Vše potřebné obstarává metoda Render( OpenglState OGL, MarblesRenderData data ). Technika: přepisování dat (souřadnic) v předem připravených VBO bufferech nastavených do režimu "BufferUsageHint.DynamicDraw", buffery se mapují do paměti aplikace a v unsafe režimu se pomocí ukazatelů souřadnice přepisují. Default implementace kreslí místo kuličky jen jeden trojúhelník, to budete muset změnit!
    V pilotní implementaci jsou použity dva jednoduché shadery, velmi podobné těm z předchozích projektů 086shader a 087fireworks.

Náměty

O dokonale pružném rázu nebo nepružném rázu se můžete dočíst v každé učebnici mechaniky nebo např. na Wikipedii (sledujte i odkazy). Základy reakce na náraz jsou např. v tomto článečku, v dalším se lze dočíst o základy Eulerovské integrace apod. Předpokládá se, že si o problematice sami něco málo nastudujete..

Technicky

Jeden krok fyzikální simulace světa se spouští v metodě Form1.Simulate(), jsou implementovány dvě varianty základních smyček simulátoru:

Synchronní: kdy je jeden krok simulace ihned následován jedním vykresleným snímkem. To je implementováno uvnitř funkce Application_Idle(). Rychlost simulace i vykreslování je při zapnuté vertikální synchronizaci omezena frekvencí zobrazovacího zařízení (můžete však VSync vypnout a sledovat příp. vyšší rychlost simulace a vykreslování).

Asynchronní: kdy se simulace i vykreslování počítají ve dvou samostatných vláknech. Pokud asynchronní MT režim zapnete, bude se simulace počítat maximální rychlostí v samostatném vláknu, zatíží tedy na 100% jedno jádro vašeho CPU (viz Form1.SimulationLoop()). Vykreslování zůstává ve funkci Application_Idle() a je obvykle řízeno rychlostí displeje (simulovaná scéna pravděpodobně příliš nezatíží Vaši grafickou kartu).

Screencast

Pro zajímavost byla do projektu 058marbles zabudována funkce "screencast", tj. ukládání vykreslených snímků v reálném čase na disk (z nich by bylo možné později vyrobit video). Funkce nezávislého transparentního sreencastu zajišťuje třída OpenglSupport.Screencast, režim se zapíná v parametrické řádce screencast=true a musí se opět ručně vypnout screencast=false.

Během zapnutého režimu "screencast" se na disk do aktuálního adresáře zapisují jednotlivé snímky ve formátu PNG. Tento mechanismus je implementován asynchronně ve vedlejším vláknu CPU a neměl by zpomalovat Váš program. Pokud by disk nestíhal zapisovat, v paměti se uschová fronta až 500 dosud nezapsaných snímků, aktuální velikost fronty snímků se zobrazuje jako číslo v závorce ve stavové řádce programu. Pokud by se fronta systematicky zvětšovala, Váš počítač zřejmě nestíhá a byde lepší screencast vypnout (silně doporučujeme při tomto režimu používat VSync!).

Bonusy

Body navíc budu přidělovat za jakékoli nadstandardní řešení: dynamicky přidávané kuličky (mohou naopak i zanikat), složitější geometrie kolizní scény, otáčení kuliček a tření při nárazu, realističtější nedokonale-pružný ráz, tření o vzduch (realistická balistika), alternativní zajímavé gravitační pole (a la "Angry Birds Space"), apod.

Termín

Odevzdat do: 31. 8. 2021

Body

Základ: 12 bodů (jednoduchá ale funkční simulace, povinné jsou kolize mezi kuličkami navzájem a mezi kuličkami a stěnami, gravitační pole),
dalších až 10 bodů: bonus za zajímavá rozšíření (viz výše)

Projekt

Visual Studio projekt: 058marbles

Zdrojový soubor

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


Copyright (C) 2012-2021 J.Pelikán, last change: 2021-06-07 13:52:48 +0200 (Mon, 07 Jun 2021)