Stratos: Punto de Encuentro de Desarrolladores

¡Bienvenido a Stratos!

Acceder

Foros





Teoría para colocar una cámara.

Iniciado por tawky, 17 de Agosto de 2011, 09:35:15 AM

« anterior - próximo »

tawky

Hola.

Necesito ayuda para colocar una cámara dándome el VRP , VPN y el VUP.

Las definiciones matemática que encuentro por ahí no las entiendo, y sin eso no puedo ponerme a programar el algoritmo.

Gracias de antemano.

tawky

Si necesitáis que os de mas información para entender lo que necesito decírmelo.

Tengo realizada una escena con C y OpenGL, la camara esta colocada por defecto.

Lo que quiero hacer es introducir una segunda cámara, y pasandole la VRP, VPN y VUV por consola calcular el sitio y hacia donde miraría la cámara.

Pero es que no tengo ni idea de como se hace ni teórica ni practica.

Cualquier cosa que podáis pasarme o decirme donde mirar me sera de gran ayuda, estoy bloqueado con esto.

Gracias.

Warchief

<Perdon por la falta de acentos, no tengo tilde en este teclado>

VRP es la posicion.
VPN es la direccion donde mira.
VUV es el vector "up" de la camara.

A partir de VPN y VUV se puede obtener el vector right/left mediante producto vectorial. Eso te da los 3 ejes de coordenadas de la camara, que junto a la posicion, te da la transformacion de la camara. Lo que tienes que hacer en construir esa matriz de transformacion, que sera de la forma:
M = RT (donde R es rotacion y T traslacion)

Sean n, u y v los ejes de la camara en coordenadas locales. (* es producto vectorial)
n = VPN / |VPN| (es decir, n es el vector front de la camara, que es como dijimos VPN, pero hay que normalizar)
u = n*VUV / |n*VUV| (es decir, u es el vector up de la camara en coordenadas locales y normalizado)
v = u*n (obtenemos vector right/left de la camara, que ya esta normalizado por ser producto de dos normalizados)
Con esos tres ejes ya tienes R = (u, v, n)

Ya solo queda hallar la traslacion, que se calcula transformando el punto VRP a las nuevas coordenadas:
t = -pR (donde p es el punto = VRP, y R es la matriz de rotacion que hemos creado)

M = RT, dado que R es 3x3 y T 3x1, necesitas anyadir W 1x3 = 0,0,0,1 para tener una matriz de transformacion 4x4.
Pon la matriz a la camara y problema resuelto.

Espero que con eso puedas entender mejor ahora las definiciones que leas por ahi.

Si quieres hacer trampas mira el metodo computeMatrix() de aqui:
http://www.cs.ucl.ac.uk/teaching/3079/java-lab1/question/camera.java

IMPORTANTE:
El orden de los vectores y de los productos vectoriales es importante para la orientacion de la camara, asegurate de que el eje de coordenadas (left/right) coincide con la escena que tienes en opengl. En el fichero java aplican signo negativo a n, probablemente por esta razon.



tawky

Entonces.Voy a explicarlo como si de una cámara real se tratase para ver si me entero de una vez.  :-[, si hay algo mal solo decirlo que seguro que me equivoco.

VRP donde coloco el trípode de la cámara.
VPN ahora muevo la cámara para que apunte a donde quiero.
VUV es como he anclado la cámara al trípode, es decir con el visor arriba, abajo, izquierda, etc.

Me he perdido un poco, ¿para que sirve el  vector right/left?

Creo que me faltan matemáticas para entender todo esto. Para que sirve hacer el producto vectorial y luego normalizar, explícamelo de la forma mas sencilla que no tengo mucho nivel  ^_^'.

Voy a googlear un poco a ver si entiendo mas todo esto que me has puesto.   

Muchas gracias. ;)


Warchief

Opengl tiene otras funciones mas sencillas para decirle donde poner la camara. gluLookAt es la que necesitas. Hace lo que he explicado antes, de forma que no lo tienes que implementar tu, yo pensaba que querias hacer la matematica detras de ello.
Llama a gluLookAt con los parametros:
eye = VRP
center = VRP + VPN
up = VUV
http://pyopengl.sourceforge.net/documentation/manual/gluLookAt.3G.html


- - - -  - - - -  - - - -  - - - -  - - - -  - - - -  - - - -  - - - -  - - - -
Explicacion de la matematica
- - - -  - - - -  - - - -  - - - -  - - - -  - - - -  - - - -  - - - -  - - - -

VRP donde coloco el trípode de la cámara.
Si, mas o menos. El centro de la camara seria la posicion exacta.

VPN ahora muevo la cámara para que apunte a donde quiero.
Si, mas o menos. Es el vector que va desde el centro de la camara hacia donde apunta.

VUV es como he anclado la cámara al trípode, es decir con el visor arriba, abajo, izquierda, etc.
No entiendo lo del visor, pero mas o menos, es parte de la rotacion de la camara. Es el vector que apunta para arriba de la camara.

En un sistema de 3 coordenadas necesitas 3 ejes para representar un punto. El mundo/escena opengl tiene uno donde todos los objetos estan definidos, pero cada objeto tiene los suyos propios. En la camara, VPN y VUV son 2 de esos 3 vectores. El tercero, por las propiedades de los ejes se puede sacar mediante el producto vectorial de los otros dos.

Para decirle a opengl donde esta un objeto y la rotacion que tiene se emplea una matriz 4x4, que es lo que hemos calculado a partir de los datos que has dado (es la que calcula gluLookAt.)



Para que sirve hacer el producto vectorial y luego normalizar
Si no sabes esto, si, te falta bastante base de matematicas todavia.

Wikipedia: En álgebra lineal, el producto vectorial es una operación binaria entre dos vectores de un espacio euclídeo tridimensional que da como resultado un vector ortogonal a los dos vectores originales.

Normalizar es hacer que un vector tenga magnitud 1. Los ejes de coordenadas tienen que estar normalizados.

Fuente de las imagenes:
http://shitohichiumaya.blogspot.com/2011/01/what-matrix-glulookat-generates-1.html



tawky

Primero voy a empezar probando con gluLookAt para ver el funcionamiento.

Actualmente tengo un código así:

printf("Introduce la coordenada X del VRP ");scanf("%f",&Geyex);
printf("Introduce la coordenada Y del VRP ");scanf("%f",&Geyey);
printf("Introduce la coordenada Z del VRP ");scanf("%f",&Geyez);
printf("Introduce la coordenada X del VPN ");scanf("%f",&Gcenterx);
printf("Introduce la coordenada Y del VPN ");scanf("%f",&Gcentery);
printf("Introduce la coordenada Z del VPN ");scanf("%f",&Gcenterz);
printf("Introduce la coordenada X del VUV ");scanf("%f",&Gupx);
printf("Introduce la coordenada Y del VUV ");scanf("%f",&Gupy);
printf("Introduce la coordenada Z del VUV ");scanf("%f",&Gupz);

gluLookAt(Geyex,Geyey,Geyez,Geyex+Gcenterx,Geyey+Gcentery,Geyez+Gcenterz,Gupx,Gupy,Gupz);

Lo que no se muy bien es que valores meterle por consola.

He probado por ejemplo con 0,0,20 0,0,0 1,1,1 pero pierdo de vista la escena.
¿ Podéis pasarme unos valores validos?
- Yo creo que con el VRP no hay problemas, solo lo he alejado algo en el eje z.
- Con el VPN l estoy diciendo que mire al eje de coordenadas.
- VUV aqui es donde me pierdo , no se muy bien lo que he hecho poniendo 1,1,1.

tawky

La cámara que enfoca la escena completa es:

Plano_delantero=10;
Plano_trasero=6000;
Observador_distancia=32*Plano_delantero;
Observador_angulo_x=-30;
Observador_angulo_y=0;
camX=0;
camY=-80;

glEnable(GL_DEPTH_TEST); // se habilita el z-bufer

glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glFrustum(-Tamanio_x,Tamanio_x,-Tamanio_y,Tamanio_y,Plano_delantero,Plano_trasero);

Para moverla Sin VRP, ni VPN ni VUV :

glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glTranslatef(camX,camY,-Observador_distancia);
glRotatef(Observador_angulo_x,1,0,0);
glRotatef(Observador_angulo_y,0,1,0);

Tras esto me sale así:



He usado tu valores de java: VRP 0,0,0 VPN 0,0,-1 VUV 0,1,0

Y me sale así: pero no se si es correcto.


Warchief


VUV es un vector como si fuera tu altura, simplemente tiene que ir en lo que consideres "hacia arriba" para la camara.

Si los ejes son con "hacia arriba" en Z, usa:
VPN=0,0,0 Mirando al eje de coordenas (o donde quieras)
VRP=10,10,10 La posicion de la camara.
VUV=0, 0, 1 Hacia arriba en Z

Si los ejes son con "hacia arriba" en Y, usa:
VPN=0,0,0 Mirando al eje de coordenas (o donde quieras)
VRP=10,10,10 La posicion de la camara.
VUV = 0, 1, 0 Hacia arriba en Y

Por lo general arriba no es en X.

En vez de meter los valores a mano, haz un update:

while ( true )
{
    VRP.X += 1.0f // luego prueba otras coordenadas
    glLookAt( blah )
    Render();
}

tawky

Creo que empiezo a entender el funcionamiento de esto, pero aun me queda.

¿Al iniciar una cámara donde esta colocada, donde mira y donde tiene el VUV?

¿ Así seria?
Vamos a calcular la n.

//vpn
  • ;vpn[y];vpn[z]; aqui tenemos los valores de VPN.
    mag = sqrt(vpn
  • * vpn
  • + x[y] * x[y] + x[z] * x[z]);
    if (mag)
    {
       n
  • = vpn
  • /mag;
       n[y]= vpn[y] /mag;
       n[z]=vpn[z] / mag;
    } //sacamos la n , ¿ya esta normalizada no?

    aux_u
  • = n
  • *VUV
  • ;
    aux_u[y] = n[y]*VUV[y];
    aux_u[z] = n[z]*VUV[z];

    mag = sqrt(aux_u
  • * aux_u
  • + aux_u[y] * aux_u[y] + aux_u[z] * aux_u[z]);
    if (mag)
    {
       u
  • = aux
  • /mag;
       u[y]= aux[y] /mag;
       u[z]=aux[z] / mag;
    } //sacamos la u , ¿ya esta normalizada no?

    v
  • = u
  • *n
  • ;
    v[y] = u[y]*n[y];
    v[z] = u[z]*n[z];

    a partir de ahí no se como hacer la translacion y mucho menos la rotación....


Warchief


void gluLookAt (GLdouble eyeX, GLdouble eyeY, GLdouble eyeZ,
                            GLdouble centerX, GLdouble centerY, GLdouble centerZ,
                            GLdouble upX, GLdouble upY, GLdouble upZ );
eyeX, eyeY, eyeZ
Specifies the position of the eye point.
centerX, centerY, centerZ
Specifies the position of the reference point.
upX, upY, upZ
Specifies the direction of the up vector.



gluLookAt ( vrp.x, vrp.y, vrp.z, 0, 0, 0, vuv.x, vuv.y, vuv.z );

// Ejemplos para Z = up:
// gluLookAt ( 50, 50, 50,  0, 0, 0, 0, 0, 1 );
// gluLookAt ( 50, 50, 10,  0, 0, 0, 0, 0, 1 );


tawky

Hola. Sigo usando el gluLookAt haber si me entero del funcionamiento.

Estoy poniendo la botonera de la cámara.

ASDW lo uso para mover el VPN en x e y.

Los cursores los quiero usar para girar la cámara.

¿Que valores le tengo que dar al VRP para que la cámara vaya girando sobre el ejeY con un incremento de 15 grados cada pulsación?

tawky

Cita de: tawky en 24 de Agosto de 2011, 12:40:54 PM
Hola. Sigo usando el gluLookAt haber si me entero del funcionamiento.

Estoy poniendo la botonera de la cámara.

ASDW lo uso para mover el VPN en x e y.

Los cursores los quiero usar para girar la cámara.

¿Que valores le tengo que dar al VRP para que la cámara vaya girando sobre el ejeY con un incremento de 15 grados cada pulsación?

Por favor, ¿alguien sabe como girar la cámara?

Gracias.

tawky

Hola , sobre la función gluLookAt:

Dices que:
eye = VRP
center = VRP + VPN
up = VUV

No entiendo por que sumar el VRP + VPN.

Si yo tengo un objeto en el 0,0,0  quiero poner una cámara para verlo. Debo de poner el gluLookAt(0,0,-20,0,0,0.0,1,0) no?

si le sumo el VRP como dices quedaria gluLookAt(0,0,-20,0,0,-20,0,1,0) y esto no tiene sentido no?

Warchief

VRP + VPN es para mirar al frente.

Como puse antes:
centerX, centerY, centerZ     Specifies the position of the reference point.

Y puse ejemplos mirando al 0,0,0.

[b]gluLookAt ( vrp.x, vrp.y, vrp.z, 0, 0, 0, vuv.x, vuv.y, vuv.z );[/b]
// gluLookAt ( 50, 50, 50,  0, 0, 0, 0, 0, 1 );
// gluLookAt ( 50, 50, 10,  0, 0, 0, 0, 0, 1 );


- - - -

Para lo que quieres hacer (cámara rotando alrededor de un objeto) tienes que:
1) partir de la posición del objeto
2) sabiendo los ángulos (horizontal y vertical) que quieres que tenga la cámara, calcular el vector desde el objeto
3) multiplicar ese vector por la distancia
Esto te da la posición o EYE.

Center es la posición del objeto.
Up lo he dicho ya varias veces.

Después querrás que el objeto no sea fijo, así que WASD tiene que afectar a ese objeto que la cámara mira, no a la cámara misma, ya que la posición de la cámara depende de los ángulos, que normalmente se controlan con el ratón.

Si quieres que WASD modifiquen la cámara, pero siempre mirar al 0,0,0, entonces modifica los ángulos horizontal y vertical, y la distancia. Necesitas al menos 6 teclas, ya que son 3 parámetros.

tawky

Cita de: Warchief en 18 de Agosto de 2011, 07:03:12 PM
VRP es la posicion.
VPN es la direccion donde mira.
VUV es el vector "up" de la camara.

A partir de VPN y VUV se puede obtener el vector right/left mediante producto vectorial. Eso te da los 3 ejes de coordenadas de la camara, que junto a la posicion, te da la transformacion de la camara. Lo que tienes que hacer en construir esa matriz de transformacion, que sera de la forma:
M = RT (donde R es rotacion y T traslacion)

Sean n, u y v los ejes de la camara en coordenadas locales. (* es producto vectorial)
n = VPN / |VPN| (es decir, n es el vector front de la camara, que es como dijimos VPN, pero hay que normalizar)
u = n*VUV / |n*VUV| (es decir, u es el vector up de la camara en coordenadas locales y normalizado)
v = u*n (obtenemos vector right/left de la camara, que ya esta normalizado por ser producto de dos normalizados)
Con esos tres ejes ya tienes R = (u, v, n)

Ya solo queda hallar la traslacion, que se calcula transformando el punto VRP a las nuevas coordenadas:
t = -pR (donde p es el punto = VRP, y R es la matriz de rotacion que hemos creado)

M = RT, dado que R es 3x3 y T 3x1, necesitas anyadir W 1x3 = 0,0,0,1 para tener una matriz de transformacion 4x4.
Pon la matriz a la camara y problema resuelto.

Espero que con eso puedas entender mejor ahora las definiciones que leas por ahi.

Si quieres hacer trampas mira el metodo computeMatrix() de aqui:
http://www.cs.ucl.ac.uk/teaching/3079/java-lab1/question/camera.java

IMPORTANTE:
El orden de los vectores y de los productos vectoriales es importante para la orientacion de la camara, asegurate de que el eje de coordenadas (left/right) coincide con la escena que tienes en opengl. En el fichero java aplican signo negativo a n, probablemente por esta razon.


Aun sigo liado con la cámara. Pero me quedo rematarlo.
Ya tengo la cámara casi implementada.
Los pasos que sigo para son los siguientes:
a- Doy por consola VRP,VPN,VUV.
Como la cámara es fija , los translate y rotate se hace sobre el objeto.
b- Translate(-VRPx,-VRPy,VRPz).
c- Roto sobre X poniendo el VPNy=0 , el VPNz cambia en consecuencia.
d- Roto sobre Y ponuendo el VPNx=0, el VPNz cambia en consecuencia.
e- Roto sobre Z para alinear la u sobre el eje X. Necesito calcular u y v.

n = VPN / |VPN| (es decir, n es el vector front de la camara, que es como dijimos VPN, pero hay que normalizar)
u = n*VUV / |n*VUV| (es decir, u es el vector up de la camara en coordenadas locales y normalizado)
v = u*n (obtenemos vector right/left de la camara, que ya esta normalizado por ser producto de dos normalizados)
Con esos tres ejes ya tienes R = (u, v, n)

PROBLEMA. Antes del paso c calculo el n,u,v, pero tras los pasos c y d se me han movido.

De n(VPN) llevo el control, pero de u no se como hacerlo.











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.