P R O G R A M U J E M Etextúrou celú obrazovku. Tu nám staèí poui dvojparametrový variant funkcie glVertex,pretoe sme v ortografickom móde. Nakoniec sa prepneme <strong>na</strong>spä <strong>do</strong> perspektívneho mó−du, zapneme håbkový test, vypneme blending a obnovíme maticu, ktorú sme si <strong>na</strong> zaèiat−ku uloili.Orto();glBegin(GL_QUADS);glTexCoord2f(0.0f,1.0f); glVertex2f(0.0f,0.0f);glTexCoord2f(0.0f,0.0f); glVertex2f(0.0f,800.0f);glTexCoord2f(1.0f,0.0f); glVertex2f(800.0f,600.0f);glTexCoord2f(1.0f,1.0f); glVertex2f(800.0f,0.0f);glEnd();Perspectiv();glE<strong>na</strong>ble(GL_DEPTH_TEST);glDisable(GL_BLEND);glPopMatrix();glEnd();}Výborne, aj toto máme za sebou. Hor' sa <strong>do</strong> kresliacej funkcie! Dajme tomu, e chce−me ma rozmazaný rotaèný pohyb kocky. U viete, ako objekty rotova. Takisto viete vy−kresli kocku, take tam, kam má ís kocka, pôjde komentár /*SEM POJDE KOCKA*/.void DrawGLScene(void){... //poèiatoèné <strong>na</strong>stavenia môeme preskoèiPomocou funkcie Casovac zistíme, èi máme vyrenderovanú kocku skopírova <strong>do</strong> textú−ry a vyrenderova aj motion blur.if(Casovac(60)){Najprv zmeníme ve¾kos viewportu <strong>na</strong> štvorec so stranou ve¾kosti 512 (aby sa námvmestil <strong>do</strong> textúry). Potom zavoláme funkciu motion_blur, ktorá vyrenderuje motion blur.Napokon vykreslíme kocku, bindujeme textúru, <strong>do</strong> ktorej sa má obrazovka skopírova, apomocou glCopyTexImage2D ju skopírujeme. Nakoniec vyèistíme color buffer aj depthbuffer a <strong>na</strong>stavíme viewport <strong>na</strong> pôvodnú hodnotu.glViewPort(0,0,512,512);motion_blur();/*SEM POJDE KOCKA*/glBindTexture(GL_TEXTURE_2D,texture[0]); //textúra, <strong>do</strong> ktorej sa skopíruje obrazovkaglCopyTexImage2D(GL_TEXTURE_2D,0,GL_RGB,0,0,512,512,0); //skopíruj obrazovku <strong>do</strong> tex−túry – PCR è. 6/2003glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);glViewPort(0,0,800,600);}Ale ak ešte nemáme vykresli motion blur, lebo <strong>na</strong> to nie je èas, staèí nám vykresli nor−málnu kocku, ktorá je u v skopírovanej textúre. Èie opä zavoláme funkciu motion_blura <strong>na</strong>kreslíme kocku.motion_blur();/*SEM POJDE KOCKA*/} //koniec DrawGLSceneA je to! Teraz staèí spusti program a uvidíte rotujúcu kocku, ktorá sa otáèa a za òouje „šmuha“. Skúste sa pohra s èíslami, <strong>do</strong>stanete iný výsle<strong>do</strong>k. Tento efekt sa pouívamálokedy, ale je východiskom pre radial blur, o ktorom si niekedy povieme. Len spome−niem, e radial blur je priestorové rozmazanie, èie objekt vyzerá, akoby iaril. Ale ajmotion blur nájde svoje uplatnenie v hre (<strong>na</strong>príklad ak je hlavný hrdi<strong>na</strong> mierne pripitý, ulen musíte vyrieši, ako objekty zobrazova dvojmo ☺).HEIGHT MAPPING. U máte <strong>do</strong>s prechádzok po miestnostiach, bu<strong>do</strong>vách a po<strong>do</strong>b−ných uzavretých priestoroch? Chceli by ste prevetra OpenGL aj <strong>na</strong> èerstvom vzduchu nie−kde v prírode? Presne tak. Našou druhou témou bude height mapping alebo, povedané<strong>na</strong>šou ¾ubozvuènou slovenèinou, terén. Táto téma zahàòa <strong>na</strong>èítanie terénu zo súboru,jeho vykreslenie a následne aj pohyb po òom. Teraz si ukáeme <strong>na</strong>jjednoduchší spôsob,ako zobrazi terén v jednej farbe, a <strong>na</strong>budúce si povieme nieèo o textúrovaní terénu.Terén bude uloený v súbore typu raw, èo nie je niè iné ako samotné dáta v binárnomformáte. Mapa v grafickom prehliadaèi vyzerá ako biele mraky <strong>na</strong> èiernej oblohe, prièomplatí, e èím belší pixel, tým je to miesto vyššie. Ako však vytvori takúto mapu? Existuje<strong>na</strong> to program, ktorý som mal, ale musel som formátova hard disk a u neviem, skadesom ho stiahol. Ak si však spomeniem, dám vám to ihneï vedie. Tento program je šíre−ný aj so zdrojovými kódmi a ponúka hneï nieko¾ko algoritmov <strong>na</strong> vytvorenie terénu.Problém je len v tom, e výškovú mapu ukladá vo formáte tga, ale nie je problém ho sko−pírova <strong>do</strong> <strong>na</strong>mi pouívaného formátu raw. Ale <strong>do</strong>s bolo teórie, poïme <strong>na</strong> prax.Ako vdy aj tentoraz vychádzame zo základného zdrojového kódu s kamerou <strong>na</strong> pre−sun po teréne a svetlom. Textúrovanie zatia¾ nepotrebujeme. Do projektu pridajte novýsúbor a pomenujte ho hoci teren.cpp. Tento súbor bude obsahova funkcie <strong>na</strong> <strong>na</strong>èítaniea vykreslenie terénu. V programe budeme pracova s mapou ve¾kosti 1024 × 1024 pixe−lov. Prvou funkciou bude funkcia, ktorej zadáme súradnice bodu <strong>na</strong> mape, smerník <strong>na</strong>pole mapy a tá vráti jeho výšku.#include #incldue #include #include #include int Vyska(BYTE *mapa, int X, int Y){Aby sme vylúèili monos, e zadáme súradnice mimo mapy, urobíme malú fintu. Èís−lami, ktoré sme zadali, podelíme èíslo 1024, èo je ve¾kos mapy. Nepodelíme ich však nor−málnym delením, ale delením typu modul (zaujímavé slovo). Toto delenie vracia zvyšokpo celoèíselnom delení, a tak aj keby sme zadali hodnoty správne, vrátená výška by zod−povedala výške <strong>na</strong> mape. Takto získané èísla uloíme <strong>do</strong> premenných mapax a mapay.int mapax=X%1024;int mapay=Y%1024;Takisto sa musíme uisti, èi pole, z ktorého máme èíta údaje, existuje. Ak nie, funkciuukonèíme návratovou hodnotou 0.if(!mapa) return 0;Keïe pole mapa je jednorozmerné, musíme nájs správne miesto v pamäti. Bolo by¾ahšie ako údaje <strong>na</strong>èítava hodnoty z dvojrozmerného po¾a, ale bolo by obané <strong>do</strong>ò hod−noty zapisova zo súboru.return mapa[mapax+(y*1024)];}Druhou funkciou v tomto súbore bude vyrenderovanie mapy. Funkcia bude ma názovRenderMap a bude ma jeden parameter, a to pole, z ktorého bude èíta údaje. Taktomôeme <strong>na</strong>rába s viacerými mapami súèasne, pravdae, aj nároky <strong>na</strong> pamä budú väèšie(<strong>na</strong>príklad jed<strong>na</strong> mapa s rozmermi 1024*1024 pixelov zaberá v pamäti 1 MB, èo je <strong>do</strong>s).Na zaèiatok si definujeme zopár premenných <strong>na</strong> uloenie aktuálnej pozície <strong>na</strong> mape asúradníc vrcholu.void RenderMap(BYTE VyskovaMapa[]){int mx,my=0; //pozícia <strong>na</strong> mapeint x,y,z; //súradnice vrcholuAj tu otestujeme, èi existuje pole s mapou, a ak áno, môeme zaèa vykres¾ova mapupo štvorcoch.if(!VyskovaMapa) return;glBegin(GL_QUADS);Cez dva vnorené cykly for prejdeme postupne celú mapu. Lene bolo by to nároèné <strong>na</strong>výpoètový výkon a aj zobrazovanie by bolo nároèné. Preto budeme <strong>na</strong>èítava kadý 16.bod mapy. Výzor sa ve¾mi nezmení a poèítaèu to urýchli prácu.for(mx=0;mx
P R O G R A M U J E M EFILE *subor=NULL;subor=fopen(cesta,"rb");if(subor==NULL){PostQuitMessage(0);}Ak sme zadali správnu cestu a súbor sa nám podarilo otvori, môeme dáta <strong>na</strong>èíta <strong>do</strong>po¾a, ktoré sme funkcii zadali. Ak sme hotoví, súbor môeme zavrie.fread(mapa,1,velkost,subor);fclose(subor);}Súbor teren.cpp teraz môeme uloi a zavrie. Do súboru init.cpp si pridáme definíciufunkcie LoadRAW, pretoe ju linker z externého súboru nerozpozná. Takisto si definuje−me pole typu byte s rozmermi 1024 × 1024 bajtov, spolu teda 1 MB.BYTE mapa[1024*1024];void LoadRAW(LPSTR cesta, int velkost, BYTE* mapa);Do funkcie InitGL si pridáme volanie funkcie LoadRaw, ktorou <strong>na</strong>èítame údaje o mape<strong>do</strong> po¾a.LoadRAW(„dat/mapa.raw“,1024*1024,mapa);Ešte treba zmeni posledný parameter volania funkcie gluPerspective z ResizeGLSceneaspoò <strong>na</strong> hodnotu 3000.0f, pretoe mapa je ve¾ká a pri pôvodnom <strong>na</strong>stavení by sme junevideli celú. Ak ste to zmenili, presuòte sa <strong>do</strong> funkcie s kresliacou funkciou, kde si defi−nujte pole mapa ako externú premennú a pridajte aj definíciu funkcie RenderMap. Potomstaèí zavola z kresliacej funkcie:RenderMap(mapa);A je to hotové. Po skompilovaní by sa vám mal objavi poh¾ad <strong>na</strong> prekrásnu krajinu, aak máte v projekte aj kameru, môete sa po nej aj poprechádza. No nie je to nádhera?ZÁVER. Touto èasou sme opä pokroèili o krok <strong>do</strong> tajov OpenGL. Ak máte nejaké pri−pomienky, návrhy alebo vám nieèo nejde, <strong>na</strong>píšte mi, teším sa <strong>na</strong> vaše e−maily (ale aknemusíte, tak zbytoène nepíšte ☺). Nabudúce si preberieme textúrovanie vyrenderovanejkrajiny, a ak zvýši priestor, aj detekciu kolízie medzi kamerou a terénom. Take máte sa<strong>na</strong> èo teši. Prajem pekný zvyšok júla.Lukáš StaòaDelphi v praxi / 28. èas: Otázky a odpovede II.Témy, ktoré som si <strong>na</strong>plánoval ako obsah týchto èastí, som trošku posunul, a to z jedi−ného dôvodu. Pokladám za potrebné uvies isté rutiny, ktoré sa priam pýtali <strong>na</strong> svetlo sve−ta práve prostredníctvom vás. Verím, e sa mi podarilo odpoveda všetkým, ktorí sa <strong>na</strong>mòa obrátili s prosbou o pomoc v programovaní. Z týchto prosieb som vybral tie, ktorésom aj ja musel h¾ada vo svojom „programátorskom svete“ a ktoré sa vám pridajú priprogramovaní akejko¾vek aplikácie. Nebudú ma síce <strong>na</strong>jelementárnejší charakter progra−mu, ale myslím, e zamútite hlavu nie jednému programátorovi, ktorý uvidí isté novátor−ské riešenia vo vašom programe.MONO VLOI CUDZIU APLIKÁCIU DO NAŠEJ? Odpoveï <strong>na</strong> túto pomernejednoducho znejúcu otázku som po dlhom pátraní <strong>na</strong>šiel. Jedinou praktickou monosouje <strong>na</strong>stavi formulár ako rodièovské okno. Druhý krok pozostával z následného presunutiaexternej aplikácie funkciou MoveWin<strong>do</strong>w <strong>do</strong> rodièovského formulára, <strong>na</strong>stavenia jehopozície a rozmerov. Posledný ria<strong>do</strong>k je len <strong>na</strong>stavenie prekrytia, teda priority ok<strong>na</strong>. Naotvorenie externého programu sme pouili príkaz WinExec, kde prvým parametrom jecesta k programu a druhým spôsob otvorenia. Aplikácie, ktoré tvoria jadro systému, res−pektíve sú umiestnené v koreni operaèného systému Win<strong>do</strong>ws alebo v jeho systéme,môeme vola priamo bez uvedenia celej cesty k súboru (v príklade uvedený „notepad“ –poznámkový blok).procedure TForm1.FormCreate(Sender: TObject);var wnd:HWND;beginWinExec('notepad',SW_SHOW);wnd:=FindWin<strong>do</strong>w('notepad',nil);if Wnd0 then beginWin<strong>do</strong>ws.SetParent(Wnd, Handle);MoveWin<strong>do</strong>w(Wnd, 0, 0, ClientWidth, ClientHeight, false);SetForegroundWin<strong>do</strong>w(Wnd);end;end;EXISTUJE DIALÓG NA VYH¼ADANIE ADRESÁRA? V záloke dialógov, ia¾,takýto komponent nenájdeme. Ale pomocou direktívy kninice FileCtrl môeme vyvolaštandardný dialóg bez akéhoko¾vek vytvárania vlastných rutín a formulárov. Radšej si šet−rime sily a sústreïujme ich <strong>na</strong> zloitejšie algoritmy. Pre úplnú funkènos <strong>do</strong>píšte <strong>do</strong> klau−Obr. 1zuly uses kninicu FileCtrl (bez nej by externé vyvolanie nebolo moné). Funkcia Select−Directory zavolá dialóg, ktorého ukonèením, resp. potvrdením sa <strong>do</strong> premennej path uloícesta k vybranému adresáru. Na skúšku som v príklade pouil príkaz ShowMessage, ktorý<strong>na</strong> demonštraèné úèely postaèuje. Prostredníctvom neho uvidíme vybranú cestu.procedure TForm1.Button1Click(Sender: TObject);var path:string;beginif FileCtrl.SelectDirectory(path, [sdAllowCreate, sdPerformCreate,sdPrompt], 0) then ShowMessage(path);end;AKO ZMENI TITULOK DIALÓGU? Tentoraz hovoríme o štandardných dialógo−vých oknách, ktoré nám ponúka záloka Dialogs. Niektoré dialógy majú staticky defino−vaný titulok ok<strong>na</strong>, prièom jeho zme<strong>na</strong> podlieha zaslaniu správy SendMessage komponen−tu. V <strong>na</strong>šom prípade zmeníme titulok <strong>na</strong> komponente PrintDialog. Aj keï z praktickéhoh¾adiska takáto monos neplní nijakú dôleitú úlohu, je <strong>do</strong>bré si rozšíri monosti Send−Message. Parameter WM_SETTEXT je, samozrejme, zo skupiny Win<strong>do</strong>ws Message.procedure TForm1.PrintDialog1Show(Sender: TObject);beginSendMessage(PrintDialog1.Handle,WM_SETTEXT, 0, LPARAM(PChar('nový text akéhoko¾vekdialógu')));end;NEŠTANDARDNÝ DIALÓG „OTVORI ÈÍM“. Keïe sme zaèali dialógmi, môe−me pri nich ešte chví¾ku zosta. Pri pouívaní operaèného systému Win<strong>do</strong>ws ste sa urèitestretli s prípo<strong>na</strong>mi súborov. Tie majú rozliènú štruktúru, preto <strong>na</strong> prácu s nimi vyuívamerozlièné programy. Na u¾ahèenie práce s produktmi programov sa zaèala vyuíva inicia−lizácia príslušného programu práve pod¾a koncovky. To zabezpeèuje operaèný systém.V prípade, ak k poa<strong>do</strong>vanej koncovke nie je priradený nijaký program, operaèný systémnám ponúkne interný dialóg „otvori èím“. V òom vyberieme príslušný program, ktorýmchceme súbor otvori alebo priradi mu jeden program, v ktorom sa bude otvára vdy.Tento dialóg je súèasou dy<strong>na</strong>mickej kninice Shell32.dll patriacej k systému. Aj keï cezrozhranie Delphi môeme vola dy<strong>na</strong>mické kninice priamo, nebudeme si komplikovaivot zisovaním názvov funkcií a premenných, ktoré poskytuje spomí<strong>na</strong>ná kninica.Pouijeme radšej internú kninicu ShellAPI, ktorá je súèasou Delphi. Tú treba <strong>do</strong>písa <strong>do</strong>klauzuly uses. Vytvorili sme si funkciu OpenAs, ktorej vstupným parametrom je cesta k sú−boru. Výstup má skôr kontrolný charakter, preto nám postaèuje typ boolean. Všetko ostatnéje prácou ShellAPI s premennou TShellExecuteInfo, ktoré vyvolá spomí<strong>na</strong>ný dialóg v súvis−losti so súborom, ktorého cestu sme zadali ako vstup...Function OpenAs(Filen: String):Boolean;var Info:TShellExecuteInfo;Param:String;beginParam:=Format('Shell32.dll,OpenAs_RunDLL %s',[Filen]);ZeroMemory(@Info, SizeOf(Info));info.cbSize:=SizeOf(Info);info.lpFile:='Rundll32.exe';info.lpVerb:='Open';info.nShow:=SW_SHOWNORMAL;info.Wnd:=GetDesktopWin<strong>do</strong>w;info.lpParameters:=PChar(Param);OpenAs:=ShellExecuteEx(@Info);end;POLOKA V MENU UMIESTNENÁ VPRAVO. Komponent TMainMenu <strong>na</strong>chádza−júci sa v záloke Standard je asi to, èo pouíva kadý programátor s<strong>na</strong>iaci sa <strong>na</strong>progra−mova preh¾adný program. Samozrejme, e pouívanie poloiek menu je ve¾mi jednodu−ché, pokia¾ nechcete umiestni poloku <strong>do</strong> pravého rohu vášho programu. Takúto otázkusom <strong>do</strong>stal od èitate¾a, ktorý prive¾mi experimentuje a <strong>na</strong>padlo mu nieèo, èo som <strong>do</strong>po−114 PC REVUE 7/2003