Post on 19-Jul-2015
OpenGL jtkfejleszts
Ksztette:
Kurta Istvn
Cskszereda, 20071
TartalomjegyzkBevezets.................................................................................................................... 5 ltalnos lersok s jellemzk ................................................................................. 6A jtkok ltalnos felptse ...................................................................................................... 6 Felhasznlt fejlesztsi eszkzk .................................................................................................. 7 A jtk konfigurcis prbeszdablaka ....................................................................................... 9 A jtk irnytsa s jellemzi ................................................................................................... 10
Jtk implementcija .............................................................................................. 11OpenGL megjelents Win32 alkalmazs ltrehozsa ............................................................. 11 Modellezsi transzformcik, nzpont s nzsi irny belltsa ............................................ 19 A replgpmodell betltse s megjelentse .......................................................................... 21 Idzts s teljestmny mrs ................................................................................................... 23 Textrzs OpenGL rendszerben ............................................................................................... 23 OpenGL bvtmnyek ................................................................................................................ 26 Plyamodell betltse s megjelentse ..................................................................................... 27 Szvegmegjelents.................................................................................................................... 28 Hangok lejtszsa s vezrlse .................................................................................................. 30 Hlzat hasznlata ..................................................................................................................... 32
Knyvszet ............................................................................................................... 35
2
BevezetsAz interaktv szrakoztats jelentsen megntt az elmlt vtizedben. Szmtgpes jtkok, amely egy kis piacnak indult, egy tbb milli dollros ipargg ntte ki magt. Az elmlt pr v egy gyorsan fejld irnyzatot mutat, amelynek a vge mg nincs lthatron. Az interaktv szrakoztat ipar egy robbankony piac, amely a legjabb szmtgpes technolgikat maximlisan kihasznlja s segt a mestersges intelligencia s grafika tern j fejlesztseket ltrehozni. Attl, hogy jtkiparban dolgozunk s sok olyan emberrel beszlnnk akik ugyanebben a szakmban dolgoznak, egy dolog hajtja az embereket, hogy tanuljanak s sikereket rjenek el a jtkfejleszts tern: a szrakozs. A jtkok az egyik legismertebb formi a szoftver fejlesztsnek, s a lenygz jtkok, amelyeket kiadtak az elmlt vekben, ennek a bizonyti. Jtkok, mint Halo a Bungie Softwaretl, a jtkksztst olyan szintre emeltk, amely utn az ipar soha nem lesz mr ugyanaz., mint rgen. A jtkfejlesztket az a gondolat hajtja ebben az iparban, hogy olyan egyni virtulis vilgokat alkossanak, amelyet majd ezrek, ha nem millik fognak egy nap tapasztalni. A jtkfejleszt arra trekszik, hogy j kihvsokkal nzzen szembe, j technolgikat s vilgokat fedezzen fel. Br sok vllalat hozzjrult a 3D jtkok fejldshez, egy specilis emltst kell tenni az idSoftware-rl, amely nagy gyorstja volt a 3D jtkok emelkedsben. Tbb, mint 10 ve, John Carmack, s vllalata egy kis jtkot mutatott be a vilgnak Wolfenstein 3D nven. Wolf3D a jtk vilgot trdre knyszertette a valsidej 3D sugrkvet grafikjval s egy olyan vilggal, amely hatsra a jtkosok tbb rn keresztl a szmtgp eltt jtszottak. A jtk egy j kezdet volt az ipar szmra, s soha nem nzett vissza. 1993-ban, a Doom vilga uralkodott, s a 3D technolgit egy lpssel tovbbfejlesztette a 2.5D-s jtkmotorral. A jtkvilg nnepelt az idSoftware ltal behozott technikai jtsoktl, amelyek a Doom-ban voltak fellelhetek, de a fejlds nem llt meg itt. Egy pr vvel ksbb, Quake megvltoztatta vglegesen a 3D jtkokat. A lehetsgeket most mr csak az korltozta, hogy hny poligont kpes a CPU (s alkalomszeren a GPU) a kpernyn megjelenteni. A Quake kiadsa ta, az ipar szinte minden hnapban jabb technolgiai fejlesztsekkel gyarapodik. A 3D jtkok fejldse rvn ltrejttek a 3D gyorst krtyk, amelyek a 3D matematikai szmtsokat a sajt processzorkban vgzik el. Most minden hatodik hnapban j hardvert adnak ki, amely ktszer akkora teljestmnnyel (nyers er, gyorsasg s rugalmassg) br, mint az eldje. Ez a dolgozat a kezd jtkfejlesztknek szeretne segtsget nyjtani, hogy knnyedn megtanulhassk az alapvet technikkat s lpseket jtkprogramok ksztshez egy egyszer jtkprogram fejlesztsnek lpsenknti bemutatsa sorn, amely egy egyser replgp szimultor. Minden egyes lps fejezetenknt van trgyalva, esetenknt forrskd rszletekkel s hivatkozsokkal, hogy az adott rsz, amelyrl ppen sz van, mely forrskdban van implementlva. A dolgozat legelejn bemutatsra kerlnek a felhasznlt programok s fejlesztsi krnyezetek s rvid lers arrl, hogy mikbl is ll egy jtkprogram s kiknek a munkjra van szksg. A dolgozat leginkbb az OpenGL grafikus rendszerrl fog szlni, s annak hasznlatrl, majd sz lesz arrl is hogyan lehet hangokat hozzilleszteni a jtkunkhoz az OpenAL hangrendszer segtsgvel, majd a legvgn rviden bemutatjuk azt is, hogy hogyan kszthetnk hlzatos jtkot az addig elkszlt programunkbl. A dolgozat elksztshez nagyrszt angol forrsanyagok kerltek felhasznlsra, mivel ezekben tallhatak a legrszletesebb lersok az OpenGL-rl s a felhasznlt szoftver fejlesztsi krnyezetekrl. Remlem itten elegend informcit tudok szolgltatni azok szmra akik szeretnk megtanulni az OpenGL grafikus rendszer hasznlatt s a vele kapcsolatos jtkfejlesztsi lpseket. 3
ltalnos lersok s jellemzkA jtkok ltalnos felptseA jtkok a legalacsonyabb szintjkn szoftverek. A mai szoftvereket csoportokban fejlesztik, ahol minden csoporttag a sajt terletn dolgozik amg mindenkinek a programrszei be nem integrldnak, hogy egy egysges, sszefgg programot alkossanak. A jtkokat hasonl mdon fejlesztik, csakhogy a programozs nem az egyetlen szakterlet. Mvszek (festk) szksgesek, hogy kivl kpeket generljanak s gynyr szntereket alkossanak, amelyek elengedhetetlenek a mai jtkokban. Plya szerkesztk keltik letre a virtulis vilgot s felhasznljk a rendelkezskre bocstott mvszi alkotsokat, amelyeket a mvszek ksztettek el. A programozk rakjk ssze az ptelemeket s meggyzdnek arrl, hogy minden mkdik egysgesen. Hang technikusok s zenszek hozzk ltre a szksges hangeffektusokat, hogy a jtkosnak egy gazdag, multimdia, hihet s virtulis lmnyben legyen rsze. A formatervezk jnnek a jtk tervvel, s a producerek irnytjk mindenki munkjt. Mivel mindenki ms szakterleten dolgozik, a jtkot fel kell osztani szmos alkotelemre, amelyeket a vgn sszeraknak. A jtkokat ltalban ezekre a terletekre oszthatk: Grafika Bemenet Zene s hang Jtk logika s mestersges intelligencia Hlzat Felhasznli fellet s menrendszer Ezekbl minden szakterlet mg felbonthat sokkal meghatrozbb rszekre. Pldul a jtk logika llna fizikai effektusokbl s rszecske rendszerbl, grafika lehet 2D s/vagy 3D kpszintzissel. A kvetkez bra egy egyszer jtk felptst brzolja: Mint lthat egy jtk minden eleme szt van vlasztva a sajt alkotrszre s kommunikl a jtk tbbi elemvel. A jtk logika elem a jtk magjnak bizonyul, ahol a
bra 1 Egyszer jtk felptse
4
dntsek hozdnak meg a bemenet s kimenet vezrlsre. A fenti brn lthat architektra elgg egyszer, br a kvetkez brn lthat hogyan nz ki egy komplexebb jtk architektrja.
bra 2 Komplex jtk architektrja
Sokkal komplexebb komponensek fejlesztdnek s hasznldnak fel, ahhoz hogy bizonyos tulajdonsgokat s mkdskszsgeket implementljanak, amelyek szksgesek a jtk szoftver j mkdshez. Mikor jtkot fejlesztnk, akkor egy mtrgyat alkotunk, amelyet oly mdon is kell kezelni. Fel kell legynk kszlve j dolgok kiprblsra s jratervezznk ltez technolgikat, hogy az elvrsainknak megfeleljenek. Nincs egy meghatrozott md a jtkfejlesztsre, ugyangy mint ahogy egy kpnek a festsre sincs egy megadott eljrs. Trekedjnk arra, hogy legynk innovatvak s lltsunk fel j standardokat.
Felhasznlt fejlesztsi eszkzkA jtkprogram Microsoft Visual C++ V6 rendszerben van implementlva, felhasznlva a kvetkez rendszereket: 1. OpenGL: Az OpenGL egy szoftver interfsz a grafikus hardverhez. Ez a szoftver interfsz pr szz eljrsbl s fggvnybl ll, amelyek lehetv teszik 2 s 3 dimenzis grafikai objektumok ltrehozst, s ezeken az objektumokon mveletek elvgzst. Az OpenGL teht egy eljrs- s fggvnygyjtemny, amelyek 2 s 3 dimenzis objektumok specifikcijt tartalmazzk ezenkvl olyan eszkzket is nyjt, melyekkel szablyozni lehet ezen objektumok lekpezst a kppufferbe, amelyben az OpenGL az eredmnyknt ltrejv kpet trolja. Ennek megjelentse mr az opercis rendszer, vagy az ahhoz tartoz ablakoz rendszer feladata. Az OpenGL nem tartalmaz ablakoz rendszert, s nem tmogatja a bemeneti eszkzk kezelst sem, teht ezeket a dolgokat az adott nyelven a programoznak kell megoldania. Az OpenGL platformfggetlensgt az adatbeviteli s megjelentsi rendszertl val fggetlensg biztostja. Ugyanezen okok miatt az OpenGL nem tartalmaz olyan parancsokat sem, amelyek magas szint hromdimenzis objektumok specifiklsra szolglnnak, gy ezeket a modelleket geometriai primitvekbl kell felpteni (pontok, vonalak, sokszgek). 2. OpenAL: Az OpenAL egy szoftver interfsz az audio hardverhez. Az interfsz fggvnyek gyjtemnye, amelyek lehetv teszik a programoz szmra, hogy 5
meghatrozza azokat az objektumokat s mveleteket, amelyek szksgesek a magas minsg hang kimenethez, fleg tbbcsatorns kimenetre a 3D trben elhelyezett hangforrsok esetn egy hallgat krl. Az OpenAL platform fggetlen s knnyen hasznlhat. Az OpenGL-hez hasonl programozsi stlust, szintaxist s konvencikat alkalmaz. A programoz szempontjbl, OpenAL utastsok gyjtemnye, amelyek lehetv teszik a hang forrsok megadst s a hallgatt a hrom dimenzis trben, kombinlva olyan utastsokkal, amelyek irnytjk a hangforrsok megjelentst a kimeneti pufferbe. Az OpenAL parancsok hatsa nem garantlt, hogy azonnali, mivel vrakozsi idk lphetnek fel az implementcitl fggen, de idelis esetben ez a kss nem rzkelhet a felhasznl ltal. Egy tipikus program, amely OpenAL-t hasznl olyan fggvnyhvsokkal kezddik, amelyek megnyitnak egy hang eszkzt, amelyet, a kimenet feldolgozsra s annak a hozzcsatolt hardvern visszajtsszon (hangszrk vagy fejhallgat). Majd, hivatkozsok trtnnek, hogy egy AL kontextust foglaljunk s hozzrendeljk az audio eszkzhz. Amint egy AL kontextus lefoglaldott, a programoz szabadon hasznlhatja az AL utastsokat. Egyes utastsok a forrsok megjelentsre (pont s irnytott forrsok, ciklikus vagy sem) , mg msok a forrsok megjelentst befolysoljk, hogyan halkul el tvolsg vltozsnl s relatv irny esetn. A jtkban tallhat 3D modellek Milkshape 3D modellez program segtsgvel kszltek. Ez egy ingyenesen letlthet program, amelyben nagyon hatkonyan s gyorsan lehet modelleket kszteni. A replgp modell Half-Life modell, amely egy modell fjl s tbb animcis llomny, valamint a textrk kompillsval hozhat ltre mdl kiterjesztssel . A plyamodellek pedig Milkshape 3D modellek, amelyek ms3d kiterjesztssel mentdnek s nem ignyelnek kompillst, azonban a textrkat kell mellkelni.
bra 3 Milkshape 3D modellez program
6
A jtk konfigurcis prbeszdablakaA prbeszdablak a futtathat FlightSimulator.exe llomny vgrehajtsa utn jelenik meg s itten bellthatak a jtk paramterei, mint a felbonts s sznmlysg, kivlaszthat a kvnt textra minsg, milyen felbonts plyt szeretnnk betlteni. A plya felbontsnl 4 lehetsgnk van a megjelentett hromszgek szma alapjn. Minl tbb hromszgbl tevdik ssze a plya, annl tbb erforrsra lesz ignye az OpenGL-nek, hogy megjelentse a plyt. Mg lehetsg van a vilgts diffuse, specular komponensnek ki, illetve be kapcsolsra, valamint a vilgts teljes kikapcsolsra. Erre teljestmny nvels szempontjbl volt szksg, mert bekapcsolt specular vilgtssal sokkal kisebb a frisstsi szm (FPS frames per second). A plyhoz engedlyezhetjk vagy letilthatjuk a kd generlst, ez szintn erforrs ignyes, pldul 1000 hromszg kirajzolsa esetn nem szlelhet annyira az erforrs ignye, mint 32000 hromszg kirajzolsa esetn, amikor a megjelents mr akadozva jelenhet meg a kisebb frisstsi arny miatt. Engedlyezhetjk, vagy letilthatjuk a textra srtst, s az anisotropic szrst. A textra srts hatsra 32 bites mdban nem kvnt torzulsok lesznek
bra 4 Textra srts ki, majd bekapcsolva 16 bites sznmd esetn
szlelhetek, mg textra srts nlkl hibtlanul fognak megjelenni a textrk. A textra srtst viszont 16 bites szn md hasznlata esetn be kell kapcsolni, mert torzulsok lesznek
bra 5 Textra srts ki, majd bekapcsolva 32 bites sznmd esetn
szlelhetek anlkl, teht az ellenkezje trtnik, mint 32 bites sznmd hasznlata esetn. Az anisotropic szrs az lek elsimtsra hasznlatos OpenGL kibvt eljrs, amelyrl bvebben ksbb lesz sz. Majd lehetsgnk van, arra hogy hlzatos jtk mdot indtsunk, aktivlva a Multiplayer jell ngyzetet, ezutn pedig lehetsgnk van arra, hogy kivlasszuk, hogy szerver vagy kliens szerepet fog betlteni az indul program. Ezutn az Okra kattintva elmentdik az aktulis konfigurci a config.fdt elnevezs llomnyba s elindul a jtk, vagy az Exit gombra kattintva ments nlkl bezrul a program. 7
Felbonts, sznmlysg s frissts Textra minsg Vilgts ki/be kapcsolsa Vilgts komponenseinek ki/be kapcsolsa A plya kd effektusnak ki/be kapcsolsa Plya felbonts a (hromszgekben) Textra srts s anisotropic szrs ki/be kapcsolsa Hlzatos jtk md ki/be kapcsolsa Kliens vagy szerver mdban induljon a jtk Szerver IP cme vagy neve
bra 6 Konfigurcis ablak
A konfigurcis ablak a Visual C++ Resource editorval kszlt drag&drop technikval, majd minden windows kontrollnak kln-kln azonost lett adva, mert a forrskdban trtnik a tulajdonsgaiknak a mdostsa s ezeken az azonostkon keresztl lehet hivatkozni rjuk. A jell ngyzetek stt llapotukban ki vannak kapcsolva, a Server-Client nyomgombok kzl pedig mindig csak az egyiket lehet kivlasztani. A vilgts s hlzatos gombok ha kikapcsolt llapotban vannak, akkor az csoportjba tartoz windows kontrollok inaktv llapotba kerlnek, gy ezek llapott nem lehet mdostani.
A jtk irnytsa s jellemziJtkkzben a replgp sebessgt 5-0-ig terjed billentyk segtsgvel tudjuk belltani. A replsi irnyok vltoztatsra loklis forgats trtnik a replgp X, Y, Z tengelye krl. X tengely krli forgats a fel s lefele nyilakkal trtnik, az Y tengely krli forgats a Delete s PageDown billentyk lenyomsra vltoztathat. A Z tengely krli forgatst pedig a jobbra s balra nyilakkal tudjuk vltoztatni. A kpernyn a bal als sarokban megjelenik a replgp aktulis sebessge, az X, Y, Z tengelyek krli forgsnak a szge. A jobb als sarokban pedig az aktulis frisstsi arny. Minl nagyobb plya felbontst vlasztunk annl kisebb lesz a frisstsi arny, egyes videokrtyk esetben pedig hullmzs is fellphet a domborzat kirajzolsnl. A plyhoz ha kdt rendelnk, akkor az a plyt alkot pontok magassgnak fggvnyben szmolja ki a kd mrtkt egy adott pontban, de ez elgg teljestmnyront lehet nagy felbonts plya esetn.
8
Jtk implementcijaOpenGL megjelents Win32 alkalmazs ltrehozsaEbben a fejezetben arrl lesz, hogy miknt kell egy OpenGL megjelents ablakot ltrehozni a Visual Studio hasznlatval. Legelszr a Visual C++ segtsgvel ltrehozunk egy j projektet, a File->New menpontot kivlasztva, majd a felbukkan ablakban a Projects flre kattintunk s itt a Win32 Application elemet vlasztjuk ki, ezutn a Project name alatt megadjuk a projektnk nevt, a Location alatt pedig a mentsi helyt a projektnknek. rdemes egy j knyvtrat ltrehozni s ennek az elrsi tvonalt megadni, mert a Visual C++ klnbz fjlokat generl a kompills sorn. lltsuk a Create new workspace-re a rdigombot, ha nem azon tallhat, hogy egy tiszta munkafelleten tudjunk, dolgozni, mert hanem hozz fogja fzni egy mr ltez munkafellethez ami mr ltezik. A Platforms alatt pedig a Win32 mdot jelljk be. Az Okra kattintva a kvetkez ablakban vlasszuk az res projektet gy nem fog a Visual C++ flsleges llomnyokat generlni. Ezutn ltrehozzuk a projektnk f forrsllomnyt, amely irnytja az alkalmazs futst. Vlasszuk ki a File->New menpontot, ezutn a Files flre kattintva vlasszuk a C++ Source File pontot s a File name alatt adjunk neki nevet (Main.cpp), majd kattintsunk az Okra. Ezutn jhet a forrskd szerkesztse. Legelszr a library (fggvny gyjtemnyt tartalmaz llomny) llomnyokat csatoljuk a forrsllomnyunkhoz, gy kompills sorn a Visual Studio az alaprtelmezett knyvtraiban utna keres s hozzcsatolja a projekthez.#pragma #pragma #pragma comment (lib, "opengl32.lib") comment (lib, "glu32.lib") comment (lib, "glaux.lib")
Az els hrom llomny az OpenGL fggvnyeihez szksgesek. A kvetkez konstans hatsra a projektbe nem fogja belekompillni a ritkn hasznlt dolgokat a header llomnyokbl: #define WIN32_LEAN_AND_MEAN. A kvetkez lps a header llomnyok megadsa, amelyek hasznljk a fenti librarykben tallhat fggvnyeket, illetve azokat melyek szksgesek a windows ablak ltrehozshoz s windows kontrollok irnytshoz.#include #include #include #include #include // Header llomny a windowshoz // Windows base // Header llomny az OpenGL32 libraryhez // Header llomny az GLu32 libraryhez // Header llomny az Glaux libraryhez
Most jhetnek a globlis vltozok deklarlsai, amelyeket felhasznlunk az ablak ltrehozsra s billentyzet lekezelsre, hogy ellenrizni tudjuk, hogy a program aktv llapotban van-e, a kperny belltsok elvgzshez szksges vltozk, a kd, vilgts s anyag tulajdonsgokat tartalmaz vltozk is itten vannak deklarlva.HDC HGLRC HWND HINSTANCE DEVMODE bool bool hDC=NULL; hRC=NULL; hWnd=NULL; hInstance; // Privt GDI eszkz kapcsolat // lland megjelentsi kapcsolat // Ablak eszkzkapcsolat-ler // Alkalmazs folyamata // Kperny belltsok
dmScreenSettingsOld, dmScreenSettings; keys[256]; active=true;
// Tmb a billentyzet lekezelsre // Ablak aktv llapota, alaprtke true
GLuint fogMode[] = {GL_EXP, GL_EXP2, GL_LINEAR}; // Kd tpusok GLuint fogFilter = 2; // Melyik kd mdot hasznljuk GLfloat fogColor[4] = {0.75f, 0.75f, 0.75f, 1.0f}; // Kd szne GLfloat fogStart = 0.0f; // Kd kezdpontja GLfloat fogEnd = 5.0f; // Kd vgpontja
9
bool lighting, diffuse, specular; // Vilgts s komponenseinek ki/be kapcsolsa GLfloat LightAmbient[] = {0.5f, 0.5f, 0.5f, 1.0f}; // Ambient vilgts rtke GLfloat LightDiffuse[] = {0.7f, 0.7f, 0.7f, 1.0f}; // Diffuse vilgts rtke GLfloat LightSpecular[] = {1.0f, 1.0f, 1.0f, 1.0f}; // Specular vilgts rtke GLfloat LightPosition[] = {-999.0f, 999.9f, 999.0f, 1.0f}; // Fny pozcija float MatAmb[] = {0.5f, 0.5f, 0.5f, 1.0f}; float MatDif[] = {0.7f, 0.7f, 0.7f, 1.0f}; float MatSpc[] = {1.0f, 1.0f, 1.0f, 1.0f}; float MatShn[] = {0.7f}; // Anyag ambient rtke // Anyag diffuse rtke // Anyag specular rtke // Anyag fnyessge
Ezutn kvetkeznek azok a fggvnyek, amelyeknek csak a deklarcija van meg, mg az implementcijukra ksbb kerl sor a program szerkezet felptse s a fggvnyhivatkozsok szempontjbl.LRESULT LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM); CALLBACK ConfigDlgProc (HWND, UINT, WPARAM, LPARAM);
A kvetkez lps a fggvnyek definciinak lersai. A legels a rajzolsi terlet tmretezsvel kapcsolatos (ReSizeGLScene), vagyis mekkora terleten rajzolunk az ablakban, ami most a teljes ablak mrete lesz, s mg a vettsi mdot adjuk meg. Ebben az esetben perspektv vetts specifiklunk 75 fokos ltszggel, az ablak szlessgnek s magassgnak hnyadosa adja az aspektust, a kzeli vgsk a 0.1-ben, a tvoli vgsk meg 3000-ben lesz.GLvoid ReSizeGLScene(GLsizei width, GLsizei height) { if (height==0) // Kiszrjk a 0-val val osztst { height=1; // Magassgot egyenlv tesszk eggyel } glViewport (0,0,width,height); // Ltrejv kp mretnek megadsa glMatrixMode (GL_PROJECTION); // Kivlasztjuk a vettsi mtrixot glLoadIdentity(); // Betltjk az identikus mtrixot a vetts visszalltsra // Az ablak aspektusnak belltsa gluPerspective (75.0f, (GLfloat)width/(GLfloat)height, 0.1f, 3000.0f); glMatrixMode (GL_MODELVIEW); // A modell-nzet mtrix kivlasztsa glLoadIdentity(); // A modell-nzet mtrix visszalltsa }
A fggvny meghvsrl ksbb lesz sz. A kvetkez fggvny implementci az a fggvny, amely inicializlja az OpenGL megjelentsi mdjt (InitGL): rnykolsi modell, lsimts mdja, trl sznt, a mlysgi tesztelssel kapcsolatos belltsokat, a perspektivikus megjelents minsgt, majd ezeket kveten a kd, vilgts, s anyagtulajdonsgokat.int InitGL(GLvoid) { glEnable (GL_TEXTURE_2D); // Textrzs engedlyezse glShadeModel (GL_SMOOTH); // Elsimtott rnykolsi modell alkalmazsa glClearColor (0.0f, 0.0f, 0.0f, 1.0f); // Trlszn glClearDepth (1.0f); // Mlysgi puffer trlse (belltsa) glEnable (GL_DEPTH_TEST); // Mlysgellenrzs bekapcsolsa glDepthFunc (GL_LEQUAL); // Milyen mlysgellenrzst vgezznk glEnable (GL_COLOR_MATERIAL); // Anyag sznezs bekapcsolsa // J minsg perspektv megjelents glHint (GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST); // Kd belltsa glFogi (GL_FOG_MODE, fogMode[fogFilter]); // Kd tpus belltsa glFogfv (GL_FOG_COLOR, fogColor); // Kd sznnek belltsa glFogf (GL_FOG_DENSITY, 0.1f); // Kd srsgnek megadsa glHint (GL_FOG_HINT, GL_NICEST);// Kd minsgnek megadsa glFogf (GL_FOG_START, fogStart); // Kd kezdpontja glFogf (GL_FOG_END, fogEnd); // Kd vgpontja
10
glEnable (GL_FOG);
// Kd bekapcsolsa
if (lighting) // Ha a lighting rtke true akkor bekapcsoljuk a vilgtst { // A poligonok mindkt oldalnak megvilgtsnak bekapcsolsa glLightModelf(GL_LIGHT_MODEL_TWO_SIDE, GL_TRUE); // A GL_LIGHT1 fnyforrs ambient komponensnek belltsa glLightfv (GL_LIGHT1, GL_AMBIENT, LightAmbient); if (diffuse) // Ha diffuse rtke true akkor belltjuk a vilgtsi mdot // Fnyforrs diffuse komponensnek belltsa glLightfv (GL_LIGHT1, GL_DIFFUSE, LightDiffuse); if (specular) // Ha specular rtke true akkor belltjuk a specular mdot // Fnyforrs specular komponensnek belltsa glLightfv (GL_LIGHT1, GL_SPECULAR, LightSpecular); // A fnyforrs pozcijnak belltsa glLightfv (GL_LIGHT1, GL_POSITION, LightPosition); glEnable (GL_LIGHT1); // Fnyforrs bekapcsolsa glEnable (GL_LIGHTING); // Vilgts bekapcsolsa } // Anyag ambient, diffuse, specular tulajdonsgnak belltsa glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, MatAmb); glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, MatDif); glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, MatSpc); // Anyag csillogsnak belltsa glMaterialfv(GL_FRONT_AND_BACK, GL_SHININESS, MatShn); return true; // Az inicializls sikeres volt }
A megjelents a kvetkezkben definilt fggvny segtsgvel trtnik (DrawGLScene). Ide fognak kerlni a plya, replgp s egyb a megjelentshez szksges fggvnyhivatkozsok. Egyelre csak a kperny s mlysgi puffer trlse, majd az identikus mtrix betltse a vetts visszalltshoz fontos fggvnyek hvdnak meg.bool DrawGLScene() { // Szn s mlysgi puffer trlse glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glLoadIdentity(); // A modell-nzet mtrix visszalltsa return true; } // A kirajzolssal minden rendben
A kvetkez fggvny a fprogram vgn hvdik meg, vagy abban az esetben ha az OpenGL megjelent ablak ltrehozsa sorn hiba trtnt (KillGLWindow). A legels dolog, hogy visszavltunk a windows asztal felbontsra, majd megjelentjk a kurzort. Leellenrizzk, hogy van-e megjelentsi kapcsolatunk, leellenrizzk, hogy fel tudjuk-e szabadtani a megjelentsi s eszkz kapcsolatot. Majd felszabadtjuk a megjelentsi kapcsolatot, ha meg tudjuk tenni. Ezutn az eszkz kapcsolatot szabadtjuk fel, vgl az ablakot is felszabadtjuk s az ablak osztlyt trljk. Minden hiba esetn egy prbeszdablakban meg fog jelenni a megfelel hibazenetGLvoid KillGLWindow(GLvoid) { ChangeDisplaySettings (NULL, 0); ShowCursor (true); // Kpernyfelbonts visszalltsa // Egr mutat megjelentse
if (hRC) // Van-e megjelentsi kapcsolatunk (context)? { // Fel tudjuk-e szabadtani a megjelentsi s eszkz kapcsolatot if (! wglMakeCurrent(NULL, NULL)) { MessageBox(NULL,"Megjelentsi s eszkz kapcsolat hiba!", "Bezsri hiba", MB_OK | MB_ICONINFORMATION); }
11
// Felszabadtjuk a megjelentsi kapcsolatot if (! wglDeleteContext (hRC)) { MessageBox(NULL,"Megjelentsi kapcsolat felszabadtsa sikertelen!", "Bezrsi hiba", MB_OK | MB_ICONINFORMATION); } hRC=NULL; // Megjelentsi kapcsolat NULL rtkre lltsa } if (hDC && !ReleaseDC (hWnd, hDC)) // Eszkz kapcsolat felszabadtsa { MessageBox(NULL, "Eszkz kapcsolat felszabadtsi hiba", "Bezrsi hiba!", MB_OK | MB_ICONINFORMATION); hDC=NULL; // Megjelentsi kapcsolat NULL rtkre lltsa } if (hWnd && !DestroyWindow (hWnd)) // Ablak felszabadtsa { MessageBox(NULL, "Ablak felszabadtsa sikertelen!", "Bezrsi hiba", MB_OK | MB_ICONINFORMATION); hWnd=NULL; // Ablak NULL rtkre lltsa } // Ablak osztlynak felszabadtsa if (!UnregisterClass("OpenGL", hInstance)) { MessageBox (NULL, "Ablak osztlynak felszabadtsa sikertelen!, "Bezrsi hiba", MB_OK | MB_ICONINFORMATION); hInstance=NULL; // Alkalmazs folyamatnak NULL rtkre lltsa } }
Miutn az OpenGL felszabadt eljrst implementltuk, kvetkezik az a fggvny, amely segtsgvel felptjk az OpenGL megjelents ablakunkat (CreateGLWindow). A fggvny trzsben els lpsknt ltrehozzuk a szksges vltozkat az ablak inicializlshoz, majd ezt kveten kivlasztjuk az ablakunk folyamatt s felptjk az ablakunk osztlyt. Majd megprbljuk regisztrlni az ablak osztlyt. Ha ez sikertelen akkor kiratunk egy hibazenetet s kilpnk a programbl. Ha a regisztrci sikeres volt, kvetkezik a konfigurcis prbeszdablak megjelentse s a prbeszdablak fggvnyre val hivatkozs, ahol trtnnek a konfigurcis belltsok. Mieltt folytatnnk az ablak ltrehoz fggvny defincijt, ltre kell hozzuk a konfigurcis prbeszdablakunkat. Ezt megtehetjk, ha Visual C++-ban az Insert->Resource menpontot vlasztjuk, a felbukkan ablakban a Dialog komponenst vlasztjuk, majd az Okra kattintunk. Ennek hatsra automatikusan megjelenik a ltrehozott prbeszdablak a Visual C++ Resource editorban. A prbeszdablakra ktszer kattintva eljn annak a tulajdonsgait tartalmaz ablak, s a General flet kivlasztva bellthatjuk a nevt, amit most IDD_CONFIGra lltunk, s a Caption alatt megadhatjuk, hogy mi jelenjen meg a prbeszdablak fejlcben, ugyanitt bellthat a betstlus s mret. Miutn ez is megtrtnt vlasszuk a Styles flet s itten lltsuk a Style alatti legrdl listbl a Popup stlust, amely hatsra egy felugr ablak szerept fogja betlteni. Ugyanitt bellthatjuk, hogy milyen komponensei jelenjenek meg a prbeszdablaknak. Ebben az esetben a minimalizl s maximalizl gombok ki vannak vve, mert azt szeretnnk hogy ne lehessen a mrett vltoztatni az ablaknak. A More styles fln adjuk meg, hogy igaztsa az ablakot a kperny kzepre, amikor megjelenik, ezt a Center jellngyzet bejellsvel tehetjk meg. Ha ezzel ksz vagyunk, jhetnek a szksges windows kontrollok, amelyekkel majd ki tudjuk vlasztani a kvnt belltsokat. Elszr ltre fogjuk hozni a Felbontst bellt legrdl listt. A Controls ablakbl kivlasztjuk a Combo Box elemet, s a prbeszdablakunkon kattintva megjelenik a legrdl lista. Erre ktszer kattintva megadjuk az azonostjt, s a Styles fln kattintva, itten megadjuk a tpust ami most, Drop list lesz, ez azrt fontos mert gy a felhasznl nem tud egyni mdot berni, hanem kell vlasszon a 12
lehetsges mdok kzl. A Sort jell ngyzetbl vegyk ki a pipt, mert ha rendezni fogja az elemeket, nem tudjuk majd irnytani megfelelen a kivlasztsokat. A tbbi legrdl lista is ebben a stlusban kszl. Ahhoz hogy tudjuk az a bizonyos legrdl lista mit is vgez helyezznk el mell egy statikus szvegmezt, amelybe berjuk a nevet. A jellngyzetek is hasonlan helyezdnek el a prbeszdablakban, annyi klnbsggel, hogy a Caption alatt kell megadjuk a nevt, majd a Styles fln a Horizontal s Vertical alignmentnl Center-t vlasztunk, hogy a jellngyzetben lev szveg kzpre legyen igaztva, de ez szabadon vlaszthat. Ugyanitt be lett jellve a Push-like s Flat jellngyzetek, gy egy laptott gombhoz hasonl hatst rnk el. Ha ki van jellve vilgos rnyalat lesz a jellngyzet, ellenkez esetben pedig stt. Az Extended Style fln abban az esetben jelljk be a Transparent (tltsz mdot), hogyha a jellngyzet egy msik windows kontrol fltt van, mint pldul ebben az esetben egy Group Box fltt, ms esetekben nem jelljk be. A rdi gombok (Client s Server) a jellngyzettel hasonl stlusban kszl, csak a Styles oldalon nem jelljk be a Flat stlust. Miutn ez megtrtnt, a f forrsllomnyuk legelejre betesszk a resource.h header llomnyra val hivatkozst, mert ebben vannak eltrolva a prbeszdablak tulajdonsgai. Az ablak ltrehoz fggvnynkben, ezt kveten leellenrizzk, hogy milyen rtkkel lptnk ki a prbeszdablakbl. Ha az Okra kattintottunk az aktulis belltsok elmentdnek, ellenkez esetben kilp a programbl ments nlkl. Ezutn belltjuk az ablak mreteit, tvltunk teljes kpernys mdba. Belltjuk az ablak stlust, amely kiterjesztet felbukkan ablak s elrejtjk az egrmutatt. Az ablakot a kvnt stlusra llts utn, ltrehozzuk az ablakot. A pfd vltoz belltsval tudjuk megadni, hogy tmogassa az OpenGL-t az ablakunk, milyen sznmlysgben fusson, tmogassa-e a dupla puffer technikt s a z-buffer mlysgtesztelst. Miutn ez is megtrtnt megnzzk, hogy ltezik-e eszkzkapcsolatunk. Ha van akkor belltjuk a pixel formtumot, majd ltrehozzuk az OpenGL kapcsolatot, s bekapcsoljuk ezt. Miutn mindezek sikeresen megtrtntek megjelentjk az ablakot, egy keveset megnveljk a prioritst s a fkusz rlltjuk az ablakunkra s meghvjuk az elbbiekben definilt ReSizeGLScene fggvnyt, hogy segtsgvel belltsuk a ltmez mrett, vagyis ahov fogunk rajzolni az ablakban, ami most a teljes ablak mrete lesz teljes kpernys mdban. Ha egy if utasts trzsben false rtket trt vissza a fggvny akkor, a program le fog llni.bool CreateGLWindow() { GLuint PixelFormat; WNDCLASS wc; DWORD dwExStyle; DWORD dwStyle; RECT WindowRect; // Pixel formtum // Ablak osztly // Kibvtett ablak stlus // Ablak stlus // Ablak bal-fels s jobb-als koordintihoz
// Kivlasztjuk az ablakunk folyamatt hInstance = GetModuleHandle(NULL); // tmretezs esetn jrarajzols, s sajt eszkz kapcsolat ltrehozsa wc.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC; // WndProc fggvny lesz a rendszer zenet feldolgoz wc.lpfnWndProc = (WNDPROC) WndProc; wc.cbClsExtra = 0; // Semmilyen extra ablakadat wc.cbWndExtra = 0; // wc.hInstance = hInstance; // Folyamat belltsa // Alaprtelmezett ikon betltse wc.hIcon = LoadIcon(NULL, IDI_WINLOGO); // Az egr mutat betltse wc.hCursor = LoadCursor(NULL, IDC_ARROW); // OpenGL-hez nem szksges az ablak httr wc.hbrBackground = NULL; wc.lpszMenuName = NULL; // Nem hasznlunk ment wc.lpszClassName = "OpenGL"; // Osztly neve if (!RegisterClass(&wc)) // Megprbljuk regisztrlni az ablak osztlyt {
13
MessageBox (NULL, "Ablak osztly regisztrcis MB_OK|MB_ICONEXCLAMATION); return false; // false rtkkel kilpnk a fggvnybl }
hiba!",
"Hiba",
if (!DialogBox (hInstance, MAKEINTRESOURCE(IDD_CONFIG), NULL, (DLGPROC)ConfigDlgProc)) // Prbeszdablak megjelentse { MessageBox (NULL, "Semmi vltozs nem trtnt a belltsokban!", "Informci", MB_OK | MB_ICONINFORMATION); KillGLWindow(); // Ablak felszabadtsa exit(1); // kilpnk a fggvnybl } // Belltjuk azt, hogy milyen tulajdonsgokat fogunk mdostani a // kpernyvel kapcsolatosan dmScreenSettings.dmFields = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT | DM_DISPLAYFREQUENCY; WindowRect.left = (long)0; // Ablak keret bal szlnek pozcija WindowRect.top= (long)0; // Ablak keret fels szlnek pozcija WindowRect.right = dmScreenSettings.dmPelsWidth; // Jobb szle WindowRect.bottom = dmScreenSettings.dmPelsHeight; // Als szle // Megprbljuk belltani a kpernyt if (ChangeDisplaySettings (&dmScreenSettings, CDS_FULLSCREEN) != DISP_CHANGE_SUCCESSFUL) { MessageBox (NULL, "A kvnt teljes kpernys belltsokat nem tmogatja a videokrtya!", "Hiba", MB_OK|MB_ICONSTOP); return false; // false rtkkel kilpnk a fggvnybl } dwExStyle = WS_EX_APPWINDOW; dwStyle = WS_POPUP; ShowCursor (false); // Ablak bvtett stlusa // Ablak stlusa // Egrmutat elrejtse
// Ablak mretnek belltsa a kvnt rtkre AdjustWindowRectEx (&WindowRect, dwStyle, false, dwExStyle); // Ltrehozzuk az ablakot if (!(hWnd=CreateWindowEx (dwExStyle, // Kibvtett stlus "OpenGL", // Osztly neve NULL, // Ablak fejlc neve dwStyle | // Definilt ablak stlus WS_CLIPSIBLINGS | // Kvnt stlus WS_CLIPCHILDREN, // Kvnt stlus 0, 0, // Ablak pozcija // Az ablak szlessgnek kiszmolsa WindowRect.right-WindowRect.left, // Az ablak magassgnak kiszmolsa WindowRect.bottom-WindowRect.top, NULL, // Szl ablak nem lesz NULL, // Men nem lesz hInstance, // Folyamat // WM_CREATE-nek nem adunk t semmit NULL))) { KillGLWindow(); // Ablak felszabadtsa MessageBox (NULL, "Ablak ltrehozsi hiba!", MB_OK|MB_ICONEXCLAMATION); return false; // false rtkkel kilpnk a fggvnybl }
"Hiba",
14
// pfd megmondja windowsnak hogyan legyenek a dolgok static PIXELFORMATDESCRIPTOR pfd= { // Pixel formtum ler mrete sizeof (PIXELFORMATDESCRIPTOR), 1, // Verzi szm // Formtum kell tmogassa az ablakba val rajzolst PFD_DRAW_TO_WINDOW | // A formtum kell tmogassa az OpenGL-t PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER, // Kell tmogassa a dupla puffer technikt PFD_TYPE_RGBA, // RGBA formtum specifiklsa // Sznmlysg belltsa (unsigned char)dmScreenSettings.dmBitsPerPel, 0, 0, 0, 0, 0, 0, // Szn bitek mellzse 0, // Nem hasznlunk alfa puffert 0, // Eltolsi bit mellzse 0, // Nem hasznlunk gyjt puffert 0, 0, 0, 0, // Gyjt bitek mellzse 16, // 16 bites Z-buffer alkalmazsa 0, // Nem hasznlunk stencil puffert 0, // Nem hasznlunk kiegszt puffert PFD_MAIN_PLANE, // F rajzolsi rteg 0, // Foglalt (fenntartott) 0, 0, 0 // Rteg maszkok mellzse }; if (! (hDC = GetDC (hWnd))) // Eszkz kapcsolatot elrhet-e? { KillGLWindow(); // Ablak felszabadtsa MessageBox(NULL, "OpenGL eszkz kapcsolat ltrehozsi hiba!", "Hiba", MB_OK|MB_ICONEXCLAMATION); return false; // false rtkkel kilpnk a fggvnybl } // Kapott a windows egy megfelel pixel formtumot? if (! (PixelFormat = ChoosePixelFormat (hDC,&pfd))) { KillGLWindow(); // Ablak felszabadtsa MessageBox (NULL, "Nincs megfelel pixel formtum!", "Hiba", MB_OK | MB_ICONEXCLAMATION); return false; // false rtkkel kilpnk a fggvnybl } // Be tudjuk lltani a pixel formtumot? if(! SetPixelFormat (hDC, PixelFormat, &pfd)) { KillGLWindow(); // Ablak felszabadtsa MessageBox (NULL, "Pixel formtum belltsi hiba!", "Hiba", MB_OK | MB_ICONEXCLAMATION); return false; // false rtkkel kilpnk a fggvnybl } // Megjelentsi kapcsolat ltrehozhat-e? if (! (hRC = wglCreateContext (hDC))) { KillGLWindow(); // Ablak felszabadtsa MessageBox (NULL, "OpenGL megjelentsi kapcsolat ltrehozsa sikertelen!", "Hiba", MB_OK|MB_ICONEXCLAMATION); return false; // false rtkkel kilpnk a fggvnybl } // Megprbljuk aktivlni a megjelentsi kapcsolatot if(!wglMakeCurrent (hDC, hRC)) {
15
KillGLWindow(); // Ablak felszabadtsa MessageBox (NULL, "OpenGL megjelentsi kapcsolat aktivlsi hiba!", "Hiba", MB_OK|MB_ICONEXCLAMATION); return false; // false rtkkel kilpnk a fggvnybl } ShowWindow (hWnd, SW_SHOW); // Megjelentjk az ablakot // Priorits nvelse az ablak eltrbe helyezsvel SetForegroundWindow (hWnd); SetFocus (hWnd); // A fkuszt az ablakra lltjuk // Perspektv OpenGL szntr belltsa ReSizeGLScene (dmScreenSettings.dmPelsWidth, dmScreenSettings.dmPelsHeight); return true; // Minden sikerrel vgzdtt }
A kvetkez fggvny (DispatchEvents) segtsgvel fogjuk ellenrizni a billentyzeten trtnt gombok lenyomst, amelyek a keys tmbben vannak eltrolva. Ha egy gomb le van nyomva akkor a keys[billentykd] tmbelem rtke true lesz, ellenkez esetben false rtk tallhat benne.// Ellenrizzk a lenyomott gombokat s mveleteket vgznk azok fggvnyben void DispatchEvents() { }
Ezutn implementljuk a prbeszdablakunk fggvnyt (ConfigDlgProc). Az els lps a fggvny implementlsban, hogy deklarlunk egy objektumot a CConfigFile osztlybl, amelyet arra hasznlunk, hogy elmentsk segtsgvel az aktulis belltsokat, hogyha az Okra kattintunk, illetve a rgi belltsok betltsre. Ezen osztly a ConfigFile.h header llomnyban lett definilva s egy struktrban trolja el az adatokat. Kt tagfggvnye van: ReadCfgFromFile(paramterek) A paramterknt tadott belltsi paramterekbe berja a konfigurcis (config.fdt) llomnyban tallhat belltsokat, WriteCfgToFile(paramterek) A paramterknt tadott belltsi paramtereket elmenti a konfigurcis fjlba. A f forrsllomnyunkra visszatrve kvetkezik egy switch dntsi hl, amelyben ellenrizzk a prbeszdablakban trtn windows zeneteket (esemnyeket). A WM_INITDIALOG zenet akkor kvetkezik be amikor megjelentjk a prbeszdablakot, ebben a programkd rszletben fogjuk beolvasni a konfigurcis llomnyban eltrolt belltsokat s belltjuk a prbeszdablak eszkzeit azoknak megfelelen. A WM_COMMAND zenet a prbeszdablakban trtn billentyzet s egr mveleteket figyeli. Ha pldul kattintunk az Ok gombra akkor az annak megfelel if utasts trzsben lev programrsz hajtdik vgre, ami az Ok esetben a prbeszdablakban lev belltsokat elmenti a konfigurcis fjlba. Teht minden windows kontrollnak a prbeszdablakbl, amelynek valamilyen tulajdonsgt szeretnnk mdostani, azt itten kell megadni, pldul if (wParam == IDEXIT) EndDialog (hWnd, 0); esetn ha a wParam rtke megegyezik a kilps gomb azonostjval, vagyis kattintottunk a kilps gombon, akkor bezrja a prbeszdablakot 0-s rtket trtve vissza (program bezrsa). A WM_CLOSE zenet pedig akkor kvetkezik be amikor a prbeszdablak jobb fels sarkban lev X kilps gombra kattintunk. A windows kontrollok tulajdonsgainak mdostsra a SendDlgItemMessage fggvnyt alkalmazzuk els paramtere a prbeszdablak azonostja, amely a windows kontrollt tartalmazza(hDlg), a msodik paramter a windows kontroll azonostja(nIDDlgItem), amely az zenetet megkapja, a harmadik a kldend zenet (Msg), negyedik s tdik paramter kiegszt zenet specifikus paramterek (wParam, lParam). Ahhoz, hogy pldul egy szvegdoboznak megkapjuk a tartalmt a GetDlgItemText fggvnyt kell meghvjuk, amelynek a paramterei a kv: prbeszdablak azonostja, kontroll azonost, puffer ahov mentjk a szveget, a szveg maximlis mrete. A szvegdoboz szvegnek a belltsra pedig a SetDlgItemText fggvnyt hasznljuk. Paramterei: prbeszdablak azonostja, kontroll azonost, tadott karakterlnc. 16
Egy kontroll aktv llapotnak vltoztatsra az EnableWindow fggvnyt alkalmazzuk. Az els paramterknt a kvetkezt adjuk t, hogy megkapjuk a kontroll hivatkozst: GetDlgItem (hWnd, IDC_MULTIPLAYER_HOST), a msodik paramter pedig az aktv llapotot jelz logikai rtk, amely ktfle lehet: TRUE vagy FALSE. Ha TRUE az tadott rtk akkor, a kontroll aktv llapotba kerl, ellenkez esetben inaktv llapotba, ami azt jelenti, hogy pldul nem tudunk kattintani r. A windows esemnykezel fggvny implementcija kvetkezik ezutn (WndProc). Ebben a fggvnyben trtnik meg a keys tmb elemeinek mdostsa a gombok lenyomsnak fggvnyben. A windows esemnyeket szintn egy switch utastssal kezeljk le, amelynek paramtere a windows zenetek tartalmazja (uMsg). A WM_SYSCOMMAND a rendszerzenetek befogsra szolgl. Ezen bell van megakadlyozva, hogy elinduljon a kperny kml, vagy hogy a kperny ramtakarkos zemmdba lpjen. A WM_CLOSE zenet hatsra kilpnk a programunkbl a case trzsben meghvva a PostQuitMessage(0); fggvnyt, amelynek a paramtere a kilpsi kd. A WM_KEYDOWN zenet hatsra a keys tmbben eltroljuk a lenyomott billentynek megfelel indexen a billenty llapott, amit true-ra lltunk (keys[wParam]=true). A WM_ACTIVE case trzsn bell az ablak aktv llapotval kapcsolatos ellenrzseket s mveleteket vgznk, mint pldul ha az ablak le van kicsinytve akkor a program ne fusson s vltsunk t a jtk felbontsbl az asztal felbontsra. A fggvny vgn pedig visszatrtjk a windows esemny kezeljbe a le nem kezelt esemnyeket. Az utols fggvny, amelyet implementlni kell ebben a forrsllomnyban a WinMain fggvny, amely a program f kezelje. Ebben a fggvnyben elszr deklarlunk egy windows zenet struktrt(msg) s egy logikai vltozt(done), amely segtsgvel ellenrizzk, hogy ki kell-e lpjnk a programbl, ennek kezdeti rtke false. Ezutn meghvjuk a CreateGLWindow fggvnyt egy if utasts paramtereknt, mert ha ez a fggvny false rtkkel tr vissza azt jelenti, hogy az OpenGL ablak ltrehozsa sikertelen volt s a program tovbb nem folytatdhat, s kilpnk a WinMain fggvnybl 0-t trtve vissza. Ezutn ugyangy meghvjuk az InitGL fggvnyt is. Ha ez is sikeresen lefutott, akkor jhet a fprogram ciklusa (while), amely mindaddig hajtdik vgre mg a logikai vltoz (done) rtke true nem lesz. A ciklusban az if gon megnzzk, hogy van-e zenet, amely feldolgozsra vr. Ha igen, akkor megnzzk, hogy a kilps zenetrl van-e sz. Ha kilps zenet rkezett, akkor kilpnk a programbl s a done logikai vltoz rtkt true-ra lltjuk, hanem feldolgozzuk a berkez zenetet. Ha nem rkezett zenet, akkor az else gon megnzzk, hogy a programunk aktv-e. Ha aktv akkor, megnzzk, hogy nem tttk-e le az Esc billentyt. Ha igen akkor a done rtkt true-ra lltjuk, hanem az else gon meghvjuk a DrawGLScene fggvnyt, amellyel elvgezzk a rajzolsokat, meghvjuk a SwapBuffers fggvnyt, hogy cserljk fel a dupla puffer aktv puffert, ezutn a DispatchEvents fggvnyt hvjuk meg billentyzet aktivits ellenrzsre. A WinMain fggvny vgn pedig meghvva a KillGLWindow fggvnyt felszabadtjuk a ltrehozott OpenGL ablakot s a vgn visszatrtjk az zenet struktra aktulis aktivcis azonostjt.
Modellezsi transzformcik, nzpont s nzsi irny belltsaA modellezsi transzformcik segtsgvel lltjuk be a replgp s a plya eltolst, forgatst, mrett. A kvetkezkben felsorolt parancsok a MODELVIEW mtrixot mdostjk. A hrom OpenGL modellezsi transzformci a glTranslate*(), glRotate*(), s glScale*(). Ezek a fggvnyek egy objektumot transzformlnak elmozdtva, elforgatva, nagytva, kicsinytve, vagy tkrzve. Az elkvetkezkben egy rvid lers fog szerepelni mindhrom fggvnyrl. 1. Eltols: void glTranslate{fd} (TIPUS x, TIPUS y, TIPUS z); Megszorozza az aktulis mtrixot egy mtrixxal, amely egy objektumot elmozdt a megadott x, y, z rtkekkel (vagy a loklis koordinta rendszert mozdtja el ugyanazon mrtkkel). A kvetkez bra mutatja az eltols hatst. 17
bra 7 Eltols kvetkezmnye
2. Forgats: void glRotate{fd} (TIPUS szg, TIPUS x, TIPUS y, TIPUS z); Megszorozza az aktulis mtrixot egy mtrixxal, amely elforgat egy objektumot (vagy a loklis koordinta rendszert) az rajrsval ellenttes irnyban, a sugr krl, amely az origbl indul s thalad az (x,y,z) ponton. A szg paramter adja a forgats szgt. A mellkelt brn lthat a glRotatef(45.0, 0.0, 0.0, 0.0); fggvnyhvs hatsa, amely egy 45 fokos forgatst vgez a z tengely krl. Ha egy objektum tvolabb van a forgats tengelytl, annl nagyobb lesz a forgats mrtke (nagyobb a sugara), mint egy objektumnak, bra 8 Forgats hatsa amely kzelebb van a tengelyhez.
3. Sklzs: void glScale{fd} (TIPUS x, TIPUS y, TIPUS z); Megszorozza az aktulis mtrixot azzal a mtrixxal, amely nagyt, kicsinyt, vagy tkrz egy objektumot a tengelyek mentn. Minden x, y, z koordintja minden pontnak az objektumbl megszorzdik a megfelel argumentummal x, y, vagy z. A loklis koordinta rendszer esetn, a loklis koordinta tengelyek nagytdnak, kicsinytdnek, vagy tkrzdnek az x, y, z faktorokkal, s a hozzrendelt objektum ezekkel sklzdik. A mellkelt brn lthat a glScalef (2.0, -0.5, 1.0); fggvny bra 9 Sklzs hatsa hatsa. A fent bemutatott transzformcis fggvnyeket felhasznlva kszlt el a Camera osztly, amely a camera.h llomnyban lett deklarlva s a camera.cpp forrsllomnyban lettek definilva a tagfggvnyei. Az osztly segtsgvel vgezhetnk loklis (rotateLoc) s globlis (rotateGlob) forgatst, valamint loklis (moveLoc) s globlis (moveGlob) eltolst. A nzet belltsra a setView tagfggvnyt hasznljuk, amely a forgatsok s eltolsok utn kell 18
kvetkezzen a meghvsi sorrendben. A Camera osztlyt a Main.cpp forrsllomnyban hasznljuk fel arra, hogy a replgp mozgst s forgst szimulljuk, gy hogy a vilgot forgatjuk s mozgatjuk el a replgphez kpest. A replgp mindig egy helyben fog llni, csak az animcii vltoznak, a lenyomott billentyknek megfelelen. A forrsllomny legelejn ahol a globlis vltozkat deklarltuk ltrehozunk egy camera objektumot a Camera osztlybl. A DrawGLScene fggvnyben a mlysgi s szn puffer trlse, valamint az identikus mtrix betltse utn if utastsokban leellenrizzk, hogy volt-e billenty lenyomva, amely hatsra belltdik a megfelel animci a replgp szmra a SetAction fggvny segtsgvel, amely a ksbbiekben trgyalt CAirplane osztly tagja (replgp), s elvgznk a forgatsi szgnek megfelel loklis forgatst a kvnt tengely krl (pl. camera.rotateLoc (szg, 1, 0, 0); - Az X tengely krli loklis forgatst vgez a megadott szggel). Az elmozdulshoz a camera objektum loklis elmozdulst vgz tagfggvnyt hvjuk meg (pl. camera.moveLoc(0, 0, elmozduls); - A loklis Z tengely menti elmozdulst eredmnyez e megadott mrtkben, vagyis brmerre nz a replgp mindig elre halad). Vgl a nzet belltsra meghvjuk a setView tagfggvnyt s ennek hatsra minden amit ezutn kirajzolunk a replgphez viszonytva el lesz forgatva, tolva.
A replgpmodell betltse s megjelentseA replgpmodell betltshez elre implementlt modell betlt forrsllomnyok kerltek felhasznlsra kisebb mdostsokkal a megfelel mkdshez. A replgp mdl modell formtumban kszlt (Half-Life modell) s a kvetkez forrsllomnyok szksgesek a modell kezelsre (textra betlts, animci kezels, megjelents): MathLib.h, MathLib.cpp Az mdl modell kirajzolshoz s animciinak kiszmolshoz szksges matematikai fggvnyeket tartalmazzk. MDLFormat.h Az mdl formtum trolsi struktrja tallhat ebben a forrsllomnyban, s hivatkozik a MathLib.h-ra. MDLModel.h, MDLModel.cpp Az mdl modell betltse, kirajzolsa, animciinak belltsa, lekrdezse, animcik lejtszsnak vezrlse ezekben forrsllomnyban tallhat. Az MDLModel.h hivatkozik az MDLFormat.h llomnyra, gy a tbbi forrsllomnyunkban ahol hasznlni fogjuk a modell kezelst csak az MDLModel.h-ra kell hivatkozzunk. A modell osztly neve pedig TMDLModel, ezt fogjuk hasznlni a replgp osztlyunk modelljnek objektum definilsakor. Az mdlmodel.h forrsllomnyra val hivatkozst betesszk a Main.cpp forrsllomny elejre ahol a tbbi, forrsllomnyra val hivatkozs is tallhat. A replgp osztlyunk deklarlsa s implementlsa az Airplane.h forrsllomnyban tallhat. Mivel a deklarci s implementci egy helyen tallhat az Airplane.h forrsllomny hozzfr a Main.cpp-ben tallhat forrsllomny hivatkozsokhoz s itt nem kell jra megadni azokat. Az airplane.h forrsllomnyunk legels rszben megadjuk a betltend modell llomny elrsi tvonalt nevvel egytt, amely egy konstansban van eltrolva: #define MDLFILE00 "Data/FlightSimPlane.mdl". Itten adjuk meg a replgp fordulsi sebessgt is (TURNSPEED). Ezutn kvetkezik egy felsorols tpus, amelyben automatikusan megszmozdnak a bert konstansokat. Ezek lesznek a replgp animciinak vezrli. Ezek utn kt struktra kvetkezik, az elsben troljuk a replgp pozcijt, a jobbra, felfele s elre mutat vektornak rtkeit. A msodik struktrban troljuk el a replgp elfordulsi szgt (fokban s radinban) a kiindulsi szghez kpest, ami 0 fok az x, y, z tengely krl. Ezutn tallhat a replgp osztly deklarcija, amelynek neve CAirplane. Privt adattagjai a replgpmodell vltoz (PlaneModel), egy idmr (ctimer), amely szksges az animcik megfelel visszajtszshoz (implementcijrl ksbb lesz sz). A kvetkez 19
vltoz fogja trolni az utols kirajzols idpontjt (Previous). Az Animaton vltoz a replgp animciinak visszajtszsa eltti tesztben hasznldik fel arra, hogy leellenrizzk, hogy mr belltottuk-e a megfelel vgrehajtand animcit, mert ha minden kirajzolsi ciklusban meghvjuk a replgp modell animcijnak bellt fggvnyt, akkor mindig csak egy tredkt fogjuk ltni a teljes animcinak, mert mindig az elejre fogja lltani a visszajtszst. Az Action vltoz trolja a lejtszand animcit. Az xrot, yrot, zrot vltozk a replgp elforgatshoz szksges vltozk. A publikus vltozk a replgp sebessge (speed), pozcija (position), elfordulsi szge (angle), nyugalmi llapotot jelz logikai vltoz (idle), egy logikai vltoz, amellyel vizsglni tudjuk, hogy a replgp a talajon tallhat vagy a levegben (airborne). Egy msik logikai vltoz segtsgvel azt ellenrizzk, hogy a futmve kiengedett vagy behzott llapotban van-e(gearsin). A gearmovetime vltoz a futmvek mozgsnak ellenrzsre szolgl, vagyis az animci ne lljon meg id eltt. Az ActFrame vltoz az aktulis animcis lpst tartalmazza (az animciban hnyadik lpsben tart), ez is a futm animci esetn hasznldik fel. Az osztly tagfggvnyeinek lersai kvetkeznek. A LoadModel fggvny inicializlja az osztly vltozit nullval, belltja a replgp elforgatst gy, hogy az a kpernybe befele nzzen, inicializlja az idmrt (ctimer.Init();) s betlti a replgp modelljt (PlaneModel.Init(MDLFILE00);) s belltja a lejtszand animcit a nyugalmi llapotot tartalmazra (PlaneModel.SetSequence(IDLE1);). Render fggvny jelenti meg a replgp modellnket. Legels lpsknt belltjuk, hogy a replgpmodellnek azt az oldalt rajzolja ki csak, amely kifele nz (hromszgek oldalai az ramutat jrsval ellenttes irnyban lettek ltrehozva). Az Action vltozban eltrolt animcit belltjuk a replgp szmra egy switch utastson keresztl megkeresve a megfelelt s meghvva a PlaneModel.SetSequence fggvnyt. Az animci megadsa utn lekrdezzk az idmrtl az aktulis idt a Current vltozban eltrolva annak az 1000-vel val oszts utni hnyadost s a replgpmodellnek az animcijt elrbb lltjuk a PlaneModel.AdvanceFrame fggvnnyel, amelynek paramterknt a Current Previous rtket adjuk t (vagyis az utols kirajzols ta eltelt idt). Ezutn betltjk az identikus mtrixot, majd eltoljuk s elforgatjuk a modell-nzetet annyira, hogy a replt amikor megjelentjk htulrl lssuk azt teljes egszben. Ezutn meghvjuk a PlaneModel.DrawModel fggvnyt, amely hatsra megjelentdik a repl. A fggvny vgn elmentjk az aktulis idt a Previous vltozba, s visszakapcsoljuk azt, hogy a hromszgek mindkt oldalt kirajzolja. A GetSequence fggvny segtsgvel le tudjuk krdezni az aktulis lejtszsban lev animcit egyenesen a modellbl a PlaneModel.GetSequence fggvnyhvs eredmnyt tadva a GetSequence fggvny visszatrtsi rtknek. Az UpdateState fggvnynek az a szerepe, hogy az elfordulsi szget elmentse radinban is, s hogy a fokban trtn elforduls 0-360 fokok kztti rtkeket vehessen fel. Az osztly hasznlathoz a Main.cpp forrsllomnyban a hivatkozsokhoz betesszk az airplane.h llomnyra val hivatkozst. A globlis vltozknl ltrehozunk egy replgp objektumot (airplane) a CAirplane osztlybl. Az InitGL fggvny legelejre betesszk az airplane.LoadModel fggvnyhvst, hogy betltsk a replgpmodellt s belltsuk az animcit az airplane.SetAction fggvny segtsgvel, paramterknt most egy nyugalmi llapot llandjt adjuk t. A DrawGLScene fggvnyben ellenrizzk le if utastsok segtsgvel, hogy milyen llapotban (pl. if (airplane.gearsin){}) van a replgpnk, s hogy milyen billenty letsek trtnnek ennek megfelelen fog a replgp animcija belltdni (airplane.SetAction). Miutn az animci belltdott s a forgatsi, eltolsi transzformcik megtrtntek megjelentjk a replnket az airplane.Render fggvny meghvsval, de mieltt a kamernk setView fggvnyt meghvnnk. A DispatchEvents fggvnybe kerltek a replgp sebessgt s forgst irnyt billentyk lekezelse s ezek hatsra a vltozk belltsa. A replgp UpdateState tagfggvnyt a fprogram ciklusban hvjuk meg minden egyes lpsben, a kirajzols s esemnykezels utn. 20
Idzts s teljestmny mrsAz idmr osztly, amely segtsvel le tudjuk krdezni az aktulis rendszeridt (az az id mita a windows fut) s kiszmoljuk az aktulis kpfrisstst a Timer.h llomnyban tallhat. Az llomny legelejn tallhat annak a struktrnak a tpus defincija, amely tartalmazza az idmr mkdtetshez szksges vltozkat (TIMER). Az idmr osztlya a CTimer, amelynek privt vltozja az elbbiekben definilt struktra tpus segtsgvel ltrehozott vltoz (timer). Tagfggvnye pedig hrom darab van. Az Init tagfggvny segtsgvel inicializljuk az idmrt feltltve a timer struktrt a megfelel rtkekkel s lekrdezve az aktulis idt elmentjk ezt az idmr kezdeti idejeknt, hogy a tovbbi szmolsok az id lekrdezs esetn megfelel rtket tudjon a fggvny visszatrteni. Az aktulis id lekrdezse (amita az idmr elindtdott) a GetTime fggvny segtsgvel trtnik, amely visszatrti az aktulis id s a kezdeti id klnbsgt, amivel megkapjuk, hogy mennyi ideje fut az idmrt s ezt az rtket felhasznlva tudjuk pldul a replgp animciinak lejtszst idzteni. A kpfrissts fggvny a CalculateFPS egy vltoz rtkt nveli (timer.cur_fps) minden lpsben ahnyszor meghvdik, s amikor eltelt egy msodperc az utols kpfrisstsi arny elmentse ta, akkor elmentjk az aktulis kpfrisstst a rgi kpfrisstst tartalmaz vltozba (timer.old_fps = timer.cur_fps;), a fggvny visszatrtsi rtke pedig a timer.oldfps ,vagyis a rgi kpfrissts rtke. Az idmr hasznlathoz a Main.cpp forrsllomnyban az llomny elejre betesszk a Timer.h llomnyra val hivatkozst, hogy hasznlni tudjuk a benne tallhat osztlyt. Az idmr objektumot (timer) a globlis vltozk rszn hozzuk ltre lekpezve a CTimer osztlybl. Az idmr inicializlsa az InitGL fggvny vgn trtnik meg s a DrawGLScene fggvnyben alkalmazzuk az aktulis id s kpfrissts lekrdezsre. A CurrentTime vltozban troljuk el az aktulis idt a timer.GetTime fggvny eredmnyeknt visszaadott rtk 1000-el val osztsnak hnyadost. A PreviousTime vltoz a fggvny vgn mindig frisstdik az aktulis idvel: PreviousTime = CurrentTime;. A diffTime vltoz rtke az elz s az aktulis id klnbsge, amelyet arra hasznlunk, hogy a replgp mozgsa ne szmtgp teljestmny, hanem idfgg legyen, a diffTime rtkvel megszorozzuk pldul a sebessget s ezzel az rtkkel fog elre haladni a replgp (camera.moveLoc (0, 0, airplane.speed*diffTime);). Forgats esetn ugyangy mkdik. Az oldfps vltozban troljuk el a rgi rtkt a kpfrisstsnek. rtke a fggvny legelejn fog aktualizldni a timer.CalculateFPS fggvny meghvsra, amely rtket majd megjelentjk a kpernyn. Ugyanezen felhasznlsi mddal irnytdik a replgp futmvnek s a tbbi animcijnak kezelse a Main.cpp s Airplane.h forrsllomnyokban az idmr hasznlatval. Az idmr felhasznlsra a hlzat implementlsa sorn is lesz plda.
Textrzs OpenGL rendszerbenA valszer kpek ltrehozsnak egy fontos eszkze a textralekpezs. A valsgban a trgyak nem egysznek, hanem a felletkn mintk vannak. Ezen mintk geometriai lersa s geometriai objektumknt val kezelse azonban rendkvl idignyes s nagy trolkapacitst lekt feladat lenne. Mindamellett nem is lenne elg valszer, hiszen a mintk ltalban les kontrak, tl szablyosak lennnek. Ezzel szemben, ha egy valdi objektum felletnek kpt (mintzatt) visszk fel a szmtgppel ellltott objektumra, sokkal letszerbb lesz a kp. A trbelisg rzkeltetsnek fokozsra is alkalmas a textra, ugyanis a textrt a modelltrben 21
rendeljk hozz a geometriai alakzathoz, gy a felleti mintn is rvnyesl a centrlis vettsbl ered, n. perspektv torzts, pl. egy tglafal tvolabb lev tgli kisebbek lesznek a kpen, s a tglk szemkzti lei nem lesznek prhuzamosak. A textrkat tbbnyire ktdimenzisnak (skbelinek) gondoljuk, azonban a textrk lehetnek egy- vagy hromdimenzisak is. A textrkat lekpezhetjk gy, hogy azok lefedjk a poligonokat (poligonhlkat), de gy is, hogy a textra az objektum szintvonalait, vagy ms jellemzit szemlltesse. Az ersen ragyog fellet objektumok gy is textrzhatk, hogy azt a hatst keltsk, mintha a krnyezet tkrzdne az objektumon. A textra geometriailag egy tglalap alak terlet, mely sorokba s oszlopokba rendezett textraelemekbl, rviden texelekbl (texture element) pl fel. A textra teht adatok 1, 2 vagy 3 dimenzis tmbjnek tekinthet. Az egyes texelekhez trolt adat kpviselhet sznt, fnyerssget vagy szn s alfa rtket, azaz 1, 2, 3 vagy 4 adat tartozhat minden egyes texelhez. A tglalap alak textrkat azonban tetszleges alak poligonokra, poligonhlkra kell rhelyezni. A rhelyezs mikntjt a modelltrben kell megadni, gy a textrkra is hatnak a modell- s vettsi transzformcik. Ennek rdekben az objektumok ltrehozsakor a cscspontok geometriai koordinti mellett a textrakoordintkat is meg kell adni. Egy ktdimenzis textra koordinti a [0.,1.]x[0.,1.] egysgngyzeten bell vltoznak. Amikor a cscsponthoz hozzrendeljk a textra pontjait ezen a terleten kvl es koordintaprt is megadhatunk, de el kell rnunk, hogy az egysgngyzeten kvli koordintkat hogyan rtelmezze a rendszer, pl. ismtelje a textrt (tegye egyms mell). A textra hatsnak rvnyestse a kpmezkoordinta-rendszerben az brzoland objektum fragmentlsa utn trtnik. Elfordulhat, hogy a transzformcikon tesett textra tbb eleme ltszik egy fragmentumon, vagy ellenkezleg, tbb fragmentumon ltszik egyetlen texel. Ennek a problmnak tbbfle megoldst knlja a rendszer, a felhasznlk ltal kivlaszthat n. szrsi mveleteken keresztl. Ezek a mveletek rendkvl szmtsignyesek, ezrt a fejlettebb grafikus munkahelyek hardverbl tmogatjk a textralekpezst. Ha tbb textrt felvltva hasznlunk, akkor clszer textraobjektumokat ltrehozni, melyek egy-egy textrt (esetleg tbb felbontsban) tartalmaznak. Nhny OpenGL implementciban textraobjektumok munkacsoportjt lehet ltrehozni. A csoporthoz tartoz textrk hasznlata hatkonyabb, mint a csoporton kvliek. Ezeket a nagy hatkonysg textraobjektumokat rezidensnek nevezik, s ezek hasznlatt ltalban hardveres vagy szoftveres gyorstk segtik. A felhasznl ltal elrhat, hogy a textra hogyan hasson a megjelentend objektum sznre. Megadhatjuk, hogy a megfelel texel(ek) szne legyen a fragmentum szne (egyszeren fellrja a fragmentum sznt, mintha egy matrict ragasztannk r), elrhatjuk, hogy a textrval mdostsa (pontosabban sklzza) a fragmentum sznt, ami a megvilgts s textrzs hatst kombinlja, vgl a fragmentum sznnek s egy konstans sznnek a textraelemen alapul keverst is elrhatjuk. A textrk trolsra, betltsre s felptsre egy kln forrsllomny lett ltrehozva, az ftexture.h. A forrsllomny legelejn konstansok segtsgvel megadjuk, hogy hny bitmap kpet fogunk betlteni s hny textrnk lesz:#define MAX_TEXTURE_NAMES #define MAX_TEXTURE_FILES 8 8
Ltrehozunk egy struktra tpust Texture_File nvvel, amely egy llomnynevet trol karakterlnc formjban, s kt vltozt, amelyek az adott textrnak meg fogjk adni a minimalizlsi s maximalizlsi szrinek az rtkt. Ezen struktratpus segtsgvel ltrehozzuk a texture_file tmb vltozt, amelyet egyben inicializlunk a betltend fjlnevekkel s kvnt textra szrsi mdokkal. Ezutn ltrehozunk egy egsz szmokat tartalmaz tmbt, mely trolni fogja a beolvasott textrkra val hivatkozsokat, s majd ezen keresztl fogunk hivatkozni az egyes textrkra. Az osztly, amely segtsgvel a textra beolvasst megoldjuk a CFTexture, amelynek kt privt s egy publikus tagfggvnye van. A LoadBMP privt tagfggvny szerepe, hogy a paramterknt tadott llomnynv alapjn beolvassa a bmp llomnyt, amelyet textraknt szeretnnk felhasznlni, visszatrtsi rtke a beolvasott textra cmre hivatkoz mutat. A fggvny trzsben ltrehozunk egy file 22
nev vltozt a fjl mveletek elvgzse szempontjbl. Egy if utastsban leellenrizzk, hogy a paramterknt tadott karakterlnc tartalmaz-e valamit. Ha NULL az rtke akkor kilpnk a fggvnybl s a textra cmeknt NULL rtket trtnk vissza, ami jelzi, hogy hiba trtnt a beolvass sorn. Ezutn megnyitjuk az llomnyt olvassra. A kvetkez if utastsban megnzzk, hogy sikerltek megnyitnunk. Ha a file tartalma nem egyenl NULL-al akkor sikeresen megtrtnt az llomny megnyitsa, ami utn az if utasts trzsben bezrjuk az llomnyt, majd meghvjuk az auxDIBImageLoad fggvnyt a bitmap kp betltsre, amelynek visszatrtsi rtkt visszatrtjk a bitmap betlt fggvnynknek. A fggvny legvgn pedig NULL rtket trtnk vissza jelezve, hogy hiba trtnt. A LoadGLTexture fggvnynl a paramterknt tadott egsz rtk fog felhasznldni arra, hogy tudjuk hnyadik textrt tltjk be. A fggvny elejn tallhat Status logikai vltoz (kezdeti rtke false) fogja jelezni a fggvny vgn visszatrtdve, hogy volt-e hiba, vagy sem. A TextureImage vltoz fogja trolni a textrt. If utasts paramtereknt tadjuk a TextureImage[0] = LoadBMP (texture_file[tex_id].filename) parancsot, amely ha sikeresen lefut akkor a beolvasott bitmap a Texture_Image vltozba fog tmentdni, ellenkez esetben visszatrnk a fggvnybl a Status vltoz rtkvel, ami ez esetben false. Siker esetn az if utasts trzsben a Status vltoz rtkt true-ra lltjuk, majd egy 2D textraobjektumot hozunk ltre a TextureName[tex_id] nvhez hozzkapcsolva (glBindTexture). A textra generlshoz a glTexImage2D fggvnyt alkalmazzuk, amelyben sorban megadjuk paramterekknt, hogy 2D textrt hozunk ltre, a msodik paramter rtke 0, mivel csak egy felbontsban fogjuk trolni a textrt, a harmadik paramter a texelek sznkomponenseinek lersra szolgl, a negyedik s tdik paramterek a textra szlessgt, illetve magassgt adjk meg, a hatodik paramter a textra formtumt, a hetedik a textra tpust rja le. Az utols paramter pedig a ltrehozand textra adatainak trolsra szolgl tmb cme. A textrk sorai s oszlopai szmnak 2 hatvnyainak kell lenni. A 0-s szintet ltrehoztuk (a legnagyobb textra felbontst), s a gluBuild2DMipmaps fggvny segtsgvel ltrehozzuk a textra sszes szksges alacsonyabb felbonts vltozatt, paramterei hasonlak az elbbi fggvnyhez, azzal a kivtellel, hogy a msodik paramtert elhagyjuk . A texelek nagytsra, illetve kicsinytsre hasznlt szrket a glTexParameteri fggvny segtsgvel lltjuk be. Els paramterknt a textra dimenzijt adjuk meg (GL_TEXTURE_2D), msodik paramternek a GL_TEXTURE_MAG_FILTER a nagytshoz hasznland szr belltshoz s a GL_TEXTURE_MIN_FILTER rtket a kicsinytshez, az utols paramter pedig a szrs tpusnak megadsra szolgl: Szr GL_TEXTURE_MAG_FILTER GL_TEXTURE_MIN_FILTER Szrs tpusa GL_NEAREST, GL_LINEAR GL_NEAREST, GL_LINEAR, GL_NEAREST_MIPMAP_NEAREST, GL_NEAREST_MIMPAP_LINEAR, GL_LINEAR_MIPMAP_NEAREST, GL_LINEAR_MIMAP_LINEAR
Tblzat 1 A textrk kicsinytshez s nagytshoz megadhat szrk
A szrs tpusnak alaprtelmezettknt GL_LINEAR lett megadva mind a nagytshoz, mind pedig a kicsinytshez, hogy a legjobb minsgben jelentdjenek meg, de ez megvltoztathat a program elindulsa eltti konfigurcis ablakban trtn belltssal a Texture quality alatti legrdl listbl kivlasztva egy lehetsges mdot a hrom kzl, melyek alacsony, kzepes s magas textra minsget jelkpeznek. A glTexEnvi fggvny segtsgvel azt mondjuk meg, hogy a textrt hogyan hasznlja a rendszer. Ebben az esetben csak simn rrajzolja a felletekre, nem hasznl klnfle funkcionalitsokat, mint a textra kombinlsa a feldolgozand fragmentum sznvel. A fggvny els paramtere GL_TEXTURE_ENV kell legyen, a msodik paramter GL_TEXTURE_ENV_MODE, az utols paramter pedig GL_MODULATE gy az elbbiekben lert textra rajzolsi mdot rjk el. A fggvny vge 23
eltt egy if utastsban leellenrizzk, hogy textrt tartalmaz-e a TextureImage vltoz. Ha igen akkor felszabadtjuk azt. A fggvny legvgn pedig visszatrtjk a Status vltoz rtkt. LoadAllTextures tagfggvny segtsgvel elssorban MAX_TEXTURE_NAMES darab, jelenleg hasznlaton kvli textraobjektum nevet generlunk a TextureName tmbbe. Ezutn egy for ciklus hasznlatval, amelynek indexe (tex_id) 0-tl megy MAX_TEXTURE_FILES-ig, szerre betltjk a tex_id-nek megfelel textrt meghvva a LoadGLTexture fggvnyt a tex_id paramterrel, ha ez sikertelen lenne akkor a fggvnybl kilpnk az aktulis sikertelen betlts esetn a tex_id rtkkel. Ha a fggvny sikeres volt -1-et trtnk vissza. Az osztlyon kvl a forrsllomny vgn tallhat a GetTextureID fggvny mely, a paramterknt tadott fjlnv felhasznlsval egy for ciklusban vgigmegy minden textrn s ha tall megfelel fjlnevet a texture_file tmbben, akkor visszatrti az azonostjt, a tex_id-t. Ha nem tallt hasonlt akkor 0 rtkkel kilp a fggvnybl. Az osztly hasznlathoz a Main.cpp forrsllomnyban betesszk az llomny elejre az ftexture.h llomnyra val hivatkozst. Ezutn a globlis vltozk rszen ltrehozunk egy textures elnevezs objektumot a CFTexture osztlybl. Az InitGL fggvnyben pedig a vgre betesszk a textures.LoadAllTextures fggvnyhivatkozst egy if utastsba, mely hatsra ha sikertelenl vgzdtt a fggvny akkor -1-nl klnbz rtket fog visszatrteni s akkor kiratjuk a textrnak az azonostjt, melyet nem sikerlt betlteni s kilpnk a fggvnybl false visszatrtsi rtkkel, jelezve a programnak, hogy az inicializls nem jrt sikerrel s a program be kell zrdjon. A GetTextureID fggvny a Milkshape 3D modell betltse esetn a textra megadsnl lett felhasznlva a Model.h llomny Model::reloadTextures fggvnyben.
OpenGL bvtmnyekAhhoz, hogy az OpenGL j fejlesztseit vagy bvtmnyeit hasznlni tudjuk, szmos j OpenGL forrsllomnyt kell hozzadjunk a projektnkhz. A glext.h s wglext.h llomnyokban tallhatak a frisstett konstansok, fggvnyek s sok ms a legjabb OpenGL verzihoz. Br OpenGL szmos platformon hasznlhat a wglext.h llomny windows specifikus implementcikat tartalmaz. Ezek a bvtmnyek alkalmazhatak arra, hogy szebb s/vagy gyorsabb tegyk az OpenGL programunkat. A bvtmnyek hasznlathoz elszr ltrehozzuk a vltozkat, amelyek szksgesek a szmunkra. Ezek az ftexture.h llomny legelejn tallhatak. A gl_extension karakterlncban fogjuk trolni a lehetsges bvtmnyeket. A glFogCoordfExt vltoz fogja tartalmazni a kd belltshoz szksges fggvny cmt, ugyangy a wglSwapIntervalExt s wglGetSwapIntervalExt a kpernyfrissts belltshoz szksges fggvnyek cmeit. A bvtmnyek betltse az llomny vgn tallhat LoadGLExtensions fggvny segtsgvel trtnik. Elszr eltroljuk a rendszernk ltal tmogatott bvtmnyeket a gl_extension vltozban: gl_extension = (char *)glGetString(GL_EXTENSIONS);. Ezutn a kimentett bvtmnyekben megkeressk az strstr fggvny segtsgvel, hogy ltezik-e neknk megfelel bvtmny. Mindez egy if utasts paramtereknt addik t s emellett a konfigurcis ablakban megadott belltst is figyelembe kell vegyk. Pldul lehet, hogy a rendszernk tmogatja a textra srtst, de mi nem szeretnnk alkalmazni, akkor ne kapcsoldjon be az az rtk mely azt szablyozza. Az els if utastsban a textra srtst, a msodikban az anisotropic szrst ellenrizzk le, hogy tmogatja a rendszernk s ha igen, akkor megnzzk, hogy szeretnnk-e alkalmazni, ha igen akkor a megfelel vltoz rtke true lesz, hanem false. A bvtett kd bekapcsolsnl a fggvny cmt fogjuk eltrolni a glFogCoordfExt vltozban. Az utols dolog amit elvgznk a fggleges frissts kikapcsolsa. A forrsllomnyban lthat hogyan lett megvalstva.
24
Plyamodell betltse s megjelentseA plyamodellek a Milkshape 3D elnevezs modellez program segtsgvel kszltek s elre implementlt forrsllomnyok segtsgvel tltdnek be kisebb mdostsokat eszkzlve rajtuk, hogy megfelelen mkdhessenek. A kvetkez llomnyok tartalmazzk a modell betltshez, megjelentshez szksges osztlyokat s fggvnyeket: Model.h Tartalmaz egy Model elnevezs absztrakt osztly, amelyben struktrk segtsgvel meg vannak adva a modell ltalnos tulajdonsgainak vltozi, valamint a modell megjelentsi s textrzsi fggvnye tallhat itten. A modell betlt fggvny absztraktknt van megadva, mivel ebbl az osztlybl lett szrmaztatva egy osztly a MilkshapeModel.h llomnyban, s azt fogjuk hasznlni. MilkshapeModel.h Tartalmazza az ms3d modell adatstruktrit s a MilkshapeModel osztlyt, amely a Model osztlybl lett szrmaztatva. Ez az osztly implementlja a modell betltst s hasznlja a Model osztly tagfggvnyeit. Hasznlathoz betesszk a Main.cpp s Map.h llomnyba a MilkshapeModel.h llomnyra val hivatkozst. A Map.h llomnyban tallhat a plyt ler struktra tpus defincija (SkyBox), amely tartalmazza a plya gboltjnak s magnak a domborzatnak a textrjnak nevt s textra azonostjt. Deklarlunk egy osztlyt, melynek neve CMap. Ennek privt vltozi a SkyBox struktra tpus ltal definilt skybox vltoz a plya textrk eltrolsra, a domborzati modell (HMapModel) betltsre s megjelentsre szolgl vltoz, valamint egy egsz vltoz mely a display-lista azonostjt fogja trolni, a plya gyorsabb megjelentse miatt, mivel a displaylista elre lekompillja a benne tallhat utastsokat s ezrt minden egyes alkalommal a rendszer nem kell jra elvgezze a kompillst, hanem csak egyszer hajtdik vgre a program elejn, majd utn az azonostn keresztl hivatkozik r a kirajzols szempontjbl. Az osztlynak egyetlen privt tagfggvny a BuildDisplayList, amellyel ltrehozzuk a display listt. A fggvny legelejn lefoglalunk egy hasznlaton kvli indexet a display-lista szmra(glGenLists). Ezutn a glNewList fggvny segtsgvel magadjuk, hogy kompillt display-listt fogunk ltrehozni. Olyan rajzolsi mdot adunk meg, hogy csak az egyik oldalt rajzoljuk ki a hromszgeknek. Ezutn jn az gbolt hat oldalnak a kirajzolsi parancsai, minden oldalnak hozzrendelve a megfelel textrt (glBindTexture), glBegin(GL_QUADS) parancs kiadsra ngyszg rajzolst specifiklunk, ezutn megadjuk az oldal normlist a glNormal3f paranccsal, mindenik oldalnak a normlisa befele kell mutasson a vilgts miatt. A glFogCoordfExt fggvnnyel megadjuk, hogy az adott vertex pozciban mekkora legyen az intenzitsa a kdnek(0-1 kztt, 1-es rtk a legsrbb kdt specifiklja), megadjuk a textra koordintkat a glTexCoord2f fggvnnyel, majd a glVertex3f paranccsal megadjuk a vertex pozcijt, vgl a glEnd paranccsal lezrjuk a ngyszg rajzolst. Ezutn if utasts segtsgvel leellenrizzk, hogy szeretnnk-e kdt hozzrendelni a domborzatunkhoz. Ha a heightmap_fog rtke true akkor bekapcsolt kd mellett elszr eltoljuk a plynkat a megjelents szempontjbl megfelel pozciba s felnagytjuk, majd meghvjuk a HMapModel->draw fggvnyt, hogy jelentdjn meg a domborzat. Az else gon ugyanez a dolog trtnik, azzal a klnbsggel, hogy a kirajzols eltt kikapcsoljuk a kdt s a kirajzols utn pedig bekapcsoljuk azt. A Render tagfggvny fog szolglni arra, hogy megjelentsk a plyt belltva a megjelentend display lista azonostjt a glListBase fggvny segtsgvel, majd meghvjuk a glCallList fggvnyt, melynek hatsra megjelenti az SMapDL lista tartalmt. Mindkt fggvnynek egy display lista azonostjt kell tadni paramterknt, ebben az esetben az SMapDL azonostt.
25
Hasznlathoz a Main.cpp llomny elejre betesszk a Map.h llomnyra val hivatkozst. Ltrehozunk egy globlis dinamikus plya objektumot map nvvel a CMap osztlybl. Az InitGL fggvny trzsben a textrabetlts utn betesszk a map vltoz ltrehozst, mivel dinamikus objektumrl van sz: map = new CMap;, s inicializljuk a plyt meghvva a map->Init fggvnyt. A DrawGLScene fggvny trzsben a camera objektum setView tagfggvnynek meghvsa utn tesszk be a plya kirajzol fggvnynek meghvst, a map->Render-t. A KillGLWindow fggvny vgre betesszk a map objektumot felszabadt parancsot, amely a delete map; utastsbl ll.
SzvegmegjelentsOpenGL rendszerben, hogy szveget tudjunk megjelenteni ltre kell hozzuk a megfelel bettpust vagy betltsk a betket tartalmaz bitmap kpet s abbl, minden bet szmra kln textrt hozzunk ltre. Ezeket aztn display-listba tesszk s annak az azonostjt vltoztatva tudjuk megjelenteni a megfelel bett. A szveg megjelentsre egy kln forrsllomny lett ltrehozva fgltext.h nvvel amelyben a CFGLText nev osztlyban hrom szvegmegjelentsi md tallhat. Az osztly privt vltozi elssorban hrom display-lista azonostt a megjelentsi mdok szmra (b_base, o_base, t_base), egy textra azonost a textrzott szvegmegjelents szmra (_2DTextureFontID), valamint a 3D szveg megjelentshez felhasznlt karakter puffer (gmf). Hrom megjelentsi mdunk lesz a szveg szmra. Bittrkpes, 3D, valamint textrzott szveg megjelentsi mdjt fogjuk implementlni. Elsknt a bittrkpes szveg megjelentsrl lesz sz. A bittrkpes szvegmegjelentsnek a felptsre a BuildBitmapFont fggvny szolgl, amely paramterknt megkapja az ablakunk eszkz kapcsolatt, hogy tudja hov fogja megjelenteni a szveget. A fggvny elejn ltrehozunk egy bettpus vltozt a ltrehozand bettpus szmra (font), s egy vltoz, amely segtsgvel eltroljuk a rgi bettpus belltsokat. A b_base vltozba legenerlunk 96 karakternek trhelyet szolgltat display-listt a glGenLists fggvny segtsgvel. Ezutn a font vltozba felptjk a bettpusunkat, belltva a tulajdonsgait a CreateFont fggvny segtsgvel. Ezutn kivlasztjuk az eszkzkapcsolatunk szmra a font vltoz ltal trolt bettpust s a SelectObject fggvny eredmnyt, amellyel kivlasztjuk a bettpust, eltroljuk az oldfont vltozban. A wglUseFontBitmaps fggvny segtsgvel felptjk a b_base display listba a bittrkpes karaktereket a 32-stl kezdve 96 karaktert, hozzrendelve az eszkz kapcsolathoz. Ezutn kivlasztjuk az oldfont betkszletet, mivel ezzel a bettpussal szeretnnk megjelenteni a szvegnket. Vgl letrljk a font vltozban trolt betstlust. A bittrkpes szveg megjelentsre a glPrintBitmap fggvny szolgl melynek paramterknt a kiratand szveget fogjuk majd tadni. A fggvny vltoz argumentum lehet ezrt ki kell szedjk a kiratand szveget a paramterlistbl. Els lpsknt kikapcsoljuk a 2D textrzst. Ltrehozunk egy a kiratand szveg eltrolsra megfelel 255 karakter mret karakterlncot (text) s egy mutatt a paramterlistra (ap). Leellenrizzk, hogy kapott-e paramterknt a fggvny karakterlncot, mert ha nem akkor kilpnk a fggvnybl. Ezutn az argumentum listbl kihmozzuk a szmunkra fontos kiratand karakterlncot (vsprintf). Ezutn elmentjk az aktulis display lista bitjeit (glPushAttrib), majd belltjuk a display-lista megjelentsnek kezdeti karaktert a 32-sre (glListBase). Ezutn meghvjuk a glCallLists fggvnyt, mely hatsra ki fog ratdni a szvegnk. Ezutn visszalltjuk a rgi display-listt a glPopAttrib fggvnnyel s visszakapcsoljuk a 2D textrzst. A bittrkpes megjelents felszabadtsra a KillBitmapFont fggvny szolgl, amely a ltrehozott b_base display-listt felszabadtja a glDeleteLists fggvny segtsgvel. A kvetkez szvegmegjelentsi md a 3D szveg megjelentse. A felptse a BuildOutlineFont fggvny segtsgvel trtnik, paramtere az ablakunk eszkz kapcsolata, 26
amelyben megfogjuk jelenteni a szveget. A fggvny elejn ltrehozunk egy font elnevezs vltozt, amelyben elfogjuk trolni a kvnt a betstlust a megjelents szmra. Az o_base vltozba legenerlunk 256 karakter szmra szksges trhelyet szolgltat display-listt, majd a font vltozba elmentjk a kvnt betstlusunkat, amelyet a CreateFont fggvny segtsgvel hozunk ltre. Ezutn kivlasztjuk az eszkzkapcsolatunk szmra a font vltozban trolt bettpust a SelectObject segtsgvel. Majd a wglUseFontOutlines fggvnnyel belltjuk 3D szveg tulajdonsgait, egyben hozzkapcsolva a display listhoz, amelybe eltroldik minden egyes karakter. A 3D szveg megjelentsre a glPrintOutline fggvny szolgl, hasonl paramterrel s paramter feldolgozssal, mint a bittrkpes megjelents esetben. Ebben a megjelentsi mdban is ki kell kapcsoljuk a 2D textrzst a megjelents eltt. A megjelents szempontjbl egy for ciklusban kiszmoljuk a megjelentett szveg, hosszt, majd egy eltolst vgznk, hogy kzpre legyen majd igaztva a szvegnk a f forrsllomnyban megadott pozcihoz kpest. A megjelentse ugyangy trtnik, mint a bittrkpes szveg esetn. A fggvny vgn pedig bekapcsoljuk a 2D textrzst. A 3D szveghez ltrehozott display-lista felszabadtsa a KillOutlineFont fggvnyen bell trtnik, hasonlan a bittrkpes szveg felszabadtshoz, azzal a klnbsggel, hogy itten 256 karakter kell felszabadtsunk. A harmadik szveg megjelentsi md, mely implementlva lett a textrzott szveg megjelentse. Felptse a Build2DTextureFont fggvny segtsgvel trtnik, mely egy display-listba (t_base) elmenti a Font.bmp llomnyban tallhat betket feldarabolva egy for ciklust hasznlva a feldarabolsra. Minden bet egy ngyzetbl fog llni. A textrzott szveg megjelentsre a glPrint2DTexture fggvny szolgl, melynek paramterei segtsgvel megadjuk, hogy melyik pozciba szeretnnk kirajzolni a szveget, s magt a karakterlncot. A textrzott szveget kikapcsolt mlysg ellenrzs mellett rajzolja ki a fggvny s 2D vettsi mdot specifikl, majd a fggvny vgn visszakapcsolja a mlysg vizsglatot s a vettsi mdot visszalltja az eredetire. A felszabadt fggvny a Kill2DTextureFont, mely az elbbi szvegmdok felszabadt fggvnyeihez felszabadtja a karaktereket tartalmaz display-listt. Hasznlathoz a Main.cpp llomny elejre betesszk az fgltext.h llomnyra val hivatkozst, majd ltrehozunk egy objektumot (textit) a CFGLText osztlybl. Ahhoz pldul hogy a bittrkpes szveget jelentsnk meg, a textit objektum glBuildBitmapFont tagfggvnyre val hivatkozst betesszk az InitGL fggvny vgre, ezzel elksztve a szveg megjelentst. A szveget a DrawGLScene fggvnyben jelentjk meg. Belltjuk a megjelentsi sznt a glColor3f fggvnnyel, majd a megjelents pozcijt a glRasterPos2f fggvny segtsgvel s vgl a textit objektum glPrintBitmap tagfggvnynek segtsgvel megjelentjk a szveget. A msik kt szvegmd megjelentse is hasonlkppen mkdik. A fggvny trzsben megjegyzs jelek kztt megtallhat a msik kt md hasznlata is. A felszabadts a KillGLWindow fggvny vgre kerl meghvva a textit objektum KillBitmapFont tagfggvnyt.
27
Hangok lejtszsa s vezrlseA hangok betltsre s lejtszsra az OpenAL rendszert hasznljuk. A replgp szimultorban egyelre csak a wav fjlok lejtszsa lett implementlva. A hangrendszer inicializlsa s implementcija az audio.h forrsllomnyban tallhat. Az llomny elejn a hangrendszer hasznlathoz hozz kell rendeljk a projektnkhz a megfelel fggvny knyvtrakat (openal32.lib, alut.lib) s hivatkozsokat a szksges forrsllomnyokra (al.h, alc.h, alut.h). Ezutn kt konstans segtsgvel megadjuk, hogy hny llomny akarunk beolvasni s hny hang puffernk lesz. Egy struktra tpust (SSound) hozunk ltre, amelyet arra hasznlunk fel, hogy egy tmbt (sounds) hozzunk ltre, melyen keresztl egybl inicializljuk a tmbelemeket, megadva a fjlnevet, pozcit, oktvot, hangert s az ismtls mdjt, hogy ismtldjn-e annak a bizonyos hangnak a lejtszsa a vgre rt. A hangrendszer kezelsre egy osztlyt hozunk ltre CAudio nvvel, melynek privt vltozi a kv: alDevice hasznlt hangeszkzt fogja tartalmazni alContext eszkzkapcsolat SoundBuffer Hangadatok SoundSource Hangforrsok max_sources maximlis hangforrsok szma Az Init tagfggvny szolgl az OpenAL hangrendszer elindtsra. Elszr megprbljuk megnyitni az alaprtelmezett hangeszkzt (alcOpenDevice) s eltroljuk az eredmnyt az alDevice vltozban. Ezutn egy if utastson bell leellenrizzk az alDevice vltoz rtkkt s ha az NULL akkor nem sikerlt megnyitni az alaprtelmezett eszkzt s kiratunk egy hibazenetet, majd kilpnk a fggvnybl false visszatrtsi rtkkel, jelezve a programunknak hogy nem folytatdhat tovbb. A hibaellenrzs utn ltrehozzuk az eszkzkapcsolatot a hangeszkznkhz az alcCreateContext fggvny segtsgvel, amelynek eredmnyt tadjuk az alContext vltoznak, amellyel ismt elvgznk egy hibaellenrzst. A kvetkez lps ha nem volt hiba az eszkzkapcsolat aktuliss ttele az alcMakeContextCurrent fggvny segtsgvel. Egy if utastsban az alcGetError parancsot kiadva az alDevice paramterrel megnzzk-e, hogy egyenl-e az ALC_NO_ERROR konstanssal, ami azt jelzi, hogy minden rendben. Ha nem egyenl azt jelenti, hogy hiba trtnt s kiratunk egy hibazenetet s kilpnk a fggvnybl false rtkkel. A kvetkez lps a hangforrsok trhelynek a legenerlsa az alGenBuffers parancs segtsgvel, MAX_AUDIO_BUFFERS hangforrst generlunk le a SoundBuffer vltozba. Az elbbihez hasonl hibaellenrzst vgznk s ha nem volt hiba, akkor egy for ciklusban betltjk a wav llomnyokat a LoadWAV tagfggvny segtsgvel, melyet a kvetkez rszben implementlunk. Ha minden rendben ment a fggvny vgn true visszatrtsi rtkkel kilpnk a fggvnybl. Az egyetlen privt tagfggvny a LoadWAV, mely arra szolgl, hogy az els paramterknt tadott llomnynv ltal meghatrozott wav llomny betltse s hozzrendelje a SoundBuffer tmb, LoadWAV fggvny paramtere ltal meghatrozott indexhez a hang adatot. A fggvny els rszben tallhatak azok a vltozk melyben el fogjuk trolni ideiglenesen a betlttt wav llomny adatait s tulajdonsgait a tovbbi feldolgozshoz. Az alutLoadWAVFile parancs kiadsval betltjk az llomnyt s utna leellenrizzk, hogy nem trtnt-e hiba. Hiba esetn kiratunk egy hibazenetet s kilpnk a programbl. Ezutn hozzrendeljk a SoundBuffer megfelel indexhez a betlttt adatot az alBufferData fggvnnyel, majd a memribl felszabadtjuk a plusz helyet foglal elzetesen betlttt wav adatot amire mr nincs szksg az alutUnloadWAV fggvny segtsgvel. Mindkt lps utn hibaellenrzst vgznk, vgl a fggvny vgn ha minden rendben volt true rtkkel kilpnk. ReleaseSources fggvnyben a hangforrsokat felszabadtjuk az alDeleteSources fggvny segtsgvel, s a hang puffereket az alDeleteBuffers parancs segtsgvel. 28
A felszabadts a Release tagfggvny segtsgvel trtnik, melyben felszabadtjuk a lefoglalt eszkzt s eszkz kapcsolatot. A felszabadts els lpsben leellenrizzk, hogy van-e amit felszabadtanunk, egy if utastson keresztl. Ha nincs akkor kilpnk a fggvnybl. Meghvjuk a ReleaseSources fggvnyt a hangpufferek s forrsok felszabadtsra, majd felszabadtjuk az eszkzkapcsolatot az alcDestroyContext fggvnnyel s utna bezrjuk a hangeszkznket az alcCloseDevice paranccsal. A GetBufferID fggvny arra szolgl, hogy az llomnynv alapjn visszatrtsk az azonostjt egy bizonyos hang puffernek, melyet egy for cikluson bell vgezzk el tallat esetn visszatrti a lps szmt, amelyben tallat van. Ha nincs tallat akkor -1-t fog a fggvny visszatrteni. A CreateSources fggvny segtsgvel fogjuk ltrehozni a hangforrsok szmra a szksges trhelyet az alGenSources fggvnyt alkalmazva. A kvetkez fggvny a SetSource, mellyel belltjuk egy hangforrs pozcijt, oktvjt, hangerejt s visszajtszsi mdjt a paramterben megadott rtkek alapjn. Els kt paramtere a fggvnynek a forrs sorszma s a fjlnv mely a forrs ltal lejtszand wav hangot jelzi. Az x, y, z pozcijt a hangforrsnak elmentjk egy 3 elem vals tmbbe, mert a pozci megadsnl egy tmbt kell majd megadjuk. A buffer vltozba pedig elfogjuk trolni a GetBufferID fggvny eredmnyt, hogy tudjuk melyik elemre hivatkozzunk a SoundSource tmbbl, ezt fogjuk visszajtszani. Az alSource{if}[v] fggvny segtsgvel lltjuk be a forrs tulajdonsgait. Els paramtere a SoundSource[source], amely jelzi, hogy melyik hangforrs tulajdonsgait mdostjuk, msodik s harmadik paramtere a kvetkezk a tulajdonsgok belltsa esetn: Msodik paramter AL_BUFFER AL_PITCH AL_GAIN AL_POSITION AL_LOOPING Harmadik paramter SoundBuffer[buffer] - visszajtszand puffer pitch oktvszm (1.0 az eredeti sebessg) gain hanger position pozci megadsa loop ciklikusan jtssza-e vissza a hangot
Tblzat 2 Hangforrsok tulajdonsgainak megadsa
Ha minden sikeresen befejezdtt akkor true rtkkel kilpnk a fggvnybl. A PlaySource, PauseSource, StopSource fggvnyek a paramter ltal meghatrozott hangforrsnak elindtjk a lejtszst, szneteltetik azt, vagy lelltjk. Mindhrom fggvny felptse hasonl, a funkcionalitst vgz fggvny kivtelvel: alSourcePlay elindtja a paramterknt megadott hangforrs hangadatnak lejtszst. alSourcePause sznetelteti a lejtszst alSourceStop meglltja a lejtszst. Az utols fggvny mely ebben a CAudio osztlyban tallhat a hallgat belltsa. A SetListener fggvny paramtereknt megadjuk a hallgat pozcijt, valamint az elre s flfele mutat normlist. Ezeket a paramtereket tadjuk a loklisan ltrehozott vltozknak (position, orientation), mert a tulajdonsg belltsa tmbk tadsval trtnik. A pozcit s az irnyt az alSetListenerfv fggvny segtsgvel lltjuk be. A pozci belltsnl els paramterknt az AL_POSITION konstanst adjuk meg, msodik paramterknt pedig a position tmbt. Az irny belltsnl els paramtere a fggvnynek az AL_ORIENTATION lesz, msodik paramtere pedig az orientation tmb, mely tartalmazza az elre s flfele mutat vektor normlist. Mind a kt mvelet utn hibaellenrzst vgznk, s ha hiba trtnt akkor kilpnk a fggvnybl. Az osztly hasznlathoz pedig a Main.cpp llomny elejre betesszk az audio.h llomnyra val hivatkozst, hogy tudjuk hasznlni a benne lev osztlyt. Ltrehozunk egy 29
globlis objektumot audio nvvel a CAudio osztlybl. A WinMain fggvnyben a legelejn meghvjuk az audio.Init fggvnyt egy if utasts paramtereknt egyben leellenrizve, hogy a hangrendszer sikeresen inicializldott-e. Hiba esetn kilpnk a programunkbl. Az InitGL fggvnynk vgn lltjuk be a hangforrsokat egy for ciklusban s egyben el is indtjuk a lejtszsukat. A DrawGLScene fggvny vgn mdostjuk a replgp motor hangjnak forrst s a hallgat pozcijt. A hangrendszer felszabadtsa a WinMain fggvny vgn trtnik meg az audio.Release fggvny meghvsra.
Hlzat hasznlataA hlzattal kapcsolatos funkcionalitsok a multiplayer.h llomnyban lettek implementlva. A hlzat hasznlathoz els sorban be kell linkeljk a ws2_32.lib fggvny knyvtrat. Ltrehozzuk a hlzat inicializlshoz s hasznlathoz szksges konstansokat, mint a hlzati protokoll, hlzati port, csomag mret, s a csomag rkezst jelz. Felsorols konstanssal adjuk meg azon konstansok rtket, mellyel ellenrizni fogjuk, hogy szerverknt vagy kliensknt fut-e a programunk, illetve milyen tpus csomagot kldnk, hogy a fogad program tudja azt megfelelen feldolgozni. Mg van kt globlis vltoz, melyek arra fognak szolglni, hogy eltroljuk bennk a konfigurcis ablakban megadott hlzattal kapcsolatos belltsokat (multiplayer_mode, host). Az osztly neve mellyel a hlzatot kezeljk CMultiplayer. Privt adattagjai egy struktra, melyben a socket adatait elmentjk (sock_addr), valamint hogy milyen tpus a kapcsolat (connection_type), szerver vagy kliens. Publikus adattagok pedig maga a kommunikcis socket game_socket elnevezssel s a hlzat aktv llapott jelz active logikai vltoz. A kimen (outgoing_packet) s bejv (incoming_packet) csomagok tartalma pedig karakterlnc formjban lesznek elmentve. Az osztly els tagfggvnye melyrl sz lesz a szerver inicializl InitServer fggvny. Ezen bell legelre ltrehozunk egy vltozt, mely a socket adatait fogja tartalmaz (wsaData). Ezutn megprbljuk elindtani a kommunikcis socketet (Winsock 2.0) a WSAStartup fggvny segtsgvel, miutn a Winsock informci a wsaData vltozba kerl. Ha hiba trtnt a fggvny visszatrtsi rtke egyenl lesz a SOCKET_ERROR konstanssal, aminek kvetkeztben kilpnk a fggvnybl egy hibazenettel, elszr felszabadtva a ltrehozott Winsock socketeket. Ha a fggvny sikeresen lefutott, akkor a sock_addr vltozba eltroljuk a cmtartomny csaldjt (AF_INET - amely az internet cmek csaldjbl val), a bejv IP cmet (INADDR_ANY brmilyen IP cmrl fogad kommunikcit), a hlzati portot talaktva a megfelel tpusra (MULTIPLAYER_PORT). A game_socket vltozban eltroljuk a socket ltrehozs eredmnyt, melyet a socket fggvny segtsgvel vgznk el. Ezutn egy if utastsban leellenrizzk, hogy sikerlt-e ltrehozni a socketet. Ha nem akkor kilpnk a fggvnybl, felszabadtva a ltrehozott Winsock socketeket. Ezutn a bind fggvny segtsgvel a game_socket vltozhoz hozzcsatoljuk a sock_addr vltozban eltrolt adatokat, hogy adatokat kaphassunk a hlzaton keresztl. Ezt a fggvnyt is egy if utastson bell hvjuk meg, gy egybl le tudjuk ellenrizni, hogy trtnt-e hiba, s ha igen akkor kilpnk a fggvnybl. A socketet ezutn hallgatz mdba tesszk a listen fggvny segtsgvel, hogy tudjuk fogadni a csomagokat. A fggvny vgn az active llapotot jelz logikai vltoz rtkt true-ra lltjuk jelezve, hogy sikerlt elindtani a szervert. A connection_type vltoznak rtkl a MULTIPLAYER_SERVER rtket adjuk. Minden rendben van s kilpnk a fggvnybl true visszatrtsi rtkkel. A kvetkez fggvny a kliens inicializl fggvny, melynek neve InitClient. Egyetlen paramtere egy karakterlnc, mely a szerver nevt fogja tartalmazni mikor meghvjuk. A socket elindtsa ugyangy a WSAStartup fggvny segtsgvel trtnik, mint a szerver esetben. Ennek a fggvnynek van mg egy plusz hp elnevezs hostent tpus loklis vltozja melyben a szerver informciit troljuk el meghvva a gethostbyname fggvnyt a hostname 30
paramterrel. Ha a hp rtke ha NULL akkor kilpnk a fggvnybl egy hibazenettel s felszabadtva a ltrehozott socketeket. Ha sikeres volt a mvelet akkor feltltjk a sock_addr struktrt. Elsknt a szerver cmt (hp->h_addr, hp->h_length) msoljuk t a hp vltozbl a memcpy fggvny hasznlatval. Ezutn a cmtartomny csaldjt mentjk ugyancsak a hp vltozbl (hp->h_addrtype), vgl a hlzati portot, amit talaktva a megfelel tpusra mentnk el (MULTIPLAYER_PORT). Ezutn ltrehozzuk a socketet a socket fggvny hasznlatval s ennek eredmnyt troljuk a game_socket vltozban. A hibaellenrzs kvetkezik, hogy ltrejtte a socket. Ha nem akkor kilpnk a fggvnybl. Ha sikeres volt a mvelet csatlakozunk a szerverhez a connect fggvny segtsgvel, ha lehetsges, ellenkez esetben kilpnk a fggvnybl egy hibazenettel s felszabadtva a ltrehozott socketeket. Sikeres kapcsolat esetn elindtjuk a hallgatzst a listen fggvnnyel, hogy tudjunk csomagokat fogadni. Az active vltoz rtkt true-ra lltjuk jelezve, hogy a kliens aktv s a connection_type vltoz rtkt MULTIPLAYER_CLIENT-re lltjuk. Vgl true rtkkel kilpnk a fggvnybl, jelezve, hogy minden rendben van. A Release fggvny segtsgvel szabadtjuk fel a lefoglalt socketeket. Elszr leellenrizzk, hogy aktv-e az adott kapcsolat, mert ha nem akkor nincs amit felszabadtani is kilphetnk a fggvnybl. A closesocket fggvny meghvsval bezrjuk a kommunikcis socketnket, majd a WSACleanup fggvny meghvsra felszabadtdnak a ltrehozott socketek. A fggvny vgn az active vltoz rtkt false-ra lltjuk. A Send fggvny valstja meg az zenetkldst. A fggvny elejn leellenrizzk, hogy a hlzati kapcsolatunk aktv-e az active vltoz rtknek vizsglatval. Ha nem aktv akkor kilpnk a fggvnybl false rtkkel. Ezutn leellenrizzk, hogy a kapcsolat tpusa szerver-e, ha igen akkor a sendto fggvnyt hasznljuk az zenet elkldsre, hanem a send parancsot. A retval vltozban troljuk az zenetklds fggvnynek visszatrtsi rtkt, melyet hibaellenrzsre hasznlunk fel a fggvny vgn egy if utastsban. Ha hiba trtnt az zenet elkldsekor false rtkkel kilpnk a fggvnybl. Ha minden rendben volt a fggvny vgn true rtkkel lpnk ki a fggvnybl. A Receive fggvny az zenetfogadst valstja meg. Folyamata hasonl az zenet kldshez azzal a klnbsggel, hogy a sendto s send fggvnyek helyett szerver kapcsolat esetn az zenet fogadsra a recvfrom fggvnyt, kliens kapcsolat esetn pedig a recv fggvnyt hasznljuk. A hlzat kezels hasznlathoz a Main.cpp llomnyban a legelejre betesszk a multiplayer.h llomnyra val hivatkozst. A CMultiplayer osztlybl ltrehozunk egy globlis objektumot s a megfelel vltozkat, hogy tudjuk milyen tpus kapcsolatunk van (connection_type), vagy ha kliens kapcsolatunk van akkor egy karakterlncban el kell troljuk a szerver nevt (hostname). Ezeken kvl kell mg egy vltoz arra, hogy letroljuk mikor kldtk el a legutols csomagot (time_of_last_packet_sent), gy szablyozni tudjuk majd, hogy msodpercenknt hny csomagot kldjnk. Valamint hibajelz logikai vltozk is ltre lettek hozva tesztels szempontjbl, s hogy hibazenetet tudjunk kiratni ha baj van a csomagok kldsnl (error_sending_packet), vagy fogadsnl (error_receiving_packet). A hlzatos md inicializl fggvnynek meghvsa a WinMain fggvnyen bell trtnik annak fggvnyben, hogy milyen belltsokat vgeztnk a konfigurcis prbeszdablakban. Mindez egy if utastson bell trtnik meg. Itten lltjuk be a csomagfogads konstanst, hogy a windows esemnykezelje figyelni tudja mikor kvetkezik be egy zenet rkezse (WSAAsyncSelect). Az zenet klds a SendMultiplayerPacket fggvnyen bell trtnik meg, minden tizedmsodpercben elmentve a kldend informcit a multiplayer.outgoing_packet vltozba az sprintf fggvnyt alkalmazva. Ezutn vgznk egy hibaellenrzst a multiplayer.Send fggvny meghvsra egy if utastsban. Ezutn a time_of_last_packet_sent vltozba elmentjk az aktulis idt, hogy majd ismt vrjunk egy tizedmsodperc elteltre. Ez a fggvny a WinMain fggvny fciklusban hvdik meg mindig annak fggvnyben, hogy aktv-e a hlzati kapcsolat. Az zenet fogadsa a WndProc fggvny switch utastsn bell valsul meg, akkor hogyha a switch paramtereknt tadott uMsg rtke egyenl az MM_PACKET_RECEIVED konstans rtkvel. Ha ez teljesl akkor meghvjuk a multiplayer.Receive fggvnyt, mely