2011. február 27., vasárnap

Tao Start 14 - Obj megjelenítő

OpenGL alapozó sorozatunk mérföldkőhöz érkezett. Ugyanis minden tudásunk meg van ahhoz, hogy egy összetett 3Ds modellt jelenítsünk meg virtuális világunkban. Ha visszagondolunk, akkor eddig csupán csak kockákat, gömböket és egyéb egyszerű objektumokat ábrázoltunk. Valljuk be őszintén, nem volt túlságosan izgalmas vagy látványos a végeredmény. De most ezzel szakítunk és kész 3D modelleket fogunk betölteni és megjeleníteni.
Abban az esetben, ha magunk írunk grafikus rendszert, akkor azt célszerű felkészíteni más elterjedt formátum megértésére, mert így mások fáradságos munkájával előállított modelleket is használhatjuk. Elegendő egy gyakori formátum értelmezését létrehozni, mert mára már számos olyan program létezik, amelyek a szabványos formákat egymásba átviszik. Ilyen szabványos fájlformátumok a következők (IGES, NFS, MGF, stb.) Ezeken kívül még vannak a nem szabványos, de elterjedt modellező programok formátumai, mint pl. a POVRAY, 3D-Studio, AutoCad, stb.). Mi most a Wavefront OBJ formátumát fogjuk áttekinteni. Ez a formátum ideális a kezdő programozók számára is.

Az OBJ formátum

Az OBJ formátum egy olyan karakteres fájlformátum, mely lehetővé teszi geometriai objektumok leírását – viszonylag – egyszerű és egységes formában. Ezt a formátumot a Wavefront Technologies kezdte elsőnek kifejleszteni a saját Advanced Visualizer animációs csomagjához, még az 1980-as években. Az OBJ formátumot ott célszerű használni, ahol nagyon egyszerű modelleket jelenítünk meg, és nem kell ezeket animálni. Például jó ötlet lehet OBJ modellek használata egy egyszerű repülős játékban, mivel a repülő nem animálódik, azaz a geometriáját tekintve nem változik (csak a pozíciója, és az orientációja változhat, de azt a transzformációs mátrix beállításával egyszerűen megadhatjuk, így nincs szükségünk a modell animálására). Először magát a Wavefront fájlformátumot ismertetjük. A példa egyetlen négyszöget definiál:

# ez egy megjegyzés

v 0.0 0.1 0.0

v 1.0 0.0 0.0

v 1.0 1.0 0.0

v 0.0 1.0 0.0


vt 0.0 0.0

vt 1.0 0.0

vt 1.0 1.0

vt 0.0 1.0


vn 1.0 0.0 0.0


f 1/1/1 2/2/1 3/3/1 4/4/1


A fájl először a csúcspontokat sorolja fel a v (vertex) kulcsszóval, majd a textúra pontokat a vt (vertex texture) kulcsszóval és a normálvektorokat vn (vertex normal) kulcsszóval adja meg, végül pedig mindezeket az f (face) utasítás egymáshoz és lapokhoz rendeli. A lap utasításban például a lapot négy csúcsponttal adtuk meg (ez egy négyszög), és / jellel elválasztva minden csúcshoz közöltük a csúcspont, a textúra pont és a normálvektor sorsszámát. Most következzen pár gyakran előforduló face definíció:

Csak vertexekből áll a felület.

f v1 v2 v3 v4 ...

Minden vertexhez hozzá van rendelve egy textúra koordináta is.

f v1/vt1 v2/vt2 v3/vt3 ...

Minden vertex tartalmaz textúra koordinátát és normál vektort.

f v1/vt1/vn1 v2/vt2/vn2 v3/vt3/vn3 ...

A vertexekhez csak a felületi normális lett hozzárendelve, a textúra pont opcionális.

f v1//vn1 v2//vn2 v3//vn3 ...

Összefoglalva, az OBJ formális nyelv kulcsszavakból (<v>, <vt>, <vn>, <f>), speciális karakterekből (</>) és számokból (<Float>, <Integer>) épül fel. Az OBJ nyelvtanát következő szabályokkal adhatjuk meg:

(OBJFile) = {(Vertex)}+{(VertexTexture)}+{(VertexNormal)}+{(Face)}
(Vertex) = (v)+(Float)+(
Float)+(Float)
(VertexTexture) = (vt)+(
Float)+(Float)
(VertexNormal) = (vn)+(
Float)+(Float)+(Float)
(Face) = (f)+{(VertexOfFace)}
(VertexOfFace) = (Integer)+[(/)+[(
Integer)]+[(/)+[(Integer)]]]

A szögletes zárójel [] az opcionalitás jele, azaz a benne foglalt fogalom egyszer vagy egyszer sem jelenik meg. A teljes OBJ formátum nagyon komplex, sok olyan eszköz van benne, ami egy „egyszerű” objektum modellezéséhez feleslegesnek mondható. Ezért az itt bemutatásra kerülő példaalkalmazás csak egy olyan minimális, OBJ fájlokkal szembeni támogatást fog nyújtani, mely egy szimpla objektum megjelenítéséhez elegendő.

A Material Template Library (MTL)

Az OBJ formátum a 3D színtérben elhelyezkedő objektumok geometriáját írja le csupán. Ezen felül szükség van még az anyagjellemzőkre is a képszintézis során. A különböző anyagokat (felületeket) a fizikai tulajdonságaikkal írjuk le. Ilyen tulajdonság például a fényáteresztő képesség, fényvisszaverő képesség, törésmutató, szín stb. Ezeket a tulajdonságokat az MTL fájlformátum tartalmazza, ami hasonlóan az OBJ formátumhoz ugyancsak szöveges. Az OBJ fájl tartalmazza a hivatkozást a megfelelő MTL fájlra:

mtllib filename.mtl

Az mtllib jelzi az MTL fájlt, majd a fájlnév következik a kiterjesztéssel. Ugye milyen egyszerű? Most nézzünk meg egy egyszerű MTL fájl felépítését:

# define a material named 'Colored' newmtl Colored

A newmtl kulcsszó egy új anyagot definiál, aminek a neve „Colored

Ka 1.000 1.000 1.000 # fehér (white)

A Ka kulcsszó az anyag ambient – a környezettől független színét írja le. Az ambient tulajdonság úgy viselkedik mint a foszforeszkálás, tehát ha nem éri fény a testet, akkor is ilyen lesz a színe.

Ambient szín
Fontos megjegyeznem, hogy az ambient tulajdonság nem fényforrás, tehát attól, hogy egy testnek ambient színe van, nem fogja megvilágítani a mellette álló másik testet. Az értékét RGB-ben adjuk meg, a szokott módon.

Kd 1.000 1.000 1.000 # fehér (white)

A Kd kulcsszó az anyag diffúz (szórt) – alap színét írja le. Ez a legegyszerűbb, lényegében egy test színét határozza meg. Pontosítva a dolgot, azt mondhatjuk, hogy a diffúz tulajdonság határozza meg, hogy a felület, a rá eső fény mely komponenseit nyeli el.

Diffúz szín
Ahol nem éri fény a testet, ott nem fog érvényesülni diffúz hatása, ott tehát fekete lesz a test (árnyék). A diffúz értékét RGB -ben kell megadni.

Ks 0.000 0.000 0.000 # fekete (black (off-kikapcsolva))
Ns 10.000 # értéke 0 és 1000 között

A Ks kulcsszó az anyag spekulár színét határozza meg, ami nem má, mint tükröződés. Ha 1 1 1 -es értéket adunk neki, akkor tökéletes tükörként viselkedik (vagyis minden fényt visszaver, ami rá esik), ha 0 0 0 az értéke, akkor pedig egyáltalán nem tükröződik. Az RGB értékekkel játszva lehet színes tükröt csinálni egy felületből. A képen balról jobbra a következő értékeket adtuk meg a specular-nak:
(0 0 0), (0.33 0.33 0.33), (0.66 0.66 0.66), (1 1 1)

Spekulár szín
A felületek általában nem csak tükörszerűen viselkednek, hanem van "saját fényük", "csillogásuk" is. Az Ns kulcsszó ezt hivatott ábrázolni. A spekuláris fénysávok élességét határozza meg (minél nagyobb, annál élesebb).

Ragyogás
A Ka, Kd, Ks komponensek mellet van egy negyedik is, mégpedig a Ke vagyis az emissive összetevő. Ez egy olyan komponens, mely az előbbi háromhoz adódik hozzá, a felület világosabb lesz általa, mintha saját maga bocsátaná ki a saját fényét.
A tükröződő felületek után, a leginkább kedveltek az átlátszó anyagok (üveg, víz stb.). Egy felület átlátszóságát a transparent szabályozza. Szintén RGB értékekkel adjuk meg, hogy melyik színt mennyire engedje át a felület. Kulcsszava Tf (Transmission Filter).
A Ka, Kd, Ks, Ke komponensekkel meghatározott anyag átlátszóságát a d vagy Tr kulcsszóval is állíthatjuk, ami után meg kell adni az átlátszóság mértékét (0 nem látszik, 1 teljesen látszik):

d 0.9 # some implementations use 'd'
Tr 0.9 # others use 'Tr'


Az MTL fájlok definiálják az illuminációs modellt is az illum kulcsszóval. A kulcsszó után következő szám egy azonosító (enum), ami a használandó modellt határozza meg. Az illuminációs modellek listája:

  • 0. Color on and Ambient off
  • 1. Color on and Ambient on
  • 2. Highlight on
  • 3. Reflection on and Ray trace on
  • 4. Transparency: Glass on, Reflection: Ray trace on
  • 5. Reflection: Fresnel on and Ray trace on
  • 6. Transparency: Refraction on, Reflection: Fresnel off and Ray trace on
  • 7. Transparency: Refraction on, Reflection: Fresnel on and Ray trace on
  • 8. Reflection on and Ray trace off
  • 9. Transparency: Glass on, Reflection: Ray trace off
  • 10. Casts shadows onto invisible surfaces
Az illum 2 a fenti listán a második modellt definiálja, bővebben itt.
A komponensek mellet, textúra térképeket is definiál az MTL fájl. A map_x kulcsszó jelzi a textúra térképet, majd a fájlnév következik. Az x a map kulcsszóban a textúra fajtájára utal, így beszélhetünk ambient, diffuse, specular, alpha és akár bump mappekről.

Mindegyik textúra térképnek meg van a maga szerepe a képszintézis során. Láthatjuk, hogy az MTL fájl felépítése nagyon egyszerű és könnyedén értelmezhető.

 

Gyakorlati megvalósítás

A fenti elméleti okoskodás után jöjjön a gyakorlat. Ami most nagyon rövid lesz mivel semmilyen új OpenGL funkcióval nem szükséges megismerkednünk, csupán a fenti szövegfájlok beolvasása és értelmezése a feladatunk. Sőt, akár DirectX-el is megjeleníthetnénk a modelleket, vagyis a grafikus API tetszőleges. Mivel a C# kód könnyedén értelmezhető nem tartom fontosnak részletezni a fájl beolvasását. A példaalkalmazás elérhető itt:


A program futtatása ezt eredményezi:

3D modell a színtérben
Hát nem remek? És ez még csak a kezdet, remélhetőleg egyszer elérünk az animált modellekig... Ha valakinek valami nem teljesen világos, akkor csak arra tudom biztatni, hogy kérdezzen, hiszen kommentelni nem szégyen! :)

Felhasznált irodalom

  1. Raytracer.hu: Felületek és anyagok
  2. Wikipedia: Wavefront .obj file
  3. MTL material format (Lightwave, OBJ)
  4. Szirmay-Kalos László, Antal György, Csonka Ferenc: Háromdimenziós grafika, animáció és játékfejlesztés, ComputerBooks, Budapest, 2003

0 megjegyzés :

Megjegyzés küldése