Llevo unos dias probando mi implementación de Ray Casting, la parte inicial en la que según las coordenadas del ratón X e Y obtengo un vector de origen y una dirección.
Si utilizo gluUnProject a veces falla, para calcular los 2 puntos el inicial y el final, pasando como parametro 0.0 y 1.0 obtengo el punto inicial y el final. A veces el punto final falla.
En GameDev alguien que lo hizo como yo tenia el mismo problema.
He probado como viene en el FAQ de OpenGL
http://www.opengl.org/resources/faq/technical/selection.htm
Pues bien, con esta forma no tengo la misma precisión. Y falla un poco...
Alguien sabe de donde viene que a veces falle gluUnProject ?
Post en GameDev:
http://www.gamedev.net/community/forums/topic.asp?topic_id=396263
Por si quereis ayudarme, el código que falla al cambiar el aspect ratio es:
// http://www.opengl.org/resources/faq/technical/selection.htm
// 20.010 How can I know which primitive a user has selected with the mouse?
// Nota: no tiene tanta precision como con gluUnproject
{
int window_x = mouse_x - m_width / 2;
int window_y = (m_height - mouse_y) - m_height / 2;
float norm_x = float(window_x) / float(m_width / 2);
float norm_y = float(window_y) / float(m_height / 2);
float zNear = m_pCamera->getZNear( );
float aspect = m_pCamera->getAspectRatio( );
float x = zNear * aspect * norm_x;
float y = zNear * norm_y;
Vector3 pickRay(x, y, -zNear);
pickRay.normalize( );
Vector3 eyeRay = pickRay * m_pCamera->getViewMatrix( ).inverse( );
return Ray(m_pCamera->getPosition( ), eyeRay);
}
Hay algo que no estoy teniendo en cuenta, pero es igual al del FAQ de OpenGL: http://www.opengl.org/resources/faq/technical/selection.htm
Por qué no pruebas a hacer unos test unitarios sobre ese método o función? sobretodo probando los casos mas extremos.
Aparte, qué signigica que "el punto final falle?"
Hay que obtener 2 puntos:
- Comienzo del frustum
- Final del frustum
Un rayo tiene un vector de origen y una dirección.
El test unitario da como resultado que al intentar obtener el punto final del frustum de la camara (pasandole a glUnProject 1.0, recordemos que para el inicial Z es 0.0) repitiendo la operación inumerables veces sin modificar nada, el vector obtenido a veces no es correcto.
vDireccion = vFinal - vOrigen
El inicial debe coincidir con la posición de la camara... etc. El rayo no se tira nunca hasta el final en realidad, se obtiene la Z maxima de lo que hay en pantalla y cosas varias.
Lo chungo es que no me pasa solo a mi y he probado mil cosas del FAQ de OpenGL a hacerlo exacto y a aplicar diferentes aspectRatio. Si el aspectRatio es 1.0 graciosamente suele dar el rayo en su sitio. Lo que no recuerdo es si proyectaba bien el rayo dejando la camara quieta y apuntando a las esquinas del Viewport... he hecho mil pruebas ya xD
Lo peor que puede pasar utilizando glUnProject es que descarte los vectores que salgan q sean muy diferentes con alguna comprobación. Lo mas seguro es que me baje del CVS de MESA la función y la revise, debe haber algo chungo.
Saludos.
Nota adicional:
float bottomY = viewport[3] - mouse_y;
gluUnProject(mouse_x, bottomY, nominated_screen_z, mModelView, mProj, viewport, &world_x, &world_y, &world_z);
He entendido lo siguiente: "si llamo a gluUnproject muchas veces con los mismos valores tengo diferentes valores de retorno".
Yo he usado esa técnica de "desproyectar" y me ha funcionado bien para valores lógicos de near y far (o sea de matriz projection), qué valores tienes para esa matriz?
Solved! 3:48 de la mañana.
Al utilizar glGetIntegerv(GL_VIEWPORT, viewport); la altura me la daba mal a veces...
No debería haber usado esto ya que tengo capturado el evento de "resize" de la ventana y modifico mi width y height.
Como sabeis, en OpenGL los valores de coordenada Y empiezan abajo a la izquierda como 0, 0. y hay que hacer:
GLint viewport[4];
glGetIntegerv(GL_VIEWPORT, viewport);
float bottomY = viewport[3] - mouse_y;
no uso para nada, glGetIntegerv o glGetDoublev ( para las matrices de proyeccion y modelView ) lo controlo yo todo, imagino que de vez en cuando se hace la picha un lio al redimensionar la ventana de render y daba un valor de 512 en vez de 600 ( por ejemplo o lo q fuere equivalente al valor height real que me da la ventana ) entre frames.
Así que está todo solucionado :) viva el debugger ^^
Gracias por todo ethernet. Un saludo.
Mamonazos, es proYectar, no proJectar. Qe daño a etxo el inglés...
Sin acrituZ ni tensiones :lol:
hahahaha :P la proJsima vez que nos interrumpas... veras!
Si es que... a mi ya me pasó contigo xD y por eso ya tengo cuidado!