#if !defined VOXEL_BLOCK_INTERSECTION_LIB
#define VOXEL_BLOCK_INTERSECTION_LIB

    #define INTERSECT_PARTIAL_BLOCKS
    #define INTERSECT_SLOW_PARTIAL_BLOCKS

    bool IntersectAABox(vec3 rayPos, vec3 invRayDir, vec3 boxRadii, out float dist, inout vec3 hitNormal) {
        // This one will not intersect backfaces, or in other words this will not intersect the box from inside it.
        vec3 scaledRayPos = rayPos * invRayDir;
        vec3 minDists = -boxRadii * abs(invRayDir) - scaledRayPos; // distance to each frontfacing plane
        vec3 maxDists =  boxRadii * abs(invRayDir) - scaledRayPos; // distance to each backfacing plane

        float maxofMin = maxof(minDists); // distance to the frontfaces
        float minofMax = minof(maxDists); // distance to the backfaces

        dist = maxofMin; // Distance to intersection (if the box was intersected)

        // Deterimine normal
        if (dist == minDists.x) {
            hitNormal = vec3(invRayDir.x < 0.0 ? 1.0 : -1.0, 0.0, 0.0);
        } else if (dist == minDists.y) {
            hitNormal = vec3(0.0, invRayDir.y < 0.0 ? 1.0 : -1.0, 0.0);
        } else {
            hitNormal = vec3(0.0, 0.0, invRayDir.z < 0.0 ? 1.0 : -1.0);
        }

        // Check for intersection & return whether or not we intersected
        return dist > 0.0 && maxofMin <= minofMax;
    }
    bool IntersectAABox(vec3 rayPos, vec3 invRayDir, vec3 minBounds, vec3 maxBounds, out float dist, inout vec3 hitNormal) {
        // This will not intersect backfaces, or in other words this will not intersect the box from inside it.
        // You should use the version that rakes in radii instead of min & max bounds if you can, as it will be faster.
        vec3 minBoundsDist = (minBounds - rayPos) * invRayDir;
        vec3 maxBoundsDist = (maxBounds - rayPos) * invRayDir;

        vec3 minDists = min(minBoundsDist, maxBoundsDist);
        vec3 maxDists = max(minBoundsDist, maxBoundsDist);

        float maxofMin = maxof(minDists); // distance to frontfaces
        float minofMax = minof(maxDists); // distance to backfaces

        dist = maxofMin; // Distance to intersection (if the box was intersected)

        // Deterimine normal
        if (dist == minDists.x) {
            hitNormal = vec3(invRayDir.x < 0.0 ? 1.0 : -1.0, 0.0, 0.0);
        } else if (dist == minDists.y) {
            hitNormal = vec3(0.0, invRayDir.y < 0.0 ? 1.0 : -1.0, 0.0);
        } else {
            hitNormal = vec3(0.0, 0.0, invRayDir.z < 0.0 ? 1.0 : -1.0);
        }

        // Check for intersection & return whether or not we intersected
        return dist > 0.0 && maxofMin <= minofMax;
    }

    #ifdef INTERSECT_SLOW_PARTIAL_BLOCKS
    bool IntersectAnvil(vec3 relativeOrigin, vec3 direction, vec3 inverseDirection, bool northSouth, out float hitDist, inout vec3 hitNormal) {
        // Base
        bool intersected = IntersectAABox(relativeOrigin, inverseDirection, vec3(0.125,0,0.125), vec3(0.875,0.25,0.875), hitDist, hitNormal);

        // temp holders
        float tDist;
        vec3 tNormal;

        vec3 minBounds = northSouth ? vec3(0.25, 0.25,   0.1875) : vec3(0.1875, 0.25,   0.25);
        vec3 maxBounds = northSouth ? vec3(0.75, 0.3125, 0.8125) : vec3(0.8125, 0.3125, 0.75);
        if (IntersectAABox(relativeOrigin, inverseDirection, minBounds, maxBounds, tDist, tNormal)) {
            if (!intersected || tDist < hitDist) {
                hitDist = tDist;
                hitNormal = tNormal;
                intersected = true;
            }
        }

        minBounds = northSouth ? vec3(0.375, 0.3125, 0.25) : vec3(0.25, 0.3125, 0.375);
        maxBounds = northSouth ? vec3(0.625, 0.625,  0.75) : vec3(0.75, 0.625,  0.625);
        if (IntersectAABox(relativeOrigin, inverseDirection, minBounds, maxBounds, tDist, tNormal)) {
            if (!intersected || tDist < hitDist) {
                hitDist = tDist;
                hitNormal = tNormal;
                intersected = true;
            }
        }

        minBounds = northSouth ? vec3(0.1875, 0.625, 0.0) : vec3(0.0, 0.625, 0.1875);
        maxBounds = northSouth ? vec3(0.8125, 1.0,   1.0) : vec3(1.0, 1.0,   0.8125);
        if (IntersectAABox(relativeOrigin, inverseDirection, minBounds, maxBounds, tDist, tNormal)) {
            if (!intersected || tDist < hitDist) {
                hitDist = tDist;
                hitNormal = tNormal;
                intersected = true;
            }
        }

        return intersected;
    }
    bool IntersectFence(vec3 relativeOrigin, vec3 direction, vec3 inverseDirection, int shapeMasks, out float hitDist, inout vec3 hitNormal) {
        // Post
        bool intersected = IntersectAABox(relativeOrigin, inverseDirection, vec3(0.375,0,0.375), vec3(0.625,1,0.625), hitDist, hitNormal);

        // Check connected directions
        bool east  = (shapeMasks & 0x8) == 0x8; // 1000
        bool west  = (shapeMasks & 0x4) == 0x4; // 0100
        bool south = (shapeMasks & 0x2) == 0x2; // 0010
        bool north = (shapeMasks & 0x1) == 0x1; // 0001

        // temp holders
        float tDist;
        vec3 tNormal;

        // East-west connection
        if (east || west) {
            // Upper bar
            vec3 xUpperMin = vec3(west ? 0.0 : 0.5, 0.75,   0.4375);
            vec3 xUpperMax = vec3(east ? 1.0 : 0.5, 0.9375, 0.5625);
            if (IntersectAABox(relativeOrigin, inverseDirection, xUpperMin, xUpperMax, tDist, tNormal)) {
                if (!intersected || tDist < hitDist) {
                    hitDist = tDist;
                    hitNormal = tNormal;
                }
                intersected = true;
            }

            // Lower bar
            vec3 xLowerMin = vec3(west ? 0.0 : 0.5, 0.375,  0.4375);
            vec3 xLowerMax = vec3(east ? 1.0 : 0.5, 0.5625, 0.5625);
            if (IntersectAABox(relativeOrigin, inverseDirection, xLowerMin, xLowerMax, tDist, tNormal)) {
                if (!intersected || tDist < hitDist) {
                    hitDist = tDist;
                    hitNormal = tNormal;
                }
                intersected = true;
            }
        }

        // North-south connection
        if (south || north) {
            // Upper bar
            vec3 zUpperMin = vec3(0.4375, 0.75,   north ? 0.0 : 0.5);
            vec3 zUpperMax = vec3(0.5625, 0.9375, south ? 1.0 : 0.5);
            if (IntersectAABox(relativeOrigin, inverseDirection, zUpperMin, zUpperMax, tDist, tNormal)) {
                if (!intersected || tDist < hitDist) {
                    hitDist = tDist;
                    hitNormal = tNormal;
                    intersected = true;
                }
            }

            // Lower bar
            vec3 zLowerMin = vec3(0.4375, 0.375,  north ? 0.0 : 0.5);
            vec3 zLowerMax = vec3(0.5625, 0.5625, south ? 1.0 : 0.5);
            if (IntersectAABox(relativeOrigin, inverseDirection, zLowerMin, zLowerMax, tDist, tNormal)) {
                if (!intersected || tDist < hitDist) {
                    hitDist = tDist;
                    hitNormal = tNormal;
                    intersected = true;
                }
            }
        }

        return intersected;
    }
    bool IntersectWall(vec3 relativeOrigin, vec3 direction, vec3 inverseDirection, int shapeMasks, out float hitDist, inout vec3 hitNormal) {
        bool intersected = false;

        // Check connected directions
        bool up    = (shapeMasks & 0x10) == 0x10; // 10000
        bool east  = (shapeMasks & 0x08) == 0x08; // 01000
        bool west  = (shapeMasks & 0x04) == 0x04; // 00100
        bool south = (shapeMasks & 0x02) == 0x02; // 00010
        bool north = (shapeMasks & 0x01) == 0x01; // 00001

        // Post
        if (!((east && west && !south && !north) || (!east && !west && south && north)) || up) {
            intersected = IntersectAABox(relativeOrigin, inverseDirection, vec3(0.25, 0, 0.25), vec3(0.75, 1, 0.75), hitDist, hitNormal);
        }

        // temp holders
        float tDist;
        vec3 tNormal;

        // East-west connection
        if (east || west) {
            vec3 minBounds = vec3(west ? 0.0 : 0.5, 0.0,   0.3125);
            vec3 maxBounds = vec3(east ? 1.0 : 0.5, 0.875, 0.6875);
            if (IntersectAABox(relativeOrigin, inverseDirection, minBounds, maxBounds, tDist, tNormal)) {
                if (!intersected || tDist < hitDist) {
                    hitDist = tDist;
                    hitNormal = tNormal;
                    intersected = true;
                }
            }
        }

        // North-south connection
        if (south || north) {
            vec3 minBounds = vec3(0.3125, 0.0,   north ? 0.0 : 0.5);
            vec3 maxBounds = vec3(0.6875, 0.875, south ? 1.0 : 0.5);
            if (IntersectAABox(relativeOrigin, inverseDirection, minBounds, maxBounds, tDist, tNormal)) {
                if (!intersected || tDist < hitDist) {
                    hitDist = tDist;
                    hitNormal = tNormal;
                    intersected = true;
                }
            }
        }

        return intersected;
    }
    bool IntersectCrop(vec3 relativeOrigin, vec3 direction, vec3 inverseDirection, out float hitDist, inout vec3 hitNormal) {
        float intersectDist;
        bool intersected = IntersectAABox(relativeOrigin, inverseDirection, vec3(0,-0.0625,0.25), vec3(1, 0.9375, 0.251), hitDist, hitNormal);

        float dist; vec3 normal;
        if (IntersectAABox(relativeOrigin, inverseDirection, vec3(0,-0.0625,0.75), vec3(1, 0.9375, 0.751), dist, normal)) {
            if (!intersected || dist < hitDist) {
                hitDist = dist;
                hitNormal = normal;
                intersected = true;
            }
        }

        if (IntersectAABox(relativeOrigin, inverseDirection, vec3(0.75,-0.0625,0), vec3(0.751, 0.9375, 1), dist, normal)) {
            if (!intersected || dist < hitDist) {
                hitDist = dist;
                hitNormal = normal;
                intersected = true;
            }
        }

        if (IntersectAABox(relativeOrigin, inverseDirection, vec3(0.75,-0.0625,0), vec3(0.751, 0.9375, 1), dist, normal)) {
            if (!intersected || dist < hitDist) {
                hitDist = dist;
                hitNormal = normal;
                intersected = true;
            }
        }

        return intersected;
    }

    bool IntersectWallTorch(vec3 relativeOrigin, vec3 direction, int face, out float hitDist, inout vec3 hitNormal) {
        const float angle = radians(22.5);
        vec3 rotationOrigin = vec3(face == 0 ?  0.0 : face == 1 ? 1.0 : 0.5, 3.5/16.0, face == 2 ? 0.0 : face == 3 ?  1.0 : 0.0);
        vec3 rotationVector = vec3(face == 2 ? -1.0 : face == 3 ? 1.0 : 0.0, 0.0,      face == 0 ? 1.0 : face == 1 ? -1.0 : 0.0);

        vec3 rotatedOrigin    = Rotate(relativeOrigin - rotationOrigin, rotationVector, angle) + rotationOrigin;
        vec3 rotatedDirection = Rotate(direction, rotationVector, angle);

        vec3 minBounds = vec3(face == 0 ? -0.0625 : face == 1 ? 0.9375 : 0.4375,         3.5/16.0, face == 2 ? -0.0625 : face == 3 ? 0.9375 : 0.4375);
        vec3 maxBounds = vec3(face == 0 ?  0.0625 : face == 1 ? 1.0625 : 0.5625, 0.625 + 3.5/16.0, face == 2 ?  0.0625 : face == 3 ? 1.0625 : 0.5625);

        if (IntersectAABox(rotatedOrigin, 1.0 / rotatedDirection, minBounds, maxBounds, hitDist, hitNormal)) {
            hitNormal = Rotate(hitNormal, rotationVector, -angle);

            return true;
        }

        return false;
    }
    #endif

    bool IntersectVoxel(vec3 relativeOrigin, vec3 direction, int id, inout float hitDist, inout vec3 hitNormal) {
        if (id > 1) {
            vec3 inverseDirection = 1.0 / direction;

            if (id <= 16) {
                vec3 minBounds, maxBounds;
                minBounds = vec3(0);
                maxBounds = vec3(1, id * 0.0625 - 0.0625, 1);

                return IntersectAABox(relativeOrigin, inverseDirection, minBounds, maxBounds, hitDist, hitNormal);
            } else if (id <= 96) {
                vec3[97 - 17][2] bounds1 = vec3[97 - 17][2](
                    // Fluids
                    // This is currently just so they don't look completely awful
                    vec3[2](vec3(0), vec3(1, 8.0/9.0, 1)),
                    vec3[2](vec3(0), vec3(1, 8.0/9.0, 1)),

                    // Slabs (Top)
                    vec3[2](vec3(0, 0.5, 0), vec3(1)),
                    // Torches (not on walls)
                    vec3[2](vec3(0.4375, 0.0, 0.4375), vec3(0.5625, 0.625, 0.5625)),

                    // Pressure Plates (not pressed)
                    vec3[2](vec3(0.0625, 0, 0.0625), vec3(0.9375, 0.0625, 0.9375)),
                    // Pressure Plates (pressed)
                    vec3[2](vec3(0.0625, 0, 0.0625), vec3(0.9375, 0.03125, 0.9375)),

                    // Doors & Trapdoors
                    vec3[2](vec3(0), vec3(0.1875, 1, 1)),
                    vec3[2](vec3(0.8125, 0, 0), vec3(1)),
                    vec3[2](vec3(0), vec3(1, 1, 0.1875)),
                    vec3[2](vec3(0, 0, 0.8125), vec3(1)),
                    vec3[2](vec3(0, 0.8125, 0), vec3(1)),

                    // Buttons
                    vec3[2](vec3(0.0000, 0.375, 0.3125), vec3(0.1250, 0.625, 0.6875)),
                    vec3[2](vec3(0.8750, 0.375, 0.3125), vec3(1.0000, 0.625, 0.6875)),
                    vec3[2](vec3(0.3125, 0.375, 0.0000), vec3(0.6875, 0.625, 0.1250)),
                    vec3[2](vec3(0.3250, 0.375, 0.8750), vec3(0.6875, 0.625, 1.0000)),
                    vec3[2](vec3(0.3750, 0.000, 0.3125), vec3(0.6250, 0.125, 0.6875)),
                    vec3[2](vec3(0.3125, 0.000, 0.3750), vec3(0.6875, 0.125, 0.6250)),
                    vec3[2](vec3(0.3750, 0.875, 0.3125), vec3(0.6250, 1.000, 0.6875)),
                    vec3[2](vec3(0.3125, 0.875, 0.3750), vec3(0.6875, 1.000, 0.6250)),

                    vec3[2](vec3(0.0000, 0.3750, 0.3125), vec3(0.0625, 0.6250, 0.6875)),
                    vec3[2](vec3(0.9375, 0.3750, 0.3125), vec3(1.0000, 0.6250, 0.6875)),
                    vec3[2](vec3(0.3125, 0.3750, 0.0000), vec3(0.6875, 0.6250, 0.0625)),
                    vec3[2](vec3(0.3125, 0.3750, 0.9375), vec3(0.6875, 0.6250, 1.0000)),
                    vec3[2](vec3(0.3750, 0.0000, 0.3125), vec3(0.6250, 0.0625, 0.6875)),
                    vec3[2](vec3(0.3125, 0.0000, 0.3750), vec3(0.6875, 0.0625, 0.6250)),
                    vec3[2](vec3(0.3750, 0.9375, 0.3125), vec3(0.6250, 1.0000, 0.6875)),
                    vec3[2](vec3(0.3125, 0.9375, 0.3750), vec3(0.6875, 1.0000, 0.6250)),

                    // Cactus
                    vec3[2](vec3(0.0625, 0, 0.0625), vec3(0.9375, 1, 0.9375)),

                    // Nether portal
                    vec3[2](vec3(0, 0, 0.375), vec3(1, 1, 0.625)),
                    vec3[2](vec3(0.375, 0, 0), vec3(0.625, 1, 1)),

                    // Ladders, some states of vines
                    vec3[2](vec3(0.05, 0, 0), vec3(0.05, 1, 1)), // east
                    vec3[2](vec3(0.95, 0, 0), vec3(0.95, 1, 1)), // west
                    vec3[2](vec3(0, 0, 0.05), vec3(1, 1, 0.05)), // south
                    vec3[2](vec3(0, 0, 0.95), vec3(1, 1, 0.95)), // north

                    // Glass panes, first box (also iron bars until i get around to giving them their own model)
                    vec3[2](vec3(0.4375, 0, 0.4375), vec3(0.5625, 1, 0.5625)), // none
                    vec3[2](vec3(0.4375, 0, 0     ), vec3(0.5625, 1, 0.5   )), // north
                    vec3[2](vec3(0.4375, 0, 0.5   ), vec3(0.5625, 1, 1     )), // south
                    vec3[2](vec3(0,      0, 0.4375), vec3(0.5,    1, 0.5625)), // west
                    vec3[2](vec3(0.5,    0, 0.4375), vec3(1,      1, 0.5625)), // east
                    vec3[2](vec3(0.4375, 0, 0     ), vec3(0.5625, 1, 1     )), // north-south
                    vec3[2](vec3(0,      0, 0.4375), vec3(1,      1, 0.5625)), // east-west

                    // End rods
                    vec3[2](vec3(0.0625, 0.4375, 0.4375), vec3(1,      0.5625, 0.5625)),
                    vec3[2](vec3(0,      0.4375, 0.4375), vec3(0.9375, 0.5625, 0.5625)),
                    vec3[2](vec3(0.4375, 0.0625, 0.4375), vec3(0.5625, 1,      0.5625)),
                    vec3[2](vec3(0.4375, 0,      0.4375), vec3(0.5625, 0.9375, 0.5625)),
                    vec3[2](vec3(0.4375, 0.4375, 0.0625), vec3(0.5625, 0.5625, 1     )),
                    vec3[2](vec3(0.4375, 0.4375, 0     ), vec3(0.5625, 0.5625, 0.9375)),

                    // Stairs (straight)
                    vec3[2](vec3(0,      0,      0     ), vec3(1,      0.5,    1     )),
                    vec3[2](vec3(0,      0,      0     ), vec3(1,      0.5,    1     )),
                    vec3[2](vec3(0,      0,      0     ), vec3(1,      0.5,    1     )),
                    vec3[2](vec3(0,      0,      0     ), vec3(1,      0.5,    1     )),
                    vec3[2](vec3(0,      0.5,    0     ), vec3(1,      1,      1     )),
                    vec3[2](vec3(0,      0.5,    0     ), vec3(1,      1,      1     )),
                    vec3[2](vec3(0,      0.5,    0     ), vec3(1,      1,      1     )),
                    vec3[2](vec3(0,      0.5,    0     ), vec3(1,      1,      1     )),

                    // Stairs (outer corner)
                    vec3[2](vec3(0,      0,      0     ), vec3(1,      0.5,    1     )),
                    vec3[2](vec3(0,      0,      0     ), vec3(1,      0.5,    1     )),
                    vec3[2](vec3(0,      0,      0     ), vec3(1,      0.5,    1     )),
                    vec3[2](vec3(0,      0,      0     ), vec3(1,      0.5,    1     )),
                    vec3[2](vec3(0,      0.5,    0     ), vec3(1,      1,      1     )),
                    vec3[2](vec3(0,      0.5,    0     ), vec3(1,      1,      1     )),
                    vec3[2](vec3(0,      0.5,    0     ), vec3(1,      1,      1     )),
                    vec3[2](vec3(0,      0.5,    0     ), vec3(1,      1,      1     )),

                    // Glass panes with second box (also iron bars until i get around to giving them their own model)
                    vec3[2](vec3(0,      0, 0.4375), vec3(0.5625, 1, 0.5625)), // north-west
                    vec3[2](vec3(0,      0, 0.4375), vec3(0.5625, 1, 0.5625)), // south-west
                    vec3[2](vec3(0.4375, 0, 0.4375), vec3(1,      1, 0.5625)), // north-east
                    vec3[2](vec3(0.4375, 0, 0.4375), vec3(1,      1, 0.5625)), // south-east

                    vec3[2](vec3(0,      0, 0.4375), vec3(0.5625, 1, 0.5625)), // north, south, west
                    vec3[2](vec3(0.4375, 0, 0.4375), vec3(1,      1, 0.5625)), // north, south, east
                    vec3[2](vec3(0,      0, 0.4375), vec3(1,      1, 0.5625)), // north, east, west
                    vec3[2](vec3(0,      0, 0.4375), vec3(1,      1, 0.5625)), // south, east, west

                    vec3[2](vec3(0,      0, 0.4375), vec3(1,      1, 0.5625)), // cross

                    // Stairs (inner corner)
                    vec3[2](vec3(0,      0,      0     ), vec3(1,      0.5,    1     )),
                    vec3[2](vec3(0,      0,      0     ), vec3(1,      0.5,    1     )),
                    vec3[2](vec3(0,      0,      0     ), vec3(1,      0.5,    1     )),
                    vec3[2](vec3(0,      0,      0     ), vec3(1,      0.5,    1     )),
                    vec3[2](vec3(0,      0.5,    0     ), vec3(1,      1,      1     )),
                    vec3[2](vec3(0,      0.5,    0     ), vec3(1,      1,      1     )),
                    vec3[2](vec3(0,      0.5,    0     ), vec3(1,      1,      1     )),
                    vec3[2](vec3(0,      0.5,    0     ), vec3(1,      1,      1     ))
                );

                bool intersected = IntersectAABox(relativeOrigin, inverseDirection, bounds1[id - 17][0], bounds1[id - 17][1], hitDist, hitNormal);

                if (58 <= id) {
                    vec3[97 - 58][2] bounds2 = vec3[97 - 58][2](
                        // End rods
                        vec3[2](vec3(0,      0.375,  0.375 ), vec3(0.0625, 0.625,  0.625 )),
                        vec3[2](vec3(0.9375, 0.375,  0.375 ), vec3(1,      0.625,  0.625 )),
                        vec3[2](vec3(0.375,  0,      0.375 ), vec3(0.625,  0.0625, 0.625 )),
                        vec3[2](vec3(0.375,  0.9375, 0.375 ), vec3(0.625,  1,      0.625 )),
                        vec3[2](vec3(0.375,  0.375,  0     ), vec3(0.625,  0.625,  0.0625)),
                        vec3[2](vec3(0.375,  0.375,  0.9375), vec3(0.625,  0.625,  1     )),

                        // Stairs (straight)
                        vec3[2](vec3(0,      0.5,    0     ), vec3(1,      1,      0.5   )),
                        vec3[2](vec3(0,      0.5,    0.5   ), vec3(1,      1,      1     )),
                        vec3[2](vec3(0.5,    0.5,    0     ), vec3(1,      1,      1     )),
                        vec3[2](vec3(0,      0.5,    0     ), vec3(0.5,    1,      1     )),
                        vec3[2](vec3(0,      0,      0     ), vec3(1,      0.5,    0.5   )),
                        vec3[2](vec3(0,      0,      0.5   ), vec3(1,      0.5,    1     )),
                        vec3[2](vec3(0.5,    0,      0     ), vec3(1,      0.5,    1     )),
                        vec3[2](vec3(0,      0,      0     ), vec3(0.5,    0.5,    1     )),

                        // Stairs (outer corner)
                        vec3[2](vec3(0.5,    0.5,    0     ), vec3(1,      1,      0.5   )),
                        vec3[2](vec3(0.5,    0.5,    0.5   ), vec3(1,      1,      1     )),
                        vec3[2](vec3(0,      0.5,    0     ), vec3(0.5,    1,      0.5   )),
                        vec3[2](vec3(0,      0.5,    0.5   ), vec3(0.5,    1,      1     )),
                        vec3[2](vec3(0.5,    0,      0     ), vec3(1,      0.5,    0.5   )),
                        vec3[2](vec3(0.5,    0,      0.5   ), vec3(1,      0.5,    1     )),
                        vec3[2](vec3(0,      0,      0     ), vec3(0.5,    0.5,    0.5   )),
                        vec3[2](vec3(0,      0,      0.5   ), vec3(0.5,    0.5,    1     )),

                        // Glass panes with second box (also iron bars until i get around to giving them their own model)
                        vec3[2](vec3(0.4375, 0, 0     ), vec3(0.5625, 1, 0.5625)), // north-west
                        vec3[2](vec3(0.4375, 0, 0.4375), vec3(0.5625, 1, 1     )), // south-west
                        vec3[2](vec3(0.4375, 0, 0     ), vec3(0.5625, 1, 0.5625)), // north-east
                        vec3[2](vec3(0.4375, 0, 0.4375), vec3(0.5625, 1, 1     )), // south-east

                        vec3[2](vec3(0.4375, 0, 0     ), vec3(0.5625, 1, 1     )), // north, south, west
                        vec3[2](vec3(0.4375, 0, 0     ), vec3(0.5625, 1, 1     )), // north, south, east
                        vec3[2](vec3(0.4375, 0, 0     ), vec3(0.5625, 1, 0.5625)), // north, east, west
                        vec3[2](vec3(0.4375, 0, 0.4375), vec3(0.5625, 1, 1     )), // south, east, west

                        vec3[2](vec3(0.4375, 0, 0     ), vec3(0.5625, 1, 1     )), // cross

                        // Stairs (inner corner)
                        vec3[2](vec3(0,      0.5,    0     ), vec3(1,      1,      0.5   )),
                        vec3[2](vec3(0,      0.5,    0.5   ), vec3(1,      1,      1     )),
                        vec3[2](vec3(0,      0.5,    0     ), vec3(0.5,    1,      1     )),
                        vec3[2](vec3(0,      0.5,    0     ), vec3(0.5,    1,      1     )),
                        vec3[2](vec3(0,      0,      0     ), vec3(1,      0.5,    0.5   )),
                        vec3[2](vec3(0,      0,      0.5   ), vec3(1,      0.5,    1     )),
                        vec3[2](vec3(0,      0,      0     ), vec3(0.5,    0.5,    1     )),
                        vec3[2](vec3(0,      0,      0     ), vec3(0.5,    0.5,    1     ))
                    );

                    float tDist;
                    vec3 tNormal;
                    if (IntersectAABox(relativeOrigin, inverseDirection, bounds2[id - 58][0], bounds2[id - 58][1], tDist, tNormal)) {
                        if (!intersected || tDist < hitDist) {
                            hitDist = tDist;
                            hitNormal = tNormal;
                            intersected = true;
                        }
                    }
                }

                if (89 <= id) {
                    vec3[97 - 89][2] bounds3 = vec3[97 - 89][2](
                        // Stairs (inner corner)
                        vec3[2](vec3(0.5,    0.5,    0.5   ), vec3(1,      1,      1     )),
                        vec3[2](vec3(0.5,    0.5,    0     ), vec3(1,      1,      0.5   )),
                        vec3[2](vec3(0.5,    0.5,    0     ), vec3(1,      1,      0.5   )),
                        vec3[2](vec3(0.5,    0.5,    0.5   ), vec3(1,      1,      1     )),
                        vec3[2](vec3(0.5,    0,      0.5   ), vec3(1,      0.5,    1     )),
                        vec3[2](vec3(0.5,    0,      0     ), vec3(1,      0.5,    0.5   )),
                        vec3[2](vec3(0.5,    0,      0     ), vec3(1,      0.5,    0.5   )),
                        vec3[2](vec3(0.5,    0,      0.5   ), vec3(1,      0.5,    1     ))
                    );

                    float tDist;
                    vec3 tNormal;
                    if (IntersectAABox(relativeOrigin, inverseDirection, bounds3[id - 89][0], bounds3[id - 89][1], tDist, tNormal)) {
                        if (!intersected || tDist < hitDist) {
                            hitDist = tDist;
                            hitNormal = tNormal;
                            intersected = true;
                        }
                    }
                }

                return intersected;
            }

            #ifdef INTERSECT_SLOW_PARTIAL_BLOCKS
            else if (id <= 98) { // Anvils
                return IntersectAnvil(relativeOrigin, direction, inverseDirection, id == 98, hitDist, hitNormal);
            } else if (id <= 114) { // Fences
                return IntersectFence(relativeOrigin, direction, inverseDirection, id - 99, hitDist, hitNormal);
            } else if (id <= 146) { // Walls
                return IntersectWall(relativeOrigin, direction, inverseDirection, id - 115, hitDist, hitNormal);
            } else if (id <= 150) { // Wall torches
                return IntersectWallTorch(relativeOrigin, direction, id - 147, hitDist, hitNormal);
            }
            #endif

            else if(id == 240 || id == 241 || id == 242) {
                vec3 minBounds, maxBounds;
                minBounds = vec3(0);
                maxBounds = vec3(1);

                return IntersectAABox(relativeOrigin, inverseDirection, minBounds, maxBounds, hitDist, hitNormal);
            } if(id == 160) {
                vec3 minBounds, maxBounds;
                minBounds = vec3(0.3125, 0, 0.3125);
                maxBounds = vec3(0.6875, 0.5, 0.6875);

                return IntersectAABox(relativeOrigin, inverseDirection, minBounds, maxBounds, hitDist, hitNormal);
            }
        }

        // IDs that aren't yet considered are always intersected
        return true;
    }
#endif