Fotografický magazín "iZIN IDIF" každý týden ve Vašem e-mailu.
Co nového ve světě fotografie!
Zadejte Vaši e-mailovou adresu:
Kamarád fotí rád?
Přihlas ho k odběru fotomagazínu!
Zadejte e-mailovou adresu kamaráda:
C/C++
Jak vyzrát na efekty 2.díl - Částicové systémy
effekt
25. března 2002, 00.00 | V dnešním díle si řekneme, jak naprogramovat částicový systém, kterým můžeme vytvořit např. oheň, stopu za motorem vesmirne lodi a podobně.
V minulém článku jsem se Vám pokusil nastínit, jak se řeší čočkové efekty. Dnes jsou na řadě částicové systémy, se kterými se setkáváme ve většině her. Jejich využití je velice široké. Od tvorby ohně přes efekty zásahů střel, kouř, unikající palivo u vesmírných lodí, až ke stopám za raketami a střelami. My si tu probereme poněkud složitější způsob tvoření částicového systému, ale zato bude variabilní a budeme ho moci použít skoro na vše (kávu Vám neuvaří). V prvním kroku si musíme uvědomit co vlastně chceme. Systém rozdělíme na dvě části na emitory a na částice. Emitory budou logicky produkovat částice. Aby byl celý systém co nejjednodušší, tím myslím, aby jsme se o něj nemuseli moc starat, budeme pracovat s objekty. Nadefinujeme si tedy C_PARTICLE_EMITOR a C_PARTICLE (částice).
Co tedy chceme?Základní věc je, že emitor bude produkovat částice a ty se pak budou samy starat o své vykreslení. Emitor bude v umístěn v prostoru pomocí souřadnic x_start,y_start,z_start(můžeme použít libovolný vektor v příkladu jsou tyto proměnné zastoupeny vektorem start_position). Každý emitor chrlí částice pod nějakým úhlem, použijeme tedy ještě dva úhly alpha, beta a napočítáme matici, která bude representovat toto otočení rotation_matrix. Zde potřebujeme pouze dva úhly, protože otočení kolem vlastní osy emitoru nepotřebujeme (pokud nechceme tvořit tornádo, apod.). Další vlastnost emitoru bude barva první a poslední částice start_color a end_color. Každá částice musí mít také svoji velikost (jak na začátku, tak i na konci) start_size, end_size a také životnost life. Hlavně nesmíme zapomenout na rychlost částic speed. Teď máme sice emitor, který chrlí částice, ale částice jsou čtvercové. Pokud chceme mít částice různých tvarů, použijeme textury (v odstínech šedi - různá intesita průhlednosti) a blending pomocí funkce glEnagle(GL_BLEND);. Texturu uložíme například do proměnné texture_ID. Teď jeden příklad za všechny, takto může vypadat ona textura :
|
A co dál?
Možná by Vás zajímalo co jednotlivé funkce dělají. Tak například funkce
Bind_Texture() buď nahraje texturu a uloží její ID do texture_ID
nebo přiřadí již existující ID. Funkce New_Particle() vytvoří num
nových částic. Aby jsem Vám mohl popsat tuto funkci, musíme si nejdříve
říci, jaké další vlastnosti by měl náš emitor mít. Velice se nám bude
hodit, když se emitor bude moci hýbat s libovolným objektem (C_OBJECT
obsahuje informace o své pozici x,y,z a matici, která vyjadřuje jeho
orientaci v prostoru rotation_matrix). Přidáme tedy proměnnou C_OBEJCT
* owner, která bude ukazovat na svého vlastníka. Tím se nám rozšíří
i metody o metodu (funkci) void Link_To_Object(C_OBJECT * to); která
nastaví proměnnou owner na to. Občas by se nám mohlo
hodit mít možnost toto "svázání" zrušit. Zrušení je jednoduché,
stačí zavolat funkci Link_To_Object(NULL);, tímto programu řekneme,
že vlastník neexistuje a je po "svázání". Teď si možná myslíte,
že máme vše co potřebujeme, ale není tomu tak. Co například oheň, kouř,
atd. Teď se totiž částice pohybují po jedné přímce, ale my chceme počítat
s určitým rozptylem, musíme si proto zvolit nějaké proměnné, které budou
uchovávat veškeré informace o "rozptulu", nazvěme to spíše noise
(šum). Šum se nám hodí jak k vytvoření onoho rozptylu, tak i k různým
velikostem částic, různé barvě a různé délce života (color_noise,
size_noise, life_noise, alpha_noise, beta_noise).
|
Změna barvy, velikosti, ...
Pro vypočítání aktuální barvy, za předpokladu že známe start_color, end_color a life. Použijeme lineární interpolaci.
Jestliže c0 je výchozí barva c1 je konečná barva, t0
je čas vytvoření, t je aktuální čas, můžeme spočítat aktuální barvu
c ze vztahu :
c = c0 + (c1 - c0)* ((t - t0) / life); Pokuď je t > t0 +
life (t1), tak částice už neexistuje a nemá se co vykreslovat!!!
Částice
Ještě než začneme chrlit částice, musíme si říci, jak budou v programu
interpretovány. Samozřejmě musíme znát jejich polohu x,y,z, také
vektor pohybu speed, aktuální barvy, výchozí barvu a změnu barvy za
jednu milisekundu (1 tik systémového počítadla) color, color_start, color_decrease.
Každá částice může mít také jinou průhlednost na začátku a na konci,
proto budeme potřebovat alpha_start, alpha a alpha_decrease.
Abychom mohli provádět interpolaci barev, velikosti, atd. Musíme znát čas,
kdy byla částice vytvořena, čas zániku (délku života) a aktuální čas (life_start,
life_length a life). Poslední proměnná used nám bude říkat,
zda se částice používá, či ne, protože všechny částice uložíme do
jednoho pole o velikosti PARTICLE_NUMBER_MAX.
|
Jak pohnout s částicí
K tomuto účelu nám slouží metoda (funkce) Move().
|
Vykreslíme ji
Jelikož je částice umístěna libovolně v prostoru a kamera se na ni může dívat pod libovolným úhlem, musíme nějakým způsobem zajistit, aby byla normála plosky (částice) stále orientována směrem ke kameře. Touto problematikou jsem se zabýval již v minulém článku Jak vyzrát na efekty 1.díl - Světla. Proto se tady o ni nebudu moc rozepisovat. V podstatě jde o to, že od OpenGL získáme aktuální model_view_matrix (matice, která převádí objekty ze světa objektů do světa kamery), vymažeme z ní posunutí a transponujeme ji. Výslednou matici nazvěme transponsed_matrix.
|
Pole, do kterého částice uložíme nazveme třeba engine3d_particle_array.
Bůh stvořil Zemi za 6 dní,
částici snad vytvoříme rychleji
Nyní známe vše potřebné a můžeme se směle vrhnout do vytváření částic
|
Uznávám, že to působí dosti nepřehledně, ale je to velice jednoduché. Jak je to s tím otáčením? Každý objekt si pamatuje matici, která udává jeho orientaci v prostoru. Tak pokud máme x,y,z emitoru a směrový vektor pod jakým chrlí částice a náhodou se stane, že je "svázán" s nějakým objektem, použijeme jeho x,y,z pozici jako pozici relativní ke středu onoho objektu a následně jí otočíme podle matice, kterou má v sobě objekt uloženou. Tím dosáhneme, že bude emitor stále umístěn na konci křídla, i když se objekt otočí. Když používáme emitor pro tvorbu ohně za raketou, musíme docílit toho, aby byly částice chrleny stále stejným směrem (vzhledem k raketě), tzn. i s pozicí emitoru musíme otočit vektor, který reprezentuje směr pod jakým se částice chrlí. Proto vynásobíme maticí objektu i vektor speed.
Jak se bude vzhled částic měnit v závislosti na
nastavení emitoru?
Připravil jsem si pár obrázků, pokaždé s jiným nastavením emitoru:
1) Žádný rozptyl, výchozí i koncová velikost je stejná, tak i barva (bílá)
2) Výchozí barva je žlutá, koncová zelená
3) Stejné jako u příkladu 2, ale výchozí průhlednost je nastavena na
1.0f, koncová na 0.0f
4) Rozptyl je nastavený na 10° a koncová i výchozí průhlednost je 1.0f
5) Rozptyl je nastavený na 10° a koncová průhlednost je 1.0f
6) Stejné jako příklad 4, ale částice jsou větší
7) Stejné jako příklad 5, ale částice jsou větší
8) Oheň (v prvním případě je velikost částic 0.3f a rychlost 0.3f, v případě
druhém je velikost částic rovna 1.0f, a rychlost 1.0f)
Uff a je to! Doufám, že jsem aspoň některým z Vás pomohl a těším se na shledanou u příštího článku, tentokrát o laserech a stopách za motory.
Obsah seriálu (více o seriálu):
- Jak vyzrát na efekty 1.díl - Světla
- Jak vyzrát na efekty 2.díl - Částicové systémy
- Jak vyzrát na efekty 3.díl - stopy
- Jak vyzrát na efekty 4.díl - SkyBoxy, mlhoviny, atd.
- Jak vyzrát na efekty 5.díl - Lepší částice
-
25. listopadu 2012
-
30. srpna 2002
-
10. října 2002
-
4. listopadu 2002
-
12. září 2002
-
25. listopadu 2012
-
28. července 1998
-
31. července 1998
-
28. srpna 1998
-
6. prosince 2000
-
27. prosince 2007
-
4. května 2007