2009-10-21 22 views
5

Estoy construyendo un motor de física y tenía algo así como "pseudo-verlet" y quería actualizarlo a verlet "real". Entonces encontré un artículo y me puse a trabajar. Después de agregar lo que creo que es una buena aproximación, el motor ya no funciona. ¿Alguien puede ayudarme a entender lo que estoy haciendo mal? actualizaciónVerlet La integración está volando mi motor de física

Mi principal de carrocería clase de física, se aplica la fuerza, y aplicar sistemas de impulso:

public void Update(float timestepLength) 
{ 
    if (!this._isStatic) 
    { 
     Vector2 velocity = Vector2.Subtract(_position, _lastPosition); 
     Vector2 nextPos = _position + (_position - _lastPosition) + _acceleration * (timestepLength * timestepLength); 
     _lastPosition = _position; 
     _position = nextPos; 
     _acceleration = Vector2.Zero; 
    } 
} 

public void ApplyForce(Vector2 accelerationValue) 
{ 
    if (!this._isStatic) 
     _acceleration += (accelerationValue) * _mass; 
} 
public void ApplyImpulse(Vector2 impulse) 
{ 
    if (!this._isStatic) 
     _acceleration +=-1 * impulse; 
} 

Editar: lo he arreglado y funciona como un encanto, pero tengo dos preguntas sobre el código siguiente:

  • ¿Es correcto el código de la aplicación de impulso y, de no ser así, cuál debería ser?
  • ¿Cómo cambio la propiedad de posición para que la configuración preserve la velocidad actual del cuerpo?

Aquí está el código:

public Vector2 Position 
{ 
    get { return _position; } 
    set { _position = value;} 
} 
public void Update(float timestepLength) 
{ 
    if (!this._isStatic) 
    { 
     Vector2 velocity = Vector2.Subtract(_position, _lastPosition); 
     Vector2 velocityChange = Vector2.Subtract(velocity, Vector2.Subtract(_lastPosition, _twoStepsAgoPosition)); 
     Vector2 nextPos = _position + (_position - _lastPosition) + _acceleration * (timestepLength * timestepLength); 
     _twoStepsAgoPosition = _lastPosition; 
     _lastPosition = _position; 
     _position = nextPos; 
     _acceleration = Vector2.Multiply(velocityChange, timestepLength); 
    } 
} 

public void ApplyForce(Vector2 force) 
{ 
    if (!this._isStatic) 
     _lastPosition -= force; 
} 
public void ApplyImpulse(Vector2 impulse) 
{ 
    if (!this._isStatic) 
     _acceleration +=-1 * impulse; 
} 
+0

¿Por qué no? _acceleration - = impulse; ? –

+0

En realidad, no pensé en eso ... ¡Gracias! – RCIX

Respuesta

3

como referencia para los demás ... el papel Verlet es probable que esté refiriendo a lo siguiente: advanced character physics realizado por el equipo que creó Hitman y fue una de las primero que ha basado en la física ragdoll

todos modos ... el código original que utilizaron fue:

void ParticleSystem::Verlet() { 
     for(int i=0; i<NUM_PARTICLES; i++) { 
      Vector3& x = m_x[i]; 
      Vector3 temp = x; 
      Vector3& oldx = m_oldx[i]; 
      Vector3& a = m_a[i]; 
      x += x-oldx+a*fTimeStep*fTimeStep; 
      oldx = temp; 
     } 
} 

y que son r que tu código hace algo similar.

Lo único que siempre explotó mis simulaciones fue el uso de un paso de tiempo demasiado grande. Además, con esta integración de verlet, asegúrese de que el lapso de tiempo que usa sea constante durante todo el juego. (por ejemplo, 30 cuadros/seg por ejemplo (por lo que el paso de tiempo es 1/30)) y no fluctúa. Si lo hace se debe utilizar el time corrected verlet integration que representa esta

EDIT:

respuesta a Pregunta 2: mover su posición (sin cambiar la velocidad/aceleración) acaba de actualizar la posición a la nueva posición, y luego como una paso adicional agrega el delta de este movimiento (tan newPosition-oldPosition) al objeto viejo, por lo que esto se actualiza en consecuencia.

respuesta a la pregunta 1: Impulso es la fuerza aplicada a un objeto durante un período de tiempo. Entonces tu solución no es correcta. El impulso sería que a lo largo de X veces (o marcos), llama a su función applyForce con una fuerza fija.

+0

En realidad estoy usando http://www.gamedev.net/reference/programming/features/verlet/ como base. Lo que sucede es que la partícula realmente no se mueve en absoluto (bajo una fuerza de gravedad lineal), y si reemplazo la línea '_acceleration = Vector2.Zero;' con _acceleration = Vector2.Multiply (_acceleration, 1 - _linearDrag); actúa de forma muy inusual (las partículas comienzan a moverse y luego cuando topan con una restricción que las ata a un área que salen disparadas de la pantalla, sospecho que sus valores se ajustan a NaN poco después). – RCIX

+0

Estoy usando el verlet corregido por tiempo BTW. – RCIX

+0

Ok, ahora he actualizado mi código y mis preguntas. – RCIX

Cuestiones relacionadas