Stratos: Punto de Encuentro de Desarrolladores

¡Bienvenido a Stratos!

Acceder

Foros





Duda con cámara 3d - SetLookAt

Iniciado por Loover, 14 de Marzo de 2008, 06:25:17 PM

« anterior - próximo »

Loover

Buenas, estoy siguiendo este tutorial para crear una clase cámara: http://www.fuzzygamedev.com/2007/05/13/implementando-la-clase-camara/

El caso es que tengo una duda. Los 3 vectores que utiliza en el tutorial para definir la cámara deben ser siempre perpendiculares entre sí, sin embargo, en el método SetLookAt (y en el método SetLookPost) simplemente cambia el valor del vector dirección de la cámara por el que se introduce en los parámetros y no cambia los otros dos. Esto no lo entiendo, ¿no deberían modificarse el vector Up y el vector Right también? Y si es así, ¿cómo se haría?

Un saludo.
IndieLib Libreria 2.5d utilizando aceleración por hardware para la programación de juegos 2d.
Indie Rover The monkeys are reading!

BeRSeRKeR

Una vez creada la matriz de vista con D3DXMatrixLookAtLH (internamente genera los vectores right, up y look), puedes extraer los mismos a través de la propia matriz generada.

Corresponden a las columnas 1ª, 2ª y 3ª, respectivamente.

Saludos.
¡Si te buscan en nombre de la ley, huye en nombre de la libertad!!

Loover

Pero entonces, dicha función del tutorial que he mencionado... ¿está mal? ¿Debería actualizar el vector Up y el vector Right?

¿Teneis por ahí alguna implementación de una cámara bien hecha?
IndieLib Libreria 2.5d utilizando aceleración por hardware para la programación de juegos 2d.
Indie Rover The monkeys are reading!

tamat

Yo a mis alumnos les puse esta practica (el enunciado está en catalan pero el PDF está en castellano), bajate el código si quieres.
Por un stratos menos tenso

Loover

Gracias Tamat, acabo de mirar el código. Lo malo es que no es lo que busco, las funciones que utilizas vienen a wrappear directamente las de Opengl. Vamos, que pasas directamente los 3 vectores, suponiendo que el usuario te los va a dar bien (siempre perpendiculares entre sí).

La clase cámara que intento hacer es algo más elaborada. Mi duda planteada es otra. Es, manteniendo una cámara en la que realizo operaciones de yaw, pitch y roll, de que forma puedo hacer un SetLookAt y SetLookPos de manera correcta, de forma que si transformo el vector dirección, los otros dos se mantengan perpendiculares. Porque en el tutorial que he puesto, CREO (esa es la otra duda) que lo hace mal.

Lo que quiero saber es:
- ¿Lo hace mal en el tutorial?
- ¿Cuál sería la forma de hacer un SetLookAt y un SetLookPos correctamente en dicho tutorial?

A ver si podeis echarle un vistazo, es una clase pequeñita. Un saludo.
IndieLib Libreria 2.5d utilizando aceleración por hardware para la programación de juegos 2d.
Indie Rover The monkeys are reading!

ethernet

Pego un código de un raytracer en glsl (fuente abajo):


static const char vsh_2d[] = \
uniform vec4 fpar[4];
void main(void)
{
   gl_Position=gl_Vertex;"
   vec3 d=normalize(fpar[1].xyz-fpar[0].xyz);"
   vec3 r=normalize(cross(d,vec3(0.0,1.0,0.0)));"
   vec3 u=cross(r,d);"
   vec3 e=vec3(gl_Vertex.x*1.333,gl_Vertex.y,.75);"   //    eye space ray
   gl_TexCoord[0].xyz=mat3(r,u,d)*e;"                 //  world space ray
   gl_TexCoord[1]=vec4(.5)+gl_Vertex*.5;"             // screen space coordinate
};



fpar:

   // camera position
   fparams[ 0] = 2.0f*sinf(1.0f*t+0.1f);
   fparams[ 1] = 0.0f;
   fparams[ 2] = 2.0f*cosf(1.0f*t);
   // camera target
   fparams[ 4] = 0.0f;
   fparams[ 5] = 0.0f;
   fparams[ 6] = 0.0f;


En resumen:


 vec3 d=normalize(target.xyz-src.xyz);
 vec3 r=normalize(cross(d,vec3(0.0,1.0,0.0)));
 vec3 u=cross(r,d);
 mat3 cameraRot = mat3(r,u,d);


Faltaría añadirle la translación

fuente: http://rgba.scenesp.org/iq/demoscene/codes/isystem1k4k/isystem1k4k.htm

tamat

loover, no pretendía que mirases como wrappeo una funcion de opengl, te veo capaz de eso y de mucho mas. Esperaba más bien que le echases un ojo al PDF donde les explicaba a mis alumnos cómo substituir esas funciones de OpenGL por funciones echas por ellos, ahí sale cómo construir la matriz View y la Perspective a partir de los vectores.
Por un stratos menos tenso

Loover

Citarte veo capaz de eso y de mucho mas

No te creas, estoy verde en estos temas. Y me ha despistado mucho el tutorial citado, sigo pensando que lo hace mal. Me fuí directo al código fuente. Voy a revisar el PDF.

[edit]
Lo he mirado otra vez, ayer solo lo hice por encima. Pero... no está lo que pregunto, ¿no? ¿o sí y no me acabo de entererar? Viene a explicar como generar la matriz vista a partir de los 3 vectores, como hacen en este otro tutorial http://www.toymaker.info/Games/html/camera.html (que es lo que finalmente estoy usando).

Pero ¿cómo hacer un SetLookAt (¡ojo! en un objeto cámara implementado por mi que tiene 3 vectores (front, up y right) y quiero que mantengan el ser perpendiculares entre sí), SetLookPos (que usaría la función interior internamente)? Es que los otros dos vectores (up, right), si movemos el Front arbitrariamente, podrían quedar perpendiculares de varias maneras, no sé como se hace para que se quede de la manera más "normal" posible, que la cámara no se vaya a poner a inclinarse mucho, mientras sigue a un personaje en la escena anclada en un punto fijo (por poner un ejemplo).

¿Bastaría con esto que pone en el PDF? ¿Es esta la parte que querías que viera? ¿Viene a ser esto un LookAtPos?

CitarF = Center – Eye; //calculamos el vector front
F = F / |F| //normalizamos el vector Front
U = U / |U| //normalizamos el vector Up
S = F x U //creamos el vector Side usando producto vectorial
S = S / |S| //normalizamos el vector Side
U = S x F //calculamos un Up que sea ortonormal a F y S

Todavía nadie me ha dicho nadie si está mal en el tutorial primero que os puse, que es una de las cosas que me lían.

ethernet, el código este, me lia un huevo de pato. Aunque en el "resumen" parece que hace esto que he puesto aquí encima, ¿o no?

No estoy nada puesto en estos temas :)
IndieLib Libreria 2.5d utilizando aceleración por hardware para la programación de juegos 2d.
Indie Rover The monkeys are reading!

Loover

Voy a explicarlo de otra manera:

- Imaginaros una habitación
- Hay una cámara en la esquina superior de una de las 4 esquinas de la habitación, pegada al techo.
- Hay un bicho en el centro de la habitación.

Ahora quiero que mi cámara, apunte al bicho mientras que este se mueve por toda la habitación, y que siempre le esté apuntando directamente.

- Así que calculo el vector que va desde el punto del bicho hasta la cámara.
- Ahora, me faltan el vector Up y el Right (este lo quiero, porque con esta misma cámara, más tarde igual me da por hacer Yaw, Pitch y roll).

Y aquí es donde viene la duda.

Si lo pensais, el vector Up y Right, que deben ser perpendiculares entre sí, y perpendiculares al Front, pueden quedar de muchas formas posibles, pero lo que a mi me interesa es que queden de una manera natural, es decir, el up apuntando hacia el cielo y el right (supongo) que mas o menos paralelo al suelo, de forma que parezca que la cámara se mueve bien. Porque si calculo el vector Up y Right de cualquier manera, puede que la cámara, apunte al bicho, pero se incline un montón o esté totalmente del revés.

Y no me aclaro con eso. ¿Van los tiros por lo de que el vector Up debería, junto con el vector Front, estar contenidos en un plano PERPENDICULAR al suelo? ¿Evitaría así, como diría un director de cine, los ángulos aberrantes? (Inclinaciones de la cámara).
IndieLib Libreria 2.5d utilizando aceleración por hardware para la programación de juegos 2d.
Indie Rover The monkeys are reading!

ethernet

Hay una cosa que debes tener clara:

- para especificar una cámara necesitas dar, como mínimo, dos parámetros, por ejemplo dirección y roll o dirección y UP, lo que sea. Esto aparte de su posición, claro.

No puedes pretender que con un solo parámetro la cámara se invente a si misma. Otra cosa es que se asuman cosas, como por ejemplo que la cámara deba estar, como en la realidad, con el vector up mirando hacia arriba (razonablemente).

En el código que has puesto tiene como entradas Center, Eye y U, ese U si es (0,0,1) (suponiendo un sistema de coordenadas con Z hacia "el techo") queda una cámara como la que tú quieres, esto es, F, S y U formarán la base de vectores del sistema de coordenadas de la cámara (el álgebra de la carrera sirve para algo).

En cualquier caso gluLookAt(cam[0], cam[1], cam[2], bicho.pos[0], bicho.pos[1], bicho.pos[2], 0.0f,0.0f,1.0f); te dará lo que necesitas sin complicaciones.

Loover

Tengo claro los parámetros necesarios para especificar una cámara. Dos vectores y la posición. Eso, como el agua. Lógico y simple.

La duda es otra. La expuesta. Y sigo sin tenerla clara. No veo cómo al generar el vector Up, este va a ser correcto en todos los casos. Imagina la cámara en el techo y el bicho justo debajo... debe haber un momento en el que el vector Up se invierta, o la cámara va a seguir al bicho pero al revés...

CitargluLookAt(cam[0], cam[1], cam[2], bicho.pos[0], bicho.pos[1], bicho.pos[2], 0.0f,0.0f,1.0f);

Aquí el vector Up, siempre apunta hacia arriba.¿No debería ir variando cada vez que que se actualizar el vector dirección? (en el modelo cámara yaw, pitch, roll) Porque sino, no va a ser perpendicular a los otros dos. Y cuando hago un "fly" (es decir, me desplace por el vector Up arriba o abajo, iré recto hacia el cielo en dirección (0,0,1) , y no siguiendo dicho vector que es lo que quiero.
IndieLib Libreria 2.5d utilizando aceleración por hardware para la programación de juegos 2d.
Indie Rover The monkeys are reading!

ethernet

A ver, el vector UP que espcificas en gluLookAt no es el vector UP real, internamente hace lo que has puesto tu en el código anterior, esto es, calcular un up ortogonal.

Lógicamente pasa que si ek producto vectorial del up especificado y la dirección es 0 la cosa no funciona (en ese caso que comentas pasa), con lo cual tu debes especificar a gluLookAt un vector adecuado que me imagino será el que tú quieres calculas. Pero ojo, solo va a pasar en ese caso, la cámara no se va a invertir si especificas (0,0,1).

No sé como debes solventar ese caso en el que cross(dir, up) == 0, cuando yo he lidiado con eso símplemente he evitado tener ese caso y listo (cambiando de cámara por ejemplo). Dependerá de cada caso concreto.

Loover

¡Gracias! Ahora lo veo claro. Si me surgen más dudas durante la implementación, volveré aqui.
IndieLib Libreria 2.5d utilizando aceleración por hardware para la programación de juegos 2d.
Indie Rover The monkeys are reading!

tamat

sorry, me lié con tu pregunta y pensé que querias calcular la matriz View en funcion del eye, center y del up_no_ortonormal (normalmente 0,1,0).
Por un stratos menos tenso

Loover

No es que yo me explicara tampoco muy bien :D
IndieLib Libreria 2.5d utilizando aceleración por hardware para la programación de juegos 2d.
Indie Rover The monkeys are reading!






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.