Question

I have a physics simulation and it allows you to place area constraints, so that the bodies within will not exit that area. However if an atom goes past one of the "walls" of the area constraint it blows up the physics simulation. Why does it do this? Update method:

if (!atom.IsStatic)
{
    Vector2 force = Vector2.Zero;
    bool x = false, y = false;
    if (atom.Position.X - atom.Radius < _min.X)
    {
        force = new Vector2(-(_min.X - atom.Position.X), 0);
        if (atom.Velocity.X < 0)
            x = true;
    }
    if (atom.Position.X + atom.Radius > _max.X)
    {
        force = new Vector2(atom.Position.X - _max.X, 0);
        if (atom.Velocity.X > 0)
            x = true;
    }
    if (atom.Position.Y - atom.Radius < _min.Y)
    {
        force = new Vector2(0, -(_min.Y - atom.Position.Y));
        if (atom.Velocity.Y < 0)
            y = true;
    }
    if (atom.Position.Y + atom.Radius > _max.Y)
    {
        force = new Vector2(0, atom.Position.Y - _max.Y);
        if (atom.Velocity.Y > 0)
            y = true;
    }
    atom.ReverseVelocityDirection(x, y);
    if (!atom.IsStatic)
    {
        atom.Position += force;
    }
}
Was it helpful?

Solution 3

Wouldn't you know, after about half an hour of mindless hacking at it, i thought of simply not applying the position correction. That fixed it like a charm. For any interested, here's the updated code:

if (!atom.IsStatic)
{
    if (atom.Position.X - atom.Radius < _min.X && atom.Velocity.X < 0)
    {
        atom.ReverseVelocityDirection(true, false);
    }
    if (atom.Position.X + atom.Radius > _max.X && atom.Velocity.X > 0)
    {
        atom.ReverseVelocityDirection(true, false);
    }
    if (atom.Position.Y - atom.Radius < _min.Y && atom.Velocity.Y < 0)
    {
        atom.ReverseVelocityDirection(false, true);
    }
    if (atom.Position.Y + atom.Radius > _max.Y && atom.Velocity.Y > 0)
    {
        atom.ReverseVelocityDirection(false, true);
    }
}

OTHER TIPS

I see you're doing calculation with a constant time step T. When modeling collisions though on every step you should use time step equal to minimal time before any of atoms reach any obstacle.

Make time step variable, and atoms will never "tunnel" obstacles.

P.S. There are a lot of optimizations in collision detection, please read gamedev papers for information on those.

P.S. A bug?

force = new Vector2(-(_min.X - atom.Position.X), 0);

Force is created separately for X and Y reflection. What happens when the atom gets into a corner? Only second force will be applied.

P.P.S: Use epsilon

One more important note: if you use floating point, the error is accumulated, and you should use eps:

abs(atom.Position.Y + atom.Radium - _max.Y) < eps

where eps is a number much smaller than normal sizes in your task, e.g. 0.000001.

You seem to have solved the problem already, but I notice that "force" seems to be wrong. It moves the atom away from the boundary, even if it's on the wrong side. Suppose an atom has shot past _max.X:

if (atom.Position.X + atom.Radius > _max.X) 
    { 
        force = new Vector2(atom.Position.X - _max.X, 0); 
        ...
    } 

Now "force" will be in the +x direction, and the atom's distance from the wall will double with every iteration. Boom!

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top