2
votes

I could use some help figuring out collision response. I'm trying to implement what is presented in this paper on slides 4 to 10. Collision detection works, and the colliding entity does slide along the collision plane but with severely reduced speed. I'm not sure whether I'm properly projecting the leftover velocity on collision plane.

class CollisionPacket {
    // INPUT:
    colliderRadius: vec3;
    colliderPosition: vec3;
    colliderVelocity: vec3;

    // OUTPUT:    
    collisionFound: bool;
    collisionTime: number;  // how far can we travel before we collide?
    collisionPoint: vec3;   // point on triangle where collision ocurred
    collisionNormal: vec3;  // normal of nearest collided triangle
}

collideAndSlide(position: vec3, velocity: vec3, radius: number): vec3 {
    var packet = new CollisionPacket();

    packet.colliderRadius = radius;
    packet.colliderPosition = position;
    packet.colliderVelocity = velocity;

    packet.collisionTime = 0.0;
    packet.collisionFound = false;

    var maxIterations = 5;

    do {
        // check nearby triangles for collisions
        this.collideWorld(packet);

        var newPosition = packet.colliderPosition.copy();
        var newVelocity = packet.colliderVelocity.copy();

        if (packet.collisionFound) {
            // scale velocity vector to collide with nearest triangle
            var scaledVelocity = packet.colliderVelocity.copy().scale(packet.collisionTime);

            // move a tiny bit away from collision along collision normal
            scaledVelocity.add(packet.collisionNormal.copy().scale(0.001));

            // add scaled velocity to position
            newPosition.add(scaledVelocity);

            // and remove it from leftover velocity
            newVelocity.subtract(scaledVelocity);

            // extract part of velocity vector which is perpendicular to collision plane (CORRECT?)
            var v = packet.collisionNormal.copy().scale(vec3.dot(newVelocity, packet.collisionNormal));

            // remove that part from velocity vector
            newVelocity = vec3.difference(newVelocity, v);

            // update values for next iteration
            packet.colliderPosition = newPosition;
            packet.colliderVelocity = newVelocity;
        }
        else {
            // no collision, move as requested
            newPosition.add(packet.colliderVelocity);
        }
    } while (--maxIterations > 0 && packet.collisionFound)

    return newPosition;
}

I visualized both v and newVelocity after v has been subtracted from it and they look how they're supposed to: v is perpendicular to the collision plane, newVelocity runs parallel to it in the direction we're moving.

If I add newVelocity directly to newPosition instead of doing the recursion, like this:

                ...

                // remove that part from velocity vector
                newVelocity = vec3.difference(newVelocity, v);

                newPosition.add(newVelocity);
        }
        else {
                // no collision, move as requested
                newPosition.add(packet.colliderVelocity);
        }
    } while (false)

the entity is sliding as it should, without being slowed down, so I'm quite sure the vectors are ok.

However, maxIterations always runs down to zero, so there's always collisions. maybe that's slowing it down?

Would someone with a better understanding of the underlying math have a look?

Thank you!

EDIT:

Illustration of the vectors after the first iteration:

enter image description here

The box is colliding against the wall (invisible on this screenshot due to backface culling)

1

1 Answers

0
votes

Found the problem: I forgot to reset packet.collisionTime at the beginning of each iteration, this it what slowed it all down. It works as expected now. Maybe the code is helpful to someone else.