V tΘto lekci se nauΦφte, jak nahrßt sou°adnice vrchol∙ z textovΘho souboru a plynulou transformaci z jednoho objektu na druh². Nezam∞°φme se ani tak na grafick² v²stup jako spφÜe na efekty a pot°ebnou matematiku okolo. K≤d m∙₧e b²t velice jednoduÜe modifikovßn k vykreslovßnφ linkami nebo polygony.
Poznamenejme, ₧e ka₧d² objekt by m∞l b²t sesklßdßn ze stejnΘho poΦtu bod∙ jako vÜechny ostatnφ. Je to sice hodn∞ omezujφcφ po₧adavek, ale co se dß d∞lat - chceme p°ece, aby zm∞ny vypadaly dob°e. ZaΦneme vlo₧enφm hlaviΦkov²ch soubor∙. Tentokrßt nepou₧φvßme textury, tak₧e se obejdeme bez glaux.
#include <windows.h>// HlaviΦkov² soubor pro Windows
#include <stdio.h>// HlaviΦkov² soubor pro standardnφ vstup/v²stup
#include <math.h>// HlaviΦkov² soubor pro matematickou knihovnu
#include <gl\gl.h>// HlaviΦkov² soubor pro OpenGL32 knihovnu
#include <gl\glu.h>// HlaviΦkov² soubor pro Glu32 knihovnu
HDC hDC = NULL;// Privßtnφ GDI Device Context
HGLRC hRC = NULL;// Trval² Rendering Context
HWND hWnd = NULL;// Obsahuje Handle naÜeho okna
HINSTANCE hInstance;// Obsahuje instanci aplikace
bool keys[256];// Pole pro uklßdßnφ vstupu z klßvesnice
bool active = TRUE;// Ponese informaci o tom, zda je okno aktivnφ
bool fullscreen = TRUE;// Ponese informaci o tom, zda je program ve fullscreenu
Po deklarovßnφ vÜech standardnφch prom∞nn²ch p°idßme novΘ. Rot uklßdajφ aktußlnφ ·hel rotace na jednotliv²ch sou°adnicov²ch osßch, speed definujφ rychlost rotace. Poslednφ t°i desetinnΘ prom∞nnΘ urΦujφ pozici ve scΘn∞.
GLfloat xrot, yrot, zrot;// Rotace
GLfloat xspeed, yspeed, zspeed;// Rychlost rotace
GLfloat cx, cy, cz = -15;// Pozice
Aby se program zbyteΦn∞ nezpomaloval p°i pokusech morfovat objekt sßm na sebe, deklarujeme key, kter² oznaΦuje prßv∞ zobrazen² objekt. Morph v programu indikuje, jestli prßv∞ provßdφme transformaci objekt∙ nebo ne. V ustßlenΘm stavu mß hodnotu FALSE.
int key = 1;// Prßv∞ zobrazen² objekt
bool morph = FALSE;// Probφhß prßv∞ morfovßnφ?
P°i°azenφm 200 do steps urΦφme, ₧e zm∞na jednoho objektu na druh² bude trvat 200 p°ekreslenφ. ╚φm v∞tÜφ Φφslo zadßme, tφm budou p°em∞ny plynulejÜφ, ale zßrove≥ mΘn∞ pomalΘ. No a step definuje Φφslo prßv∞ provßd∞nΘho kroku.
int steps = 200;// PoΦet krok∙ zm∞ny
int step = 0;// Aktußlnφ krok
Struktura VERTEX obsahuje x, y, z slo₧ky pozice jednoho bodu ve 3D prostoru.
typedef struct// Struktura pro bod ve 3D
{
float x, y, z;// X, y, z slo₧ky pozice
} VERTEX;// Nazvan² VERTEX
Pokusφme se o vytvo°enφ struktury objektu. co vÜechno budeme pot°ebovat? Tak urΦit∞ to bude n∞jakΘ pole pro ulo₧enφ vÜech vrchol∙. Abychom ho mohli v pr∙b∞hu programu libovoln∞ m∞nit, deklarujeme jej jako ukazatel do dynamickΘ pam∞ti. CeloΦφselnß prom∞nnß vert specifikuje maximßlnφ mo₧n² index tohoto pole a vlastn∞ i poΦet bod∙, ze kter²ch se sklßdß.
typedef struct// Struktura objektu
{
int verts;// PoΦet bod∙, ze kter²ch se sklßdß
VERTEX* points;// Ukazatel do pole vertex∙
} OBJECT;// Nazvan² OBJECT
Pokud bychom se nedr₧eli zßsady, ₧e vÜechny objekty musφ mφt stejn² poΦet vrchol∙, vznikly by komplikace. Dajφ se vy°eÜit prom∞nnou, kterß obsahuje Φφslo maximßlnφho poΦtu sou°adnic. Uve∩me p°φklad: jeden objekt bude krychle s osmi vrcholy a druh² pyramida se Φty°mi. Do maxver tedy ulo₧φme Φφslo osm. NicmΘn∞ stejn∞ doporuΦuji, aby m∞ly vÜechny objekty stejn² poΦet bod∙ - vÜe bude jednoduÜÜφ.
int maxver;// Eventußln∞ uklßdß maximßlnφ poΦet bod∙ v jednom objektu
Prvnφ t°i instance struktury OBJECT uklßdajφ data, kterß nahrajeme ze soubor∙. Do ΦtvrtΘho vygenerujeme nßhodnß Φφsla - body nßhodn∞ rozhßzenΘ po obrazovce. Helper je objekt pro vykreslovßnφ. Obsahuje mezistavy zφskanΘ kombinacφ objekt∙ v urΦitΘm kroku morfingu. Poslednφ dv∞ prom∞nnΘ jsou ukazatele na zdrojov² a v²sledn² objekt, kterΘ chce u₧ivatel zam∞nit.
OBJECT morph1, morph2, morph3, morph4;// Koule, toroid, vßlec (trubka), nßhodnΘ body
OBJECT helper, *sour, *dest;// Pomocn², zdrojov² a cφlov² objekt
Ve funkci objallocate() alokujeme pam∞¥ pro strukturu objektu, na kter² ukazuje pointer *k p°edan² parametrem. CeloΦφselnΘ n definuje poΦet vrchol∙ objektu.
Funkci malloc(), kterß vracφ ukazatel na dynamicky alokovanou pam∞¥ p°edßme jejφ po₧adovanou velikost. Zφskßme ji operßtorem sizeof() vynßsoben²m poΦtem vertex∙. Proto₧e malloc() vracφ ukazatel na void, musφme ho p°etypovat.
Pozn. p°ekl.: Program by jeÜt∞ m∞l otestovat jestli byla opravdu alokovßna. Kdyby se operace nezda°ila, program by p°istupoval k nezabranΘ pam∞ti a aplikace by se zcela jist∞ zhroutila. Malloc() v p°φpad∞ ne·sp∞chu vracφ NULL.
void objallocate(OBJECT *k,int n)// Alokuje dynamickou pam∞¥ pro objekt
{
k->points = (VERTEX*) malloc(sizeof(VERTEX) * n);// Alokuje pam∞¥
// P°ekladatel:
// if(k->points == NULL)
// {
// MessageBox(NULL,"Chyba p°i alokaci pam∞ti pro objekt", "ERROR", MB_OK | MB_ICONSTOP);
// UkonΦit program
// }
}
Po ka₧dΘ alokaci dynamickΘ pam∞ti musφ VÄDY p°ijφt jejφ uvoln∞nφ. Funkci op∞t p°edßvßme ukazatel na objekt.
void objfree(OBJECT *k)// Uvolnφ dynamickou pam∞¥ objektu
{
free(k->points);// Uvolnφ pam∞¥
}
Funkce readstr() je velmi podobnß (·pln∞ stejnß) jako v lekci 10. NaΦte jeden °ßdek ze souboru f a ulo₧φ ho do °et∞zce string. Abychom mohli udr₧et data souboru p°ehlednß funkce p°eskakuje prßzdnΘ °ßdky (\n) a c-ΘΦkovskΘ komentß°e (°ßdky zaΦφnajφcφ //, respektive '/').
void readstr(FILE *f,char *string)// NaΦte jeden pou₧iteln² °ßdek ze souboru
{
do
{
fgets(string, 255, f);// NaΦti °ßdek
} while ((string[0] == '/') || (string[0] == '\n'));// Pokud nenφ pou₧iteln², naΦti dalÜφ
return;
}
NapφÜeme funkci pro loading objektu z textovΘho souboru. Name specifikuje diskovou cestu k souboru a k je ukazatel na objekt, do kterΘho ulo₧φme v²sledek.
void objload(char *name,OBJECT *k)// Nahraje objekt ze souboru
{
ZaΦneme deklaracφ lokßlnφch prom∞nn²ch funkce. Do ver naΦteme poΦet vertex∙, kter² urΦuje prvnφ °ßdka v souboru (vφce dßle). Dß se °φct, ₧e rx, ry, rz jsou pouze pro zp°ehledn∞nφ zdrojovΘho k≤du programu. Ze souboru do nich naΦteme jednotlivΘ slo₧ky bodu. Ukazatel filein ukazuje na soubor (po otev°enφ). Oneline je znakov² buffer. V₧dy do n∞j naΦteme jednu °ßdku, analyzujeme ji a zφskßme informace, kterΘ pot°ebujeme.
int ver;// PoΦet bod∙
float rx, ry, rz;// X, y, z pozice
FILE* filein;// Handle souboru
char oneline[255];// Znakov² buffer
Pomocφ funkce fopen() otev°eme soubor pro Φtenφ. Pozn. p°ekl.: Stejn∞ jako u alokace pam∞ti i zde chybφ oÜet°enφ chyb.
filein = fopen(name, "rt");// Otev°e soubor
// P°ekladatel:
// if(filein == NULL)
// {
// MessageBox(NULL,"Chyba p°i otev°enφ souboru s daty", "ERROR", MB_OK | MB_ICONSTOP);
// UkonΦit program
// }
Do znakovΘho bufferu naΦteme prvnφ °ßdku. M∞la by b²t ve tvaru: Vertices: x\n. Z °et∞zce tedy pot°ebujeme vydolovat Φφslo x, kterΘ udßvß poΦet vertex∙ definovan²ch v souboru. Tento poΦet ulo₧φme do vnit°nφ prom∞nnΘ struktury a potom alokujeme tolik pam∞ti, aby se do nφ vÜechny koordinßty sou°adnic veÜly.
readstr(filein, oneline);// NaΦte prvnφ °ßdku ze souboru
sscanf(oneline, "Vertices: %d\n", &ver);// PoΦet vertex∙
k->verts = ver;// Nastavφ polo₧ku struktury na sprßvnou hodnotu
objallocate(k, ver);// Alokace pam∞ti pro objekt
U₧ tedy vφme z kolikati bod∙ je objekt vytvo°en a mßme alokovßnu pot°ebnou pam∞¥. Nynφ jeÜt∞ musφme naΦφst jednotlivΘ hodnoty. Provedeme to cyklem for s °φdφcφ prom∞nnou i, kterß se ka₧d²m pr∙chodem inkrementuje. Postupn∞ naΦteme vÜechny °ßdky do bufferu, ze kterΘho p°es funkci sscanf() dostaneme ΦφselnΘ hodnoty slo₧ek vertexu pro vÜechny t°i sou°adnicovΘ osy. PomocnΘ prom∞nnΘ zkopφrujeme do prom∞nn²ch struktury. Po anal²ze celΘho souboru ho zav°eme.
JeÜt∞ musφm upozornit, ₧e je d∙le₧itΘ, aby soubor obsahoval stejn² poΦet bod∙ jako je definovßno na zaΦßtku. Pokud by jich bylo vφce, tolik by to nevadilo - poslednφ by se prost∞ nenaΦetly. V ₧ßdnΘm p°φpad∞ jich ale NESM═ b²t mΘn∞! S nejv∞tÜφ pravd∞podobnostφ by to zhroutilo program. VÜe, na co se pokouÜφm upozornit by se dalo shrnout do v∞ty: Jestli₧e soubor zaΦφnß "Vertices: 10", musφ v n∞m b²t specifikovßno 10 sou°adnic (30 Φφsel - x, y, z).
for (int i = 0; i < ver; i++)// Postupn∞ naΦφtß body
{
readstr(filein, oneline);// NaΦte °ßdek ze souboru
sscanf(oneline, "%f %f %f", &rx, &ry, &rz);// Najde a ulo₧φ t°i Φφsla
k->points[i].x = rx;// Nastavφ vnit°nφ prom∞nnou struktury
k->points[i].y = ry;// Nastavφ vnit°nφ prom∞nnou struktury
k->points[i].z = rz;// Nastavφ vnit°nφ prom∞nnou struktury
}
fclose(filein);// Zav°e soubor
Otestujeme, zda nenφ prom∞nnß ver (poΦet bod∙ aktußlnφho objektu) v∞tÜφ ne₧ maxver (v souΦasnosti maximßlnφ znßm² poΦet vertex∙ v jednom objektu). Pokud ano p°i°adφme ver do maxver.
if(ver > maxver)// Aktualizuje maximßlnφ poΦet vertex∙
maxver = ver;
}
Na °adu p°ichßzφ trochu mΘn∞ pochopitelnß funkce - zvlßÜ¥ pro ty, kte°φ nemajφ v lßsce matematiku. Bohu₧el morfing na nφ stavφ. Co tedy d∞lß? SpoΦφtß o klik mßme posunout bod specifikovan² parametrem i. Na zaΦßtku deklarujeme pomocn² vertex, podle vzorce spoΦφtßme jeho jednotlivΘ x, y, z slo₧ky a v zßv∞ru ho vrßtφme volajφcφ funkci.
Pou₧itß matematika pracuje asi takto: od sou°adnice i-tΘho bodu zdrojovΘho objektu odeΦteme sou°adnici bodu, do kterΘho morfujeme. Rozdφl vyd∞lφme zam²Ülen²m poΦtem krok∙ a koneΦn² v²sledek ulo₧φme do a.
╪ekn∞me, ₧e x-ovΘ sou°adnice zdrojovΘho objektu (sour) je rovna Φty°iceti a cφlovΘho objektu (dest) dvaceti. U deklarace globßlnφch prom∞nn²ch jsme steps p°i°adili 200. V²poΦtem a.x = (40-20)/200 = 20/200 = 0,1 zjistφme, ₧e p°i p°esunu ze 40 na 20 s krokem 200 pot°ebujeme ka₧dΘ p°ekreslenφ pohnout na ose x bodem o desetinu jednotky. Nebo jinak: nßsobφme-li 200*0,1 dostaneme rozdφl pozic 20, co₧ je takΘ pravda (40-20=20). M∞lo by to fungovat.
VERTEX calculate(int i)// SpoΦφtß o kolik pohnout bodem p°i morfingu
{
VERTEX a;// Pomocn² bod
a.x = (sour->points[i].x - dest->points[i].x) / steps;// SpoΦφtß posun
a.y = (sour->points[i].y - dest->points[i].y) / steps;// SpoΦφtß posun
a.z = (sour->points[i].z - dest->points[i].z) / steps;// SpoΦφtß posun
return a;// Vrßtφ v²sledek
}
ZaΦßtek inicializaΦnφ funkce nenφ ₧ßdnou novinkou, ale dßle v k≤du najdete zm∞ny.
int InitGL(GLvoid)// VÜechno nastavenφ OpenGL
{
glBlendFunc(GL_SRC_ALPHA, GL_ONE);// Typ blendingu
// glEnable(GL_BLEND);// Zapne blending (p°ekl.: autor asi zapomn∞l)
glClearColor(0.0f, 0.0f, 0.0f, 0.0f);// ╚ernΘ pozadφ
glClearDepth(1.0);// Nastavenφ hloubkovΘho bufferu
glDepthFunc(GL_LESS);// Typ hloubkovΘho testovßnφ
glEnable(GL_DEPTH_TEST);// Povolenφ testovßnφ hloubky
glShadeModel(GL_SMOOTH);// JemnΘ stφnovßnφ
glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);// NejlepÜφ perspektivnφ korekce
Proto₧e jeÜt∞ neznßme maximßlnφ poΦet bod∙ v jednom objektu, p°i°adφme do maxver nulu. PotΘ pomocφ funkce objload() naΦteme z disku data jednotliv²ch objekt∙ (koule, toroid, vßlec). V prvnφm parametru p°edßvßme cestu se jmΘnem souboru, ve druhΘm adresu objektu, do kterΘho se majφ data ulo₧it.
maxver = 0;// Nulovßnφ maximßlnφho poΦtu bod∙
objload("data/sphere.txt", &morph1);//NaΦte kouli
objload("data/torus.txt", &morph2);// NaΦte toroid
objload("data/tube.txt", &morph3);// NaΦte vßlec
╚tvrt² objekt nenaΦφtßme ze souboru. Budou jφm po scΘn∞ rozhßzenΘ body (p°esn∞ 486 bod∙). Nejd°φve musφme alokovat pam∞¥ pro jednotlivΘ vertexy a potom staΦφ v cyklu vygenerovat nßhodnΘ sou°adnice. Budou v rozmezφ od -7 do +7.
objallocate(& morph4, 486);// Alokace pam∞ti pro 486 bod∙
for(int i=0; i < 486; i++)// Cyklus generuje nßhodnΘ sou°adnice
{
morph4.points[i].x = ((float)(rand() % 14000) / 1000) - 7;// Nßhodnß hodnota
morph4.points[i].y = ((float)(rand() % 14000) / 1000) - 7;// Nßhodnß hodnota
morph4.points[i].z = ((float)(rand() % 14000) / 1000) - 7;// Nßhodnß hodnota
}
Ze soubor∙ jsme loadovali vÜechny objekty do struktur. Jejich data u₧ nebudeme upravovat. Od te∩ jsou jen pro Φtenφ. Pot°ebujeme tedy jeÜt∞ jeden objekt, helper, kter² bude p°i morfingu uklßdat jednotlivΘ mezistavy. Proto₧e na zaΦßtku zobrazujeme morp1 (koule) naΦteme i do pomocnΘho tento objekt.
objload("data/sphere.txt", &helper);// NaΦtenφ koule do pomocnΘho objektu
Nastavφme jeÜt∞ pointery pro zdrojov² a cφlov² objekt, tak aby ukazovali na adresu morph1.
sour = dest = &morph1;// Inicializace ukazatel∙ na objekty
return TRUE;// UkonΦφ funkci
}
Vykreslovßnφ zaΦneme klasicky smazßnφm obrazovky a hloubkovΘho bufferu, resetem matice, posunem a rotacemi. Mφsto abychom vÜechny pohyby provßd∞li na konci funkce, tentokrßt je umφstφme na zaΦßtek. PotΘ deklarujeme pomocnΘ prom∞nnΘ. Do tx, ty, tz spoΦφtßme sou°adnice, kterΘ pak p°edßme funkci glVertex3f() kv∙li nakreslenφ bodu. Q je pomocn² bod pro v²poΦet.
void DrawGLScene(GLvoid)// Vykreslovßnφ
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);// Sma₧e obrazovku a hloubkov² buffer
glLoadIdentity();// Reset matice
glTranslatef(cx,cy,cz);// P°esun na pozici
glRotatef(xrot, 1,0,0);// Rotace na ose x
glRotatef(yrot, 0,1,0);// Rotace na ose y
glRotatef(zrot, 0,0,1);// Rotace na ose z
xrot += xspeed;// Zv∞tÜφ ·hly rotace
yrot += yspeed;
zrot += zspeed;
GLfloat tx, ty, tz;// PomocnΘ sou°adnice
VERTEX q;// Pomocn² bod pro v²poΦty
P°es glBegin(GL_POINTS) oznßmφme OpenGL, ₧e v blφzkΘ dob∞ budeme vykreslovat body. V cyklu for prochßzφme vertexy. ╪φdφcφ prom∞nnou i bychom takΘ mohli porovnßvat s maxver, ale proto₧e majφ vÜechny objekty stejn² poΦet sou°adnic, m∙₧eme s klidem pou₧φt poΦet vertex∙ prvnφho objektu - morph1.verts.
glBegin(GL_POINTS);// ZaΦßtek kreslenφ bod∙
for(int i = 0; i < morph1.verts; i++)// Cyklus prochßzφ vertexy
{
V p°φpad∞ morfingu spoΦφtßme o kolik se mß vykreslovan² bod posunout oproti pozici p°i minulΘm vykreslenφ. Takto vypoΦφtanΘ hodnoty odeΦteme od sou°adnic pomocnΘho objektu, do kterΘho ka₧dΘ p°ekreslenφ uklßdßme aktußlnφ mezistav morfingu. Pokud se zrovna objekty mezi sebou netransformujφ odeΦφtßme nulu, tak₧e se sou°adnice defakto nem∞nφ.
if(morph)// Pokud zrovna morfujeme
q = calculate(i);// SpoΦφtßme hodnotu posunutφ
else// Jinak
q.x = q.y = q.z = 0;// Budeme odeΦφtat nulu, ale tφm neposouvßme
helper.points[i].x -= q.x;// Posunutφ na ose x
helper.points[i].y -= q.y;// Posunutφ na ose y
helper.points[i].z -= q.z;// Posunutφ na ose z
Abychom si zp°ehlednili program a takΘ kv∙li maliΦkΘmu efektu, zkopφrujeme prßv∞ zφskanß Φφsla do pomocn²ch prom∞nn²ch.
tx = helper.points[i].x;// Zp°ehledn∞nφ + efekt
ty = helper.points[i].y;// Zp°ehledn∞nφ + efekt
tz = helper.points[i].z;// Zp°ehledn∞nφ + efekt
VÜechno mßme spoΦφtßno, tak₧e p°ejdeme k vykreslenφ. Nastavφme barvu na zelenomodrou a nakreslφme bod. Potom zvolφme trochu tmavÜφ modrou barvu. OdeΦteme dvojnßsobek sou°adnic q od t a zφskßme umφst∞nφ bodu p°i nßsledujφcφm volßnφ tΘto funkce (ob jedno). Na tΘto pozici znovu vykreslφme bod. Do t°etice vÜeho dobrΘho znovu ztmavφme barvu a op∞t spoΦφtßme dalÜφ pozici, na kterΘ se vyskytne po Φty°ech pr∙chodech touto funkcφ a op∞t ho vykreslφme.
ProΦ jsme krßsn∞ p°ehledn² k≤d vlastn∞ komplikovali? I kdy₧ si to asi neuv∞domujete, vytvo°ili jsme jednoduch² Φßsticov² systΘm. S pou₧itφm blendingu vytvo°φ perfektnφ efekt, kter² se ale bohu₧el projevφ pouze p°i transformaci objekt∙ z jednoho na druh². Pokud zrovna nemorfujeme, v q sou°adnicφch jsou ulo₧eny nuly, tak₧e druh² a t°etφ bod kreslφme na stejnΘ mφsto jako prvnφ.
glColor3f(0, 1, 1);// Zelenomodrß barva
glVertex3f(tx, ty, tz);// Vykreslφ prvnφ bod
glColor3f(0, 0.5f, 1);// Mod°ejÜφ zelenomodrß barva
tx -= 2*q.x;// SpoΦφtßnφ nov²ch pozic
ty -= 2*q.y;
ty -= 2*q.y;
glVertex3f(tx, ty, tz);// Vykreslφ druh² bod v novΘ pozici
glColor3f(0, 0, 1);// Modrß barva
tx -= 2*q.x;// SpoΦφtßnφ nov²ch pozic
ty -= 2*q.y;
ty -= 2*q.y;
glVertex3f(tx, ty, tz);// Vykreslφ t°etφ bod v novΘ pozici
UkonΦφme t∞lo cyklu a glEnd() oznßmφ, ₧e dßle u₧ nebudeme nic vykreslovat.
}
glEnd();// UkonΦφ kreslenφ
Jako poslednφ v tΘto funkci zkontrolujeme jestli transformujeme objekty. Pokud ano a zßrove≥ musφ b²t aktußlnφ krok morfingu menÜφ ne₧ celkov² poΦet krok∙, inkrementujeme aktußlnφ krok. Po dokonΦenφ morfingu ho vypneme. Proto₧e jsme u₧ doÜli k cφlovΘmu objektu, ud∞lßme z n∞j zdrojov². Krok reinicializujeme na nulu.
if(morph && step <= steps)// Morfujeme a krok je menÜφ ne₧ maximum
{
step++;// P°φÜt∞ pokraΦuj nßsledujφcφm krokem
}
else// Nemorfujeme nebo byl prßv∞ ukonΦen
{
morph = FALSE;// Konec morfingu
sour = dest;// Cφlov² objekt je nynφ zdrojov²
step = 0;// Prvnφ (nulov²) krok morfingu
}
}
KillGLWindow upravφme jenom mßlo. Uvolnφme pouze dynamicky alokovanou pam∞¥.
GLvoid KillGLWindow(GLvoid)// Zavφrßnφ okna
{
objfree(&morph1);// Uvolnφ alokovanou pam∞¥
objfree(&morph2);// Uvolnφ alokovanou pam∞¥
objfree(&morph3);// Uvolnφ alokovanou pam∞¥
objfree(&morph4);// Uvolnφ alokovanou pam∞¥
objfree(&helper);// Uvolnφ alokovanou pam∞¥
// Zbytek nezm∞n∞n
}
Ve funkci WinMain() upravφme k≤d testujφcφ stisk klßves. Nßsledujφcφmi Üesti testy regulujeme rychlost rotace objektu.
// Funkce WinMain()
if(keys[VK_PRIOR])// PageUp?
zspeed += 0.01f;
if(keys[VK_NEXT])// PageDown?
zspeed -= 0.01f;
if(keys[VK_DOWN])// èipka dolu?
xspeed += 0.01f;
if(keys[VK_UP])// èipka nahoru?
xspeed -= 0.01f;
if(keys[VK_RIGHT])// èipka doprava?
yspeed += 0.01f;
if(keys[VK_LEFT])// èipka doleva?
yspeed -= 0.01f;
DalÜφch Üest klßves pohybuje objektem po scΘn∞.
if (keys['Q'])// Q?
cz -= 0.01f;// Dßle
if (keys['Z'])// Z?
cz += 0.01f;// Blφ₧e
if (keys['W'])// W?
cy += 0.01f;// Nahoru
if (keys['S'])// S?
cy -= 0.01f;// Dolu
if (keys['D'])// D?
cx += 0.01f;// Doprava
if (keys['A'])// A?
cx -= 0.01f;// Doleva
Te∩ oÜet°φme stisk klßves 1-4. Aby se k≤d provedl, nesmφ b²t p°i stisku jedniΦky key roven jednΘ (nejde morfovat z prvnφho objektu na prvnφ) a takΘ nesmφme prßv∞ morfovat (nevypadalo by to dob°e). V takovΘm p°φpad∞ nastavφme pro p°φÜtφ pr∙chod tφmto mφstem key na jedna a morph na TRUE. Cφlov²m objektem bude objekt jedna. Klßvesy 2, 3, 4 jsou analogickΘ.
if (keys['1'] && (key!=1) && !morph)// Klßvesa 1?
{
key = 1;// Proti dvojnßsobnΘmu stisku
morph = TRUE;// ZaΦne morfovacφ proces
dest = &morph1;// Nastavφ cφlov² objekt
}
if (keys['2'] && (key!=2) && !morph)// Klßvesa 2?
{
key = 2;// Proti dvojnßsobnΘmu stisku
morph = TRUE;// ZaΦne morfovacφ proces
dest = &morph2;// Nastavφ cφlov² objekt
}
if (keys['3'] && (key!=3) && !morph)// Klßvesa 3?
{
key = 3;// Proti dvojnßsobnΘmu stisku
morph = TRUE;// ZaΦne morfovacφ proces
dest = &morph3;// Nastavφ cφlov² objekt
}
if (keys['4'] && (key!=4) && !morph)// Klßvesa 4?
{
key = 4;// Proti dvojnßsobnΘmu stisku
morph = TRUE;// ZaΦne morfovacφ proces
dest = &morph4;// Nastavφ cφlov² objekt
}
Doufßm, ₧e jste si tento tutorißl u₧ili. AΦkoli v²stup nenφ a₧ tak fantastick² jako v n∞kter²ch jin²ch, nauΦili jste se spoustu v∞cφ. Hranφm si s k≤dem lze docφlit skv∞l²ch efekt∙ - t°eba po scΘn∞ nßhodn∞ rozhßzenΘ body m∞nφcφ se ve slova. Zkuste pou₧φt polygony nebo linky namφsto bod∙, v²sledek bude jeÜt∞ lepÜφ.
P°ed tφm, ne₧ vznikla tato lekce bylo vytvo°eno demo "Morph", kterΘ demonstruje mnohem pokroΦilejÜφ verzi probφranΘho efektu. Lze ho najφt na adrese http://homepage.ntlworld.com/fj.williams/PgSoftware.html.
napsal: Piotr Cieslak
p°elo₧il (skoro napsal znovu): Michal Turek - Woq