-
Notifications
You must be signed in to change notification settings - Fork 0
/
Ιmplementation.tex
127 lines (106 loc) · 13.8 KB
/
Ιmplementation.tex
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
\chapter{Υλοποίηση}
Η ενσωμάτωση των θεωρητικών εννοιών και προσεγγίσεων σε λειτουργικά προγράμματα είναι βασικός στόχος της επιστήμης των υπολογιστών. Στην παρούσα εργασία, μετά την απόκτηση του θεωρητικού υποβάθρου σχετικά με τις προβολές ενός 3Δ αντικειμένου σε 2Δ περιβάλλον επικεντρωνόμαστε στην υλοποίηση του προγράμματος απεικόνισης ενός μοναδιαίου κύβου για τρεις από αυτές (Προοπτική, Cavalier, Cabinet), με τη χρήση της \textlatin{OpenGL}. Στο πλαίσιο αυτό, αναλύουμε τους μετασχηματισμούς και τα μητρώα που χρησιμοποιούνται για τις προβολές στον κώδικά μας για την επιθυμητή απεικόνιση των κύβων και παρουσιάζουμε τις συναρτήσεις που χρησιμοποιήθηκαν για την καλύτερη απόδοση του προγράμματος.
\section{Προβολές και Μοναδιαίος Κύβος}
Στην εργασία μας υλοποιήσαμε ένα πρόγραμμα που εμφανίζει τρεις προβολές ενός κύβου σε ένα παράθυρο OpenGl, το οποίο έχει χωριστεί σε τρεις περιοχές: μία για Προοπτική προβολή, μια για Cavalier, μια για Cabinet. Συνολικά, εμφανίζεται το παράθυρο με τους τρεις κύβους και δίνεται η δυνατότητα στο χρήστη να τους περιστρέψει γύρω απο τους τρεις άξονες συντεταγμένων $(x,y,z)$, με επιπλέον δυνατότητα την επαναφορά. Με αυτόν τον τρόπο γίνονται εύκολα αντιληπτά τα χαρακτηριστικά κάθε προβολής, η μορφή των κύβων για κάθε περίπτωση προβολής, και το πόσο ρεαλιστική είναι η προσομοίωση. Παρακάτω αποδίδεται η δομή απεικόνισης των προβολών:
\selectlanguage{english}
\begin{verbatim}
gluPerspective(45.0f, 800.0f / 600.0f, 0.1f, 100.0f);
// Perspective Projection
glPushMatrix();
glTranslatef(-2.5f, 0.0f, -7.0f); // Μετατόπιση του κέντρου
glRotate(rotationAngleX, 1.0f, 0.0f, 0.0f); // Πληκτρολόγιο
glRotate(rotationAngleY, 0.0f, 1.0f, 0.0f);
glRotate(rotationAngleZ, 0.0f, 0.0f, 1.0f);
drawCube(0.7f, 0.7f, 0.7f); // Σχεδίαση με άσπρο χρώμα
glPopMatrix();
// Cavalier Projection
glPushMatrix();
glTranslatef(0.0f, 0.0f, -7.0f);
glRotatef(45.0f, 1.0f, 0.0f, 0.0f); // Περιστροφή στον x κατά 45μ
glRotate(rotationAngleX, 1.0f, 0.0f, 0.0f);
glRotate(rotationAngleY, 0.0f, 1.0f, 0.0f);
glRotate(rotationAngleZ, 0.0f, 0.0f, 1.0f);
glScalef(1.0f,1.0f,1.5f); // Κλιμάκωση του z
drawCube(0.0f, 1.0f, 0.0f); // Σχεδίαση με πράσινο χρώμα
glPopMatrix();
// Cabinet Projection
glPushMatrix();
glTranslatef(2.5f, 0.0f, -7.0f);
glRotatef(63.4f, 1.0f, 0.0f, 0.0f); // Περιστροφή (x) κατά 63,4μ.
glRotate(rotationAngleX, 1.0f, 0.0f, 0.0f);
glRotate(rotationAngleY, 0.0f, 1.0f, 0.0f);
glRotate(rotationAngleZ, 0.0f, 0.0f, 1.0f);
glScalef(1.0f, 1.0f, 0.75f); // Κλιμάκωση του z στο μισό
drawCube(0.0f, 0.0f, 1.0f); // Σχεδίαση με μπλε χρώμα
glPopMatrix();
\end{verbatim}
\par
Οι παραπάνω γραμμές κώδικα εκτελούν με βάση τα μητρώα μετασχηματισμών ενέργειες στην απεικόνιση του κύβου. Αλλάζει επομένως η θέση, ο προσανατολισμός και η κλίμακα του αντικειμένου και κάθε μετασχηματισμός εφαρμόζεται με σειρά. Αναλυτικότερα, για την Cavalier προβολή, εκτελείται περιστροφή γύρω από τον άξονα $x$ κατά $45^\circ$, (πρόκειται για τη χαρακτηριστική δηλαδή γωνία της προβολής), και οι κάθετες ευθείες στο επίπεδο προβολής παραμένουν σταθερές. Η απεικόνιση του κύβου γίνεται με πράσινο χρώμα. Για την Cabinet, εκτελείται περιστροφή γύρω από τον άξονα $x$ κατά $63,4^\circ$, (επίσης η χαρακτηριστική γωνία προβολής για την Cabinet) και αλλάζει κλίμακα κατά μήκος του άξονα $z$ κατά το ήμισυ $(1/2)$.
Η σύνταξη και η δομή του προγράμματος ακολουθεί τη δομή ενός βασικού προγράμματος σχεδίασης ενός 3Δ αντικειμένου σε γραφικό περιβάλλον. Η συνάρτηση display χρησιμοποιείται κάθε φορά που απαιτείται να γίνει ανανέωση του παραθύρου παρουσίασης (μεγέθυνση, πλήρη οθόνη, κάλυψη από άλλα προγράμματα κλπ) και αφορά την αρμονική απεικόνιση. Στην περίπτωση πλήρης οθόνης τα αντικείμενα δέχονται μια μικρή παραμόρφωση, αλλά η προσομοίωση συνεχίζει να είναι αποδοτική.
Με τις glMatrixMode, glLoadIdentity, gluPerspective η τρέχουσα λειτουργία χαρακτηρίζεται ως προβολή και γίνεται εφαρμογή της προοπτικής. Ορίζεται η σειρά με την οποία πρέπει να γίνουν οι μετασχηματισμοί και εφαρμόζονται με τα μητρώα που αφορούν τη θέση, τον προσανατολισμό και την κλίμακα του μοντέλου σε αρχική κατάσταση.
Για κάθε περίπτωση (Perspective, Cavalier, Cabinet) υπάρχουν οι glPushMatrix, drawCube, glPopMatrix. Σε αυτό το σημείο εκτελείται μια σειρά μετασχηματισμών και στη συνέχεια απεικονίζεται έναν κύβο. Οι μετασχηματισμοί περιλαμβάνουν μετατόπιση (translate), περιστροφή (rotate) και κλιμάκωση (scale) του κύβου. Η glutSwapBuffers() ενημερώνει το παράθυρο παρουσίασης για να ανταλλάξει τους front buffer και back buffer (ρυθμιστές). Αυτό κάνει την τρέχουσα εικόνα ορατή στο παράθυρο. Η glClear() σε συνδυασμό με τους ρυθμιστές βάθους (depth buffers) καθαρίζουν το παράθυρο από προηγούμενο περιεχόμενο και το προετοιμάζουν για τη νέα απεικόνιση που ακολουθείται από τους παραπάνω μετασχηματισμούς.
Τα βήματα επαναλαμβάνονται με τη χρήση ανάλογων μετασχηματισμών, ειδικών για κάθε περίπτωση. Δηλαδή η προβολή Cavalier έχει τη χαρακτηριστική γωνία $45^\circ$, ενώ η Cabinet τη χαρακτηριστική γωνία των $63^\circ$. Ο συνδυασμός όλων αυτών των ενεργειών έχει ως αποτέλεσμα την απεικόνιση του κύβου στις τρεις ζητούμενες προβολές, ενώ επιτυγχάνεται ο επανακαθορισμός του περιβάλλοντος απόδοσης προβολής για τη σωστή απεικόνιση των γραφικών στο παράθυρο.
\vspace{3em}
\begin{figure}[H]
\includegraphics[width=1.0\textwidth]{images/test1.jpeg}
\caption{Στιγμιότυπο του εκτελέσιμου προγράμματος πριν την περιστροφή από το χρήστη}
\end{figure}
\begin{figure}[H]
\includegraphics[width=1.0\textwidth]{images/after_rotation.jpeg}
\caption{Στιγμιότυπο του εκτελέσιμου προγράμματος μετά την περιστροφή από το χρήστη}
\end{figure}
\par
Έπειτα, ακολουθεί μια συνάρτηση για το πληκτρολόγιο καθώς το πρόγραμμα δίνει τη δυνατότητα στο χρήστη να περιστρέψει τους κύβους σε πραγματικό χρόνο. Η περιστροφή γίνεται γύρω από τους άξονες συντεταγμένων $(x,y,z)$ με τα πλήκτρα x,y,z αντιστοίχως, ενώ αν ο χρήστης επιθυμεί την περιστροφή από την αντίθετη κατεύθυνση αρκεί να πατήσει τα πλήκτρα X,Y,Ζ αναλόγως.
\begin{verbatim}
void keyboard(unsigned char key, int x, int y) {
switch (key) {
case 'r':
case 'R':
rotationAngleX = 0.0f;
rotationAngleY = 0.0f;
rotationAngleZ = 0.0f;
break;
case 'x':
rotationAngleX += 1.0f;
break;
case 'X':
rotationAngleX -= 1.0f;
break;
case 'y':
rotationAngleY += 1.0f;
break;
case 'Y':
rotationAngleY -= 1.0f;
break;
case 'z':
rotationAngleZ += 1.0f;
break;
case 'Z':
rotationAngleZ -= 1.0f;
break;
}
\end{verbatim}
\section{Υλοποίηση σε \textlatin{OpenGL}}
Η εργασία υλοποιήθηκε σε προγραμματιστικό περιβάλλον με τη χρήση \textlatin{C++/OpenGL} και χρησιμοποιήθηκε η βιβλιοθήκη \textlatin{GLUT} για τη δημιουργία γραφικού παραθύρου και την αλληλεπίδραση με το χρήστη.
\vspace{3em}
Οι κύριες συναρτήσεις που ορίστηκαν στον κώδικα αναγράφονται στον παρακάτω πίνακα.
\vspace{3em}
\begin{longtable}{p{6cm}|p{7cm}}
\textbf{Μητρώα Μετασχηματισμών - Συναρτήσεις} & \textbf{Ερμηνεία} \\ \hline
\textlatin{\lstinline[language=C++]!glTranslatef()!} & Μητρώο μετατόπισης κύβου στις συντεταγμένες $(x,y,z)$ του διανύσματος μετατόπισης \\ \hline
\textlatin{\lstinline[language=C++]!glRotatef()!} & Μητρώο περιστροφής του κύβου γύρω από τον άξονα που καθορίζεται απο τις συντεταγμένες $(x,y,z)$ και γωνία περιστροφής σε μοίρες \\ \hline
\textlatin{\lstinline[language=C++]!glScalef()!} & Μητρώο αλλαγής κλίμακας του κύβου στις τρεις διαστάσεις \\ \hline
\textlatin{\lstinline[language=C++]!(GL_QUADS)!} & Σχεδίαση κατανεμημένων πολυγώνων (quads) που αναπαριστούν τις πλευρές του κύβου. \\ \hline
\textlatin{\lstinline[language=C++]!glVertex3f()!} & Καθορισμός κορυφών των πολυγώνων \\ \hline
\textlatin{\lstinline[language=C++]!(GL_LINES)!} & Σχεδίαση γραμμών που αναπαριστούν τις διαγώνιες του κύβου και άκρες των γραμμών μεταξύ των κορυφών του κύβου \\ \hline
\textlatin{\lstinline[language=C++]!drawCube()!} & Απεικόνιση του κύβου με χρώμα που περνιέται ως ορίσματα\\ \hline
\textlatin{\lstinline[language=C++]!display()!} & Απεικόνιση του κύβου με διαφορετικές προβολές\\ \hline
\textlatin{\lstinline[language=C++]!gluPerspective()!} & Καθορισμός προοπτικής προβολής με παραμέτρους fovy, aspect, zNear, zFar\\ \hline
\textlatin{\lstinline[language=C++]!reshape()!} & Ενημέρωση παραμέτρων του παραθύρου \\ \hline
\textlatin{\lstinline[language=C++]!glViewPort()!} & Προσαρμογή περιοχής απεικόνισης \\ \hline
\textlatin{\lstinline[language=C++]!keyboard()!} & Καθορισμός προγράμματος βάση χρήστη \\ \hline
\textlatin{\lstinline[language=C++]!glLoadIdentity()!} & Φόρτωση μονάδας τροποποίησης στον πίνακα προβολής. Ακύρωση τροποποιήσεων και επαναφορά στην αρχική κατάσταση\\ \hline
\textlatin{\lstinline[language=C++]!glPushMatrix()!} & Αποθήκευση τρέχουσας κατάστασης πίνακα προβολής \\ \hline
\textlatin{\lstinline[language=C++]!glPopMatrix()!} & Επαναφορά του πίνακα προβολής στην προηγούμενη κατάσταση αποθήκευσης στη στοίβα\\ \hline
\caption{Πίνακας Mητρώων Μετασχηματισμών και Συναρτήσεων}
\end{longtable}