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 3.díl - stopy
effekt
12. dubna 2002, 00.00 | Dnes se budeme zabývat vykreslením čar v prostoru(např. laserové paprsky,atd.), stopami za motory, střelami, atd.
A máme tu další díl seriálu Jak vyzrát na kolize. Tentokrát se budeme zabývat vykreslováním "čar". Nebudou to čáry jako takové, spíše čtyřúhelníky, které zadáme dvěma body a tloušťkou (jako u čáry). Pomocí této techniky si ušetříme spoustu času, poněvadž vykreslujeme jen jeden čtyřúhelník místo několika čtyřúhelníků a můžeme tím dosáhnout ještě lepšího efektu. O čem to vlastně mluvím? Představme si např. nějakou akční hru. Většina asi zná hru Half-Life, tak si to popíšeme na ní. Pokud se nepletu, po několika dnech urputného boje s emzáky dostanete včeličkomet (každý to nazývá jinak, je to taková
ta ošklivá zbraň, jediná, která má nekonečno nábojů). Když z ní vystřelíte, spatříte za výstřely stopu, která je z jakéhokoliv úhlu pohled stejně tlustá. Tohoto efektu je možné docílit dvěma způsoby :
a) budeme za střelou vykreslovat válec, jehož jedna podstava leží v hlavni a druhá ve střele (to ale zabere spoustu času)
b) vykreslíme za střelou čtyřúhelník tak, aby jeho normála byla stále orientována ke kameře (viz
obr.-z pohledu kamery)
Jak ho vykreslit?
Jak jsme si již řekli, chceme vykreslit čtyřúhelník který bude mít libovolnou tloušťku (width), jeho osa bude procházet body A a B a normála bude stále orientována ke kameře. Nejprve si určíme vektor v (z A do B), potom vektor u (od kamery do A). Upozorňuji, že musíme počítat s jednotkovými vektory!!! Tak, teď máme dva vektory, ještě zbývá vektor, který je kolmý na vektor u (u je osa, takže kolmý vektor na ni bude normála). Označme si ho tedy b. Pomocí skalárního součinu můžeme "promítnout" vektor u do v a dostaneme vektor x. (x = v * (u * v)). Jak je patrné z obrázku, vektor u je součet vektorů b a x, x a u známe, tak můžeme spočítat vektor b (u = b + x ... b = u - x). Po dlouhých útrapách jsme dostali normálový vektor požadované plochy. Ještě ale zbývá nějaký vektor, který nám řekne kde je v té ploše "nahoře". Nazvěme tedy tento vektor c a spočítejme ho tak, že vektorovým součinem vynásobíme vektory v a b. Opět zdůrazňuji, že musíme počítat s vektory jednotkovými! A je hotovo! Ve finále určíme souřadnice bodů P1,P2,P3,P4.
P1x = Ax + cx * width (tloušťka)
P1y = Ay + cy * width (tloušťka)
P1z = Az + cz * width (tloušťka)
...
A co dál
Mnozí z vás si asi řeknou :" A co s tím? Vždyť čáru můžeme vykreslit i normálně." To je sice pravda, ale čára, kterou budeme kreslit normálním způsobem (v OpenGL pomocí glBegin(GL_LINES)...glEnd() ) se nebude zmenšovat v závislosti na vzdálenosti od kamery, ale bude stále stejně tlustá. Domnívám se, že to nebude tvořit příliš dobrý dojem, když budete 10cm od výstřelu a stopa za projektilem bude stejně tlustá, jako když budete od výstřelu vzdáleni 300km. Taky pomocí normálního kreslení čáry nedocílíte efektu zužování čáry, který budeme potřebovat při kreslení stop za motory. A to jsem ještě nezmínil problém s nanášením textury na "normálně" vykreslenou čáru.
Jak bude vypadat vykreslovací funkce?
Vykreslovací
funkce by měla mít asi tyto parametry:
a) výchozí bod (A nebo sx,sy,sz)
b)
koncový bod (B nebo ex,ey,ez)
c) tloušťku na začátku
a na konci (width_start a width_end)
d) kameru, pro kterou
čáru kreslíme (použijeme třídu C_CAMERA, která obsahuje x,y,z)
e)
barvu na začátku a na konci (použijeme typ T_COLOR_RGBA jde o pole 4
floatů (r,g,b,alpha) color_start a color_end)
U bodu P1 nastavíme texturový koordinát automaticky na (1.0f,0.0f), u P2 na (1.0f,1.0f), P3 na (0.0f,0.0.f) a u P4 na (0.0f,1.0f).
|
Kde jsou ty stopy?
Teď sice dokážeme vykreslovat čáry (plochy, prostě říkejme tomu čáry) :-) Ale pokud budeme chtít vykreslit stopu za motorem nebo střelou, budeme muset tuto funkci trochu upravit. Za prvé si musíme do nějakého pole uložit značky pro stopy (tzn. např. každých 100ms necháme v prostoru značku, která bude mít souřadnice motoru). řekněme tedy, že chceme nakreslit stopu za motorem, která bude mít 20 značek (čím více, tím je stopa hezčí, ale program je pomalejší), jedna značka bude existovat 1000ms(zivot) = 1s. Vytvoříme tedy pole o 20 prvcích (pocet_znacek) (nejlépe x,y,z) a spočítáme si interval po kterém budeme muset vytvořit novou značku, protože jedna již nebude existovat (interval_nova = zivot / pocet_znacek). Z toho vyplývá, že po čase interval_nova zrušíme poslední značku v poli (pole[pocet_znacek - 1]) a ostatní položky tohoto pole posuneme o jednu dále (pole[i + 1] = pole[i]). A do pole[0] (první značka) uložíme x,y,z motoru (nebo projektilu,...). Při vykreslování budeme vykreslovat čáry mezi pole[i] a pole[i+1]. Také doporučuji vykreslit čáru mezi motorem a pole[0]. :-) Každá značka může mít jinou barvu, tloušťku, to už záleží na vás. Také můžete říci, že má stopa mít na začátku barvu takovou a na konci barvu makovou a pomocí lineární interpolace dopočítat barvu ostatních značek (systém výpočtu je stejný jako u částic, proto ho zde nebudu znovu popisovat, pokud si s tím nevíte rady, nahlédněte do článku Jak vyzrát na efekty 2.díl). Tímto způsobem můžeme měnit nejen barvu, ale i tloušťku, atd.
Je tu ale jeden malý problémek: čáry mezi jednotlivými značkami
nemůžeme vykreslovat takto:
Draw_Line(pole[0],pole[1],...);
Draw_Line(pole[1],pole[2],...);
Protože
tento způsob funguje pouze v případě, že značky pole[0],pole[1],pole[2],...
leží v jedné přímce. Pokud tomu tak není, liší se vektor z bodu A
do B, tím i vektor, který udává, kde je v ploše "nahoře"
(viz. výše). Tím pádem neleží jednotlivé body plochy (vykreslované
čáry) v jedné rovinně a dojde ke kostrbatému vzhledu (viz obr.1).
My se budeme snažit přiblížit obr.2. Pro tento účel musíme
trochu opravit předešlou vykreslovací fci. Jednou z hlavních změn
bude to, že ji nebudeme zadávat dva body, ale jen jeden bod. čára se
vykreslí až po zadání druhého bodu. Tzn. k vykreslení dvou spojitých
čar budeme potřebovat 3 body.
int Draw_Continuous_Line(float
x,float y,float z,const C_CAMERA& camera,float width,float cr,float cg,float
cb,float alpha,int flag);
x,y,z jsou souřadnice značky, C_CAMERA je x,y,z kamery,
width je tloušťka značky, cb,cg,cr je barva značky,
alpha je průhlednost.
flag je parametr:
RENDERER_SHAPE_BEGIN ... začátek nové čáry (nastaví
nové výchozí x,y,z)
RENDERER_SHAPE_SEGMENT ... segment čáry (z předešlého
x,y,z vypočítá potřebné vektory a vektor "nahoru" si uloží)
|
A je hotovo!
Nadefinovali jsme si tedy vše potřebné funkce a teď se můžeme podívat, čeho se dá s nimi dosáhnout:
1)Výchozí barva je modrá, koncová černá, používáme alpha-blending, počáteční šířka je 0.5f, koncová 0.0f
2)Tady je situace podobná, jenom jsme použili noise pro barvu (viz částicové systémy - Jak vyzrát na efekty 2.díl), počáteční šířka je 0.5f, koncová 0.0f, životnost 10s, 50 značek
3)Tyto dva obrázky jsou zde pro porovnání rozdílu stopa s texturou a bez (nastavení je stejné jako u prvního obrázku, textura je u druhého obr. tato )
4) situace jako u obr. 2, liší se pouze koncovou šířkou, zde je 2.0f (počáteční je 0.5f)
5) toto jsou ukázky předešlých nastavení, místo přechodu modrá-černá jsem použil přechod žlutá-zelená
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