Stratos: Punto de Encuentro de Desarrolladores

¡Bienvenido a Stratos!

Acceder

Foros





Camara y vectores

Iniciado por ozharu, 18 de Febrero de 2007, 01:49:02 PM

« anterior - próximo »

ozharu

Estoy haciendo una camara libre para poder debuguear el mundo, los movimientos de las camara los tengo hechos mediante quaterniones, con lo cual la clase de la camara solo tiene una posicion y una orientacion. Ademas tengo una camara en 3 persona que funciona mediante From, up y to.

Mi problema es que cuando cambio de la camara de 3 persona a la camara debug, quiero que esta tenga la misma vista que la otra ( que mire en la misma direccion). Mi problema es que no se como sacar el quaternion que me describa esa orientacion, ya que el quaternion que calculo hace que mi camara rote completamente mal

killrazor

Jejeje, curioso, yo tambien estoy liado con una camara parecida, tambien basada en quaterniones. La respuesta es: depende de como implementes las rotaciones.

Para mi camara por ejemplo, no es porblema, puesto que guardo la direccion en un vector y la posicion en otro. Lo que hago es una camara muy basica, que hace eso, con un metodo setPosition() y otro lookAt().

A partir de ahi derivo los diferentes tipos de camara que necesito. Cuando quiero psar de una camara a otra uso el constructor de copia para que internamente se copien todos los datos que necesito.

Te pego algo de codigo:

void glCamera::SetPrespective()
{
glQuaternion q;

// Fabricar los cuaterniones que representan nuestras rotaciones
m_qPitch = m_qPitch.fromAxisRot(Vector3<GLfloat>(1.0f,0.0f,0.0f),m_PitchDegrees);
m_qHeading = m_qHeading.fromAxisRot(Vector3<GLfloat>(0.0f,1.0f,0.0f),m_HeadingDegrees);
// Combine the pitch and heading rotations and store the results in q
q = m_qPitch * m_qHeading;
glMatrix4 matrix(q.transform());

// Let OpenGL set our new prespective on the world!
glMultMatrixf(matrix.data);

// Create a matrix from the pitch Quaternion and get the j vector
// for our direction.
matrix = m_qPitch.transform();
m_DirectionVector.j = matrix[9];

// Combine the heading and pitch rotations and make a matrix to get
// the i and j vectors for our direction.
q = m_qHeading * m_qPitch;
matrix = q.transform();
m_DirectionVector.i = matrix[8];
m_DirectionVector.k = matrix[10];



// Translate to our new position.
glTranslatef(-m_Position.x, -m_Position.y, m_Position.z);

/*
// para debug
char title[100];
sprintf_s(title,"Position x: %.2f, y: %.2f, z: %.2f, pitch: %.2f, head: %.2f",m_Position.x,m_Position.y,m_Position.z,m_PitchDegrees,m_HeadingDegrees);
SDL_WM_SetCaption(title,NULL);
*/
}

Este es el metodo principal. Lo pongo al principio del metodo de dibujado para que me haga una rotacion global del mundo. Las variables son facilmente deducibles, las que tienen una q son los quaterniones.

Esta funcion la sace de la camara basada en cuaterniones que encontre en nehe.

Tambien supongo que no tendras problemas en hacer un constructor de copia ni en derivar la camara para convertirla en tercera persona o tipo quake.

Para setear la posicion yo uso este metodo:

void glCamera::setPosition(GLfloat x,GLfloat y,GLfloat z,GLfloat heading, GLfloat pitch)
{
m_Position.x = x;
m_Position.y = y;
m_Position.z = z;
m_HeadingDegrees = heading;
m_PitchDegrees = pitch;
}


El problema lo encuentro con el lookAt(). Tengo la posicion de la camara, y el punto al que quiero mirar. Ademas tengo mi vector de direccion. Mi problema es que tengo que sacar los angulos de rotacion de Z sobre XY y de X sobre YZ.
Uso la siguiente funcion:

void glCamera::lookAt(GLfloat x,GLfloat y,GLfloat z)
{
// proyectar vectores sobre XY
glVector2 destDirXY(x - m_Position.x, y - m_Position.y);
glVector2 actualDirXY(m_DirectionVector.x - m_Position.x, m_DirectionVector.y - m_Position.y);
// normalizando
destDirXY.normalize();
actualDirXY.normalize();
GLfloat modules = destDirXY.length()*actualDirXY.length();
GLfloat dotProd = destDirXY.dotProduct(actualDirXY);
m_HeadingDegrees += RAD2DEG(acos(dotProd/modules));

// proyectar vectores sobre ZY
glVector2 destDirYZ(y - m_Position.y, z - m_Position.z);
glVector2 actualDirYZ(m_DirectionVector.y - m_Position.y, m_DirectionVector.z - m_Position.z);
// normalizado
destDirYZ.normalize();
actualDirYZ.normalize();
m_PitchDegrees += acos(DEG2RAD(destDirYZ.dotProduct(actualDirYZ)/(destDirYZ.length()*actualDirYZ.length())));
}


Pero no me hace bien esa rotacion. Si pones tu codigo a lo mejor lo sacamos entre los dos. Si me solucionas este problema, tambien mejor para ti, y ademas te puedo pasar el resto de las clases.

Gracias.

ozharu

No tengo el codigo de las funciones aqui, pero te comento como lo he hecho,

Parto de la base que quieres una orientacion nueva para la camara, entonces hay que ir a hacer las operaciones al mundo. Yo tomo la position y el lookAt del destino, y con ello

Vector sinNormalizar(vecTo - vecFrom)
         sinNormalizar.y = 0
          sinNormalizar.normaliza()
       


Mi eje Y es el Up. Una vez que tengo esto, utilizo una funcion que dado un vector origen y un destino me calcula el quaternion correspondiente.


Quaternion rotation1 = setShortestRotation(Vector (0,0,1), VectorNormalizado)(componentw y =0)

Con esto ya tendrias el Yaw, ahora nos falta el pitch. Para ello oriento el vector unitario con este quaternion

VectorYaw = orientaVector(rotation,Vector(0,0,1))
         Quaternion rotation2 = setShortestRotation(vectorYaw, VectorNormalizado) (pero con la componente con su valor original, vamos que normalizas el vector entero, sin poner la y a 0)
       Quaternion final = rotacion1 *rotation2; o al reves, no me acuerdo    


Este modo te evita usar matrices, aunque tb se puede hacer por matrices. Si tienes dudas de las matrices preguntamelo y te digo como se haria (aunque no toy seguro al 100%

Pero esto funciona y bien

killrazor

Pues la verdad es que mucho no lo entiendo. No es que no entienda de matrices pero no se que haces aqui

Vector sinNormalizar(vecTo - vecFrom)
sinNormalizar.y = 0
sinNormalizar.normaliza()


Ni aqui

Quaternion rotation1 = setShortestRotation(Vector (0,0,1), VectorNormalizado)(componentw y =0)


Creo que hace lo mismo que mi funcion setPerspective(), es decir saca un quaternion para cada rotacion y despues hace producto de cuaterniones. Fijate en las ultimas lineas de la funcion setPerspective, como setea el direction vector por que es mas o menos lo que tu necesitas.

killrazor

Bien, por mi parte ya esta resuelto. Use coordenadas esfericas para sacar las rotaciones, pero dentro del flujo de mis calculos. Si quieres, contacta conmigo y podemos echarnos una mano.






Stratos es un servicio gratuito, cuyos costes se cubren en parte con la publicidad.
Por favor, desactiva el bloqueador de anuncios en esta web para ayudar a que siga adelante.
Muchísimas gracias.