Sunteți pe pagina 1din 8

================================ pentru uzul studentilor ================================

Laboratorul 3 Calitatea experientei utilizatorului


Obiective:

Imbunatatirea aspectului vizual al ferestrei


Animatie in functie de timp
Redarea textului in fereastra aplicatiei

Imbunatatirea aspectului vizual al ferestrei


Programele dezvoltate in cadrul laboratoarelor anterioare contin o problema legata de
proportiile scenei la evenimentul de redimensionare a ferestrei de afisare (Fig. 1).

Figura 1. Scena deformata in urma redimensionarii (stanga), si rezolvarea acestei probleme (dreapta)
Solutia la aceasta problema consta in reapelarea functiei gluPerspective ori de cate ori se
doreste redimensionarea ferestrei de afisare.
Figura 2 ilustreaza spatiul vizual creat de catre functia gluPerspective.
Elaborat de: Conf. Dr. D.M.Popovici
Masterand M.Polceanu

http://www.cerva.ro

================================ pentru uzul studentilor ================================

Figura 2. Functia gluPerspective


Biblioteca Freeglut (la fel ca majoritatea alternativelor lui GLUT) pune la dispozitie functia
glutReshapeFunc prin care se poate specifica o procedura care se apeleaza la evenimentul de
deformare a ferestrei de afisare. (indicatie: fovy = Field Of View on Y)
In acest sens, vom defini o procedura numita resize:
static void
resize(int width, int height)
{
glViewport(0, 0, width, height);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(45.0f, (GLfloat)width/(GLfloat)height,
2.0f, 100.0f);
glMatrixMode(GL_MODELVIEW);
}
Odata definita, aceasta poate fi specificata ca parametru al functiei glutReshapeFunc din
cadrul functiei main:
glutReshapeFunc(resize);
Observati ca acelasi cod pe care l-am folosit in functia resize, este prezent si in functia
initGL pe care am folosit-o pe parcursul laboratoarelor anterioare. Singura diferenta o constituie
apelul functiei glViewport, ce are ca scop actualizarea pozitiei camerei in cadrul ferestrei de
afisare. Lipsa acestui apel de functie va duce la o deplasare nedorita a punctului de vedere in cadrul
ferestrei.

Elaborat de: Conf. Dr. D.M.Popovici


Masterand M.Polceanu

http://www.cerva.ro

================================ pentru uzul studentilor ================================

Exercitiul 1. Adaptati programul de mai jos astfel incat sa beneficieze de aceasta


imbunatatire. (Codul este exemplul din laboratorul trecut, simplificat).
#include <GL/freeglut.h>
#include <stdlib.h>
#include <stdio.h>
#include <math.h>
void initGL(int width, int height)
{
const GLfloat light_ambient[] = { 0.0f, 0.0f, 0.0f, 1.0f };
const GLfloat light_diffuse[] = { 1.0f, 1.0f, 1.0f, 1.0f };
const GLfloat light_specular[] = { 1.0f, 1.0f, 1.0f, 1.0f };
const GLfloat light_position[] = { 2.0f, 5.0f, 5.0f, 0.0f };
glEnable(GL_LIGHT0);
glEnable(GL_LIGHTING);
glLightfv(GL_LIGHT0, GL_AMBIENT, light_ambient);
glLightfv(GL_LIGHT0, GL_DIFFUSE, light_diffuse);
glLightfv(GL_LIGHT0, GL_SPECULAR, light_specular);
glLightfv(GL_LIGHT0, GL_POSITION, light_position);
glEnable(GL_CULL_FACE);
glCullFace(GL_BACK);
glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_LESS);
glEnable(GL_COLOR_MATERIAL);

glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(45.0f, (GLfloat)width/(GLfloat)height,
2.0f, 100.0f);
glMatrixMode(GL_MODELVIEW);
static void
display(void)
{
static int frame,timebase=0;
int time;
char s[100];
frame++;
time=glutGet(GLUT_ELAPSED_TIME);
if (time - timebase > 1000)
{
sprintf(s,"[FPS:%4.2f]
Lab
3:
Calitatea
utilizatorului",frame*1000.0/(time-timebase));
glutSetWindowTitle(s);
Elaborat de: Conf. Dr. D.M.Popovici
Masterand M.Polceanu

experientei

http://www.cerva.ro

================================ pentru uzul studentilor ================================

timebase = time;
frame = 0;
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glLoadIdentity();
static
static
static
static

float
float
float
float

axisRot = 0.0f;
globRotR = 0.0f;
globRotG = 120.0f;
globRotB = 240.0f;

glColor3f(1.0f, 0.0f, 0.0f);


glPushMatrix();
glTranslatef(0.0f,0.0f,-20);
glRotatef(globRotR, 0,0,1);
glTranslatef(5.0f,0.0f,0.0f);
glRotatef(axisRot,0,1,0);
glutSolidCube(2);
glPopMatrix();
glColor3f(0.0f, 1.0f, 0.0f);
glPushMatrix();
glTranslatef(0.0f,0.0f,-20);
glRotatef(globRotG, 0,0,1);
glTranslatef(5.0f,0.0f,0.0f);
glRotatef(axisRot,0,1,0);
glutSolidCube(2);
glPopMatrix();
glColor3f(0.0f, 0.0f, 1.0f);
glPushMatrix();
glTranslatef(0.0f,0.0f,-20);
glRotatef(globRotB, 0,0,1);
glTranslatef(5.0f,0.0f,0.0f);
glRotatef(axisRot,0,1,0);
glutSolidCube(2);
glPopMatrix();
axisRot += 1.0f; axisRot=fmod(axisRot, 360.0f);
globRotR += 0.5f; globRotR=fmod(globRotR, 360.0f);
globRotG += 0.5f; globRotG=fmod(globRotG, 360.0f);
globRotB += 0.5f; globRotB=fmod(globRotB, 360.0f);
}

glutSwapBuffers();
static void
idle(void)
{
glutPostRedisplay();
}
Elaborat de: Conf. Dr. D.M.Popovici
Masterand M.Polceanu

http://www.cerva.ro

================================ pentru uzul studentilor ================================

/* Punct de intrare in program */


int
main(int argc, char *argv[])
{
int width = 640;
int height = 480;
glutInit(&argc, argv);
glutInitWindowSize(width,height);
glutInitWindowPosition(10,10);
glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH);
glutCreateWindow("");
glutDisplayFunc(display);
glutIdleFunc(idle);
initGL(width, height);
glutMainLoop();
}

return EXIT_SUCCESS;

Animatie in functie de timp


Probabil ati observat faptul ca viteza la care este redata animatia din laboratorul anterior
depinde foarte mult de computer si de rezolutia (dimensiunea) ferestrei.
In aceste conditii este dificil sa programam o animatie care sa se supuna unor reguli bine
stabilite, de exemplu un cub sa execute 3.5 rotatii pe secunda in jurul axei sale.
Cuvantul cheie in problema expusa mai sus este secunda sau, mai exact, timpul. Desi
conform ultimilor teorii trecerea timpului nu este constanta, acest aspect nu este usor perceptibil de
catre utilizatorul uman in absenta echipamentelor de specialitate. Astfel, putem presupune ca
timpul curge in acelasi ritm intotdeauna, si avem in acest fel posibilitatea de a crea animatii ce
nu depind de viteza de redare a placilor video, sau de rezolutia ferestrei.
Solutia acestei probleme vine cu calculul diferentei de timp intre apelurile functiei display,
adica timpul scurs intre doua afisari consecutive ale scenei. Stiind diferenta de timp, putem calcula
pasul la care trebuie sa redam animatia obiectelor din scena.
Astfel, in functia display() vom calcula valoarea dt, diferenta de timp:
static int lasttime=0;
int rightnow = glutGet(GLUT_ELAPSED_TIME);
float dt = ((float)(rightnow-lasttime))/1000.0f;
lasttime = rightnow;
Functia glutGet cu parametrul GLUT_ELAPSED_TIME intoarce intregul timp scurs de la
apelul functiei glutInit (pe care il facem la inceputul programului, in functia main).
Elaborat de: Conf. Dr. D.M.Popovici
Masterand M.Polceanu

http://www.cerva.ro

================================ pentru uzul studentilor ================================

Exercitiul 2. Completati programul de la exercitiul 1, adaugand calculul diferentei de


timp.
Exercitiul 3. Folosind viteza si acceleratia din laboratorul anterior (codul este reluat
in continuare), simulati o cadere libera a unui corp de la o inaltime de 30 metrii, pana
ce atinge solul (y=0). (g=9.81) :: ATENTIE: codul trebuie modificat pentru a lua in
considerare valoarea lui dt.
Structura MaterialPoint si functia moveMe din laboratorul anterior:
struct MaterialPoint
{
float x, y, z; //pozitie
float vx, vy, vz; //viteza
float ax, ay, az; //acceleratie
};
void moveMe(MaterialPoint *m)
{
glTranslatef(m->x, m->y, m->z);
m->vx += m->ax;
m->vy += m->ay;
m->vz += m->az;

m->x += m->vx;
m->y += m->vy;
m->z += m->vz;

Redarea textului in fereastra aplicatiei


Majoritatea aplicatiilor, din orice domeniu, contin informatii in format text. Cu ajutorul
textului putem afisa informatii importante despre starea aplicatiei, mesaje (de eroare sau nu) catre
utilizator, sau orice nu se poate exprima usor prin imagini.
Vom defini o functie ce deseneaza un sir de caractere in fereastra de afisare:
void renderBitmapString(float x, float y, void *font,
*string)
{
glMatrixMode(GL_MODELVIEW);
glPushMatrix();
glLoadIdentity();
glMatrixMode(GL_PROJECTION);
glPushMatrix();
glLoadIdentity();
glDisable(GL_LIGHTING);
glColor3f(0.0f, 1.0f, 0.0f);
Elaborat de: Conf. Dr. D.M.Popovici
Masterand M.Polceanu

char

http://www.cerva.ro

================================ pentru uzul studentilor ================================

glRasterPos2f(x,y);
char *c;
for (c=string; *c != '\0'; c++)
{
glutBitmapCharacter(font, *c);
}
glEnable(GL_LIGHTING);
glPopMatrix();
glMatrixMode(GL_MODELVIEW);
glPopMatrix();
Obs: pentru ca textul sa fie vizibil in cadrul ferestrei, parametrii x si y trebuie sa fie in
intervalul [-1, 1].
In functia main, facem apel la procedura de redare a textului astfel:
char text[100];
sprintf(text,"axisRot: %4.2f",axisRot);
renderBitmapString(-0.99f, -0.91f, GLUT_BITMAP_9_BY_15, text);
sprintf(text,"globRotR: %4.2f",globRotR);
renderBitmapString(-0.99f, -0.98f, GLUT_BITMAP_9_BY_15, text);

Figura 3. Redarea textului in fereastra

Elaborat de: Conf. Dr. D.M.Popovici


Masterand M.Polceanu

http://www.cerva.ro

================================ pentru uzul studentilor ================================

Exercitiul 4. Folosind functia de afisare a textului, completati programul de la


exercitiul 3 pentru a afisa acceleratia si viteza curenta a corpului in cadere, si de
asemenea a timpului ce s-a scurs de cand a inceput sa cada.
Exercitiul 5. Folosind functia de citire a tastaturii din laboratorul anterior (reluata mai
jos), imbunatatiti programul ce simuleaza caderea, facand posibila aplicarea unei
forte (acceleratii) asupra corpului la apasarea unei taste.
Functia de citire a tastaturii din laboratorul anterior:
static void
keyboard(unsigned char key, int x, int y)
{
switch (key)
{
case 'a':
//s-a apasat tasta A
break;
case 'b':
//s-a apasat tasta B
break;
case 'c':
//s-a apasat tasta C
break;
}
}
glutKeyboardFunc(keyboard);

Exercitiul 6. Adaptati programul astfel incat


activati/dezactivati afisarea textului in fereastra.

la

apasarea

unei

taste

sa

* Exercitiul 7. Adaptati programul astfel incat la apasarea unei taste sa se genereze


un nou cub in scena (dinamic, ori de cate ori este apasata tasta respectiva). [acest
exercitiu valoreaza un + la nota]

Elaborat de: Conf. Dr. D.M.Popovici


Masterand M.Polceanu

http://www.cerva.ro

S-ar putea să vă placă și