|
|
|
Paolo Cignoni |
|
cignoni@iei.pi.cnr.it |
|
http://vcg.iei.pi.cnr.it/~cignoni |
|
Ricevimento mercoledi ore 11 Area CNR |
|
|
|
24 ottobre 2001 |
|
|
|
|
Le prossime esercitazioni saranno tutte dedicate
allo sviluppo di |
|
A Steroid
(A clone of Asteroid doped by OpenGl) |
|
un remake della versione arcade Asteroids (1979
Atari) |
|
|
|
|
|
|
Portability (Win and Linux Platforms) |
|
Usi OpenGL |
|
Mantenga la stessa filosofia di gioco di
Asteroids (no 3d) |
|
Sia piu’ vario dell’originale |
|
Sia ben progettato (e.g. documentato,
manutenibile, estendibile ecc) |
|
Sia un buon esempio di progetto... |
|
|
|
|
C++ (http://www.icce.rug.nl/docs/cplusplus/) |
|
STL (http://www.sgi.com/Technology/STL/) |
|
OpenGL (http://www.opengl.org) |
|
GLUT (http://www.opengl.org/Documentation/GLUT.html) |
|
Doc++ (http://www.rsdi.com/doc++/) |
|
e altro…. |
|
|
|
|
|
It is a documentation system for C, C++ and Java
generating both TeX and HTML output for online browsing of your
documentation. |
|
The documentation is extracted directly from the
C/C++ header/source files or Java class files. |
|
Here is a short list of highlights: |
|
hierarchically structured documentation
automatic class graph generation (as Java applets for HTML) |
|
cross references |
|
high end formatting support including
typesetting of equations |
|
http://www.rsdi.com/doc++/ |
|
|
|
|
Doc++ legge i sorgenti e produce una
documentazione in html o in TeX. |
|
Il meccanismo di base e’ scrivere i commenti nel
codice con una particolare sintassi (“/**” o “///”).
Ad es. |
|
|
|
/** Glut Callback on release of arrow keys. |
|
It should stop the thrust and the rotation of
the ship. |
|
*/ |
|
void SpecialKeyUp(int key, int x, int y){ |
|
... |
|
} |
|
La prima riga diventa il sommario del commento
mentre il resto del commento diventa la descrizione dettagliata |
|
|
|
|
|
|
|
|
|
Visual Computing Group library |
|
http://vcg.iei.pi.cnr.it (mail to
cignoni@iei.pi.cnr.it) |
|
Piccola libreria per la gestione di punti 3d con
coordinate del tipo specificato a piacere |
|
Overloading di Tutti i classici operatori (+ -
prodotto scalare, ecc.) |
|
Shorthand per le chiamate Opengl |
|
glVertex(Point3<type>) |
|
glNormal(Point3<type>) |
|
Typedef dei casi piu’ comuni ( |
|
typedef Point3<float> Point3f ; |
|
typedef Point3<double> Point3d ; |
|
|
|
|
Esempio: |
|
using namespace vcg; |
|
Point3f MidPoint(Point3f &p1, Point3f
&p2){ |
|
return
(p1+p2)/2.0f; |
|
} |
|
Point3f FaceNormal(Point3f &p1, Point3f
&p2, Point3f &p3){ |
|
return Normalize( (p2-p1)^(p3-p1)); |
|
} |
|
|
|
|
|
|
The Standard Template Library (STL) consists of
containers, generic algorithms, iterators, etc |
|
It is a general purpose library consisting of
algorithms and data structures. |
|
The data structures that are used in the
algorithms are abstract in the sense that the algorithms can be used on
(practically) every data type. |
|
http://www.sgi.com/Technology/STL/ |
|
|
|
|
|
|
The vector class implements an (expandable)
array. To use the vector, the header file vector must be included: |
|
#include <vector> |
|
Vectors can be used like arrays, and can be
defined with a fixed number of elements. E.g., to define a vector of 30
ints we do |
|
vector<int>
iVector(30); |
|
Note the specification of the data type that is
to be used: the datatype is given between angular brackets after the vector
container name. |
|
|
|
|
|
|
The list class implements a list datastructure.
To use the list, the header file list must be included: |
|
#include <list> |
|
|
|
|
|
|
|
|
|
|
|
list<string> target; |
|
list<string>::iterator from; |
|
for (from = target.begin(); from !=
target.end(); ++from) cout << *from << " "; |
|
cout << endl; |
|
target.sort(); |
|
|
|
|
|
|
|
|
back(), returning the last element of the list. |
|
clear(), |
|
begin(), returning the first element of the
list. |
|
empty(), |
|
size(), |
|
swap(argument), swaps two lists. |
|
|
|
elements may be erased: |
|
erase() and clear() both erase all elements, |
|
erase(pos) erases all elements starting at
position pos, |
|
erase(begin, end) erases elements indicated by
the iterator range [begin, end). |
|
elements may be inserted at a certain position pos: |
|
insert(pos, source) inserts source at pos, |
|
insert(pos, begin, end) inserts the elements in
the iterator range [begin, end). |
|
|
|
|
|
|
GLUT is a window system independent toolkit for
writing OpenGL programs. |
|
It implements a simple windowing application
programming interface (API) for OpenGL. |
|
GLUT provides a portable API so you can write a
single OpenGL program that works on both Win32 PCs and X11 workstation |
|
http://www.opengl.org/Documentation/GLUT.html |
|
|
|
|
|
Glut fornisce un’interfaccia comune con il S.O. |
|
Gestione interazione applicazione-utente tramite
Callback |
|
funzioni che sono chiamate dalla coppia S.O. GLUT in risposta a vari eventi
(pressione di un tasto del mouse o
della tastiera, reshape della finestra, necessita’ di ridisegnare il
contenuto della finestra ecc) |
|
Il flusso principale dell’applicazione e’ in
mano al sistema operativo. |
|
|
|
|
|
Inizializzare |
|
glutInit(&argc, argv) |
|
Definire e aprire una finestra |
|
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA |
GLUT_DEPTH); |
|
glutInitWindowSize(sizex,sizey); |
|
glutInitWindowPosition(xpos,ypos); |
|
glutCreateWindow(char *name) |
|
preparare le funzione callback che SO invocherà |
|
glutDisplayFunc(myRedrawFunc) |
|
glutKeyboardFunc(myKeyFunc); |
|
|
|
Passare al SO il controllo. |
|
glutMainLoop() |
|
|
|
|
|
void Display(void) |
|
Chiamata ad ogni redraw, di solito |
|
Clear schermo |
|
Setup matrix |
|
Drawing… |
|
glutSwapBuffers() |
|
|
|
|
void Key(unsigned char key, int x, y) Chiamata
ad ogni pressione di tasto |
|
Struttura tipica: |
|
{ |
|
switch
(key) { |
|
case
'q': exit(0); |
|
case '
': DoSomething(); break; |
|
} |
|
|
|
|
|
|
|
Se il controllo di quando devo disegnare lo
schermo e’ in mano al SO come si fa a ridisegnare continuamente lo schermo? |
|
Due soluzioni |
|
Idle function Callback: invocata ogni volta che
il so non ha nulla di piu urgente da fare |
|
Timer callback: invocata ogni tot msec |
|
In entrambi i casi si deve sempre controllare
quanto tempo e’ passato dall’ultimo redraw per far sì che l’animazione sia
fluida |
|
|
|
|
|
L’applicazione verrà sviluppata in vari passi,
aggiungendo man mano sempre piu’ funzionalita’ |
|
Prima versione |
|
Progettazione dei primi livelli della gerarchia
delle classi principali |
|
Rendering Wireframe |
|
|
|
|
|
|
|
Asteroide Frattale |
|
Scrivere la
class AstF : public Ast
Il cui costruttore ha una piccola procedura che genera un profilo
irregolare, memorizzandone la forma. Per generare un tale profilo partire
da un quadrato o da un triangolo e aggiungere il punto di mezzo ad ogni
lato e spostarlo di una piccola quantità casuale. Continuare ricorsivamente
a suddividere ogni lato fino a quando
non si e’ raggiunto una ventina di lati. |
|
|
|
|
|
|
|
Nuova Astronave |
|
Scrivere la
class Ship2: public Ship
dove la funzione di redraw e’ modificata in maniera tale da disegnare
(sempre in wireframe) un’ astronave piu’ sofisticata in cui quando il
motore e’ acceso la fiamma cambia forma e colore |
|
|
|
|
|
Nuova Astronave |
|
Scrivere la
class Ship3: public Ship
dove (almeno) i metodi
Bullet* Ship::Shoot()
void GameSession::Shoot()
sono modificati in maniera tale da permettere all’astronave di sparare tre
colpi contemporanemaie a raggiera |
|
|
|
|
|
Debugging |
|
Ci sono una serie di errori (tutti involontari
ma alcuni volontariamente non corretti) che vanno trovati e corretti. Ad
es: |
|
Posizionamento iniziale asteroidi |
|
gestione reshape |
|
ecc. |
|
|
|
|
I Template sono un meccanismo che permette di
definire funzioni e classi basate su argomenti e oggetti dal tipo non
specificato |
|
|
|
template class <T> swap(T &a, T
&b); |
|
|
|
template class <T> class List {...}; |
|
|
|
Queste funzioni e oggetti generici diventano
codice completo una volta che le loro definizioni sono usate con oggetti
reali |
|
|
|
|
Scambio tra due oggetti generici: |
|
|
|
template <class T> void swap(T &a, T
&b){ |
|
T tmp = a; |
|
a = b; |
|
b = tmp; |
|
} |
|
|
|
int main(){ |
|
int a = 3, b = 16; |
|
double d = 3.14, e = 2.17; |
|
swap(a, b); |
|
swap(d, e); |
|
// swap (d, a); errore in compilazione! |
|
|
|
return (0); |
|
} |
|
|
|
|
|
|
Notare che la definizione di una funzione
template è simile ad una macro, nel senso che la funzione template non è
ancora codice, ma lo diventerà una volta che essa viene usata |
|
Il fatto che il compilatore generi codice
concreto solo una volta che una funzione è usata ha come conseguenza che
una template function non può essere mai raccolta in una libreria a run
time |
|
Un template dovrebbe essere considerato come una
sorta di dichiarazione e fornito in un file da includere. |
|
|
|