1

In C++ I implemented a small collision detection and response system in my small voxel game. For now only AABB vs Voxel (the voxel is a cube so it's a AABB, too).

Actually all works fine with one special exception, if the player (AABB) is moving exactly in 45 degrees to a edge of a voxel the player is glitching a little in and out fastly. On the images down you can see it.

Now I am wondering what causing this problem but I can't find any logical error!? So here how I do it in pseudo code currently:

float xNew = xCurrent + xVelocity * deltaTime;
float yNew = yCurrent + yVelocity * deltaTime;
float zNew = zCurrent + zVelocity * deltaTime;

float xCorrected = xNew;
float yCorrected = yNew;
float zCorrected = zNew;

// If the player is moving to right side.
if (xNew < xCurrent)
{
    %DO THE FOLLOWING FOR EACH OF THE 4 CORNERS OF THE PLAYER AABB,%
    %ON THE RIGHT FACE, UNTIL ONE COLLISION OCCURS%
    {
        float x = xNew;
        float y = yCurrent + %CORNER_Y_OFFSET%;
        float z = zCurrent + %CORNER_Z_OFFSET%;

        if (getVoxelAt(x, y, z).isSolid())
        {
            xCorrected = (unsigned int)x + 1;

            // Abbort and check z axis.
            break;
        }
    }
}
else if(...)
// Check for the opposite direction...

// If the player is moving to front side.
if (zNew < zCurrent)
{
    %DO THE FOLLOWING FOR EACH OF THE 4 CORNERS OF THE PLAYER AABB,%
    %ON THE RIGHT FACE, UNTIL ONE COLLISION OCCURS%
    {
        float x = xCurrent + %CORNER_X_OFFSET%;
        float y = yCurrent + %CORNER_Y_OFFSET%;
        float z = zNew;

        if (getVoxelAt(x, y, z).isSolid())
        {
            zCorrected = (unsigned int)z + 1;

            // Abbort and check Y axis.
            break;
        }
    }
}
else if(...)
// Check for the opposite direction...

// Y axis check, not important for now....

// Apply corrected positions.
xCurrent = xCorrected;
yCurrent = yCorrected;
zCurrent = zCorrected;

EDIT:

Z Axis, not Y axis on the screenshot. My mistake.

Screenshot example Diagram of example

Glorfindel
  • 21,988
  • 13
  • 81
  • 109

1 Answers1

0

The problem is that the advance in X and Z direction are done independently.

If only X is advanced, there is no collision

float x = xNew;
float y = yCurrent + %CORNER_Y_OFFSET%;
float z = zCurrent + %CORNER_Z_OFFSET%;

If only Z is advanced, there is no collision

float x = xCurrent + %CORNER_X_OFFSET%;
float y = yCurrent + %CORNER_Y_OFFSET%;
float z = zNew;

So during the first update, the player (AABB) goes inside the voxel a little bit. During next update, there are collisions in X and Z checks, so the player is moved back. The next update, again, no collision in X or Z independently. And that is causing the glicth.

You can add another test advancing both X and Z at the same time to avoid the penetration and the glitch.

float x = xNew;
float y = yCurrent + %CORNER_Y_OFFSET%;
float z = zNew;
gotanod
  • 299
  • 1
  • 3
  • 7