[PC] ayuda colisiones

hola, estoy haciendo un juego tipo arkanoid, es en 3d y el motor que gasta usa las colisiones con aabb y para calcular una colision se usa una recta, creo la recta de la posicion actual a la posicion anterior de la esfera y calculo la interseccion y gracias a la normal de la aabb se la direccion de rebote. Casi funciona, algunas veces no rebota y continua bien... alguna idea?
Sin código fuente dificilmente se puede ayudar xD.

Creo que sería mucho más adecuado calcular las colisiones en 2D, ya que en un juego tipo Arkanoid la tercera dimensión no se usa para nada (aunque luego los gráficos sean 3D).
saulotmalo escribió:hola, estoy haciendo un juego tipo arkanoid, es en 3d y el motor que gasta usa las colisiones con aabb y para calcular una colision se usa una recta, creo la recta de la posicion actual a la posicion anterior de la esfera y calculo la interseccion y gracias a la normal de la aabb se la direccion de rebote. Casi funciona, algunas veces no rebota y continua bien... alguna idea?



Hombre, no se exactamente como sera tu juego y hasta que punto necesitas emplear colisiones 3d y no entiendo que es eso de "aabb" pero te voy a dar algunos consejos, porque yo he trabajado en algunas historias en el pasado, que hacian uso de "colisiones" de rectas.


Veamos, lo primero que tienes que tener en cuenta, es el fallo de precision en punto flotante.

Por ejemplo, puedes calcular la interseccion de dos rectas, averiguar el punto de interseccion y luego comparar si pertenece ese punto a los dos segmentos que tratas de comparar, pero, eso te fallara si no introduces un margen de tolerancia a la hora de comprobar si los puntos estan dentro del segmento.

Como no se exactamente que metodo usas, no te puedo ayudar mas y tampoco se si tu fallo se debe a que solo calculas la colision basandote en la recta que parte desde el punto central de la bola, o un unico punto en la "superficie" calculado a partir del vecto de desplazamiento y el radio de la bola u otro metodo, pero tampoco viene mal utilizar varios puntos de comprobacion si utilizas un metodo similar a esto que describo.
hola, soy saulotmalo, tengo dos cosas pensadas, la primera sería o bien crear una recta paralela y desplazar la que tengo y entonces envolvería la bola, o bien usar una perpendicular a la que creo en primera instancia y con un tamaño determinado, cual de los dos métodos creeis que será mejor?
testeb escribió:hola, soy saulotmalo, tengo dos cosas pensadas, la primera sería o bien crear una recta paralela y desplazar la que tengo y entonces envolvería la bola, o bien usar una perpendicular a la que creo en primera instancia y con un tamaño determinado, cual de los dos métodos creeis que será mejor?


Veamos.

Supongo que si estas haciendo un Arkanoid, tendras una serie de ladrillos apilados al estilo del original, solo que como dices que lo estas haciendo en 3D, supongo que tienes la "pared" al fondo y la "raqueta" la tienes justo en frente.


En este caso, quiza te interese mas desglosar el espacio 3D en espacios 2D.

De esta forma, podrias detectar si un punto esta dentro del rectangulo del ladrillo, de la misma forma que lo harias en un Arkanoid en 2D, solo que aqui, primero comprobarias si un punto de la bola, cae dentro de un ladrillo en el plano sobre el eje Y y luego lo harias sobre el plano del eje Z.

Para obtener los puntos de la bola, podrias generar una serie de puntos utilizando el radio de la bola y las funciones seno y coseno, de la misma forma que cuando tratas de dibujar un circunferencia, solo que con menos puntos. Las detecciones serian rapidas porque solo tienes que saber si un punto esta dentro de un rectangulo cuyos lados estan en paralelo con los ejes (vamos, que no está girado)

La unica precaucion que tendrias que tener, usando este metodo, es que la bola no se desplazase dando saltos muy grandes, de forma que pudiera ocurrir que se dibujara la bola justo antes y despues de un ladrillo, al desplazarla.

Usar este metodo, te podria ayudar bastante para corregir la visualizacion de la bola, pues como sabes, el problema es que detectas el choque cuando la bola esta DENTRO de un ladrillo y lo suyo seria dibujarla sin que atraviese el ladrillo, jejeje
Colisiones 2D.

También puedes descomponer el palo en unos cuantos puntos y calcular una colisión punto-recta para cada punto de la siguiente forma:

1) Calculas la distancia entre el centro de la esfera y el punto.
2) Si la distancia es menor que el radio de la esfera es que colisionan.

Si usas este método hay que distribuir los puntos de forma que la distancia entre dos puntos seguidos sea menor que el diámetro de la esfera.
hola, he estado probando un par de cosas y uff que lio! xD si quereis os pongo un ejecutable para que veais lo que pasa ya que el caso esque es muy raro :S sé que el algoritmo falla en algún lado pero no sé donde..
saulotmalo escribió:hola, he estado probando un par de cosas y uff que lio! xD si quereis os pongo un ejecutable para que veais lo que pasa ya que el caso esque es muy raro :S sé que el algoritmo falla en algún lado pero no sé donde..


Joe, me vas a hacer desempolvar algunos conceptos que tengo aparcados desde hace unos 7 años y ponerme manos a la obra para hacer una rutina de colisiones mediante volumenes cubicos (usando esferas, es muy facil XD)

No te prometo nada, pero a lo mejor miro algo de esto, que a mi tambien me interesa el tema de las colisiones y en especial crear volumenes mediante objetos torno y poder detectar colisiones, usando los procedimientos mas rapidos y sencillos posibles que pueda crear. Al menos, al usar objetos de forma cubica, no deberia tener demasiado problema para detectar colisiones XD
esta noche te envio al privado una copia del codigo ( quiero privacidad hasta que lo releasee y me fio de ti ;) ) te ordenaré un poco el código que ahora mismo solo lo leo yo xD.

ah si por cierto aabb aligned axis bounding box. toma nombre... por cierto en teoría las colisiones ya lo verás pero las debería detectar el propio motor pero pasa de mi... :( en fin ya te lo enseñaré creo que lo que me dijiste de la precision puede tener que ver, ya que siempre pasa en los límites, intentaré habilitar algún tipo de traza para que te sea más fácil... pero no te prometo nada :(

y muchas gracias por la ayuda!!!!! :)
saulotmalo escribió:esta noche te envio al privado una copia del codigo ( quiero privacidad hasta que lo releasee y me fio de ti ;) ) te ordenaré un poco el código que ahora mismo solo lo leo yo xD.

ah si por cierto aabb aligned axis bounding box. toma nombre... por cierto en teoría las colisiones ya lo verás pero las debería detectar el propio motor pero pasa de mi... :( en fin ya te lo enseñaré creo que lo que me dijiste de la precision puede tener que ver, ya que siempre pasa en los límites, intentaré habilitar algún tipo de traza para que te sea más fácil... pero no te prometo nada :(

y muchas gracias por la ayuda!!!!! :)


Okis.

Entonces la deteccion es muy facil, ya que realmente, estas haciendo lo que yo te decia que hicieras, solo que la 'bola' en vez de usar el volumen esferico, es mas sencillo usar puntos estrategicamente situados en la superficie y comprobar que quedan dentro de las cajas.

Yo mi idea del tipo de deteccion que me gustaria hacer, se basa en construir objetos utilizando una unidad de volumen relativamente sencilla, que me permite obtener un plano que representa un corte en seccion de la pieza (que seria un triangulo o dos ) y terminar comparando si dos triangulos colisionan en un espacio 2D.

Hace muchos años estuve trabajando en algo como esto, pero lo acabe dejando y ahora no poseo el codigo fuente :S .

Lo mas complejo, es que partiendo de un plano, hay que crear una matriz de transformacion que alinee ese plano con alguno de los ejes, para luego aplicarla sobre las piezas de volumen a comparar y poder cortarlas en seccion al pasar por ese plano y que te cree una superfice en 2D para comparar.

Como puedes ver, suena un tanto complejo, pero lo interesante es que no tiene por que ser lento y se pueden meter por medio algunas comprobaciones rapidas para evitar hacer calculos inutiles.

Para comprobar colisiones en objetos 3D, se puede recurrir a comprobar si un triangulo toca la "piel" de otro objeto, pero nunca te dira si estas dentro de el, a menos que tu hayas construido el objeto de forma que tengas alguna referencia volumetrica.

Yo lo que hacia es construir volumenes usando unas piezas elementales que me permitian cosntruir objetos torno o extruidos de una forma sencilla.

¿Para que usaba yo esto? Pues... para poder restar o sumar objetos, añadiendo o quitando la "piel" que hiciera falta ;)

EDITADO:

He creado dos rutinas, una para detectar la colision de dos cajas (la bola estaria dentro de una caja tambien) y otra para detectar si unpunto esta dentro de una caja (esta se puede utilizar para afinar las detecciones aun mas)

La cajas estaran alineadas a lo ejes universales y por eso solo requieren el punto central del objeto y el ancho,alto, fondo de la caja.


// TestBoxes: compara si dos cajas colisionan
// x1,y1,z1 -> posicion espacial de box 1
// dx1,dy1,dz1-> ancho,alto,fondo de box 1

// x2,y2,z2 -> posicion espacial de box 2
// dx2,dy2,dz2-> ancho,alto,fondo de box 2
// retorno: 1 si hay colision y 0 si no la hay

int TestBoxes(float x1,float y1,float z1,float dx1,float dy1,float dz1,float x2,float y2,float z2,float dx2,float dy2,float dz2)
{
int f;
float ax1,ay1,az1,ax2,ay2,az2;
float bx1,by1,bz1,bx2,by2,bz2;


// obtiene coordenadas de comparacion de las cajas

ax1=x1-(dx1/2.0f);
ax2=ax1+dx1;
ay1=y1-(dy1/2.0f);
ay2=ay1+dy1;
az1=z1-(dz1/2.0f);
az2=az1+dz1;

bx1=x2-(dx2/2.0f);
bx2=bx1+dx2;
by1=y2-(dy2/2.0f);
by2=by1+dy2;
bz1=z2-(dz2/2.0f);
bz2=bz1+dz2;



f=0;
if((ax1>=bx1 && ax1<=bx2) || (ax2>=bx1 && ax2<=bx2) ||
   (bx1>=ax1 && bx1<=ax2) || (bx2>=ax1 && bx2<=ax2)) f=1; // las x se cruzan

if(f==1)
{
if((ay1>=by1 && ay1<=by2) || (ay2>=by1 && ay2<=by2) ||
   (by1>=ay1 && by1<=ay2) || (by2>=ay1 && by2<=ay2)) f=2; // las y se cruzan

}

if(f==2)
{
if((az1>=bz1 && az1<=bz2) || (az2>=bz1 && az2<=bz2) ||
   (bz1>=az1 && bz1<=az2) || (bz2>=az1 && bz2<=az2)) f=3; // las z se cruzan
}

if(f==3) return 1; // hay colision

return 0; // no hay colision
}



// TestPointInBox: compara si un punto esta dentro de la caja
// x1,y1,z1 -> posicion espacial del punto a comprobar

// x2,y2,z2 -> posicion espacial del box
// dx2,dy2,dz2-> ancho,alto,fondo del box
// retorno: 1 si elpunto esta dentro del box y 0 si no lo está

int TestPointInBox(float x1,float y1,float z1,float x2,float y2,float z2,float dx2,float dy2,float dz2)
{

float bx1,by1,bz1,bx2,by2,bz2;


// obtiene coordenadas de comparacion de la caja

bx1=x2-(dx2/2.0f);
bx2=bx1+dx2;
by1=y2-(dy2/2.0f);
by2=by1+dy2;
bz1=z2-(dz2/2.0f);
bz2=bz1+dz2;




if((x1>=bx1 && x1<=bx2) && (y1>=by1 && y1<=by2) && (z1>=bz1 && z1<=bz2)) return 1; // el punto esta dentro de la caja

return 0;// el punto no esta dentro de la caja
}


Estas funciones, te tienen trabajar, pero recuerda lo que te he dicho por MP, que estas rutinas detectaran solo si hay colision o no y luego deberias interpolar la posicion, desde la actual hasta la antigua usando un paso mas fino, hasta que la bola quede fuera del objeto, si quieres dibujarla sin que atraviese el ladrillo.

Sobre las reglas de rebote, la primera regla es que en principio, si la bola va hacia adelante y se topa con un obstaculo de frente, sale rebotada hacia atras y en principio, salvo que algo se oponga, conserva el mismo movimiento lateral y en tu caso, vertical.


Para saber si debes cambiar el sentido del desplazamiento lateral, puedes usar muchos trucos, trabajando de igual forma que si lo hicieras en 2D.

Tus piezas estan todas distribuidas en un panel a una distancia que tu conoces y puedes saber con calculos muy sencillos, si la bola ha chocado con un objeto que esta en frente o lateralmente, pero te recomiendo que antes de corregir el angulo de desplazamiento de la bola, corrijas la posicion de esta interpolando pasos entre la posicion moderna y la antigua, de forma fina, hasta que no se produzca colision con el ladrillo detectado.

Entonces, te costara menos determinar el angulo de rebote, porque por ejemplo, si en esa posicion corregida ves que tienes un ladrillo justo arriba de la bola y otro justo a la izquierda de la bola, pues ya sabes que el rebote será hacia adelante y a la derecha.

Lo mismo se aplicaria par los ladrillos que esten encima y debajo, claro: solo es cuestion de dividir el espacio 3D en dos vistas en 2D y trabajar a partir de ellas.
ahora después de desayunar probaré esto, te lo has currado mucho! tienen punta de ser rápidas esas funciones, aunque parezca mentira en en el arkanoid son fácil 100 ladrillos y xupa mucho... bueno luego te comento, muchas gracias.


pd: que putada lo del link :( con lo bonito que estaba xD
Las funciones pueden ser mas rapidas si en vez de especificar el ancho, especificas ancho/2 , eliminas las divisiones internas y haces que por ejemplo ax1=x1-dx; y ax2=x1+dx1;

De todas formas, desde hace un rato, estoy trabajando en la colision de cajas no alineadas con los ejes.

La mayor dificultad estriba, en que tengo que sacar unas funciones capaces de situar una de las cajas de forma alineada con los ejes, creando una matriz que pueda situar el resto de las cajas en relacion a
esa caja de referencia.

Despues, es solo cuestion de comprobar si los segmentos de las cajas a comprobar, atraviesan la caja de referencia (cosa mas facil de lo que parece).

El unico requisito, es que las cajas se construyan segun unas reglas establecidas y que a la hora de comparar, los vertices esten ya posicionados en el universo.

A ver si tengo un poco de suerte y habilidad y consigo hacer unas rutinas que sean eficientes XD
Madre dios, menudo lio estais montando para hacer una mierda de Arkanoid.

Estoy leyendo cada burrada ,¿sistemas de colisiones? ¿interpolacion? ¿angulos?. No hace falta nada de eso para hace un arkanoid clonico por muy 3d ke sea, simplemente teniendo la posicion y velocidad de la pelota, posicion de la raketa y una matriz con la posicion de los ladrillos y con unos cuantos IFes para calcular las diferencias de posicion para saber si chocan y si chocan las formulas del rebote son facilisimas no hace falta angulos ni nada.

Y Hermes por lo que estas comentando sobre tu "sistema de colision de cajas no alineadas con los ejes" vas por mal camino, calculando segmentos (aristas), cuando tengas 10 cajas tu sistema reventara cualquier ordenador, eso en la vida ira a una velocidad decente.

Simplemente con la diferencia de angulos de las 2 cajas, la distancia de sus centros y sus tamaños sobra.

Perdonad si suena como si os hechase la bronca, pero calcular si hay lineas que se cruzan es lo ultimo de lo ultimisimo ke hay ke hacer. Poco futuro en la programacion de juegos os veo asi XD.

Saludos y tomaroslo a bien.
Santo99 escribió:Madre dios, menudo lio estais montando para hacer una mierda de Arkanoid.

Estoy leyendo cada burrada ,¿sistemas de colisiones? ¿interpolacion? ¿angulos?. No hace falta nada de eso para hace un arkanoid clonico por muy 3d ke sea, simplemente teniendo la posicion y velocidad de la pelota, posicion de la raketa y una matriz con la posicion de los ladrillos y con unos cuantos IFes para calcular las diferencias de posicion para saber si chocan y si chocan las formulas del rebote son facilisimas no hace falta angulos ni nada.

Y Hermes por lo que estas comentando sobre tu "sistema de colision de cajas no alineadas con los ejes" vas por mal camino, calculando segmentos (aristas), cuando tengas 10 cajas tu sistema reventara cualquier ordenador, eso en la vida ira a una velocidad decente.

Simplemente con la diferencia de angulos de las 2 cajas, la distancia de sus centros y sus tamaños sobra.

Perdonad si suena como si os hechase la bronca, pero calcular si hay lineas que se cruzan es lo ultimo de lo ultimisimo ke hay ke hacer. Poco futuro en la programacion de juegos os veo asi XD.

Saludos y tomaroslo a bien.


Humm, ¿tu has visto las funciones que le he pegado? Para hacer un Arkanoid 3D no hace falta mucho mas, pero las cosas dependen de si quieres tener una pelota que es una caja cuadrada o quieres una pelota redonda, o si quieres que vaya a distintas velocidades y con distintos angulos de rebote.

Si te fijas, le aconsejo que utilice metodos de deteccion 2D pra el juego, pero lo que yo estoy haciendo ahora, no es para mover un arkanoid y si te crees que lo que estoy haciendo, con 10 cajas va petar, esperate que lo haga y luego me lo dices [burla2]

Lo de lo segmentos que dices tu, es lo ultimo de lo ultimo, pues depende nen, del metodo que utilices, ya que para empezar, existen metodos muy rapidos para saber si una caja esta en el area de influencia de otra (buscando los valores minimos y maximos,, puedes crear una caja alineada con los ejes, que mediante la rutina que he posteado, te evita "sobrecargar" la CPU)


Luego, el sistema que utilizo calcula una matriz que te posiciona la caja de referencia en un universo donde esa caja esta alineada con los ejes y solo hay que aplicar la matriz a los 8 vertices de la caja a comparar.

Entonces, se aplican una serie de reglas: por ejemplo, si un vertice de una de las cajas, esta dentro de la caja de referencia (cosa que es facilisima y muy rapida de comprobar), ya no tengo que hacer nada mas.

En el caso de que los cajas se crucen y los vertices no queden dentro de ninguna de ellas (caso posible), solo hay que mirar si los segmentos sobrepasan los limites de una de las dimensiones, interpolar para cortar el segmento y comprobar si esos vertices nuevos, quedan dentro de la caja.

A ti te parecra muy lioso todo esto, pero cuando lo tenga rulando, veras como no se peta comparando 10 cajas XD.

Ademas, no me queda otra, por que necesito este tipo de detecciones ya y no, no es para hacer un simple Arkanoid ;)
Lo de 10 era un ejemplo a ojo, dependera mucho del ordenador.

Y sigo insistiendo que tu sistema como funcionar funcionara pero lo ke se dice optimizado no lo es.

Ya simplemente por usar la funcion esa ya lo ralentizaras. Como minino si por cada iteracion de colision entre cajas hubiese "solo" ke usar esa funcion para saber si esta dentro, el ordenador estaria haciendo bastantes divisiones de coma flotante y distintos calculos de operadores logicos.

Eso como minino

Como yo te digo por cada iteracion haces 2 operaciones trigonometricas, 2 multiplicaciones y una resta. Osea ya seguro que es bastante mas rapido

Y si contamos ke tu tienes ke hacer uso de esa funciona mas de una vez seguramente. Lo hace aun mas rapido lo que yo te digo respecto a lo ke te digo.

Y lo del arkanoid, como yo he dicho no tiene porke ser una caja cuadrada la pelota, y no, no hace falta sistema de colisiones, ni tampoco calculos raros.

Bueno, haced lo que querais, yo he dao mi opinion.
Santo99 escribió:
Como yo te digo por cada iteracion haces 2 operaciones trigonometricas, 2 multiplicaciones y una resta. Osea ya seguro que es bastante mas rapido



No veo que estes diciendo nada XD.

¿a que te refieres? ¿A la deteccion necesaria para hacer un Arkanoid o a la deteccion de cajas no alineadas?

Yo necesito una deteccion de cajas no alineadas con respecto a ningun eje (vamos, como si giras dos cubos aleatoriamente y luego tratas de comprobar si colisionan) y si conoces un metodo mas rapido y mejor que el que estoy empleando, pues explicalo y cuelga el codigo necesario.

Yo de momento, tengo un codigo hecho ya que es capaz de coger un caja en cualquier posicion y postura y alinearlo con respecto a los tres ejes, creando una matriz para referenciar el resto de cajas.

Aun tengo que mirar unos cuantos detalles, pero si obvio la posibilidad de que un objeto pueda estar atravesando a otro, con comprobar si un vertice queda dentro de la caja, ya seria suficiente.

Ahora si algun conoce un metodo mejor y mas eficiente, que haga lo MISMO que estoy pretendiendo hacer, pues que lo diga coño, que para algo esto es un foro de desarrollo :P (yo solo he visto metodos basados en esferas y eso no me interesa para lo que quiero hacer)
mmm lo he estado pensando, primero quiero responder a lo de usar un sistema tan complejo para un arkanoid... si... tiene su lógica no es por el arkanoid en si, es por aprender!! una vez lo sepa hacer para esto podré aplicar mejor colisiones en otro tipo de juegos.

A ver sobre lo de que las funciones de hermes son costosas... lo he pensado algorimicamente y no, no lo son. Suponiendo que quiero calcular colisiones para n ladrillos la funcion tendrá un coste fijo A(alfa) por calcular la colisión y un coste dependiente de la talla del problema n-> A*n como el n será mallor que A se puede despreciar n. Por lo tanto el coste de la función será lineal, al igual que todas las funciones del renderizado, ya que estas requieren n pasadas ya que se han de mirar n objetos. asi que el render y la colision se me quedarán con un orden n+n= n... y como todos sabemos O(n) no está mal.
Solo un pequeño detalle a lo dicho por saulotmalo:
asi que el render y la colision se me quedarán con un orden n+n= n... y como todos sabemos O(n) no está mal.


No he tenido tiempo de ver los códigos ni reflexionar sobre lo que estáis discutiendo, pero ten cuidado con los costes asintóticos. Todos sabemos que O(n) es mejor que O(2^n), pero hay O(n) y O(n). Las constantes pueden afectar y mucho, sobretodo en aplicaciones como videojuegos. Resumiendo, no son lo mismo 30 fps que 15 fps, por poner un ejemplo.

Saludos
saulotmalo escribió:mmm lo he estado pensando, primero quiero responder a lo de usar un sistema tan complejo para un arkanoid... si... tiene su lógica no es por el arkanoid en si, es por aprender!! una vez lo sepa hacer para esto podré aplicar mejor colisiones en otro tipo de juegos.

A ver sobre lo de que las funciones de hermes son costosas... lo he pensado algorimicamente y no, no lo son. Suponiendo que quiero calcular colisiones para n ladrillos la funcion tendrá un coste fijo A(alfa) por calcular la colisión y un coste dependiente de la talla del problema n-> A*n como el n será mallor que A se puede despreciar n. Por lo tanto el coste de la función será lineal, al igual que todas las funciones del renderizado, ya que estas requieren n pasadas ya que se han de mirar n objetos. asi que el render y la colision se me quedarán con un orden n+n= n... y como todos sabemos O(n) no está mal.


saulotmalo, a mi me pasa igual que a ti: me gusta aprender y todos los metodos que uso, los hago a partir de conocimientos mas o menos basicos (mis estudios se cortaron en 3º FP, que no llegue a acabar, osea, a hace unos 26 años XD)

Pero mira, para hacer la rutina esa que tienes, he pillado dos cajas rectangulares que tengo y las he comparado visualmente y ahi tienes las rutinas.

Las puedes optimizar mas si quieres, no es nada dificil pero yo soy de los que piensan que primero, aprende a andar y luego corre.


Hace unos dos años, en el foro de PS2Reality, un amigo mio planteó un problema:

Resulta que PS2, tiene capacidad de clipping para los triangulos que se dibujan en pantalla, pero hay un problema: el poligono no debe ser demasiado grande, porque el dato que almacena un vertice, es de 16 bits y si no recuerdo mal, los 4 mas bajos se utilizan como coma fija. Asi que si se sale del borde, se mostrara un poligono corrupto en pantalla.


Mi amiguete pregunto si alguien sabia como hacer un clipping por software y me puse manos a la obra y consegui hacer una rutina en C, que era capaz de fraccionar un triangulo en varios, teniendo en cuenta detalles como ajustar la textura y la iluminacion (interpolando), etc

Lo hice como reto y porque en casos concretos, pensé que podria ser util y cuando le hcie un test de velocidad en la propia PS2, creo que andaba por 60 Mil poligonos por segundo o asi (fraccionando triangulos) la rutina, lo cual no esta mal para usos concretos y teniendo en cuenta que no estaba nada optimizado.

La rutina que estoy haciendo ahora para detectar cajas no alineadas, si alguien tiene el conocimiento para hacerlo mejor que yo, le quedaria muy agradecido que NOS echara una mano, pero el problema, mi querido saulot, es el de siempre: que hay mucha gente que habla mucho, pero ayuda muy poco.

Yo por lo menos, trato de hacerlo lo mejor que sé y si alguien me pide que le eche una mano, aqui estoy.

En programacion hay que ser atrevido, pues es asi como te diviertes y aprendes, ya sea porque lo haces tu mismo o porque alguien te corrige y te enseña a hacer las cosas mejor, pero claro, para eso hace falta que haya gente dispuesta a enseñar...
si si está muy bien en cuando acabe de ver roky uno me pongo ha acer test a ver si lo consigo, alguna idea para calcular el rebote? antes usaba las normales pero claro ahora solo sé si colisiona no se por donde colisiona o con que pano... en fin

PD: me referia que el coste esta bien en O(n) porque luego siempre puedes aplicar heuristicos o otras cosas como aconseja hermes y puedes tener un O(n) pero que en la práctica actue como un logn, supongo que todos conocemos el caso del mergesort y el quicksort
Hermes escribió:blah ... pero el problema, mi querido saulot, es el de siempre: que hay mucha gente que habla mucho, pero ayuda muy poco.


Espero que no te refieras a mi porque no veo el motivo, la verdad.

--

Respecto a mejorar algo, pues si no se me escapa nada (lo cuál tampoco me extrañaría), en la función TestPointInBox quizá podrías usar el producto flotante en lugar de la división flotante. (* 0.5f en lugar de / 2.0f).

No sé si el compilador hará algo al respecto ni cómo es la arquitectura en la que estáis trabajando (NDS quizá?). Pero al menos en todas las arquitecturas que he visto yo, la división flotante es bastante más lenta que el producto, más del doble quizá. He hecho una cutre prueba rápida en mi PC y si no me dejo nada en el tintero:

$ gcc algo.c -o algo -W -Wall
$ ./algo
Test div: 0.391174
Test mul: 0.186806
$ gcc algo.c -o algo -W -Wall -O3
$ ./algo
Test div: 0.338365
Test mul: 0.168882


Donde Test div es la prueba con "/ 2.0f" y Test mul con "* 0.5"


Saludos y espero no haber dicho muchas mentiras xD
NeoRave escribió:

Espero que no te refieras a mi porque no veo el motivo, la verdad.

--

Respecto a mejorar algo, pues si no se me escapa nada (lo cuál tampoco me extrañaría), en la función TestPointInBox quizá podrías usar el producto flotante en lugar de la división flotante. (* 0.5f en lugar de / 2.0f).

No sé si el compilador hará algo al respecto ni cómo es la arquitectura en la que estáis trabajando (NDS quizá?). Pero al menos en todas las arquitecturas que he visto yo, la división flotante es bastante más lenta que el producto, más del doble quizá. He hecho una cutre prueba rápida en mi PC y si no me dejo nada en el tintero:



Donde Test div es la prueba con "/ 2.0f" y Test mul con "* 0.5"


Saludos y espero no haber dicho muchas mentiras xD


No, no lo digo por ti: lo digo en general, que si alguien teine algo que aportar, que lo aporte, pero si vamos a criticar un metodo y no aportamos una solucion, no llegamos a ninguna parte.

Lo que tu dices, es cierto, pero si te fijas arriba, he puesto una solucion que no necesita ni de division, ni de multiplicacion, ya que al fin y al cabo, las dimensiones de las cajas que albergaran la bola y los ladrillos, no van a variar y son conocidas.

La rutina la he pegado tal cual, porque lo que me interesa, es que quien la vea, la entienda.

Fijate que el problema de partida, viene porque saulotmalo ha estado utilizando unas rutinas integradas en un motor grafico, que tienen algun tipo de fallo y le da problemas y el no sabe como solucionarlos.

Asi que yo le agrego la rutina tal cual y si hay que optimizar, se hace y en vez de usar floats usamos enteros de coma fija si es necesario, pero yo prefiero que el pueda mirar la rutina y saber de donde salen los datos y porque las cosas son asi ;)
ufff no puedo.. en serio... esto es imposible... he probado con lo tuyo hermes y tampoco me va, luego he portado tu idea y lo he mezclado con lo del motor, así las colisiones las hacía caja contra caja en vez de línea contra caja... y nada. Ya estoy desesperado posteo el código de esta parte por si alguien quiere hecharle un vistazo que igual soy yo que no lo veo o algo ufff pero increible...

     core::vector3df  vertices[4]; // aqui almaceno la posicion de la caja de la bola escalada ( luego se ha de trasladar )
     vertices[0].set(core::vector3df(-1.25,1.25,0));
     vertices[1].set(core::vector3df(1.25,1.25,0));
     vertices[2].set(core::vector3df(1.25,-1.25,0));
     vertices[3].set(core::vector3df(-1.25,-1.25,0));   
     bool f=false; 
     for(int h=0;h<3;h++){       

    line.start=vertices[h]+node->getPosition();
     line.end=vertices[h+1]+node->getPosition();
     for (int i=0;i<selectoresBlokes.size();i++){
         if(smgr->getSceneCollisionManager()->getCollisionPoint(line,selectoresBlokes[i], colision,triangulo)){
             ITriangleSelector * tsAux;
             f=true;
             tsAux=selectoresBlokes[selectoresBlokes.size()-1];
             selectoresBlokes[i]=tsAux;
             selectoresBlokes.pop_back();
             blokes[i]->remove();
             blokes[i]=blokes[blokes.size()-1];
             blokes.pop_back();
             var=triangulo.getNormal();
             if (var.X > 10){
                 modo=0;break;
             }
             if (var.X < -10){
                 modo=1;break;
             }
             if (var.Y > 10){
                 modo=2;break;
             }
             if (var.Y < -10){
                 modo=3;break;
             }

             
         }
      }
      if(f)break;
      }



Si quereis puedo postear un ejecutable para que veais con vuestros ojos donde falla... un saludo!
Una buena optimización sería tener dos tipos de detección de colisiones, una "general" y otra precisa": con cada bloque calculas la distancia respecto al centro de la esfera, y si la distancia es lo suficientemente pequeña, realizar otro tipo de detección más precisa.

Otra optimización podría ser tener los bloques ordenados en memoria según su altura respecto al palo y ejecutar las detecciones de colisión con los bloques que están a la misma altura que la esfera e ignorar el resto.

Y repito, la detección de colisiones debería ser 2D y sin números en coma flotante. Todo esto sin contar las posibles optimizaciones asociadas a C o al procesador.

Algunás páginas sobre optimización en C:
http://www.abarnett.demon.co.uk/tutorial.html
http://www.prism.uvsq.fr/~cedb/local_copies/lee.html

SIEMPRE hay optimizaciones por hacer. Otra cosa es empezar a hacerlas antes de que te funcione nada [Ooooo] .
Hermes escribió:Lo que tu dices, es cierto, pero si te fijas arriba, he puesto una solucion que no necesita ni de division, ni de multiplicacion, ya que al fin y al cabo, las dimensiones de las cajas que albergaran la bola y los ladrillos, no van a variar y son conocidas.


Bien, ya había comentado que no había leído todo con calma. Al menos me ha servido para aprender algo y tenerlo en cuenta más adelante. Y también como ejemplo de que O(n) hay muchos :-)

Saludos y suerte. Intentaría ayudar más concretamente, pero debo estudiar :-P
saulotmalo escribió:ufff no puedo.. en serio... esto es imposible... he probado con lo tuyo hermes y tampoco me va, luego he portado tu idea y lo he mezclado con lo del motor, así las colisiones las hacía caja contra caja en vez de línea contra caja... y nada. Ya estoy desesperado posteo el código de esta parte por si alguien quiere hecharle un vistazo que igual soy yo que no lo veo o algo ufff pero increible...


Vamos a ver...

por lo que veo, tu encierras la bola en una caja BIDIMENSIONAL (mis rutinas son para emplearlas en una caja tridimensional)

El codigo que posteas, para mi no tiene mucho sentido porque no conozco el motor y no puedo ver como se realizan las comprobaciones a nivel interno, pero te adelanto una cosa: no puedes usar una deteccion de cajas si no tienes los vertices de esas cajas correctamente situadas en el universo.

Veamos, se supone que tu situas cada objeto o bien directamente en el espacio (utilizando una matriz universal unidad) o mediante una matriz que hace un escalado y posicionamiento del objeto.

Pues bien, si usas el segundo metodo, ahi empieza el primer problema porque la caja la deberias situar en el mismo punto en el espacio, con las dimesiones correctas.


El motor grafico, necesita de otra matriz mas, una matriz especial que se llama, matriz de proyeccion. Pues bien, ese es un problema si el motor esta intentando detectar colisiones habiendo aplicado esta transformacion, debido a que los objetos se deforman para aparecer mas grandes si estan mas cercanos y mas pequeños si estan mas lejanos y tu caja no resulta adecuada.

Pero volviendo a la matriz que se encarga de situar el objeto en el espacio... cada objeto que trates de situar, puede tener una matriz distinta, pues si tienes una caja que corresponde a un ladrillo, la vas a ir colocando en distintas posiciones para formar una pared


Eso quiere decir, que tu necesitaras tener las coordenadas de la caja, tal y como estarian situadas en el espacio (una vez aplicadas las transformacion universal) , para poder detectarlas.

Olvidate de la proyeccion, por completo y piensa en terminos de situacion de los objetos en un universo tuyo particular.

Tu imaginate el Arkanoid de toda la vida. Asi es como deberias disponer las piezas, solo que si el Arkanoid dispone las piezas en 2D, utilizando X e Y, tu deberas situar las cajas en X-Z y apilar cajas encima y debajo (Y)

Pero tendras que tener esas coordenadas almacenadas en una tabla ya (lo mejor y mas sensato) y utilizar las cajas teniendo las coordenadas conocidas, INDEPENDIENTEMENTE de como sean dibujadas, usando la matriz de proyeccion.

CONSEJO: pasa de ese motor grafico y usalo para DIBUJAR. Por algo se llama motor grafico y no de colisiones... Situa tus ladrillos directamente en el espacio, utiliza una matriz universal unidad y luego dispon la camara de forma ue puedas ver esa pared de ladrillos, pero las detecciones, hazlas SIEMPRE utilizando la disposicion final de los objetos en el universo y no como las apreciaria el ojo.

EDIT:

Edito porque tengo una duda:

¿no estaras intentando hacer un Arkanoid 2D (como los de toda la vida) pero usando un motor 3D, verdad? XD
Hermes a ver... creo que esto te va ha hacer mucha gracia... creo que es un arcanoid como tu lo llamas de toda la vida, mira os subo un ejecutable y lo probais a ver que os parece y tal... mirad el fallo solo sale contadas ocasiones :( y en realidad no sé a que se debe.

http://www.megaupload.com/?d=3J520CG3

yo casi me he dado por vencido...

pd: si me decís como os va de velocidad y tal tambien sería un detalle, ya que a mi me va a 60 fps guay... pero sé que con menos de un p IV y una gráfica de nueva generación o de la anterior le costará xD
saulotmalo escribió:Hermes a ver... creo que esto te va ha hacer mucha gracia... creo que es un arcanoid como tu lo llamas de toda la vida, mira os subo un ejecutable y lo probais a ver que os parece y tal... mirad el fallo solo sale contadas ocasiones :( y en realidad no sé a que se debe.

http://www.megaupload.com/?d=3J520CG3

yo casi me he dado por vencido...

pd: si me decís como os va de velocidad y tal tambien sería un detalle, ya que a mi me va a 60 fps guay... pero sé que con menos de un p IV y una gráfica de nueva generación o de la anterior le costará xD


:p [+risas] [+risas] [+risas] Pues si, me ha hecho mucha gracia.

Yo me pensaba que ibas a hacer un arkanoid con una vista similar al Tetris 3D y no un Arkanoid al estilo como lo has hecho.

He notado que cuando falla, se dispara el efecto de colision, asi que me da a mi que el problema es, que cuando detectas una colision, borras un ladrillo incorrecto

Esto te puede ocurrir si los ladrillos estan bastante pegados (las cajas de deteccion) y no las has separado lo suficiente. Tal vez se solapen, asi que te recomendaria que pruebes a usar una caja de deteccion que sea algo menos alta y ancha que el ladrillo que dibujas ,porque da la sensacion de que detectas el choque de una pieza, pero luego para borrarla, al hacer las operaciones para situarla en tu tabla de ladrillos (para activr el flag de borrado) la conversion falla y borras OTRO ladrillo.
Voy a ver si me aclaro :) porque no se si se podrá hacer menor la caja en el motor sino vuelvo a instalar tus funciones y listo, crees que haciendo menor la caja de la bola bastaría?? o no sería un buen método?
saulotmalo escribió:Voy a ver si me aclaro :) porque no se si se podrá hacer menor la caja en el motor sino vuelvo a instalar tus funciones y listo, crees que haciendo menor la caja de la bola bastaría?? o no sería un buen método?


Antes tendria que saber, de que tamaño es la caja que usas.

Veo que los ladrillos estan separados por un espacio ¿ese espacio es producto de una transparencia en la textura o de la separacion de las cajas?
mira los ladrillos hazte cuenta de que están totalmente juntos, ya que la caja que envuelve al modelo se tocan entre si, eso lo habías hacertado, he pensado en estrechar la caja en el eje Y ( de arriba a abajo)
saulotmalo escribió:mira los ladrillos hazte cuenta de que están totalmente juntos, ya que la caja que envuelve al modelo se tocan entre si, eso lo habías hacertado, he pensado en estrechar la caja en el eje Y ( de arriba a abajo)


jeje, el viejo truco de las cajas que se tocan XD
como diría un colega mio... me ha costao pero lo he ganao!!!!.

Todos teniamos parte de razón al final!!!! me he puesto en serio a pensar porque fallaba... la colision no era porque el objeto moría entonces? vamos a ver que pasa cuando el objeto hace lo que nodebía hacer... exacto 2 problemas... las colisiones a veces se equivocaban de pared pero no tiene sentido que si xoca siga la misma trayectoria para eso digo oye si vas a seguir la misma trayectoria cambia de sentido y además solo hay un sentido posible que es modificar la coordenada contraria a la pared que te has encontrado. Y listo! funciona.

Muchas gracias a todos por esta ayuda :) creo que sin vosotros me ubiese tocado ir a tutorias a ablar con alguno de mis viejos profesores de gráfica que me caen bien, pero no me gusta madrugar.
32 respuestas