>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
Textury na 3D polygony
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
Zde musím poděkovat Robertu Schmidtovi (Robert@stud.unit.no), který
napsal takový krátký pokec o jedné z mnoha metod mapování textur,
kterou bych teď asi trochu přiblížil, neboť je jednoduchá a
pochopitelná (ne že by ostatní nebyly)...
Textury jsou vlastně malé (není pravidlo) bitmapy, které se "nalepí"
na 3D polygon. Tento pak vypadá daleko realističtěji (viděli jste
Dooma ? - když se rozhlédnete okolo, všude jsou textury), než pouhé
stínování jednobarevných polygonů (představte si Dooma bez textur)
...
Je libo obrázek ? Tady je !
No jak vidíte, snažil jsem se :) ... Ale z5 k obrázku - následuje
komentář :
pp - je vektor táhnoucí se z počátku souřadnic do bodu, který
právě
bb - je vektor vedoucí z počátku do jednoho z vrcholů polygonu
ss - je vektor jdoucí z počátku do bodu na obrazovce, a je
součástí vektoru pp. Tento vektor má tedy souřadnice
[ssx,ssy,ssz] a souřadnice ssx resp. ssy by měly být v
rozmezí 0-319 resp. 0-199. Z souřadnice je libovolná a
odpovídá vzdálenosti obrazovky od oka (viz 3d
transformace).
uu - je jeden ze dvou vektorů ohraničujících polygon
vv - to samý jako uu
a*uu, b*vv - vyžadují trochu více vysvětlení - hodnoty a&b by
měly být vždycky mezi 0 a 1 - pokud vede vektor pp do
polygonu. Jsou to tedy relativní souřadnice bodu
náležícího polygonu. No a úplné souřadnice získáme
vynásobením velikostí vektoru (neboť jsme je vlastně
předtím tímto vydělili - proč, ukážu za chvíli...)
Hlavní myšlenkou tohoto algoritmu je najít pro každý vektor ss čísla
a&b, která představují bod v polygonu. Dojdeme k tomu matematickou
úvahou :
Vektor pp je definován jako :
pp = bb + a * uu + b * vv (vyplývá z obrázku)
No a jak jste jistě postřehli, je vektor pp prodloužením vektoru ss.
Lze tedy napsat :
pp = k * ss
Dosadíme-li do první rovnice získáme :
k * ss = bb + a * uu + b * vv ,
Což se dá samozřejmě coby parametrická rovnice přímky rozepsat jako:
k * ssx = bbx + a * uux + b * vvx
k * ssy = bby + a * uuy + b * vvy
k * ssz = bbz + a * uuz + b * vvz
No a máme 3 rovnice a 3 neznámé, takže co nám chybí ?
....trying to computing ...
Vzhledem k tomu, že jsem tvor strašně línej, nechal jsem to za sebe
spočítat MathCad (neni úplně blbej, i když to tak na první pohled
vypadá. Dnes mohu zodpovedne prohlasit, ze NEJLEPCI matyematickej
program je MAPLE). Takže finální výsledky :
(vvy*bbz-bby*vvz)*ssx + (vvz*bbx-bbz*vvx)*ssy + (vvx*bby-bbx*vvy)*ssz
a = ------------------------------------------------------------------------
(uuy*vvz-vvy*uuz)*ssx + (uuz*vvx-vvz*uux)*ssy + (uux*vvy-vvx*uuy)*ssz
(bby*uuz-uuy*bbz)*ssx + (bbz*uux-uuz*bbx)*ssy + (bbx*uuy-uux*bby)*ssz
b = -------------------------------------------------------------------------
(uuy*vvz-vvy*uuz)*ssx + (uuz*vvx-vvz*uux)*ssy + (uux*vvy-vvx*uuy)*ssz
Docela dobrý rovnice, ne ???
Abych neodběhl od tématu ... co teď s tím a&b ? No nic jednoduššího
než je vynásobit velikostma textury (bitmapy), kterou máme někde v
paměti schovanou. A vzhledem k tomu, že tyhle čísla jsou mezi 0 a 1,
tak se nám tam ta bitmapa krásně nalepí.
Takhle by to mohlo vypadat v programu :
for y:=0 to 199 do
for x:=0 to 319 do
{
výpočet a&b ;
if (a>=0) and (a<1) and (b>=0) and (b<1) then
putpixel(x,y,bitmapa[a* bmp_size, b*bmp_size]);
}
Tenhle příklad se ale hodí akorát tak na vyzkoušení, neboť není
_vůbec_ optimalizován.
Co by se na něm dalo vylepšit ?
• nepočítat a&b pro všechny body na obrazovce, neboť ne všechny
náleží polygonu (viz vyplňování polygonů)
• všechno co se nemění dát do konstant a počítat mimo smyčku
Nevýhoda této metody je to, že na jeden pixl připadá minimálně jedno
dělené, což sice není katastrofa, ale v složitějších algoritmech
nebo scénách to může brzdit.
výheň