La specifica principale di questo progetto e' l'implementazione del movimento della telecamera, sia interattivamente
utilizzando la tastiera, che automaticamente dando luogo ad un'animazione.
Prima di andare avanti introduciamo alcune strutture dati che sono servite nell'implementazione.
La prima e' la struttura
keyFrame:
typedef struct keyFrame
{
GLfloat position[3];
GLfloat rotation[3];
GLfloat TD[3];
GLfloat TS[3];
int num;
keyFrame *next;
keyFrame *prev;
};
che rappresenta un keyframe all'interno dell'animazione. La demo inclusa con il codice comprende 7 keyframe
(
KEYNUM), fra un
keyframe ed il seguente vengono interpolati 250 frame intermedi (
STEPS)
per un totale di 1750 complessivi per l'animazione, le coordinate di tali frames (posizione e rotazione) vengono
contenute in questi array:
float framePos[TOTALFRAME][3];
float frameRot[TOTALFRAME][3];
La struttura dati e' definita come una
double-linked list, in questo modo il primo keyFrame sara' il successivo
dell'ultimo ed il percorso della telecamera sara' ciclico.
I valori
STEPS e
KEYNUM inoltre possono essere modificati
nel
header Core.h e nel file che contiene le le coordinate per i keyframe
Data/keyframes, in modo da ottenere un diverso percorso o un'animazione piu' lenta/veloce.
4.1. L'interpolazione dei keyFrames
Per ottenere un'animzione "morbida", e' stato adottato un metodo di interpolazione fra punti
detto "
di curve di Hermite". Tale metodo e' semplice da calcolare ma allo stesso tempo molto potente.
La curva prodotta e' anche conosciuta come KB-spline, curva controllabile tramite i tre parametri di
tensione,
continuita' e
bias, che analizzeremo in seguito, in'oltre il codice
comprende la possibilita' di utilizzare le funzioni di bezier per produrre un diverso tipo di spline.
Per calcolare la curva di Hermite abbiamo bisogno dei seguenti vettori:
- P1: il punto di partenza della curva
- T1: la tangente (eg direzione e velocita') ovvero come la curva lascia il punto di partenza
- P2: il punto di arrivo della curva
- T2: la tangente (eg direzione e velocita') ovvero come la curva incontra il punto di arrivo
Questi quattro vettori sono semplicemente moltiplicati con le quattro funzioni base di Hermite
e sommati assieme:
h1(s) = 2s^3 - 3s^2 + 1
h2(s) = -2s^3 + 3s^2
h3(s) = s^3 - 2s^2 + s
h4(s) = s^3 - s^2
ecco i grafici delle quattro funzioni (da sinistra a destra: h1, h2, h3, h4), tutti i grafici, ad eccezione
di h4, sono stati tracciati da (0,0) a (1,1).
Esprimendo tutto in forma di matrice otteremmo la seguente formula:
Il vettore S: il punto di interpolazione e la sua potenza fino alla terza
il vettore C: i parametri della curva di Hermite
la matrice h: la forma matriciale della quattro polinomiali di Hermite
| s^3 | | P1 | | 2 -2 1 1 |
S = | s^2 | C = | P2 | h = | -3 3 -2 -1 |
| s^1 | | T1 | | 0 0 1 0 |
| 1 | | T2 | | 1 0 0 0 |
Per calcolare un punto sulla curva si costruisce il vettore
S,
lo si moltiplica con la matrice
h e quindi si moltiplica per
C.
P = S * h * C
Se invece volessimo creare una curva di
Bezier ci basterebbe sostituire la matrice
h
con la seguente matrice di coefficenti
| -1 3 -3 1 |
b = | 3 -6 3 0 |
| -3 3 0 0 |
| 1 0 0 0 |
Controllare delle tangenti per rendere la curva puo' essere difficile, cosi' come sara' difficile
stabilire che forma avra' una curva se dobbiamo definirla. In piu' per ottenere delle curve strette
bisogna trascinare i punti della tangente molto lontano dalla curva stessa. Per questo motivo in realta'
e' stato utilizzato un tipo particolare di curve di Hermite, i Kochanek-Bartels Splines (detti anche
TCB-Splines).
La differenza sostanziale con le Hermite semplici sta' nella presenza di alcune funzioni molto utili
per calcolare l'equazione delle tangenti utilizzando tre parametri di cui ho accennato sopra:
- Tensione: quanto strettamente la curva piega
- Continuita': Quant'e' rapido il cambiamento di direzione
e di velocita'
- Bias: qual'e' la direzione della curva non appena passa il punto chiave
L'equazione della tangente "entrante":
(1-t)*(1-c)*(1+b)
TS = ----------------- * ( P - P )
i 2 i i-1
(1-t)*(1+c)*(1-b)
+ ----------------- * ( P - P )
2 i+1 i
L'equazione della tangente "uscente":
(1-t)*(1+c)*(1+b)
TD = ----------------- * ( P - P )
i 2 i i-1
(1-t)*(1-c)*(1-b)
+ ----------------- * ( P - P )
2 i+1 i
Quando bisogna interpolare la curva si deve usare questo vettore:
| P(i) |
C = | P(i+1) |
| TD(i) |
| TS(i+1) |
4.2. Le funzioni che creano l'animazione
Nel codice del programma il lavoro appena spiegato viene svolto da due funzioni:
- bool loadKeyFrames(char *filename);
- void keyFrameInterpolation(keyFrame *cur, float t, float c, float b, bool hermite);
loadKeyFrames(): carica da un file di testo le coordinate di posizione e di rotazione
per ogni keyFrame. Ogni riga del file deve avere 3 coordinate per la posizione e 3 coordinate per la rotazione
in questa forma:
p X Y Z r X Y Z
ed il numero di keyframe definiti dev'essere uguale a
KEYNUM.
keyFrameInterpolation(): calcola i punti intermedi tra un keyframe ed il successivo,
memorizzandoli negli array
framePos[][] e
frameRot[][].
Utilizza come parametri tre
float t,
c
e
b, che sono la
tensione,
continuita' e
bias, ed in piu' un
booleano hermite, che stabilisce quale matrice usare per il
calcolo della curva,
Hermite o
Bezier.
Durante l'esecuzione del programma un indice
currentFrame stara' ad indicare l'attuale
frame da disegnare.