Taller #3 - Centro de Computación Gráfica

Anuncio
UNIVERSIDAD CENTRAL DE VENEZUELA
FACULTAD DE CIENCIAS
ESCUELA DE COMPUTACIÓN
INTRODUCCIÓN A LA COMPUTACIÓN GRÁFICA
TALLER #2: Quaternions
Los Quaternions es una forma alternativa de representar rotaciones a través de cualquier
eje. Matemáticamente, son una extensión del conjunto de números complejos. Presentan 4
dimensiones, que se obtienen al mezclar un vector y un escalar.
Estos se encuentran en el espacio R4. Se pueden representar de dos maneras: Q = {x,y,z,w}
donde Q es el quaternion a representar, {x,y,z} son los valores correspondientes del eje a
rotar y w sería un escalar que es la magnitud a rotar, la otra representación es una matriz
4x4 que nos servirá para utilizar en OpenGL.
¿Por qué usar Quaternions?
Presentan varias ventajas comparado con las rotaciones por matrices:
- Pueden representarse en 4 números, a diferencia con los 9 números de las matrices
de rotación.
- Al ejecutar rotaciones, ciertos errores se acumulan después de una cantidad. En los
Quaternions, estos errores tardan mucho más en acumularse que en las rotaciones
matriciales.
- Se pueden convertir a manera matricial de una forma trivial.
- Similar a las matrices de rotación, se pueden multiplicar Quaternions para
representar múltiples rotaciones en un elemento.
Veamos ciertas operaciones de los Quaternions:
Conjugada: La conjugada de los quaternions, es sencillamente pasar a negativo la parte
vectorial de ellos, así que teniendo el Q={x,y,z,w} su conjugada es Q’={-x,-y,-z,w}
Quaternion Quaternion::conjugada()
{
Quaternion Q(-x,-y,-z,w);
return Q;
}
Normalizar: es similar a normalizar un vector, obtenemos un quaternion unitario (magnitud
1).
void Quaternion::normalize()
{
float magnitude=(x*x) + (y*y)+(z*z)+(w*w);
magnitude=sqrt(magnitude);
w=w/magnitude;
x=x/magnitude;
y=y/magnitude;
z=z/magnitude;
}
Multiplicación de dos Quaternions: cuando uno multiplica dos quaternions, lo que obtiene
es la rotación acumulada de ambos. Vale acotar que multiplicar Q1*Q2 es distinto a
multiplicar Q2*Q1 ya que el orden de aplicar las rotaciones afecta el resultado.
Quaternion Quaternion::operator* (Quaternion &q)
{
Quaternion Q(w*q.x + x*q.w + y*q.z - z*q.y,
w*q.y + y*q.w + z*q.x - x*q.z,
w*q.z + z*q.w + x*q.y - y*q.x,
w*q.w - x*q.x - y*q.y - z*q.z);
return Q;
}
Convertir un quaternion en una matriz: Este método consiste en transformar el quaternion
de 4 dimensiones en una matriz de rotación 4x4, la cual le permite a OpenGL utilizarla por
medio de la instrucción glMultMatrixf(), con lo que lograremos multiplicar el quaternion de
por la rotación que deseamos.
void Quaternion::CreateMatrix(float *pMatrix)
{
if(pMatrix)
{
// First row
pMatrix[ 0] = 1.0f - 2.0f * ( y * y + z * z );
pMatrix[ 1] = 2.0f * ( x * y - w * z );
pMatrix[ 2] = 2.0f * ( x * z + w * y );
pMatrix[ 3] = 0.0f;
// Second row
pMatrix[ 4] = 2.0f * ( x * y + w * z );
pMatrix[ 5] = 1.0f - 2.0f * ( x * x + z * z );
pMatrix[ 6] = 2.0f * ( y * z - w * x );
pMatrix[ 7] = 0.0f;
// Third row
pMatrix[ 8] = 2.0f * ( x * z - w * y );
pMatrix[ 9] = 2.0f * ( y * z + w * x );
pMatrix[10] = 1.0f - 2.0f * ( x * x + y * y );
pMatrix[11] = 0.0f;
// Fourth row
pMatrix[12] = 0;
pMatrix[13] = 0;
pMatrix[14] = 0;
pMatrix[15] = 1.0f;
}
}
Aplicar rotación a Quaternion: Dando el eje y el ángulo de rotación y el ángulo, el siguiente
algoritmo sirve para generar un quaternion:
void Quaternion::CreateFromAxisAngle(float *vector, const float &in_degrees)
{
float angle = float((in_degrees / 180.0f) * PI);
float result = float(sin(angle/2.0f));
w = float(cos(angle/2.0f));
// Calculate the x, y and z of the quaternion
x = float(vector[0] * result);
y = float(vector[1] * result);
z = float(vector[2] * result);
}
Donde vector es un vector de 3 posiciones, indicando en que eje se va a rotar y in_degrees
es la rotación a aplicar. Es necesario normalizar el quaternion después de aplicar una
rotación, por si acaso hay valores muy cercanos a cero.
OBJ
Object File Format (OBJ) es un formato de data simple que representa geometrías en 3D,
nombrando la posición de cada vértice, las coordenadas UV de cada textura, las normales, y
las caras que hacen a cada polígono definida por la lista de vértices. Los vértices deberían
ser guardados en contra de las agujas del reloj (counter-clockwise), haciendo la declaración
de las normales innecesarias.
El formato, acepta comentarios. La línea es comentada (o el resto de la línea) usando el
símbolo de numeral (#).
Los vértices empiezan definidos con la letra “v”, las texturas con las letras “vt”, las
normales con las letras “vn” y las caras con “f”.
En las caras, los vértices, las coordenadas de textura y las normales están separadas por el
carácter slash (/) ordenados respectivamente y sin espaciados entre los slash separadores.
Como las coordenadas de textura y las normales son opcionales de colocar, entonces
pueden o no aparecer en la cara:
-
-
-
Vértices: Un vértice válido tiene como valor mínimo 1 y le corresponde algún valor
de la lista de vértices (f 1 2 3)
Vértices/Coordenadas-de-textura: Opcional, la coordenada de textura tiene también
un valor mínimo 1 y corresponde con algún valor de la lista de coordenadas de
textura (f 1/1 2/4 3/6 4/8).
Vértices/Coordenadas-de-textura/Normal: Opcional, la normal tiene un valor
mínimo de 1 y debe corresponder con algún valor de la lista de normales
(f 2/3/4 5/1/3 3/6/2).
Vértice//Normal: Opcional, aquí no tiene definida una coordenada de textura pero si
una normal (f 1//3 2//6 3//9).
Un OBJ contiene varios tipos de definición. El siguiente cuadro muestra el formato
ejemplo:
# Lista de vértices, con (x,y,z[,w]) coordenadas, w es opcional y por defecto es 1.0.
vxyzw
v ...
...
# Lista de coordenadas de textura, en (u[,v][,w]) coordenadas, ‘v’ y ‘w’ son opcionales y
#por defecto son 0.
vt u v
vt ...
...
# Lista de normales en formato (x,y,z); las normales pueden no ser unitarias.
vn x y z
vn ...
...
# Definición de caras
f v1 v2 v3…
f v1/vt1 v2/vt2 v3/vt3…
f v1/vt1/vn1 v2/vt2/vn2 v3/vt3/vn3…
f v1//vn1 v2//vn2 v3//vn3…
...
Ahorita se muestra un ejemplo de una definición de un cuadrado sin normales y sin
coordenadas de textura:
v 10.0 -50.0 -10.0
v 10.0 50.0 -10.0
v -10.0 -50.0 -10.0
v -10.0 50.0 -10.0
f314
f412
Destacamos nuevamente que un archivo OBJ posee más información que un OFF al tener
coordenadas de textura y normales. También posee información de control como donde está
la imagen de las coordenadas de textura, donde obtener los materiales de los vértices, los
nombres de los grupos y objetos y muchas otras cosas.
Para la realización de la tarea #2, no es necesaria nada de esta información, solo los vértices
y las caras.
Referencias:
Matrix And Quaternions FAQ http://web.archive.org/web/20041029003853/http:/www.j3d.org/matrix_faq/matrfaq_latest.html
OpenGL Tutorials: Using Quaternions to represent rotation –
http://content.gpwiki.org/index.php/OpenGL:Tutorials:Using_Quaternions_to_represent_rotation
OBJ - http://en.wikipedia.org/wiki/Wavefront_.obj_file
Alejandro Sans GDICG
Descargar