My Tiled Collision Detection Algorithm Anti Tunneling, Super Fast Projectile support (c# code inside)

Hello Everyone I have finally got my collision detection working for a 2D or 3D tiled / grid / Volex world.

I am going to share it with all of you feel free to use it as you wish.

Its based on this ray casting algorithm
I have modified it and the result is a fairly fast algorithm that dos not allow tunnelling and is 100% accurate with collisions even when hitting the corner of an object.

The code bellow is for 3D but to work in 2D all you need to do is delete all the 3D stuff

THIS WILL ONLY WORK FOR A GRID SIZE OF 1
so if you are using a tile system that is 30x30 pixels and a pixel is what you move in you would have to convert 30 to 1
therefore
`Vector3 collPoint = Pos + ColOffset;
collPoint /= tileSize;

deltaVelocity /= tileSize;
`
alternatively you can alter the algorithm to work with any size grid without having to scale your inputs.

Things to note:
add this function to your movable objects.

Pos = position of the object
DeltaVelocity = the amount the object is going to move this update
ColOffset = This is where on the object you want to check a collision. Pos represents the center of the object. So usinging colOffset add points around your object to create a collision mesh.

There are still areas where performance could be improved but currently performance is not an issue for me so I have no plans to improve it.

/// <summary> /// a list of all faces /// </summary> public enum Face { Front = 5, Back = 4, Left = 2, Right = 0, Top = 3, Bottom = 1, None = -1, XAxis = 6, YAxis = 7, ZAxis = 8, Center = 6 }

/// <summary>
    /// check a colition of a point
    /// </summary>
    /// <param name="ColOffset">offset for each point from center of mob</param>
    private void CheckCollOfPoint(Vector3 ColOffset)
    {
        Vector3 collPoint = Pos + ColOffset;

        Point3D origin = Point3D.Zero;
        origin.X = (int)Math.Floor(collPoint.X); //get the whole numbers of each axis
        origin.Y = (int)Math.Floor(collPoint.Y);
        origin.Z = (int)Math.Floor(collPoint.Z);

        //set the direction of the vector
        Point3D Step = Point3D.Zero;
        if (deltaVelocity.X > 0)
            Step.X = 1;
        else
            Step.X = -1;

        if (deltaVelocity.Z > 0)
            Step.Z = 1;
        else
            Step.Z = -1;

        if (deltaVelocity.Y > 0)
            Step.Y = 1;
        else
            Step.Y = -1;

        //calculate how many updates each axis will take to collide
        //we are only interested in handling collision that will collide this update
        Vector3 tDelta = Vector3.Zero;
        if (deltaVelocity.X != 0) 
            tDelta.X = Math.Abs(1f / deltaVelocity.X);
        else
            tDelta.X = float.PositiveInfinity;

        if (deltaVelocity.Y != 0)
            tDelta.Y = Math.Abs(1f / deltaVelocity.Y);
        else
            tDelta.Y = float.PositiveInfinity;

        if (deltaVelocity.Z != 0)
            tDelta.Z = Math.Abs(1f / deltaVelocity.Z);
        else
            tDelta.Z = float.PositiveInfinity;

        //get the fraction componate from the position so 1.2 would be 0.2
        Vector3 Fraction = Vector3.Zero;
        Fraction.X = Math.Abs(collPoint.X - (int)origin.X);
        Fraction.Y = Math.Abs(collPoint.Y - (int)origin.Y);
        Fraction.Z = Math.Abs(collPoint.Z - (int)origin.Z);

        //the fraction would be different depending on the direction of our vector
        //for example lets use posx as 1.3
        //the fraction for a positive vector would be 1.3 - (int)1.3 = 0.3
        //however a negative vector would be 1 - (1.3 - (int)1.3 = 0.7
        //the code below check if the vector is negative and calcualtes the correct fraction
        if (deltaVelocity.X > 0)
            Fraction.X = (1 - Fraction.X);
        if (deltaVelocity.Y > 0)
            Fraction.Y = (1 - Fraction.Y);
        if (deltaVelocity.Z > 0)
            Fraction.Z = (1 - Fraction.Z);

        //get a base for how far in to the next grid slot we are based on time needed and 
        //how close we are
        Vector3 tMax = Vector3.Zero;
        tMax.X = tDelta.X * Fraction.X;
        tMax.Y = tDelta.Y * Fraction.Y; 
        tMax.Z = tDelta.Z * Fraction.Z;

        //check to make sure we dont get any NaN
        //you get a NaN if you do infinity * 0
        if (float.IsNaN(tMax.Z))
            tMax.Z = float.PositiveInfinity;
        if (float.IsNaN(tMax.Y))
            tMax.Y = float.PositiveInfinity;
        if (float.IsNaN(tMax.X))
            tMax.X = float.PositiveInfinity;

        //the piont to check
        Point3D checkPos = origin;

        //the face that is colliding          
        Face CollisionFace;
        while (tMax.X <= 1 || tMax.Y <= 1 || tMax.Z <= 1) //while there is a collision
        {
            CollisionFace = Face.None;
            if (tMax.X < tMax.Y)
            {
                if (tMax.X < tMax.Z)
                {
                  //  checkPos.X += Step.X;
                    tMax.X += tDelta.X;
                    CollisionFace = Face.XAxis;
                }
                else
                    if (tDelta.Z != float.PositiveInfinity)
                    {
                     //   checkPos.Z += Step.Z;
                        tMax.Z += tDelta.Z;
                        CollisionFace = Face.ZAxis;
                    }
                    else continue;

            }
            else
            {
                if (tMax.Y < tMax.Z)
                {
                  //  checkPos.Y += Step.Y;
                    tMax.Y += tDelta.Y;
                    CollisionFace = Face.YAxis;
                }
                else
                    if (tDelta.Z != float.PositiveInfinity)
                    {
                     //   checkPos.Z += Step.Z;
                        tMax.Z += tDelta.Z;
                        CollisionFace = Face.ZAxis;
                    }
                    else
                        continue;
            }

            
            if (checkPos.Y >= 0 && checkPos.Y < Sector.Sector_Height) //make sure we are in the world
            {
                {
                   
                    switch (CollisionFace)
                    {
                        case Face.XAxis:
                            if (GetBlock(new Point3D(checkPos.X + Step.X, checkPos.Y, checkPos.Z)).Info.Solid)
                            {
                                
                                //   Jump(); //auto jump

                                if (Step.X > 0) //if we are moving positive
                                    Pos.X = checkPos.X + 1- ColOffset.X - .01f;
                                else
                                    Pos.X = checkPos.X - ColOffset.X + .01f;

                                    Vel.X = 0;
                                    deltaVelocity.X = 0;
                                }
                            break;

                        case Face.ZAxis:
                            if (GetBlock(new Point3D(checkPos.X, checkPos.Y, checkPos.Z + Step.Z)).Info.Solid)
                            {
                                 //   if (!GetBlock(new Point3D(checkPos.X, checkPos.Y + 1, checkPos.Z)).Info.Solid)
                                   //     Jump();

                                    if (Step.Z > 0) //if we are moving positive
                                        Pos.Z = checkPos.Z + 1 - ColOffset.Z - .01f;
                                    else
                                        Pos.Z = checkPos.Z - ColOffset.Z + .01f;
                                    Vel.Z = 0;
                                    deltaVelocity.Z = 0;
                            }
                            break;

                        case Face.YAxis:
                            if (GetBlock(new Point3D(checkPos.X, checkPos.Y + Step.Y, checkPos.Z)).Info.Solid)
                            {
                                    if (Step.Y > 0)
                                    {
                                        Pos.Y = checkPos.Y + 1- ColOffset.Y - .001f;
                                    }
                                    else
                                    {
                                        Pos.Y = checkPos.Y - ColOffset.Y + .001f;
                                        _grounded = true;
                                    }

                                    Vel.Y = 0;
                                    deltaVelocity.Y = 0;
                            }
                            break; 
                    }
                }
            }
        }
    }`