tiistai 8. tammikuuta 2008

UV datan pakkaaminen kuvaan

Haluaisitko flash ohjelman jossa 3d-animaation pintatekstuureja voisi muuttaa. Voisit esim. tehdä renderoidun kuvan huoneesta ja muuttaa huoneen seinien tapetit ja vaihtaa lattian. Mikä olisi erityisen hienoa voisit laittaa seinälle minkä tahansa tapettikuva tai vaikka oman naamasi jos siltä jostain syystä tuntuu :).

Koska flashin tehot eivät riitä "kunnolliseen" oikeaan 3d-renderointiin (joka olisi tietysti ideaalista) olisi erityisen mieluisaa saada edes 3d-mallin tai scenen UV-koordinaatit flashiin per pikseli. Tämä mahdollistaisi 3d-mallien tekstuurien vaihtamisen ilman, että 3d-mallia tarvitsee oikeasti renderoida ja vieläpä perspektiivi korjattuna. Lisäksi tällä tavalla 3d-mallin polygonimäärällä ei ole merkitystä, joten 3d-malli voi sisältää miljoonia polygoneja, jos niin tahdot.

Niinpä tein 3D Studio Maxilla scriptin, joka tallensi renderoidun kuvan jokaisen pikselin UV-koordinaatit ja kirjoitti ne tekstitiedostoon. Ongelmaksi tuli hyvin nopeasti tekstitiedoston kasvava koko, joten aloin kirjoittaa data binäärimuotoisena. Tämä korjasi koko ongelmaa jossain määrin, mutta yllätyin melkoisesti huomatessani ettei flashilla voinut lukea binäärimuotoisia tiedostoja. Niinpä päätin pakata UV-datan kuvaan, joita flash lukee kiltisti eikä minun edes tarvitse kirjoittaa omaa tiedostoformaattia.

Itse UV-koordinaattien pakkaaminen kuvaan ei ole kovin hankalaa. Periaatteessa normaaliin PNG kuvaan voi tallentaa mitä tahansa 32 bittistä tietoa, koska jokainen neljä kanavaa (ARGB) on 8 bittisiä. ARGB kuvat kuitenkin alkavat viedä ikävästi tilaa ja kestävät ladata palvelimelta, joten päätin tyytyä 24 bittiseen tarkkuuteen eli R, G ja B kanaviin.

Ajatellaan UV-koordinaatistoa 24bit 2d-matriisina jolloin sen koko on 256^3 = 16777216. Koska haluamme matriisista yhtä leveän kuin korkeankin saamme leveyden laskettua seuraavasti Math.sqrt(16777216) = 4096. Tämän perusteella voimme sanoa, että maksimi tektuuriresoluutio on 4096*4096 pikseliä. Toki sen kokoinen tekstuuri veisi melkoisesti tilaa, mutta se on tällä systeemillä maksimi koko.
Meillä on siis 4096*4096 kokoinen matriisi eli 4096 numeroa U koordinaatille ja 4096 numeroa V koordinaatille. UV:t on kuitenkin usein yksikkövektoreita joten ne pitää skaalata meidän rangellemme U*4096 ja V*4096. Lopuksi vielä pyöristämme U:n ja V:n kokonaisluvuksi. Näin meillä on kaksi kokonaislukua jotka voimme pakata yhdeksi luvuksi näin V*4096+U. Nyt meillä on yksi luku jonka voimme jo kirjoittaa kuvaan. Kuvaformaattien lukijat tietysti luulevat, että numero tarkoittaa RGB arvoa ja piirtää siksi melko erikoisia kuvia.














UV koordinaatit pakattuna kuvaan.

Meitä ei kuitenkaan kiinnosta miltä kuva näyttää vaan data jota kuvassa on. Lukemalla pikselin arvon voimme purkaa siitä UV:t seuraavasti.
V = Math.floor(pikselin_arvo / 4096.0)
U = (pikselin_arvo / 4096.0) - V
V = V / 4096.0
Näin meillä on jälleen samat UV:t (pienin pyöristyseroin), kuin alussa niitä kuvaan pakattaessa. Ja nyt voimme piirtää tekstuurin haluamastamme kuvasta.
X = U*tekstuurikuvan_leveys
Y = V*tekstuurikuvan_korkeus














Tekstuurikuva


Ja tein vielä ohjelman joka lukee UV arvot kuvasta piirtää kuvan teksturoimalla sen tekstuurikuvalla.














Pakatun UV datan mukaan piiretty kuva.


Koska itse renderointi on lineaarista tulee kuvaan pientä epätarkuutta, mutta ajatus kuitenkin näyttää toimivan. Seuraavaksi sitten on vuorossa enemmän itse koodia niin flashin kuin 3dsmax scriptinkin osalta. Tällä kertaa kuitenkin pysytellään näin teoriassa.

4 kommenttia:

xcx kirjoitti...

Binääri tiedostojen lukeminen on sittenkin mahdollista flashilla. Tämä on erittäin mieluisaa ja poistaa melkoisesti vaiheita tästä UV hässäkästä. Lisää tästä seuravalla keralla.

Anonyymi kirjoitti...

teeppä sama skripti Cinema 4D:lle niin lahjoitan 100 €.

xcx kirjoitti...

:) Valitettavasti C4D:n C.O.F.F.E.E ei ole minulle vähäkään tuttu. Myöskään C4D ei ole minulle tuttu softa, joten scriptin kirjoittaminen C4D:lle ei onnistu minulta. Joskin scriptin voi toki kirjoittaa mihin tahansa 3d softaan, jossa on hyvä scripti tuki.

xcx kirjoitti...

Valitettavasti 3dsmax scripti on vielä julkaisematta, joka on ollut kyllä valmiina jo pitkän aikaa, mutta flash esimerkki ei ole valmis ja nyt en ole sen parissa viettänyt aikaa. Muut asiat ovat tuntuneet kiireellisimmiltä, mutta aion kyllä palata siihen.