[Vissza a CD főoldalra]
Példaprogramok
A könyv egyes fejezetei végén C++ nyelvű programrészletek mutatják be,
hogy az elmélet hogyan alkalmazható a gyakorlatban. A programok teljes
változatban a CD-n megtalálhatók.
A példaprogramok fordítása
A programokat Borland C++ és Microsoft C++ fordítóprogrammal fordítottuk
le. A fordítás során "nagy" memóriamodellt illetve WIN32 módot kell választani.
A fordítóprogram kapcsolóinak és a
defines.h fájl
WINDOWS konstansának a megfelelő beállításával MS-Windows és DOS környezetben
futtatható programokat hozhatunk létre.
A programok közös kerete
A programok közös grafikus keretrendszert használnak, amely a következő
fájlokból áll.
-
defines.h: fordítási paraméter fájl. Ebben
a fájlban leírhatjuk, hogy a következő fordítás során DOS vagy MS-Windows
alkalmazást kívánunk-e a készíteni (WINDOWS), a könyvtár logikai vagy fizikai
eszközkoordinátákkal dolgozzon-e (LOGCOORD), foglaljunk-e memóriát a z-buffernek
(ZBUFFER), és hogy mekkora legyen a grafikus terület maximális mérete (XRES,
YRES). Előfordulhat, hogy a lefordított program a z-buffer lefoglalása
során "Dinamikus memória elfogyott'' hibaüzenettel rögtön az indítás után
leáll. Ezen úgy segíthetünk, hogy vagy teljes egészében kikapcsoljuk a
z-buffer memóriát (a 2D programok és a sugárkövetés úgy sem használják),
vagy pedig csökkentjük a grafikus terület méretét.
-
types.h: általános típus fájl. Ez a fájl a
beállított környezet alapján elhelyezi a megfelelő include direktívákat
(MS Windows esetén a windows.h-t, DOS esetén a graphics.h-t) és definiálja
a környezetfüggetlen elérés típusait (Coord, RGBColor).
-
tga.h: a generikus, nyújtózkódó tömb sablon (Array)
definíciós fájlja.
-
menu.h: egyszerűsített menükezelés fájlja.
-
zbuffer.h: a z-buffer osztály fájlja.
-
draw.h: a fizikai szintű kezelés deklarációs fájlja.
Itt a fizikai szintű elérés típusait (PCoord, PColor, ROP, PVertex)
és függvényeinek a prototípusát adjuk meg.
-
draw.cpp: a fizikai szintű rajzolás fájlja. A PLine
rutinban a szakaszrajzoláshoz a Bresenham algoritmust implementáltuk. A
3D háromszögek árnyalt megjelenítését a PFacet eljárás végzi el,
amely a takarási viszonyokat z-buffer algoritmussal határozza meg, a színt
pedig Gouraud árnyalással interpolálja.
-
objwin.h: az objektum-orientált, logikai szintű
eszközkezelő deklarációs fájlja. Itt található a Window osztály,
ami a grafikus kimenetet eszközfüggetlen módon illeszti és eseményvezérelt
felhasználói kommunikációt valósít meg.
-
window.cpp: az objektum-orientált eszközkezelő
implementációs fájlja. A Window osztály tagfüggvényein kívül, itt írtuk
le azokat a beviteli eszközöket illesztő rutinokat és fizikai szintű kiviteli
eljárásokat (Pixel, PReadPixel, PClear) is, amelyek függnek a futási
környezettől (jelen esetben MS-Windows vagy DOS/BGI). Ez azt jelenti, hogy
ha az olvasó más környezetekre is szeretné használni a megadott programokat,
csak ezt a fájlt kell kiegészítenie.
-
tga.h: TARGA fájlkezelő osztályok definíciója. A TARGA
formátum kezelését két osztály támogatja. A TGAOutputFile egy TARGA
fájlt készít el, aTGAInputFile pedig egy TARGA fájlt olvas be. Ezen
osztályokat használjuk a képek mentéséhez és betöltéséhez.
-
color.h: színkezelés deklarációs fájlja. Ebben a
fájlban található a Spectrum generikus osztály és a Color szín osztály
definíciója.
TARGA formátumú képek megjelenítése: tgashow.exe
Figyelem: ha a program az indítása után egy üres képet tölt be,
akkor nem találta meg a képfájlt (image.tga). Ekkor állítsa az internet
böngésző "kezdet" tulajdonságát a CD gyökerére! Ez úgy ellenőrizhető, hogy
a fájl megnyitás a gyökérkönyvtárból indul.
A tgashow példaprogram TARGA típusú képfájlokat jelenít meg. A programot
a 1.7 fejezetben tárgyaltuk. A képfájl nevét parancssor argumentumként
kell megadni. A megjelenített képet medián szűrő és doboz szűrő algoritmusokkal
módosíthatjuk, majd az eredményt eltárolhatjuk.
A programmal előállított képek:
Egy zajos kép |
mediánszűrés után |
dobozszűrés után |
Az alkalmazás belépési pontját, az ablakobjektumát és a szűrőalgoritmusokat
a tgashow.cpp fájl tartalmazza. A programhoz,
az általános keretfájlokon kívül a tga.h fájl
tartozik, amelyben a TARGA fájlkezelő osztályok definíciója található.
A TARGA formátum kezelését két osztály támogatja. A TGAOutputFile egy TARGA
fájlt készít el, aTARGAInputFile pedig egy TARGA fájlt olvas be. Ezen osztályokat
használjuk a képek mentéséhez és betöltéséhez.
Gumivonal rajzoló program: gumi.exe
Ez a program a 2.3.4 fejezetben tárgyalt gumivonal rajzoló implementációja,
amely az eseményvezérelt programozás fogásait mutatja be. A teljes program
a gumi.cpp fájlban olvasható, amelyet a keretrendszerhez
kell hozzászerkeszteni.
Színszerkesztő: color.exe
A színszerkesztő program a 4.3 fejezet színkezelő osztályait és algoritmusait
használja fel. A program segítségével a grafikus terület háttérszínét változtathatjuk
RGB, CMY, HLS színrendszerben illetve monokromatikus spektrum hullámhosszának
a módosításával.
Az interaktív kezelői felületet a colgen.cpp fájl valósítja meg, amely
épít a color.h színosztályaira és a color.cpp-ben
implementált színkonverziós és a színillesztő algoritmusokra. Ezekben a
fájlokban található a Spectrum generikus osztály és a Color
szín osztály definíciója, és a Color osztály színkonverziós rutinjai és
a színillesztő függvényei.
2D grafikus rendszer: 2d.exe
Ez az alkalmazás egy teljes 2D grafikus rendszert mutat be. A program
lényeges elemeit a 7. fejezetben ismertettük. A program segítségével interaktív
módon törtvonalakat, Bezier görbéket és Lagrange görbéket definiálhatunk.
A korábban definiált görbéket az egér kurzor és a bal egérgomb segítségével
kiválaszthatjuk. A bal egérgomb lenyomásával majd a lenyomott gombbal az
egér mozgatásával a kiválasztott görbét áthelyezhetjük. A kiválasztott
objektumokat XOR módban rajzoljuk, az áthelyezés hasonló a gumivonal technikához.
A program tartalmazza a görbék modellezéséhez szükséges adatszerkezeteket
és algoritmusokat. A megjelenítéshez a teljes 2D grafikus csővezetéket
implementáltuk, amely vektorizálja a görbéket, alkalmazza a modellezési
és nézeti transzformációkat, Cohen-Sutherland algoritmussal elvégzi a vágást,
majd Bresenham algoritmussal raszterizálja a kapott szakaszokat.
A 2d.cpp a virtuális világot és a kamerát összefogó
színteret (Scene), a színtér módosításához és megjelenítéséhez szükséges
függvényeket, azaz a bemeneti és a kimeneti csővezeték algoritmusait, és
a felhasználói interakció eljárásait adja meg.
A további programfájlok:
-
2d.h: 2D geometria. Itt írtuk le az euklideszi pont
(Point2D), a projektív pont (HomPoint2D), a téglalap (RectAngle),
és a geometriai transzformációk (Transform2D) osztályait.
-
polynom.h: paraméteres görbék polinomjai. A
Lagrange interpolációhoz és Bezier approximációhoz szükséges
polinomok szerepelnek ebben a fájlban.
-
world2.h: a 2D virtuális világ objektumtípusai.
Ez a fájl írja le a 2D virtuális modellek szerkezetét.
-
world2.cpp: a 2D virtuális világ vektorizációja.
A fájlban található tagfüggvények a 2D virtuális világ objektumaihoz tartozó
vektorizációs algoritmusokat implementálják.
-
camera2.h: 2D kamera. Az ablakból és a nézetből
álló 2D kameraosztályt találhatjuk meg itt, amely a 2D nézeti transzformáció
előállításáért felelős.
-
pipe2.h: 2D kimeneti csővezeték típusai. A fájl a
2D kimeneti csővezetéken átvihető objektumtípusokat (pont, szakasz, téglalap,
szakaszlista) adja meg, és leírja a transzformációjukat.
-
pipe2.cpp: 2D kimeneti csővezeték eljárásai. Itt
lelhetjük fel a 2D kimeneti csővezeték eljárásait, mint például a Cohen-Sutherland
szakasz vágás algoritmusát.
A kimeneti csővezeték végén megjelenő szakaszokat a keret draw.cpp
fájljában implementált a Bresenham algoritmus raszterizálja, a pixel műveleteket
pedig a window.cpp fájlban valósítottuk meg.
3D grafikus rendszer inkrementális képszintézissel: 3d.exe
A programmal előállított képek:
Tömör megjelenítés |
huzalváz megjelenítés |
Ez az alkalmazás egy teljes 3D grafikus képszintézis rendszert mutat be,
amely z-buffer takarási algoritmust és Gouraud-árnyalást alkalmaz.
A 3D.cpp fájl a virtuális világot és a kamerát
összefogó színteret (Scene), a kimeneti csővezetéket működtető függvényt
(Render), és a felhasználói interakció eljárásait adja meg. A virtuális
világot a sphere fájlban építjük fel.
A további fájlok:
-
3d.h: 3D geometria. Ez a 3D euklideszi és projektív
pont és a 3D homogén lineáris geometriai transzformációk definíciós fájlja.
-
world3.h: a 3D virtuális világ objektumtípusai.
A fájl a 3D virtuális világ objektumait definiálja. A virtuális világ transzformálható
objektumokból áll, amelyek primitívekből épülnek fel. Egy primitív képviselhet
egy gömböt (Sphere), háromszögekkel közelített (PolyFace3D) felületet,
törtvonalat (PolyLine3D) vagy különböző súlyfüggvényeket használó paraméteres
görbéket (Curve3D).
-
world3.cpp: a 3D virtuális világ vektorizációja
és tesszellációja. Itt adtuk meg a 3D virtuális világ objektumaihoz tartozó
vektorizációs és tesszellációs algoritmusokat. A képszintézis első lépéseként
az általános primitíveket pontokkal, szakaszokkal és háromszögekkel közelítjük.
A szakaszokkal történő közelítést vektorizációnak, a háromszögekkel történő
közelítést pedig tesszellációnak nevezzük. Görbéket nyilván csak vektorizálni
lehet, a felületeket viszont tetszés szerint vektorizálhatjuk vagy tesszellálhatjuk.
Az első esetben huzalváz megjelenítéshez, a másodikban pedig tömör megjelenítéshez
jutunk.
-
camera3.h: 3D kamera deklarációja. A fájl a 3D
virtuális világ leképzéséhez szükséges kamerát definiálja, amely a nézeti
transzformáció előállításáért felelős.
-
camera3.cpp: 3D nézeti transzformáció előállítása.
A fájlban 3D nézeti transzformációt kiszámító CalcTransf tagfüggvényt implementáltuk
mind párhuzamos, mind pedig perspektív vetítés esetén.
-
pipe3.h: 3D kimeneti csővezeték objektumtípusai.
A 3D kimeneti csővezetéken átvihető objektumokat a RenderPrimitive3D osztályból
származtathatjuk. Az ilyen objektumok konkrét típusai a pont (Marker3D),
a szakasz (Line3D), a szakaszlista (LineList3D) és a háromszöglista (TriangleList3D).
Az objektumok pontjait (Transform) és normálvektorait (TransformNormals)
transzformálhatjuk, és homogén osztással előállíthatjuk a transzformált
pontok Descartes koordinátáit (HomDivPoints). A vágási műveleteket két
lépésben hajthatjuk végre. A DepthClip homogén koordinátákban az első és
hátsó vágósíkra vág, a Clip pedig Descartes koordinátákban nézet téglalapjára.
Az Illuminate tagfüggvény a normálvektorok alapján az egyes pontokban látható
radianciát számítja ki, a Draw pedig raszterizálja a primitíveket.
-
pipe3.cpp: a 3D csővezeték eljárásai. A 2D kimeneti
csővezeték eljárásait találhatjuk itt meg, mint például a Cohen-Sutherland
szakasz vágás homogén koordinátákra és 3D térre általánosított algoritmusát,
és a brdf.h-ban megfogalmazott BRDF modellekre építő illuminációs algoritmust.
-
brdf.h: BRDF modellek. A felületek optikai tulajdonságait
a BRDF modellekkel írjuk le. Egy felület lehet fénykibocsátó (Emitter)
és a környezetéből ide érkező fényt is visszaverheti illetve törheti. Az
visszaverődés lehet diffúz (DiffuseMaterial), spekuláris (SpecularMaterial)
vagy ideális (IdealReflector). A fénytörésnél csak az ideális esetet modellezzük
(IdealRefractor). Ebből az inkrementális képszintézisben a
DiffuseSpecularMaterial
osztályt
használjuk. A brdf.h fájlban az SColor típus megadásánál két lehetőség
közül választhatunk. Mivel a sugárkövető program mindenütt az SColor típust
használja, a brdf.h-ban szereplő RGBCOL konstans értékével szabályozhatjuk,
hogy a spektrumot csak a vörös, zöld és kék színek hullámhosszain számítjuk
vagy több hullámhosszon követjük a fény terjedését a térben.
A kimeneti csővezeték végén megjelenő szakaszokat a keret draw.cpp
fájljában implementált Bresenham algoritmus raszterizálja, a 3D
háromszögeket (facet) pedig z-buffer takarási módszert és Gouraud
árnyalási eljárást megvalósító függvény alakítja át pixelekké (PFacet).
Ezen műveletek kódolása során a nagysebességű, célszerűen gépi kódú implementáció,
illetve a hardver támogatás lehetőségének a bemutatása érdekében csakegész
műveleteket használtunk.
Sugárkövetés: ray.exe
A programmal előállított képek:
lokális illumináció |
lokális illumináció árnyékszámítással |
rekurzív sugárkövetés |
globális illumináció inverz fényútkövetéssel |
Ez a példa több alapvető módszert demonstrál, a nem-rekurzív és a rekurzív
sugárkövetést, a sugárkövetés kiegészítését a sztochasztikus mintavételezés
és az utószűrés kombinálását alkalmazó csipkézettség csökkentéssel, és
egy inverz fénykövetés elvű Monte-Carlo globális illuminációs algoritmust.
A felületek optikai tulajdonságainál textúra leképzést is beállíthatunk.
A sugárkövető algoritmusok a ray.cpp fájlban találhatók.
A virtuális világot a tsphere fájlban építjük fel.
Az alkalmazás még az alábbi fájlokból építkezik:
-
3d.h: 3D geometria. Ez a 3D euklideszi és projektív
pont és a 3D homogén lineáris geometriai transzformációk definíciós fájlja.
-
camera3.h: 3D kamera deklarációja. A fájl a 3D
virtuális világ leképzéséhez szükséges kamerát definiálja, amely a nézeti
transzformáció előállításáért felelős.
-
camera3.cpp: 3D nézeti transzformáció előállítása.
A fájlban 3D nézeti transzformációt kiszámító CalcTransf tagfüggvényt implementáltuk
mind párhuzamos, mind pedig perspektív vetítés esetén.
-
brdf.h: BRDF modellek. A felületek optikai tulajdonságait
a BRDF modellekkel írjuk le. Egy felület lehet fénykibocsátó (Emitter)
és a környezetéből ide érkező fényt is visszaverheti illetve törheti. Az
visszaverődés lehet diffúz (DiffuseMaterial), spekuláris (SpecularMaterial)
vagy ideális (IdealReflector). A fénytörésnél csak az ideális esetet modellezzük
(IdealRefractor). Ebből az inkrementális képszintézisben a DiffuseSpecularMaterial
osztályt használjuk, a sugárkövetés pedig mindet. A FresnelFunction fémekre
a visszaverődési tényezőt számítja ki. A GeneralMaterial a különböző visszaverődési
és törési típusokat egyesíti. Egy BRDF modellnek alapvetően két funkciója
van. Egyrészt megmondja, hogy adott megvilágítás és nézőpont esetén milyen
intenzitású fényt kap a megfigyelő. Másrészt, egy belépő irány birtokában
a BRDF és a kilépő szög koszinuszának szorzatának arányában egy véletlen
kilépő irányt generál. Ebből a két funkcióból az elsőre minden algoritmusnak
szüksége van, a másodikat viszont csak a Monte-Carlo módszerek használják.
A brdf.h fájlban az SColor típus megadásánál két lehetőség közül választhatunk.
Mivel a sugárkövető program mindenütt az SColor típust használja, a brdf.h-ban
szereplő RGBCOL konstans értékével szabályozhatjuk, hogy a spektrumot csak
a vörös, zöld és kék színek hullámhosszain számítjuk vagy több hullámhosszon
követjük a fény terjedését a térben.
-
brdf.cpp: fémek törésmutatói. A fájlban a fémekhez
szükséges törésmutató táblázatokat találhatjuk meg, amelyeket a Fresnel
együtthatók számításához használunk. Itt definiáljuk az alacsony diszkrepanciájú
sorozatot jelképező objektum egy példányát is.
-
uniform.h: véletlen és alacsony-diszkrepanciájú
sorozatok.
Térfogat-vizualizáció masírozó kockák algoritmussal:
march.exe
Figyelem: ha a program az indítása után csak egy fekete hátteret
hajlandó rajzolni, akkor nem
találta meg a voxeltömb fájlt (head64.vox). Ekkor állítsa
az internet böngésző "kezdet" tulajdonságát a CD gyökerére! Ez úgy ellenőrizhető,
hogy a fájl megnyitás a gyökérkönyvtárból indul.
A programmal előállított képek:
head128.vox fájl megjelenítése
110-es szintértékkel |
head128.vox fájl megjelenítése
60-as szintértékkel |
Ez az alkalmazás egy voxeltömböt tölt be a parancssor argumentumával
megnevezett fájlból, majd az interaktívan változtatható érték felhasználásával
a masírozó kockák algoritmussal szintfelületet generál, amit az inkrementális
3D képszintézis rendszer kimeneti csővezetékén jelenít meg. A térfogatmodellt
leíró fájl bináris. A fájl egy egész számmal kezdődik, amely meghatározza
a voxeltömb felbontását. A méret mezőt követő bájtsorozat pedig az egyes
voxelek sűrűségértékeit adja meg. Ha például az első szóban 128-t találunk,
a fájl még ezen kívül 128 x 128 x 128 bájtot tartalmaz.
A CD-n jelenleg ugyanazon modell három különböző felbontású változata
található:
-
head32.vox: 32x32x32-es fej
-
head64.vox: 64x64x64-es fej
-
head128.vox: 128x128x128-as fej
A masírozó kockák algoritmus és a kezelői felület a march.cpp
fájlban található. Az algoritmus a polytab.h-ban
lévő konfiguációk alapján ismeri fel a lehetséges felület-voxel metszési
típusokat.
Az alkalmazás ezen kívül felhasználja az általános keretrendszert és
a következő fájlokat:
-
3d.h: 3D geometria. Ez a 3D euklideszi és projektív
pont és a 3D homogén lineáris geometriai transzformációk definíciós fájlja.
-
camera3.h: 3D kamera deklarációja. A fájl a 3D
virtuális világ leképzéséhez szükséges kamerát definiálja, amely a nézeti
transzformáció előállításáért felelős.
-
camera3.cpp: 3D nézeti transzformáció előállítása.
A fájlban 3D nézeti transzformációt kiszámító CalcTransf tagfüggvényt implementáltuk
mind párhuzamos, mind pedig perspektív vetítés esetén.
-
pipe3.h: 3D kimeneti csővezeték objektumtípusai.
A 3D kimeneti csővezetéken átvihető objektumokat a RenderPrimitive3D osztályból
származtathatjuk. Az ilyen objektumok konkrét típusai a pont (Marker3D),
a szakasz (Line3D), a szakaszlista (LineList3D) és a háromszöglista (TriangleList3D).
Az objektumok pontjait (Transform) és normálvektorait (TransformNormals)
transzformálhatjuk, és homogén osztással előállíthatjuk a transzformált
pontok Descartes koordinátáit (HomDivPoints). A vágási műveleteket két
lépésben hajthatjuk végre. A DepthClip homogén koordinátákban az első és
hátsó vágósíkra vág, a Clip pedig Descartes koordinátákban nézet téglalapjára.
Az Illuminate tagfüggvény a normálvektorok alapján az egyes pontokban látható
radianciát számítja ki, a Draw pedig raszterizálja a primitíveket.
-
pipe3.cpp: a 3D csővezeték eljárásai. A 2D kimeneti
csővezeték eljárásait találhatjuk itt meg, mint például a Cohen-Sutherland
szakasz vágás homogén koordinátákra és 3D térre általánosított algoritmusát,
és a brdf.h-ban megfogalmazott BRDF modellekre építő illuminációs algoritmust.
-
brdf.h: BRDF modellek. A felületek optikai tulajdonságait
a BRDF modellekkel írjuk le. Egy felület lehet fénykibocsátó (Emitter)
és a környezetéből ide érkező fényt is visszaverheti illetve törheti. Az
visszaverődés lehet diffúz (DiffuseMaterial), spekuláris (SpecularMaterial)
vagy ideális (IdealReflector). A fénytörésnél csak az ideális esetet modellezzük
(IdealRefractor). Ebből az inkrementális képszintézisben a
DiffuseSpecularMaterial
osztályt
használjuk.
IFS megjelenítő: ifs.exe
Figyelem: ha a program az indítása után csak egy fekete hátteret
hajlandó rajzolni, akkor nem
találta meg az IFS definíciós fájlt (ifscode). Ekkor állítsa
az internet böngésző "kezdet" tulajdonságát a CD gyökerére! Ez úgy ellenőrizhető,
hogy a fájl megnyitás a gyökérkönyvtárból indul.
A programmal előállított képek:
pafrany2 képe |
sierpien: 2D Sierpienski halmaz képe |
Ez az alkalmazás az ifscode fájlból illetve a
parancssorban megadott nevű fájlból egy IFS-t olvas be és azt véletlen
bolyongással megjeleníti.
Egy IFS fálj szerkezete (a kulcsszavakat kiemeltük):
v ablak_bal ablak_alsó ablak_jobb
ablak_felső // az ablak paraméterei
w a1 b1 c1 d1 px1 py1
// az első affin leképzés
p valószínűség1
// az első leképzés valószínűsége
w a2 b2 c2 d2 px2 py2
// az második affin leképzés
p valószínűség2
// az második leképzés valószínűsége
...
A CD-n jelenleg a következő IFS fájlok találhatók:
-
ifscode vagy pafrany1: egy
kevésbé hajlott páfrány
-
pafrany2: elősen hajlott páfrány
-
sierpien: 2D Sierpienski halmaz
Az IFS megjelenítő és a kezelői felület az ifs.cpp
fájlban található. Az alkalmazás ezen kívül az alábbi fájlokat használja
fel:
-
2d.h: 2D geometria. Itt írtuk le az euklideszi pont
(Point2D), a projektív pont (HomPoint2D), a téglalap (RectAngle),
és a geometriai transzformációk (Transform2D) osztályait.
-
camera2.h: 2D kamera. Az ablakból és a nézetből
álló 2D kameraosztályt találhatjuk meg itt, amely a 2D nézeti transzformáció
előállításáért felelős.
[Vissza a CD főoldalra]
|