Stratos: Punto de Encuentro de Desarrolladores

¡Bienvenido a Stratos!

Acceder

Foros





Ratón y perspectiva 3d

Iniciado por zunou, 18 de Enero de 2010, 08:55:59 PM

« anterior - próximo »

zunou

 :D Me explico, lo que intento hacer es seleccionar un objeto con un cursor, el problema es que ese objeto está en 3d y en perspectiva, pero de frente, es decir, la vista es como si fuera en 2d  tengo la cámara mirando a Z y frente a ella los objetos, alineados con z=0, osea que solo van de izquierda a derecha y de arriba a abajo .... el tema es que no tengo ni idea de como hacer coincidir las coordenadas del raton con la de el objeto en 3d, ya que al estar en perspectiva las posiciones no son iguales, y no se como hacerlas coincidir en 3d.

^_^' No se si me explico.

¿Alguien me puede dar una idea de como hacerlo?

[EX3]

Me suena que los tiros iban por algo llamado "mouse picking": http://www.google.com/search?ie=UTF-8&oe=UTF-8&sourceid=navclient&gfns=1&q=mouse+picking

En los SDK de DirectX al menos recuerdo mas de una demo mostrando esta tecnica. Siento no poder detallarte mas ya que soy del 2D, no 3D (de ahi el enlace a la busqueda de google  ^_^')

Salu2...
José Miguel Sánchez Fernández
.NET Developer | Game Programmer | Unity Developer

Blog | Game Portfolio | LinkedIn | Twitter | Itch.io | Gamejolt

zunou

Si, mas o menos es eso, lo que pasa es que la mayoria de las explicaciones que he encontrado con lo de picking se centran mas en saber la distancia desde la cámara, para calcular la profundidad, y saber si tiene otro objeto delante y esas cosas, y otros utilizan funciones de glu, y yo estoy utilizando tambien opengl ES, y como que no tiene esas funciones.... pero mas o menos me dan una idea :D,  veré a ver si saco algo.

gracias EX3.

Si alguien conoce alguna otra forma, se lo agradecería mucho  :D

Shaitan

Tienes que pasar de coordenadas de pantalla a coords 3d (gluunproject). Te puedes escribir tu mismo el código equivalente a gluUnproject, mira aqui:
http://www.opengl.org/discussion_boards/ubbthreads.php?ubb=showflat&Number=268884

Una vez tienes esta coordenada deberías crear un rayo entre el ojo (0,0,0) y esa coordenada buscar la intersección  de ese rayo con cada objeto que tengas visible. Con eso puedes calcular el tamaño del vector entre el ojo (0,0,0) y la intersección calculada, es decir la distancia del objeto. El objeto cuya distancia sea menor, será el seleccionado.

J.
<º))))><.·´¯`·.Shaitan´¯`·.¸.·´¯`·._.·

zunou

Ok, le dare un vistazo a eso a ver si puedo montarme un gluUnproject.

gracias!

Prompt

No uses GL_PICKING solo está acelerado en las gráficas más gordas, por ejemplo las versiones QUADRO de nVidia. Debes usar "gluUnproject" :)

Un vez que tengas ese rayo, debes iterar por los BBOX (por ejemplo) de los objetos de pantalla para saber a cual le das, y si tienes varios en la lista pues, te quedas por ejemplo con el más cercano a la cámara.

zunou

Ok, me estoy mirando el src de gluUnproject  y las funciones que lo acompañan, lo de BBOX creo que no lo necesito (creo) porque solo quiero usar los ejes x e y, es decir que todos los objetos estan a z=0, tenia pensado crearme como un segundo cursor (cx, cy) que sería el resultado de transformar las coordenadas x e y del cursor normal , aún no he visto bien como funciona gluUnproject, pero seria algo asi ¿no?

blau

Yo lo hago asi desde Xna por si te aporta algo:

Código (csharp) [Seleccionar]

public Ray ScreenToRay(Vector2 posicion)
        {
            Viewport Viewport = GestorCamaras.Viewport;
            Vector3 nearSource = Viewport.Unproject(new Vector3(posicion.X, posicion.Y, Viewport.MinDepth), projection, view, Matrix.Identity);
            Vector3 farSource = Viewport.Unproject(new Vector3(posicion.X, posicion.Y, Viewport.MaxDepth), projection, view, Matrix.Identity);
            Vector3 direction = farSource - nearSource;

            direction.Normalize();

            return new Ray(nearSource, direction);
        }

Prompt

Cita de: zunou en 19 de Enero de 2010, 03:03:25 PM
Ok, me estoy mirando el src de gluUnproject  y las funciones que lo acompañan, lo de BBOX creo que no lo necesito (creo) porque solo quiero usar los ejes x e y, es decir que todos los objetos estan a z=0, tenia pensado crearme como un segundo cursor (cx, cy) que sería el resultado de transformar las coordenadas x e y del cursor normal , aún no he visto bien como funciona gluUnproject, pero seria algo asi ¿no?

Un BBOX es un bouding box, que viene a significar "caja / cuadro delimitador", da igual que sea 2D o 3D necesitas sabes "donde acaba y donde empieza un objeto" para saber si le has dado, y si quieres algo más fino, si tienes más de un objeto mezclado, luego dentro haces otra pasada para ver a que mesh le das con la misma técnica.

kraj0t

Hay otra técnica que también se usa, conocida como selección en buffer. No sé si es lo que quieres, pero es muy útil para conseguir precisión 'pixel-perfect', usando la imagen tal y como sale por pantalla.

Básicamente, consiste en lo siguiente: cuando el usuario hace click renderizas tu escena en memoria, en un buffer. En el buffer, pintas los objetos con colores planos, un color único para cada objeto. En un mapa, almacenas cada objeto identificándolo con su color. Usando las coordenadas del ratón puedes pillar el pixel concreto sobre el que se ha pulsado, comprobar su color, y buscar en el mapa qué objeto se pulsó.

Para mejorar la eficiencia, puedes usar un buffer pequeño (por ejemplo, 320x240 para una resolución de 1024x768). También puedes limitar lo que se dibuja en el buffer a una sección de la pantalla.

Aquí tienes un enlace a un post de los foros de Ogre3d donde Sinbad explica cómo implementarlo. Es pseudocódigo, nada de C++ ni Ogre.
Muerte y destrucción a tú
¿A yo?
¡A tú!

zunou

#10
Parece interesante, pero ya he conseguido que me funcione con gluUnproject, con muy buena precisión, así que de momento me quedo con eso :), pero gracias.

Cita de: Prompt en 20 de Enero de 2010, 10:05:03 AM
Un BBOX es un bouding box, que viene a significar "caja / cuadro delimitador", da igual que sea 2D o 3D necesitas sabes "donde acaba y donde empieza un objeto" para saber si le has dado, y si quieres algo más fino, si tienes más de un objeto mezclado, luego dentro haces otra pasada para ver a que mesh le das con la misma técnica.

A, si, te habia entendido otra cosa, no sé por que  XD, si , los objetos los rodeo con una caja para saber si el cursor 3d está dentro de los limites de esa caja.

Bueno, pues parece que ya está solucionado el misterio, muchas gracias a todos por la ayuda  :)

Saludos!

Eskema

Yo tengo el project/unproject portado por si lo necesitas, aunque supongo que tu has hecho lo mismo ;)

blau

Uups, se que llego tarde, pero creia que habia añadido esto al anterior post:


public static Vector3 Unproject(this Viewport viewport, Vector3 screenSpace, Matrix projection, Matrix view, Matrix world)
            {
                Vector3 position = new Vector3();
                position.X = (((screenSpace.X - (float)viewport.X) / ((float)viewport.Width)) * 2f) - 1f;
                position.Y = -((((screenSpace.Y - (float)viewport.Y) / ((float)viewport.Height)) * 2f) - 1f);
                position.Z = (screenSpace.Z - viewport.MinDepth) / (viewport.MaxDepth - viewport.MinDepth);

                Vector4 us4 = new Vector4(position, 1f);
                Vector4 up4 = Vector4.Transform(us4, Matrix.Invert(Matrix.Multiply(Matrix.Multiply(world, view), projection)));
                Vector3 up3 = new Vector3(up4.X, up4.Y, up4.Z);
                return up3 / up4.W;
            }

zunou

Si, es  lo que hace el glUproject, luego lo que hago es dividir las coordenadas resultantes que me da la funcion, entre z=1 y lo que dé lo multiplico por la distancia de la cámara al objeto, así de simple.

Cita de: Eskema en 20 de Enero de 2010, 03:16:11 PM
Yo tengo el project/unproject portado por si lo necesitas, aunque supongo que tu has hecho lo mismo ;)

Pues si, XD ha sido tan facil como copiar y pegar las funciones desde el src de openGL  XD creo que no he tenido que modificar nada, no sé porque no las han añadido ogl ES  desde un principio, lo mismo pasa con gluLookAt, o perspective ¿?

Eskema

Pues si, supongo que glut no es un estandard para los de opengl y por eso no estan incluidas, pero bueno "portarlas" no supone mucho esfuerzo ;)






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.