Você está na página 1de 12

Universidade Federal de Santa Maria

Departamento de Eletrnica e Computao


Prof. Cesar Tadeu Pozzer
Disciplina: Computao Grfica Avanada
pozzer@inf.ufsm.br
03/01/2013

Rotao em eixo arbitrrio


1. Gimbal Lock
Quando se usa ngulos de Euler para fazer rotaes, pode ocorrer que, aps algumas operaes, dois eixos
podem ficar alinhados, como mostrado na seguinte figura. Este problema tambm muito comum com
programas de modelagem 3D como Maya, 3Dstudio, dentre outros. Quando isso acontece, perde-se um grau de
liberdade. Detalhes da origem do termo Gimbal lock podem ser vistos em [19, 21].

http://es.youtube.com/watch?v=rrUCBOlJdt4

http://en.wikipedia.org/wiki/Yaw,_pitch,_and_roll

Sabendo-se que a concatenao de transformaes ao se usar ngulos de Euler ocorre na ordem RzRyRx, se a
primeira rotao for em y, apenas o eixo x alterado (que passa a ser igual ao z, o que resulta no gimbal lock).
Uma rotao inicial em x no muda os eixos de rotao y e z. A rotao em z muda os eixos x e y, ou seja,
rotacionar em x equivale a rotacionar em y e vice-versa. Ao se usar quatrnio, qualquer rotao sempre ocorre
no eixo que foi especificado, independente das transformaes que a precederam, o que evita o surgimento do
gimbal lock. Entretanto, para modelagem 3D, torna mais complexo a visualizao das rotaes necessrias.
Uma situao clara deste problema pode ser visualizada caso realize-se uma rotao de y = 90o. Aplicando-se
aps uma rotao de z = -90o ou x = 90o obtm o mesmo resultado, ou seja, perdeu-se um grau de liberdade,
pois rotaes em z ou x tm o mesmo efeito. Pode verificar isso calculando-se as matrizes de transformao.
glRotatef(camera_roll,
glRotatef(camera_yaw,
glRotatef(camera_pitch,

0.0f, 0.0f, 1.0f); // Rotate X, Y, Z


0.0f, 1.0f, 0.0f);
1.0f, 0.0f, 0.0f);

0 0 1
R y (90 ) = 0 1 0
1 0 0
0

1 0 0
R x (90 ) = 0 0 1
0 1 0
0

0 1 0
R z (90 ) = R z (270 ) = 1 0 0
0 0 1
0

0 0 1 1 0 0 0 1 0 0 0 1 0 1 0
R y R x = R z R y = 0 1 0 0 0 1 = 1 0 1 0 1 0 = 0 0 1
1 0 0 0 1 0 0 0 1 1 0 0 1 1 0

2. Uso de matrizes de transformao


Para se fazer a rotao em um eixo A = (x,y,z) unitrio deve-se inicialmente decompor o vetor P em suas
componentes paralela (projAP) e perpendicular (perpAP) ao eixo A, conforme mostrado na seguinte figura.
Deve-se observar que a componente paralela se mantm constante durante a rotao em relao ao eixo A.
Desta forma, para se fazer a rotao, deve-se somente calcular a rotao do vetor perpAP em relao a A. Para
isso, deve-se ter uma base no plano perpendicular ao eixo A. Esta base pode ser definida pelos vetores (projAP)
e AP.
A

A
P
P

AP
(AP)A

proj A P = ( A P )A

[P (AP)A]cos + (AP)sin

P (AP)A

perp A P = P ( A P )A

Sabe-se que P A = P A cos , ou seja, a norma do vetor projetado dada por P cos =

P A
A . Para se

obter um vetor na direo do vetor A, deve-se multiplicar pelo vetor unitrio A, ou seja,

proj A P =

P A A P A
=
A , para o caso do vetor A no ser unitrio.
2
A A
A

A rotao de perpAP no plano definido pelos vetores P (AP)A e AP por um ngulo dado por

[P ( A P )A]cos + ( A P )sin

Sabe-se que a norma do vetor resultante do produto vetorial de dois vetores A e P dada por
A P = A P sin . Como A = 1 , temos que A P = P sin . Como perp A P = P sin , a base do
sistema de rotao tem dois vetores com a mesma norma, no sendo necessrio normaliz-los.
Expandindo-se o termo [P ( A P )A]cos obtm-se

P cos ( A P )A cos

Adicionando-se projAP obtm-se P como

P' = P cos ( A P )A cos + ( A P )sin + ( A P ) A


P' = P cos + ( A P )sin + ( A P ) A(1 cos )

Em notao matricial temos

1 0 0 Px
P = 0 1 0 Py
0 0 1 Pz
0
Ay Px
Az

A P = Az
0
Ax Py
Ay
Ax
0 Pz

Ax2
Ax Ay Ax Az Px
P A

A( A P ) = proj A P =
A = Ax Ay
Ay2
Ay Az Py
2
A
Ax Az Ay Az
Az2 Pz

Ou seja, P' = P cos + ( A P )sin + ( A P )A(1 cos ) pode ser expresso como

0
1 0 0

P' = 0 1 0 P cos + Az
Ay
0 0 1

Az
0
Ax

Ax2
Ay

Ax P sin + Ax Ay
Ax Az
0

Ax Ay
Ay2
Ay Az

Ax Az

Ay Az P(1 cos )
Az2

Combinando os termos e considerando c = cos() e s = sin(), obtm a matriz de rotao RA()

c 0 0 0
Az s Ay s Ax2 (1 c ) Ax Ay (1 c ) Ax Az (1 c )


0
Ax s + Ax Ay (1 c ) Ay2 (1 c ) Ay Az (1 c ) P
P' = 0 c 0 + Az s


0 Ax Az (1 c ) Ay Az (1 c ) Az2 (1 c )
0 0 c Ay s Ax s
P' = R A ( )P
Ax2 (1 c ) + c

R A ( ) = Ax Ay (1 c ) Az s
Az Ax (1 c ) + Ay s

Ax Ay (1 c ) + Az s
A (1 c ) + c
2
y

Ay Az (1 c ) Ax s

Ax Az (1 c ) Ay s

Ay Az (1 c ) + Ax s
Az2 (1 c ) + c

3. Quatrnios
Nmeros complexos
Sabemos que uma rotao no plano euclidiano pode ser expressa por uma matriz de transformao

cos
R( ) =
sin

sin
. Como as funes sin e cos tm perodo de 2 , R ( ) = R ( + 2 k ) . Como o
cos

espao de rotaes no plano pode ser representado pelo circulo unitrio, qualquer ponto z deste crculo pode ser
representado por um nmero complexo z=a+bi da seguinte forma

z = e i z = cos z + i sin z

(frmula de Euler [13])

ou seja, a parte real a = Re( z ) = cos z representa o eixo x, e a parte imaginria b = Im( z ) = sin z o eixo y.
Neste caso z considerado um complexo unitrio, pois z =

z z = a 2 + b 2 = 1 , onde z = a bi o

conjugado de z = a + bi .
De forma mais genrica um ponto arbitrrio p = (x,y) do plano, em sua forma polar, pode ser expresso como

p = re

i p

onde

y
r = x 2 + y 2 , p = arctg
x
Im

z
|z|

Re

O inverso de um nmero complexo dado por


_

1
1 c di
z
z
= =
= 2
= 2
2
z c + di c di c + d
z

Quatrnios
Expandindo-se para uma situao no R4, pode-se definir uma base cannica representada por {1, i, j, k}, onde 1
= (1,0,0,0), i = (0,1,0,0), j = (0,0,1,0), k = (0,0,0,1). Neste caso, i,j,k so componentes complexas, e esta
estrutura algbrica conhecida como quatrnio, uma extenso dos nmeros complexos. Historicamente, os
quatrnios foram criados por William Rowan Hamilton em 1843 e somente em 1985, Shoemake os introduziu
na Computao Grfica. Atualmente so largamente utilizados em aplicaes grficas que fazem uso de
rotaes, como forma de evitar o gimbal lock e para facilitar interpolao entre rotaes.
Um quatrnio pode ser visto como um vetor 4D que possui a seguinte forma:

q = w, x, y , z = w + xi + yj + zk
Em representao vetorial pode-se escrever q = s + v, onde s representa a parte escalar (componente w de q) e
v representa a parte vetorial (componentes x, y e z de q).
Valem as seguintes regras para multiplicao de componentes imaginrias:
i2 = j2 = k2 = -1
ij = -ji = k
jk = -kj = i
ki = -ik = j

Propriedades de Quatrnios
A soma de dois quatrnios q1 e q2 associativa e dada por (s1+s2, v1+v2).

A multiplicao por um escalar a por um quatrnio q dada por aq = (aw, av).


_

*
O conjugado de um quatrnio q = (s, v), representado por q ou q , dado por

q * = q = w xi yj zk
_

q* = q = s v
O produto interno (escalar) de dois quatrnios dado por

q1 q 2 = w1 w2 + x 1 x 2 + y1 y 2 + z1 z 2
A norma de um quatrnio dada por
2

q = q q = q q = ( s, v)(s,v) = s 2 + v v = w 2 + x 2 + y 2 + z 2
ou

q = w + x2 + y2 + z 2
2

Um quatrnio q unitrio quando |q| = 1. Para normalizar um quatrnio deve-se dividir cada componente pela
norma

q=

s+v
w x y z
=
, , ,
q
q q q q

O inverso de quatrnio no zero (|q| 0) dada por


_

q 1
Se o quatrnio for unitrio, temos q

q
= 2
q

=q

void Quaternion::normalise()
{
// Don't normalize if we don't have to
float mag2 = w * w + x * x + y * y + z * z;
if (fabs(mag2 - 1.0f) > TOLERANCE) {
float mag = sqrt(mag2);
w /= mag;
x /= mag;
y /= mag;
z /= mag;
}
}
Quaternion Quaternion::getConjugate() //somente para quaternio unitrio
{
return Quaternion(-x, -y, -z, w);
}

A multiplicao de quatrnios no comutativa, ou seja, q1q2 diferente de q2q1. Dados dois quatrnios q1 =
w1+x1i+y1j+z1k e q2 = w2+x2i+y2j+z2k, a multiplicao dada por
q1q2 = (w1w2 x1x2 y1y2 z1z2)
+ (w1x2 + x1w2 + y1z2 z1y2)i
+ (w1y2 - x1z2 + y1w2 + z1x2)j
+ (w1z2 + x1y2 - y1x2 z1w2)k
Em representao vetorial, q1 = s1 + v1 e q2 = s2 + v2, temos

q1q2 = s1s2 v1.v2 + s1v2 + s2v1 + v1 v2


ou
q1q2 = (s1s2 v1.v2, s1v2 + s2v1 + v1 v2) (partes escalar e vetorial)

Quaternion Quaternion::operator* (const Quaternion &rq) const


{
// the constructor takes its arguments as (x, y, z, w)
return Quaternion(w*rq.x + x*rq.w + y*rq.z - z*rq.y,
w*rq.y + y*rq.w + z*rq.x - x*rq.z,
w*rq.z + z*rq.w + x*rq.y - y*rq.x,
w*rq.w - x*rq.x - y*rq.y - z*rq.z);
}

Rotao com Quaternions


Para se poder usar quatrnios para representar rotao de um ponto P em eixo arbitrrio, deve-se encontrar uma

(P ) , que preserve ngulos, comprimentos e direo (handedness), ou seja (P ) = P ,


(P1 ) (P2 ) = P1 P2 e (P1 ) (P2 ) = (P1 P2 ) .

funo

A classe de funes do tipo

q (P ) = qPq 1 ,

onde q um quatrnio no nulo, satisfaz os requisitos para

definio de rotaes. A demonstrao pode ser vista em [1].


O seguinte quatrnio q faz com que P = qPq-1 seja um ponto rotacionado de um ngulo em relao a um eixo
arbitrrio A. A demonstrao pode ser vista em [1].

q = cos

+ A sin

Deve-se observar que se o vetor A for normalizado, o quatrnio ser unitrio


2

q = q q = (cos , A sin )(cos , A sin )


= cos 2 + sin 2 ( A A)
= cos 2 + sin 2
=1
Para aplicar a equao P = qPq-1 deve-se ter um ponto P qualquer do espao R3, representado por meio de um
quatrnio com parte real nula, ou seja, P = (0,P). A parte real deste produto nula e a parte imaginria
corresponde ao ponto rotacionado, ou seja, o ponto P dado por P = (0,P). O quatrnio que corresponde a
rotao nula q = (1, 0A) = (1,0) = (1,0,0,0).
Como exemplo, suponha a rotao do ponto P = (2,0,1) em um ngulo de 90o em torno do eixo z. Neste caso,


deve-se usar o quatrnio q = (cos 45 0 , sin 450 (0,0,1)) = 1 , 1 (0,0,1) = 1 , 0,0, 1 e o ponto P =
2

2
2

2
(0,(2,0,1)) expresso na forma de quatrnio. Observe que o quatrnio P no precisa ser unitrio.

P= qPq 1
1
1
1
1
=
, 0,0,
(0, (2,0,1))
, 0,0,

2
2
2
2


1 2
2
1
1
1
= 0 0 0
,
+ 0 + 0 0, 0 0 + 0 +
,
+ 0 0 0
, 0,0,

2 2
2
2
2
2

1 2 2 1 1
1
=
,
,
,

, 0,0,

2 2 2 2 2
2

1
1
1
1
= 0 0 + , 0 + 1 1 0,0 + 1 + 1 + 0, + 0 0 +
2
2
2
2

= (0, (0,2,1))

Como resultado, obteve-se o quatrnio q = (0,(0,2,1)). Tomando-se apenas a parte imaginria, tem-se o ponto P
= (0,2,1), como esperado.
Como o produto de dois quatrnios tambm representa uma rotao, pode-se concatenar vrias rotaes em um
nico quatrnio. O produto q1q2 representa uma rotao primeiro por q2 seguido por q1. Uma vez que

q1 q 2 Pq21 q11

= (q1 q 2 )P q q

1 1
2
1
1
1 2

= (q1 q 2 )P (q q

= q r Pq r1
pode-se concatenar quantos quatrnios se desejar para gerar um nico quatrnio representando toda srie de
rotaes. Isso mostra que qualquer conjunto de rotaes pode ser reduzida a uma nica rotao em um nico
eixo.
O seguinte exemplo ilustra este processo para concatenao de uma rotao x = -60 seguida de uma rotao y
= 90. Estas rotaes so representadas pelos quatrnios

3 1

q x = cos 300 , sin 300 (1,0,0) = , (1,0,0)


2 2

1 1
q y = (cos 450 , sin 450 (0,1,0)) =
,
(0,1,0) .
2 2

Calculando qr = qyqx obtem-se

1 1
(0,1,0) 3 , 1 (1,0,0) = 6 , 10 1 , 3 , 1
qr =
,
2 2
2 2
4 4 5 5 5
ou seja, estas duas rotaes equivalem a rotao de = 104.5 em torno do eixo A = 1 , 3 , 1 , pois

5 5 5

6.
104.5
cos
=
2
4

Uma vantagem menor do uso de quatrnio se refere ao nmero de operaes necessrias para concatenao de
transformaes. A seguinte tabela ilustra um comparativo com matrizes de rotao.
Mtodo
Matriz rotao
Quatrnio

Armazenamento
9
4

# multiplicaes
27
16

# adies
18
12

# total operaes
45
28

Para aplicar uma rotao a um ponto, o uso de matriz de rotao necessita menor custo computacional.
Mtodo
Matriz rotao
Quatrnio

# multiplicaes
9
21

# adies
6
18

# total operaes
15
39

Como multiplicar um quatrnio por outro gasta 16 multiplicaes, e como so necessrias duas multiplicaes
para rotacionar um ponto, deve-se fazer otimizaes para reduzir este processamento para apenas 21
multiplicaes. O seguinte cdigo ilustra esta otimizao [8].
Vector3 Quaternion::operator* (const
{
float t2 =
a*b
float t3 =
a*c
float t4 =
a*d
float t5 = -b*b
float t6 =
b*c
float t7 =
b*d
float t8 = -c*c
float t9 =
c*d
float t10 = -d*d
return Vector3( 2*( (t8 + t10)*v1
2*( (t4 + t6)*v1
2*( (t7 - t3)*v1
}

Vector3 &vec) const (revisar)

+ (t6 - t4)*v2 + (t3 + t7)*v3 ) + vec.x,


+ (t5 + t10)*v2 + (t9 - t2)*v3 ) + vec.y,
+ (t2 + t9)*v2 + (t5 + t8)*v3 ) + vec.z);

Vector3 Quaternion::operator* (const Vector3 &vec) const


{
Vector3 vn(vec);
vn.normalise();
Quaternion vecQuat, resQuat;
vecQuat.x = vn.x;
vecQuat.y = vn.y;
vecQuat.z = vn.z;
vecQuat.w = 0.0f;
resQuat = vecQuat * getConjugate();
resQuat = *this * resQuat;
return (Vector3(resQuat.x, resQuat.y, resQuat.z));
}

Muitas vezes pode ser necessrio representar um quatrnio unitrio por uma matriz de rotao, especialmente
quando se est utilizando alguma API grfica, como no caso do OpenGL. A transformao envolve o uso de
lgebra de matrizes. A demonstrao pode ser encontrada em [1].
1 2 y 2 2 z 2
2 xy 2 wz
2 xz + 2 wy
0

2
2
1 2x 2z
2 yz 2 wx
0
2 xy + 2 wz
Mq =

2 yz + 2 wx 1 2 x 2 2 y 2 0
2 xz 2 wy

0
0
0
1

2
2
2
2
Caso o quatrnio no for unitrio (w + x + y + z 1), deve-se utilizar a seguinte matriz de converso:
w2 + x2 + y 2 + z 2
2 xy 2 wz
2 xz + 2 wy
0

2
2
2
2
2 xy + 2 wz
w x +y z
2 yz 2 wx
0

Mq =

2 xz 2 wy
2 yz 2 wx
w2 x 2 y 2 + z 2 0

0
0
0
1

Deve-se observar que esta matriz est no formato adotado pela API OpenGL (column-major format ), ou seja, a
matriz aparece no lado direito da multiplicao. Deve-se lembrar que a multiplicao de matrizes RP equivale a
PTRT. Deve-se calcular a matriz M q = M qT caso seja adotado matrizes em formato row-major.
Matrix4 Quaternion::toMatrix() const
{
float x2 = x * x;
float y2 = y * y;

float z2 = z * z;
float xy = x * y;
float xz = x * z;
float yz = y * z;
float wx = w * x;
float wy = w * y;
float wz = w * z;
return Matrix4(1.0f - 2.0f * (y2
2.0f * (xy + wz),
2.0f * (xz - wy),
0.0f, 0.0f, 0.0f,

+ z2), 2.0f * (xy - wz), 2.0f * (xz + wy), 0.0f,


1.0f - 2.0f * (x2 + z2), 2.0f * (yz - wx), 0.0f,
2.0f * (yz + wx), 1.0f - 2.0f * (x2 + y2), 0.0f,
1.0f);

Para se obter um quatrnio a partir de uma matriz de rotao deve-se realizar os seguintes clculos. Deve-se
verificar se a expresso 1 + m00 + m11 + m22 , que representa a soma da diagonal principal, tambm chamada de
trao da matriz, maior que zero. Caso contrrio, deve-se fazer um tratamento especial. Para isso, consulte [4,
16].

w=

(m m12 )
x = 21
(4w)

1 + m00 + m11 + m22


2

(m m20 )
y = 02
(4w)

z=

(m10 m01 )
(4w)

Outra transformao importante a converso de ngulos de Euler para quatrnios. O processo muito simples.
Basta transformar cada ngulo de Euler (x no eixo x - pitch, y no eixo y yaw e z no eixo z - roll) em um
quatrnio e aps multiplicar estes quatrnios para obter um quatrnio resultante. Assumindo a ordem de
multiplicao de matrizes do OpenGL, temos que a transformao RxRyRz dada por

q x = (cos ( x / 2), (sin ( x / 2),0,0))


q y = (cos ( y / 2), (0, sin ( y / 2),0))

q z = (cos ( z / 2), (0,0, sin ( z / 2)))


q = qx q y qz
Para realizar o processo inverso, ou seja, obter os ngulos de Euler e eixo a partir do quatrnio utiliza-se o
seguinte algoritmo.
void Quaternion::toAxisAngle(Vector3 *axis, float *angle)
{
float scale = sqrt(x * x + y * y + z * z);
axis->x = x / scale;
axis->y = y / scale;
axis->z = z / scale;
*angle = acos(w) * 2.0f;
}

Deve-se observar que fazendo-se uso de rotao e eixo arbitrrio, pode-se obter o mesmo resultado que com o
uso de quatrnion.

4. Interpolao Linear Esfrica - SLERP


A interpolao entre vetores uma estratgia muito usada para se fazer animaes de modelos, considerando-se
que cada keyframe esteja associada a um vetor direo. A forma mais simples de se fazer a interpolao de dois
vetores (ou quatrnios) por meio da interpolao linear (no plano), como mostrado na seguinte equao.

q(t) = (1 t )q1 + tq2


O problema desta soluo que o vetor resultante q(t) no mantm a mesma norma durante essa interpolao,
da mesma forma como ocorre a animao via o formato MD2. Uma soluo fazer a normalizao do vetor
resultante, com a seguinte equao.

q1

q(t ) =

(1 t )q1 + tq2
(1 t )q1 + tq2

q (t )
q (t )

q(t)

q2
Mesmo essa soluo ainda no adequada. Pode-se observar que a taxa de variao (velocidade angular) do
vetor q(t) no constante. Como mostrado no seguinte grfico, a variao maior no ponto mdio entre os
vetores q1 e q2.

cos1 (q(t ) q1 )

t
Deste modo, deseja-se achar uma funo q(t) que interpole os vetores com uma taxa constante e que mantenha
norma unitria do vetor resultante.

q(t) = a(t)q1 + b(t)q2


Se os vetores q1 e q2 forem ortogonais, a soluo torna-se bem simples, e dada por

q(t) = cos(t )q1 + sin(t )q2


sendo o ngulo entre os vetores q1 e q2. Porm, se os vetores no forem ortogonais, deve-se utilizar a seguinte
equao. A demonstrao pode ser vista em [1,27,28,29,30].
q
1

q(t ) =

sin[ (1 t )]
sin[ t ]
q1 +
q2
sin
sin

a(t)

(1-t)

sin (1 t ) sin t
+
desta equao geram valores entre [1,
sin
sin

q(t)
sin((1-t))

Os termos

sin

q2

2 ] com t variando no intervalo [0,1],

como mostrado na seguinte figura. Cada termo isolado tem variao no linear entre [0, 1], justamente para
garantir a variao constante na velocidade angular do vetor resultante q(t).

10

2
1

t
0

5. Programa Demo
Este programa foi desenvolvido para comprar as diferentes formas de aplicar rotao em eixos. Ele ilustra o uso
de ngulos de Euler, quaternions extrados de ngulos de Euler, rotao via quatrnion, rotao em eixo
arbitrrio e eixo arbitrrio extrado de quatrnion. Por ele, pode-se nitidamente notar que as duas primeiras
solues no tratam o problema de gimbal lock. Esse demo pode ser baixado no site da disciplina.

6. Referncias Bibliogrficas
[1] Eric Lengyel. Mathematics for 3D Game Programming and Computer Graphics. Charles River Media, 2002.
[2] Gomes, J., Velho, L. Computao Grfica, Volume 1. IMPA, 1998.
[3] Marcelo Gattass, PUC-Rio, Notas de aula.
[4] http://www.j3d.org/matrix_faq/matrfaq_latest.html
[5] http://en.wikipedia.org/wiki/Quaternions
[6] http://www.gamasutra.com/features/19980703/quaternions_01.htm
[7] http://www.genesis3d.com/~kdtop/Quaternions-UsingToRepresentRotation.htm

11

[8] http://en.wikipedia.org/wiki/Quaternion_rotation
[9] http://www.genesis3d.com/~kdtop/Quaternions-UsingToRepresentRotation.htm
[10] http://www.euclideanspace.com/maths/geometry/rotations/conversions/matrixToQuaternion/index.htm
[11] http://www.nationmaster.com/encyclopedia/Quaternions-and-spatial-rotation
[12] http://www.opengl.org/resources/faq/technical/transformations.htm
[13] http://en.wikipedia.org/wiki/Euler%27s_formula
[14] http://www.ime.unicamp.br/~vaz/4nion.htm
[15] http://en.wikipedia.org/wiki/Slerp
[16] http://www.euclideanspace.com/maths/geometry/rotations/conversions/matrixToQuaternion/index.htm
[17] http://www.gamedev.net/reference/articles/article1095.asp
[18] http://everything2.com/e2node/Gimbal%2520Lock
[19] http://www.allanbrito.com/2007/04/18/gimbal-lock/
[20] http://www.anticz.com/eularqua.htm
[21] http://history.nasa.gov/alsj/gimbals.html
[22] http://www.dhpoware.com/demos/glCamera2.html
[23] http://en.wikipedia.org/wiki/Yaw,_pitch,_and_roll

[24] http://www.cprogramming.com/tutorial/3d/rotation.html
[25] http://www.gamedev.net/reference/articles/article1199.asp
[26] http://www.gamedev.net/community/forums/topic.asp?topic_id=25314
[27] 3D math primer for graphics and game development. Fletcher Dunn,Ian Parberry
[28] Visualizing quatrnions. Andrew J. Hanson
[29] 3D game engine design: A Practical Approach to Real-Time Computer Graphics. David H. Eberly
[30] http://number-none.com/product/Understanding%20Slerp,%20Then%20Not%20Using%20It/

12