Pregunta

He implementado el código de la pregunta " a la bola de Colisión - Detección y Manipulación " en Objective-C. Sin embargo, cada vez que las bolas chocan en un ángulo su velocidad aumenta dramáticamente. Todos los cálculos vector se realiza mediante cocos2d-iPhone, con el encabezado CGPointExtension.h. ¿Cuál es la causa de esta aceleración no deseada?

El siguiente es un ejemplo de aumento de la velocidad:

Entrada:
== masa 12.56637
velocity.x == 1.73199439
velocity.y == -10,5695238

ball.mass == 12.56637
ball.velocity.x == 6.04341078
ball.velocity.y == 14.2686739

Salida:
== masa 12.56637
velocity.x == 110.004326
velocity.y == -10,5695238

ball.mass == 12.56637
ball.velocity.x == -102,22892
ball.velocity.y == -72,4030228

#import "CGPointExtension.h"
#define RESTITUTION_CONSTANT (0.75) //elasticity of the system

- (void) resolveCollision:(Ball*) ball
{
    // get the mtd (minimum translation distance)
    CGPoint delta = ccpSub(position, ball.position);
    float d = ccpLength(delta);
    // minimum translation distance to push balls apart after intersecting
    CGPoint mtd = ccpMult(delta, (((radius + ball.radius)-d)/d)); 


    // resolve intersection --
    // inverse mass quantities
    float im1 = 1 / [self mass]; 
    float im2 = 1 / [ball mass];

    // push-pull them apart based off their mass
    position = ccpAdd(position, ccpMult(mtd, (im1 / (im1 + im2))));
    ball.position = ccpSub(ball.position, ccpMult(mtd, (im2 / (im1 + im2))));

    // impact speed
    CGPoint v = ccpSub(velocity, ball.velocity);
    float vn = ccpDot(v,ccpNormalize(mtd));

    // sphere intersecting but moving away from each other already
    if (vn > 0.0f) return;

    // collision impulse
    float i = (-(1.0f + RESTITUTION_CONSTANT) * vn) / ([self mass] + [ball mass]);
    CGPoint impulse = ccpMult(mtd, i);


    // change in momentum
    velocity = ccpAdd(velocity, ccpMult(impulse, im1));
    ball.velocity = ccpSub(ball.velocity, ccpMult(impulse, im2));

}
¿Fue útil?

Solución

Yo soy el que escribió el código pelota rebote original que se hace referencia. Si descarga y probar ese código, se puede ver que funciona bien.

El siguiente código es correcto (la forma en que originalmente tenía):

// collision impulse
float i = (-(1.0f + RESTITUTION_CONSTANT) * vn) / (im1 + im2);
CGPoint impulse = ccpMult(mtd, i);

Este es el código de la física muy común y se puede ver que es casi exactamente en práctica de este tipo en los siguientes ejemplos:

Esto es correcto, y que ~ ~ no está creando un CDR por encima de 1,0, como otros han sugerido. Este es el cálculo del vector de impulso relativa basa en la masa y coeficiente de restitución.

Haciendo caso omiso de la fricción, un simple ejemplo 1d es el siguiente:

J = -Vr(1+e) / {1/m1 + 1/m2}  

donde E es la CDR, Vr es su velocidad normalizada y J es un valor escalar de la velocidad de impulso.

Si usted planea en hacer algo más avanzado que este le sugiero que utilice una de las muchas bibliotecas física ya está ahí. Cuando he usado el código anterior que estaba bien para un par de bolas pero cuando en rampa que hasta varios cientos empezó a ahogarse. He utilizado el motor de física Box2D y su solucionador podía manejar más bolas y es mucho más precisa.

De todos modos, me daba su código y, a primera vista se ve bien (que es una traducción bastante fiel). Es probablemente una pequeña y sutil de error de un valor incorrecto que se pasa en, o un problema de matemáticas del vector.

No sé nada sobre el desarrollo iPhone pero sugeriría establecer un punto de interrupción en la parte superior de dicho método y el seguimiento de cada uno de los pasos que resulta valor y encontrar donde el golpe en marcha es. Asegurarse de que el MTD se calcula correctamente, las velocidades de impacto, etc, etc hasta que vea donde se está introdujo el gran aumento.

Informe de vuelta con los valores de cada paso en ese método y vamos a ver lo que tenemos.

Otros consejos

Después de haber revisado el código original y los comentarios de su creador original, el código parece el mismo, por lo que si el original es una aplicación correcta, sospecharía una biblioteca de vectores mal o algún tipo de variable no inicializada.

¿Por qué estás añadiendo 1,0 al coeficiente de restitución?

De: http://en.wikipedia.org/wiki/Coefficient_of_restitution

El CDR es generalmente un número en el intervalo [0,1]. Cualitativamente, 1 representa una colisión perfectamente elástica, mientras que 0 representa una colisión perfectamente inelástica. Un COR mayor que uno es teóricamente posible, lo que supone una colisión que genera energía cinética, como las minas terrestres que son lanzados juntos y explosión.

Otro problema es el siguiente:

/ (im1 + im2)

Usted está dividiendo por la suma de los inversos de las masas para conseguir el impulso a lo largo del vector de contacto - probablemente se debe dividiendo por la suma de las masas mismas. Esto se magnificando su impulso ( "eso es lo que ha dicho").

En esta línea:

CGPoint impulse = ccpMult(mtd, i);

mtd tiene que se han normalizado. ocurrió el error porque en el MTD código original se normalizó en una línea anterior pero no en el código. Lo puede solucionar haciendo algo como esto:

CGPoint impulse = ccpMult(ccpNormalize(mtd), i);
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top