Foro de elhacker.net

Programación => Programación C/C++ => Mensaje iniciado por: BlackM4ster en 10 Abril 2013, 20:36 pm



Título: Ayuda con las matemáticas !!!
Publicado por: BlackM4ster en 10 Abril 2013, 20:36 pm
Hola, estoy programando bounding boxes y tengo un problema a la hora de girar el objeto. P es el centro del objeto, tenemos el tamaño de x y de z. También tenemos el ángulo de rotación respecto al eje Z. Cual sería la formula para sacar el punto B en el segundo ejemplo?

(http://img189.imageshack.us/img189/2849/ayudap.jpg)


Título: Re: Ayuda con las matemáticas !!!
Publicado por: avesudra en 10 Abril 2013, 21:30 pm
Es que te podría ayudar pero no entiendo como está el objeto en el plano ahora mismo, aunque suponiendo que quieres girarlo con respecto al eje Z puedes usar trigonometría(que creo que sigue valiendo en el 3D por lo menos en este caso):
Siendo un punto B(1x,2y,3z) girarlo con respecto al eje Z 20º ,como la altura no cambia pues puedes girarlo con trigonometría quedando el punto

B' = ( cos(20) * 1 , 2 * sen (20) , 3z) = ( 0,93x , 0,68y , 3z)

(http://img820.imageshack.us/img820/5430/capturadepantallade2013z.png)


Título: Re: Ayuda con las matemáticas !!!
Publicado por: BlackM4ster en 10 Abril 2013, 21:33 pm
mm interesante, lo estaba resolviendo yo de esta manera:
Código:
dist[1] = sqrt(pow(pj.x-vx[1],2)+pow(pj.z-vz[1],2));
for (int i=1;i!=9;i+=2){
vx[i] = pj.x + dist[1] * sin((pj.ang_x+ang[i])*PI/180);
vz[i] = pj.z + dist[1] * cos((pj.ang_x+ang[i])*PI/180);}


Título: Re: Ayuda con las matemáticas !!!
Publicado por: amchacon en 10 Abril 2013, 21:37 pm
En lugar de PI/180, pon:

Código:
0,0174532

Le quitas a la maquina una división ingame (recuerda que la división es una operación costosa).


Título: Re: Ayuda con las matemáticas !!!
Publicado por: BlackM4ster en 10 Abril 2013, 21:45 pm
Muchas gracias a los 2, es cierto, pero la optimizacion la haré más tarde  ;-)


Título: Re: Ayuda con las matemáticas !!!
Publicado por: Kilowatt en 11 Abril 2013, 16:26 pm
Siento si interrumpo, solo pasaba por aqui, vi el problema y me gustaria poner mi solucion a ver si la ven bien.

Trasladas el eje a p (Al final sumaras las coordenadas del vector (OP) que une el origen que finalmente uses y el punto p).

Ahora, conoces el vector Bp (B con coordenadas con respecto a P)  y quieres B'P (B' con coordenadas tambien con respecto a P). En tu ejemplo, Bp seria ((-tam_x/2)X + (tam_z/2) Z).

Sabiendo Bp conoces Xbp y Zbp, sus coordenadas, por lo que tambien:
El modulo de Bp: Mbp = ((Xbp^2)+(Zbp^2))^(1/2);
Su angulo con respecto al eje P: Abp=arctg(Zbp/Xbp);

Tambien sabes el angulo de rotacion, que sera positivo o negativo segun el sentido de rotacion, en tu ejemplo negativo: -Ar.

Asi que las coordenadas de B'p seran ((Mbp*Cos(Abp - Ar))X + (Mbp*Sen(Abp - Ar))Z)

Y tu punto B' con respecto al eje que quieras usar (O) sera:

B' = (Xb'p + Px, Zb'p + Pz); Donde (Xb'p , Zb'p) son las coordenadas del vector B'p, ya hallado ; y (Px , Pz) son las coordenadas del punto p con respecto a O.


Título: Re: Ayuda con las matemáticas !!!
Publicado por: BlackM4ster en 12 Abril 2013, 15:12 pm
 ;-) Te aplaudo, gracias por la respuesta. Ahora mismo, los bounding boxes son cuadrados (angulos de 45º y 135), asi que directamente los pongo yo. Estoy trabajando en un loader de objetos en 3D. Cuando acabe de hacerlo, aplicaré tu forma ya que no serán todos cuadrados. Por casualidad no sabrias detectar colisiones entre un bounding box alineado al objeto y otro? o uno alineado y el otro a los ejes?


Título: Re: Ayuda con las matemáticas !!!
Publicado por: Kilowatt en 22 Abril 2013, 19:51 pm
Antes de nada, perdon por la tardanza.

Realmente no se a que te refieres con bounding box alineado al objeto, porque de programacion en C no voy muy alla, solo he hecho java. De todas formas voy a suponer que el bounding box delimita hasta donde llega el objeto (por su nombre) y quieres saber si hay colision entre dos de estas cajas. A no ser que ya haya metodos que faciliten el trabajo, detectar una colision lleva un poquito de trabajo desde mi punto de vista, pero supongamos algo:

Lo normal es que no haya colisiones, asi que un metodo que no requiera mucho trabajo por parte del PC y que si da true significa que NO HAY colisiones sera el siguiente (Ojo, si este algoritmo da true significa que no hay colisiones, pero si da false no significa nada, puede que las haya o puede que no, y tendremos que estudiarlo mas a fondo, pero en principio esta bien para ponerlo de condicion en un if y ahorrarnos computo si lo normal es que no se produzcan colisiones).

El principio es el siguiente: Tenemos dos bounding boxes, una centrada en P0 y otra en P1, si sus origenes distan mas de la distancia entre el punto de la BB en P0 mas lejano del centro (P0), sumado a la distancia del punto de la BB en P1 mas lejano del centro (P1), es imposible que haya colision.

Esto es, si el modulo del vector que va desde P0 hasta P1, desde ahora P01, es menor que dicha distancia, da false. Definamos algunas cosas:

P01 = ((XP0 - XP1)X + (ZP0 - ZP1)Z); Vector P01
MP01 = ((XP01)^2 + (ZP01)^2)^(1/2) = ((XP0 - XP1)^2 + (ZP0 - ZP1)^2)^(1/2) ; Modulo del vector P01

Ahora necesitamos la distancia al centro del punto(s) mas lejano. Siendo cuadrados, dichos puntos son los vertices, llamemos a la longitud del lado de la BB0, L0, y L1 para el lado de BB1. Voy a generalizarlo para rectangulos, pues en tu ejemplo has llamado de distinta forma a los lados (tam_x y tam_z), asi que supongo que no tienen porque ser iguales, de esta forma BB0 tiene los lados L0A y L0B, y BB1 tiene L1A y L1B. (Ejemplo: si la caja de tu dibujo fuera BB0, L0A seria tam_x y L0B sera tam_z o al reves, el orden es indiferente). Definimos:

DM0 = ((L0A/2)^2 + (L0B/2)^2)^(1/2); Mayor distancia desde P0 hasta un punto contenido en BB0, esto es, a cuanta distancia esta el punto mas externo de BB0.
DM1 = ((L1A/2)^2 + (L1B/2)^2)^(1/2); Analogo a DM0, pero para BB1.

Asi, si MP01 es menor que DM0 + DM1, el algoritmo da true y deberias estudiar mas a fondo lo que esta pasando con otro algoritmo que pensare luego para hacerlo con la mayor simpleza que se me ocurra. Sin embargo, si da false, puedes descartar toda posibilidad de colision.

Espero que te sirva de algo, aunque lo he hecho bastante rapido sin pensarlo mucho, asi que puede ser que tenga errores o que haya una manera mas rapida y facil de hacerlo y la he pasado por alto. Intentare ponerte que haria yo en caso de que diera false lo antes posible.

Un saludo.


Título: Re: Ayuda con las matemáticas !!!
Publicado por: Kilowatt en 22 Abril 2013, 21:14 pm
He estado pensando un poco lo de las colisiones, y aunque creo que voy camino de dar con un metodo, me facilitaria mucho las cosas saber con que informacion de las bounding boxes cuentas en todo momento, ademas de las coordenadas del centro y la longitud de sus lados. Si pudiera conocer su grado de inclinacion o la posicion concreta de sus vertices en ese momento por ejemplo atajaria bastante, ya que con lo que se estoy haciendo cosas demasiado complejas para calcular algo tan simple, asi que dudo que tenga alguna utilidad.


Título: Re: Ayuda con las matemáticas !!!
Publicado por: BlackM4ster en 23 Abril 2013, 15:14 pm
Pues yo he conseguido sacar los ocho vertices de ambos bounding boxes y sería con eso


Título: Re: Ayuda con las matemáticas !!!
Publicado por: leosansan en 23 Abril 2013, 15:53 pm
Pues yo he conseguido sacar los ocho vertices de ambos bounding boxes y sería con eso

Si las cajas están perpendiculares al suelo, vamos apoyadas o paralelas al suelo, bastaría "jugar" con los cuatro vértices del suelo de cada caja y, aún así, hay unos cuantitos casos. ¿Seguro que el programa no trae incorporada la opción collision?.

(http://i1280.photobucket.com/albums/a497/leosansan/GRAFICOS1/colision_zps2c073565.jpg)

REEDITO:

Cada línea rosa es una posible colisión, en total ocho y como hay cuatro lados treinta y dos en total y usando distancia de un punto a una recta inclusive, suponiendo que la caja móvil se pueda acercar a la fija por delante, por detrás, por la derecha, por la izquierda o por cada esquina.Y eso sin girar el cubo móvil respecto al tercer eje. Creo que debe haber un método más simple que el puramente matemático. Pero si lo consideras "razonable" me pongo a ello

Saluditos y ánimos! ....
(http://st.forocoches.com/foro/images/smilies/aaaaa.gif)

REEDITO: Ya he conseguido reducir los 16 casos de colisiones"laterales" a uno sólo usando las coordenadas de los centros.


Título: Re: Ayuda con las matemáticas !!!
Publicado por: BlackM4ster en 24 Abril 2013, 14:37 pm
Gracias  ;-)
No, no hay ningún método "collision" para hacerlo por que básicamente lo estoy programando yo al 100% (de librería externa sólo el OpenGL)
He conseguido detectar la colisión, determinar si choca de frente, desde arriba o desde abajo. En los casos de Arriba y abajo, funciona bien (arriba, pues gravedad = 0; y desde abajo, Aceleracion = -Aceleración). El problema viene cuando tengo que programar que, determine con qué cara choca, la dirección, y la dirección de desplazamiento. Alguna forma sencillita de hacerlo?


Título: Re: Ayuda con las matemáticas !!!
Publicado por: Kilowatt en 24 Abril 2013, 23:59 pm
Bueno, yo he estado pensando como detectar las colisiones, y personalmente si las cajas son rectangulares, de lados sin ninguna relacion entre si, y que pueden medir cualquier valor distinto de 0, creo que no se puede hacer de una manera sencilla. Seria mas o menos abordable si las cajas no giraran, pero ademas pueden incidir una sobre otra en cualquier grado de inclinacion.

Ademas tengo una pregunta ¿Las cajas pueden atravesarse entre si? Si no fuera asi (seria como simular solidos) se cumpliria una propiedad interesante, y que da pie a simplificar el algoritmo: "En todos los choques, al menos un vertice de una de las cajas de encuentra sobre la superficie de la otra". Y podria empezar a trabajar por ahi, comprobando la pertenencia de los vertices de la caja 0 a las rectas que delimitan la 1, y que ademas lo hagan en el intervalo de valores en que los puntos de dicha recta forman el lado de la caja 1. Con un calculo reciproco de este estilo, para todos los vertices y para todas las rectas, habria una deteccion 100% segura de la colision o no colision, y ademas se sabria al menos un punto de contacto, que quizas te sirva para, posteriormente, jugar con las fisicas como comentas.

En principio con solo la distancia entre los centros no se puede detectar con absoluta certeza una colision de cajas rectangulares de forma arbitraria, y que pueden no estar alineadas con los ejes de ninguna forma, pues son capaces de girar sobre su centro incrementos de angulo no acotados.


Título: Re: Ayuda con las matemáticas !!!
Publicado por: BlackM4ster en 25 Abril 2013, 16:41 pm
jaja gracias por tu respuesta, ya he conseguido detectar las colisiones perfectamente, ahora me falta la parte dificil, determinar si puedo avanzar o no hacia ellas


Título: Re: Ayuda con las matemáticas !!!
Publicado por: Kilowatt en 25 Abril 2013, 16:51 pm
Seria interesante ver como lo has hecho, o que lo explicaras por encima si estas de acuerdo. ¿A que te refieres con avanzar hacia ellas?


Título: Re: Ayuda con las matemáticas !!!
Publicado por: BlackM4ster en 26 Abril 2013, 14:53 pm
Pues, con lo de moverme hacia ellas, me refiero a que, cuando avanzas hacia un objeto, choques y no lo puedas atravesar, pero teniendo un vector de dirección especifico para cuando estás colisionando y deslizarte por la cara.

El codigo de detección es algo así:
Código
  1. bool Colision_Pj_Objeto(int IdObjeto){
  2.  
  3. pj.bounding.Crear(pj.bounding.Tipo,0);
  4. objeto[IdObjeto].bounding.Crear(objeto[IdObjeto].bounding.Tipo,IdObjeto);
  5.  
  6. for(int i=1;i<9;i++){
  7. if(Colision_Punto_ABCD(pj.bounding.vx[i],pj.bounding.vy[i],pj.bounding.vz[i],IdObjeto) == true) return 1;
  8. }
  9.  
  10. return 0;
  11. }
  12.  
  13. bool Colision_Punto_ABCD(float p_x,float p_y,float p_z,int IdObjeto){
  14.  
  15. //if(objeto[IdObjeto].usado == true){
  16.  
  17.    if(p_x >= objeto[IdObjeto].bounding.vx[1] && p_x <= objeto[IdObjeto].bounding.vx[3] &&
  18.    p_y >= objeto[IdObjeto].bounding.vy[2] && p_y <= objeto[IdObjeto].bounding.vy[1] &&
  19.    p_z >= objeto[IdObjeto].bounding.vz[5] && p_z <= objeto[IdObjeto].bounding.vz[1])
  20.    {
  21.        return true;
  22. }
  23. return false;
  24. }


Título: Re: Ayuda con las matemáticas !!!
Publicado por: BlackM4ster en 26 Abril 2013, 14:57 pm
Saco una foto, estoy haciendo un game engine (mi primer juego, justo acababa de aprender c++ de forma decente cuando me metí con OpenGL). Os cuento el problema desde el principio:
Tengo 3 tipos de detectores de colisiones programados:
 - Bounding sphere (para cosas que no requieren precision absoluta como coger monedas)
 - Axis aligned Bounding Box (Los bloques de terreno "B")
 - Objet aligned bounding box (El personaje "A")
Tengo programada una simulación de la gravedad que hace que cada frame (el juego está capado a 30fps) baje un poco a no ser que haya colision. Detectar la colision entre los dos bloques es fácil, pero no sé luego como saber si estoy chocando de frente, de costado... y a partir de eso evitar ciertos movimientos como caminar hacia el objeto (deslizarse por el objeto)
Dejo un video del juego en cuestión (Minuto 2:15, donde el cursor es rojo, es el que digo)

(http://img198.imageshack.us/img198/886/plantillajuego201304141.bmp)
PdWymO3883Y


Título: Re: Ayuda con las matemáticas !!!
Publicado por: amchacon en 26 Abril 2013, 15:34 pm
Pues, con lo de moverme hacia ellas, me refiero a que, cuando avanzas hacia un objeto, choques y no lo puedas atravesar, pero teniendo un vector de dirección especifico para cuando estás colisionando y deslizarte por la cara.
Por decir algo, no puedes hacer que su velocidad sea cero?.

O activar algun booleano para indicar que deje de mover.


Título: Re: Ayuda con las matemáticas !!!
Publicado por: BlackM4ster en 26 Abril 2013, 17:10 pm
Si, es lo que estoy intentando: que cuando choques con una cara, la dirección hacia esa cara se bloquee y no se desplace hacia ese eje. He conseguido hacerlo bastante decente, ya os contaré  ;-)


Título: Re: Ayuda con las matemáticas !!!
Publicado por: Kilowatt en 26 Abril 2013, 17:11 pm
Como dicen arriba, podrias simplemente pararlo, o si sabes un punto que hace colision me imagino que sabras la cara del otro objeto con la que estas colisionando, y si conoces la direccion del movimiento y la velocidad, podrias hacer que en el momento de la colision solo permaneciera la componente de la velocidad tangencial a dicha superficie, si la hubiera. Asi la caja cuando chocara se seguiria moviendo pero nunca hacia dentro de la otra, sino pegado a ella, deslizando.

Simplificandolo para un objeto movil y otro inmovil, se puede hacer de una manera sencilla, pero me tienes que decir si puedes saber sobre que cara del objeto inmovil chocas y si conoces la velocidad y la direccion del objeto movil en todo momento. Si conoces esas tres cosas se hace facil.



Título: Re: Ayuda con las matemáticas !!!
Publicado por: BlackM4ster en 26 Abril 2013, 19:52 pm
Sé la velocidad con la que se mueve hacia la cara (constante)
Sé la cara con la que choca
Sé la dirección del personaje


Título: Re: Ayuda con las matemáticas !!!
Publicado por: Kilowatt en 26 Abril 2013, 21:47 pm
Pues como escribir matematicas aqui es tedioso y encima no se entiende bien, te subo una imagen con la idea escrita en papel si te parece bien.

Edito: Ya esta.

http://img46.imageshack.us/img46/5752/003lbp.jpg (http://img46.imageshack.us/img46/5752/003lbp.jpg)

Si hay algo que no se entiende (no me extrañaria, tengo una caligrafia vergonzosa) dimelo.


Título: Re: Ayuda con las matemáticas !!!
Publicado por: BlackM4ster en 28 Abril 2013, 10:43 am
Muchas gracias  ;-)
Lo de la velocidad nueva, no lo había pensado jajaja


Título: Re: Ayuda con las matemáticas !!!
Publicado por: Kilowatt en 28 Abril 2013, 20:25 pm
Seguramente todo esto se pueda optimizar, pero eso ya lo vas mirando tu que ahi estoy un poco verde. Quiza seria mejor idea para comprobar cual de los dos sentidos es el correcto que te fijes en los modulos de los vectores resta entre la velocidad y las posibles direcciones, y el menor es el correcto. Creo que es mejor calcular unas cuantas sumas y restas que un arccos. Suerte.


Título: Re: Ayuda con las matemáticas !!!
Publicado por: BlackM4ster en 29 Abril 2013, 15:17 pm
La optimización, viene luego  ;-)
Te dejo un enlace para que pruebes:

Sin colisiones
Código:
https://www.dropbox.com/s/0m9mhmrgmhmt7an/Juego%20Isc.rar
Con colisiones
Código:
https://www.dropbox.com/s/6il280vqch0u2r4/Juego%20Isc%20con%20Colisiones.rar


Título: Re: Ayuda con las matemáticas !!!
Publicado por: Kilowatt en 4 Mayo 2013, 14:28 pm
Siento no haberlo podido probar antes. Has hecho bastantes progresos, te felicito.

Aunque me imagino que querras seguir desarrollandolo, asi que tengo un par de preguntas. Cuando te acercas a un objeto, aparecen unas cajas con los vertices marcados. ¿Esas son las bounding boxes de las que hablamos? Si asi es, en muchas ocasiones resulta que no estan alineadas con la caja de texturas, asi que puedes penetrar en la textura aunque las cajas en si no se intercalen.

Parece que las colisiones entre estas cajas se detectan perfectamente y que has conseguido que permanezca solo la componente tangencial de la velocidad, asi que quiza sea solo un problema de alinear las cajas a las texturas, y con eso quedaria bien. Bueno, tu eres el que esta manejando el proyecto de primera mano, asi que ya me cuentas si estoy diciendo disparates. Suerte!


Título: Re: Ayuda con las matemáticas !!!
Publicado por: BlackM4ster en 5 Mayo 2013, 09:46 am
jajaj Si, si, tienes razón. Al final, decidí hacerlo con las dos alineadas a los ejes, ya que al ser cubos, no se nota mucha diferencia. Los cubos que se ven cuando estás cerca son los bounding, que solo se activan si estás a una distancia considerable para que el CPU no se sobrecargue de cálculos absurdos  :laugh:

Lo seguiré desarrollando cuando tenga tiempo (exámenes), aunque por ahora, lo básico ya lo tengo: movimiento, cámaras, colisiones... ya veremos como acaba este proyecto xD

Para ser mi primer programa en C++ con OpenGL, no está nada mal. Con vuestra ayuda he sacado varias cosas. Gracias !!!  ;-)