Lekce 25

Lekce 25 - Morfovßnφ objekt∙ a jejich nahrßvßnφ z textovΘho souboru

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

ZdrojovΘ k≤dy

Lekce 25

<<< Lekce 24 | Lekce 26 >>>