Disegnare un Orologio con OpenGL

Continuiamo a vedere la gestione delle matrici in OpenGL e più in particolare, in questa lezione, vedremo come poterle utilizzare due o più. Avevamo visto che con il comando glLoadIdentity() potevamo resettare una matrice, quindi era possibile lavorare ogni volta con una matrice pulita, magari una volta per un oggetto e poi per gli altri. Questo però non è il metodo migliore, sarebbe difatti più utile poter memorizzare alcune posizioni intermedie ( rappresentate da matrici ) per poterci di nuovo lavorare in seguito. Questo è possibile tramite la matrix stack ( pila di matrici ) che noi possiamo mettere da parte con il comando glPushMatrix() e poi ripristinare a quel punto con glPopMatrix(). Vediamo l’utilizzo delle pile di matrici con il disegno di un orologio, come mostrato nell’immagine qui sotto:

Orologio Disegnato con OpenGL

Orologio Disegnato con OpenGL

Ecco il codice che ho utilizzato:

// File FirstWin.cpp per le trasformazioni

#include <GL/glut.h>
#include <time.h>

void Init()
{
   glClearColor(0.0, 0.0, 0.0, 0.0);
   glShadeModel(GL_FLAT);
   glEnable(GL_DEPTH_TEST);
}

void Draw()
{
   int i;
   float ang;
   time_t ltime;
   struct tm today;

   time(<ime);
   _localtime64_s(&today, <ime);

   glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
   glMatrixMode(GL_MODELVIEW);
   glLoadIdentity();

   glColor3f(0.4f, 0.4f, 0.4f);
   for (i = 0; i < 60; i++)
   {
     glPushMatrix();
     glRotatef((6.0f * i), 0.0f, 0.0f, 1.0f);
     glTranslatef(0.0f, 20.0f, 0.0f);
     glBegin(GL_LINES);
      glVertex3f(0.0f, 0.0f, 0.0f);
     glVertex3f(0.0f, 2.0f, 0.0f);
     glEnd();
     glPopMatrix();
   }

   ang = - ((float)today.tm_hour * (360 / 12));
   glPushMatrix();
   glRotatef(ang, 0.0f, 0.0f, 1.0f);
   glColor3f(0.4f, 1.0f, 0.4f);
   glBegin(GL_TRIANGLES);
     glVertex3f(-1.0f, 0.0f, 0.0f);
     glVertex3f(1.0f, 0.0f, 0.0f);
     glVertex3f(0.0f, 12.0f, 0.0f);
   glEnd();
   glPopMatrix();

   ang = - ((float)today.tm_min * (360 / 60));
   glPushMatrix();
   glRotatef(ang, 0.0f, 0.0f, 1.0f);
   glColor3f(0.4f, 0.4f, 1.0f);
   glBegin(GL_TRIANGLES);
     glVertex3f(-1.0f, 0.0f, 0.0f);
     glVertex3f(1.0f, 0.0f, 0.0f);
     glVertex3f(0.0f, 15.0f, 0.0f);
   glEnd();
   glPopMatrix();

   ang = - ((float)today.tm_sec * (360 / 60));
   glPushMatrix();
   glRotatef(ang, 0.0f, 0.0f, 1.0f);
   glColor3f(1.0f, 0.4f, 0.4f);
   glBegin(GL_TRIANGLES);
   glVertex3f(-1.0f, 0.0f, 0.0f);
   glVertex3f(1.0f, 0.0f, 0.0f);
   glVertex3f(0.0f, 20.0f, 0.0f);
   glEnd();
   glPopMatrix();

   glutSwapBuffers();
}

void Animation()
{
   glutPostRedisplay();
}

void Resize(int iWidth, int iHeight)
{
   glViewport(0, 0, (GLsizei)iWidth, (GLsizei)iHeight);
   glMatrixMode(GL_PROJECTION);
   glLoadIdentity();
   glOrtho(-50.0f, 50.0f, -50.0f, 50.0f, 0.0f, 100.0f);
   glMatrixMode(GL_MODELVIEW);
   glLoadIdentity();
}

void Tastiera(unsigned char key, int x, int y)
{
   if (key == 27)
      exit(0);
   glutPostRedisplay();
}

int main(int argc, char** argv)
{
   glutInit(&argc, argv);
   glutInitDisplayMode(GLUT_DOUBLE|GLUT_RGB|GLUT_DEPTH);
   glutInitWindowSize(350, 350);
   glutInitWindowPosition(100, 100);
   glutCreateWindow("OpenGL - Orologio");
   Init();
   glutDisplayFunc(Draw);
   glutReshapeFunc(Resize);
   glutKeyboardFunc(Tastiera);
   glutIdleFunc(Animation);
   glutMainLoop();
}

Nella funzione di disegno ho trovato l’ora corrente del sistema, poi ho creato le linee sui minuti dell’orologio tramite delle semplici rotazioni sulla matrice che ogni volta viene ripristinata. Per le lancette ho seguito la stessa tecnica; se ci fossero comunque problemi di comprensione potete chiedermi una spiegazione più accurata.

<< Lezione Precedente – Lezione Successiva >>

Informazioni su Giampaolo Rossi

Sviluppatore di software gestionale da oltre 28 anni.
Questa voce è stata pubblicata in Grafica, Programmazione e contrassegnata con . Contrassegna il permalink.