package electrosphere.util.math; import org.joml.Vector3d; import org.joml.Vector3i; /** * Utilities for dealing with geometry */ public class GeomUtils { /** * Gets the minimum distance from a point to an axis aligned cube * @param pos the position to check against * @param cubeMin The min position of the cube * @param cubeMax The max position of the cube * @return the distance */ public static double getMinDistanceAABB(Vector3d pos, Vector3d cubeMin, Vector3d cubeMax){ double minX = cubeMin.x; double minY = cubeMin.y; double minZ = cubeMin.z; double maxX = cubeMax.x; double maxY = cubeMax.y; double maxZ = cubeMax.z; if(pos.x > minX && pos.x < maxX){ if(pos.y > minY && pos.y < maxY){ if(pos.z > minZ && pos.z < maxZ){ return 0; } else if(Math.abs(pos.z - minZ) < Math.abs(pos.z - maxZ)){ return pos.distance(pos.x,pos.y,minZ); } else { return pos.distance(pos.x,pos.y,maxZ); } } else if(Math.abs(pos.y - minY) < Math.abs(pos.y - maxY)){ if(pos.z > minZ && pos.z < maxZ){ return pos.distance(pos.x,minY,pos.z); } else if(Math.abs(pos.z - minZ) < Math.abs(pos.z - maxZ)){ return pos.distance(pos.x,minY,minZ); } else { return pos.distance(pos.x,minY,maxZ); } } else { if(pos.z > minZ && pos.z < maxZ){ return pos.distance(pos.x,maxY,pos.z); } else if(Math.abs(pos.z - minZ) < Math.abs(pos.z - maxZ)){ return pos.distance(pos.x,maxY,minZ); } else { return pos.distance(pos.x,maxY,maxZ); } } } else if(Math.abs(pos.x - minX) < Math.abs(pos.x - maxX)){ if(pos.y > minY && pos.y < maxY){ if(pos.z > minZ && pos.z < maxZ){ return pos.distance(minX,pos.y,pos.z); } else if(Math.abs(pos.z - minZ) < Math.abs(pos.z - maxZ)){ return pos.distance(minX,pos.y,minZ); } else { return pos.distance(minX,pos.y,maxZ); } } else if(Math.abs(pos.y - minY) < Math.abs(pos.y - maxY)){ if(pos.z > minZ && pos.z < maxZ){ return pos.distance(minX,minY,pos.z); } else if(Math.abs(pos.z - minZ) < Math.abs(pos.z - maxZ)){ return pos.distance(minX,minY,minZ); } else { return pos.distance(minX,minY,maxZ); } } else { if(pos.z > minZ && pos.z < maxZ){ return pos.distance(minX,maxY,pos.z); } else if(Math.abs(pos.z - minZ) < Math.abs(pos.z - maxZ)){ return pos.distance(minX,maxY,minZ); } else { return pos.distance(minX,maxY,maxZ); } } } else { if(pos.y > minY && pos.y < maxY){ if(pos.z > minZ && pos.z < maxZ){ return pos.distance(maxX,pos.y,pos.z); } else if(Math.abs(pos.z - minZ) < Math.abs(pos.z - maxZ)){ return pos.distance(maxX,pos.y,minZ); } else { return pos.distance(maxX,pos.y,maxZ); } } else if(Math.abs(pos.y - minY) < Math.abs(pos.y - maxY)){ if(pos.z > minZ && pos.z < maxZ){ return pos.distance(maxX,minY,pos.z); } else if(Math.abs(pos.z - minZ) < Math.abs(pos.z - maxZ)){ return pos.distance(maxX,minY,minZ); } else { return pos.distance(maxX,minY,maxZ); } } else { if(pos.z > minZ && pos.z < maxZ){ return pos.distance(maxX,maxY,pos.z); } else if(Math.abs(pos.z - minZ) < Math.abs(pos.z - maxZ)){ return pos.distance(maxX,maxY,minZ); } else { return pos.distance(maxX,maxY,maxZ); } } } } /** * Gets the minimum squared distance from a point to an axis aligned cube * @param pos the position to check against * @param cubeMin The min position of the cube * @param cubeMax The max position of the cube * @return the distance */ public static double getMinSquaredDistanceAABB(Vector3d pos, Vector3d cubeMin, Vector3d cubeMax){ double minX = cubeMin.x; double minY = cubeMin.y; double minZ = cubeMin.z; double maxX = cubeMax.x; double maxY = cubeMax.y; double maxZ = cubeMax.z; if(pos.x > minX && pos.x < maxX){ if(pos.y > minY && pos.y < maxY){ if(pos.z > minZ && pos.z < maxZ){ return 0; } else if(Math.abs(pos.z - minZ) < Math.abs(pos.z - maxZ)){ return pos.distanceSquared(pos.x,pos.y,minZ); } else { return pos.distanceSquared(pos.x,pos.y,maxZ); } } else if(Math.abs(pos.y - minY) < Math.abs(pos.y - maxY)){ if(pos.z > minZ && pos.z < maxZ){ return pos.distanceSquared(pos.x,minY,pos.z); } else if(Math.abs(pos.z - minZ) < Math.abs(pos.z - maxZ)){ return pos.distanceSquared(pos.x,minY,minZ); } else { return pos.distanceSquared(pos.x,minY,maxZ); } } else { if(pos.z > minZ && pos.z < maxZ){ return pos.distanceSquared(pos.x,maxY,pos.z); } else if(Math.abs(pos.z - minZ) < Math.abs(pos.z - maxZ)){ return pos.distanceSquared(pos.x,maxY,minZ); } else { return pos.distanceSquared(pos.x,maxY,maxZ); } } } else if(Math.abs(pos.x - minX) < Math.abs(pos.x - maxX)){ if(pos.y > minY && pos.y < maxY){ if(pos.z > minZ && pos.z < maxZ){ return pos.distanceSquared(minX,pos.y,pos.z); } else if(Math.abs(pos.z - minZ) < Math.abs(pos.z - maxZ)){ return pos.distanceSquared(minX,pos.y,minZ); } else { return pos.distanceSquared(minX,pos.y,maxZ); } } else if(Math.abs(pos.y - minY) < Math.abs(pos.y - maxY)){ if(pos.z > minZ && pos.z < maxZ){ return pos.distanceSquared(minX,minY,pos.z); } else if(Math.abs(pos.z - minZ) < Math.abs(pos.z - maxZ)){ return pos.distanceSquared(minX,minY,minZ); } else { return pos.distanceSquared(minX,minY,maxZ); } } else { if(pos.z > minZ && pos.z < maxZ){ return pos.distanceSquared(minX,maxY,pos.z); } else if(Math.abs(pos.z - minZ) < Math.abs(pos.z - maxZ)){ return pos.distanceSquared(minX,maxY,minZ); } else { return pos.distanceSquared(minX,maxY,maxZ); } } } else { if(pos.y > minY && pos.y < maxY){ if(pos.z > minZ && pos.z < maxZ){ return pos.distanceSquared(maxX,pos.y,pos.z); } else if(Math.abs(pos.z - minZ) < Math.abs(pos.z - maxZ)){ return pos.distanceSquared(maxX,pos.y,minZ); } else { return pos.distanceSquared(maxX,pos.y,maxZ); } } else if(Math.abs(pos.y - minY) < Math.abs(pos.y - maxY)){ if(pos.z > minZ && pos.z < maxZ){ return pos.distanceSquared(maxX,minY,pos.z); } else if(Math.abs(pos.z - minZ) < Math.abs(pos.z - maxZ)){ return pos.distanceSquared(maxX,minY,minZ); } else { return pos.distanceSquared(maxX,minY,maxZ); } } else { if(pos.z > minZ && pos.z < maxZ){ return pos.distanceSquared(maxX,maxY,pos.z); } else if(Math.abs(pos.z - minZ) < Math.abs(pos.z - maxZ)){ return pos.distanceSquared(maxX,maxY,minZ); } else { return pos.distanceSquared(maxX,maxY,maxZ); } } } } /** * Gets the minimum squared distance from a point to an axis aligned cube * @param pos the position to check against * @param cubeMin The min position of the cube * @param cubeMax The max position of the cube * @return the distance */ public static double getMinSquaredDistanceAABB(Vector3i pos, Vector3i cubeMin, Vector3i cubeMax){ int minX = cubeMin.x; int minY = cubeMin.y; int minZ = cubeMin.z; int maxX = cubeMax.x; int maxY = cubeMax.y; int maxZ = cubeMax.z; if(pos.x > minX && pos.x < maxX){ if(pos.y > minY && pos.y < maxY){ if(pos.z > minZ && pos.z < maxZ){ return 0; } else if(Math.abs(pos.z - minZ) < Math.abs(pos.z - maxZ)){ return pos.distanceSquared(pos.x,pos.y,minZ); } else { return pos.distanceSquared(pos.x,pos.y,maxZ); } } else if(Math.abs(pos.y - minY) < Math.abs(pos.y - maxY)){ if(pos.z > minZ && pos.z < maxZ){ return pos.distanceSquared(pos.x,minY,pos.z); } else if(Math.abs(pos.z - minZ) < Math.abs(pos.z - maxZ)){ return pos.distanceSquared(pos.x,minY,minZ); } else { return pos.distanceSquared(pos.x,minY,maxZ); } } else { if(pos.z > minZ && pos.z < maxZ){ return pos.distanceSquared(pos.x,maxY,pos.z); } else if(Math.abs(pos.z - minZ) < Math.abs(pos.z - maxZ)){ return pos.distanceSquared(pos.x,maxY,minZ); } else { return pos.distanceSquared(pos.x,maxY,maxZ); } } } else if(Math.abs(pos.x - minX) < Math.abs(pos.x - maxX)){ if(pos.y > minY && pos.y < maxY){ if(pos.z > minZ && pos.z < maxZ){ return pos.distanceSquared(minX,pos.y,pos.z); } else if(Math.abs(pos.z - minZ) < Math.abs(pos.z - maxZ)){ return pos.distanceSquared(minX,pos.y,minZ); } else { return pos.distanceSquared(minX,pos.y,maxZ); } } else if(Math.abs(pos.y - minY) < Math.abs(pos.y - maxY)){ if(pos.z > minZ && pos.z < maxZ){ return pos.distanceSquared(minX,minY,pos.z); } else if(Math.abs(pos.z - minZ) < Math.abs(pos.z - maxZ)){ return pos.distanceSquared(minX,minY,minZ); } else { return pos.distanceSquared(minX,minY,maxZ); } } else { if(pos.z > minZ && pos.z < maxZ){ return pos.distanceSquared(minX,maxY,pos.z); } else if(Math.abs(pos.z - minZ) < Math.abs(pos.z - maxZ)){ return pos.distanceSquared(minX,maxY,minZ); } else { return pos.distanceSquared(minX,maxY,maxZ); } } } else { if(pos.y > minY && pos.y < maxY){ if(pos.z > minZ && pos.z < maxZ){ return pos.distanceSquared(maxX,pos.y,pos.z); } else if(Math.abs(pos.z - minZ) < Math.abs(pos.z - maxZ)){ return pos.distanceSquared(maxX,pos.y,minZ); } else { return pos.distanceSquared(maxX,pos.y,maxZ); } } else if(Math.abs(pos.y - minY) < Math.abs(pos.y - maxY)){ if(pos.z > minZ && pos.z < maxZ){ return pos.distanceSquared(maxX,minY,pos.z); } else if(Math.abs(pos.z - minZ) < Math.abs(pos.z - maxZ)){ return pos.distanceSquared(maxX,minY,minZ); } else { return pos.distanceSquared(maxX,minY,maxZ); } } else { if(pos.z > minZ && pos.z < maxZ){ return pos.distanceSquared(maxX,maxY,pos.z); } else if(Math.abs(pos.z - minZ) < Math.abs(pos.z - maxZ)){ return pos.distanceSquared(maxX,maxY,minZ); } else { return pos.distanceSquared(maxX,maxY,maxZ); } } } } /** * Gets the minimum squared distance from a point to an axis aligned cube * @param pos the position to check against * @param cubeMin The min position of the cube * @param cubeMax The max position of the cube * @return the distance */ public static double getMinSquaredDistanceAABBUnrolled(int posX, int posY, int posZ, int minX, int minY, int minZ, int maxX, int maxY, int maxZ){ if(posX > minX && posX < maxX){ if(posY > minY && posY < maxY){ if(posZ > minZ && posZ < maxZ){ return 0; } else if(Math.abs(posZ - minZ) < Math.abs(posZ - maxZ)){ return (posZ - minZ) * (posZ - minZ);// pos.distanceSquared(posX,posY,minZ); } else { return (posZ - maxZ) * (posZ - maxZ);//pos.distanceSquared(posX,posY,maxZ); } } else if(Math.abs(posY - minY) < Math.abs(posY - maxY)){ if(posZ > minZ && posZ < maxZ){ return (posY - minY) * (posY - minY);//pos.distanceSquared(posX,minY,posZ); } else if(Math.abs(posZ - minZ) < Math.abs(posZ - maxZ)){ return (posY - minY) * (posY - minY) + (posZ - minZ) * (posZ - minZ);//pos.distanceSquared(posX,minY,minZ); } else { return (posY - minY) * (posY - minY) + (posZ - maxZ) * (posZ - maxZ);//pos.distanceSquared(posX,minY,maxZ); } } else { if(posZ > minZ && posZ < maxZ){ return (posY - maxY) * (posY - maxY);//pos.distanceSquared(posX,maxY,posZ); } else if(Math.abs(posZ - minZ) < Math.abs(posZ - maxZ)){ return (posY - maxY) * (posY - maxY) + (posZ - minZ) * (posZ - minZ);//pos.distanceSquared(posX,maxY,minZ); } else { return (posY - maxY) * (posY - maxY) + (posZ - maxZ) * (posZ - maxZ);//pos.distanceSquared(posX,maxY,maxZ); } } } else if(Math.abs(posX - minX) < Math.abs(posX - maxX)){ if(posY > minY && posY < maxY){ if(posZ > minZ && posZ < maxZ){ return (posX - minX) * (posX - minX);//pos.distanceSquared(minX,posY,posZ); } else if(Math.abs(posZ - minZ) < Math.abs(posZ - maxZ)){ return (posX - minX) * (posX - minX) + (posZ - minZ) * (posZ - minZ);//pos.distanceSquared(minX,posY,minZ); } else { return (posX - minX) * (posX - minX) + (posZ - maxZ) * (posZ - maxZ);//pos.distanceSquared(minX,posY,maxZ); } } else if(Math.abs(posY - minY) < Math.abs(posY - maxY)){ if(posZ > minZ && posZ < maxZ){ return (posX - minX) * (posX - minX);//pos.distanceSquared(minX,minY,posZ); } else if(Math.abs(posZ - minZ) < Math.abs(posZ - maxZ)){ return (posX - minX) * (posX - minX) + (posY - minY) * (posY - minY) + (posZ - minZ) * (posZ - minZ);//pos.distanceSquared(minX,minY,minZ); } else { return (posX - minX) * (posX - minX) + (posY - minY) * (posY - minY) + (posZ - maxZ) * (posZ - maxZ);//pos.distanceSquared(minX,minY,maxZ); } } else { if(posZ > minZ && posZ < maxZ){ return (posX - minX) * (posX - minX) + (posY - maxY) * (posY - maxY);//pos.distanceSquared(minX,maxY,posZ); } else if(Math.abs(posZ - minZ) < Math.abs(posZ - maxZ)){ return (posX - minX) * (posX - minX) + (posY - maxY) * (posY - maxY) + (posZ - minZ) * (posZ - minZ);//pos.distanceSquared(minX,maxY,minZ); } else { return (posX - minX) * (posX - minX) + (posY - maxY) * (posY - maxY) + (posZ - maxZ) * (posZ - maxZ);//pos.distanceSquared(minX,maxY,maxZ); } } } else { if(posY > minY && posY < maxY){ if(posZ > minZ && posZ < maxZ){ return (posX - maxX) * (posX - maxX);//pos.distanceSquared(maxX,posY,posZ); } else if(Math.abs(posZ - minZ) < Math.abs(posZ - maxZ)){ return (posX - maxX) * (posX - maxX) + (posZ - minZ) * (posZ - minZ);//pos.distanceSquared(maxX,posY,minZ); } else { return (posX - maxX) * (posX - maxX) + (posZ - maxZ) * (posZ - maxZ);//pos.distanceSquared(maxX,posY,maxZ); } } else if(Math.abs(posY - minY) < Math.abs(posY - maxY)){ if(posZ > minZ && posZ < maxZ){ return (posX - maxX) * (posX - maxX);//pos.distanceSquared(maxX,minY,posZ); } else if(Math.abs(posZ - minZ) < Math.abs(posZ - maxZ)){ return (posX - maxX) * (posX - maxX) + (posY - minY) * (posY - minY) + (posZ - minZ) * (posZ - minZ);//pos.distanceSquared(maxX,minY,minZ); } else { return (posX - maxX) * (posX - maxX) + (posY - minY) * (posY - minY) + (posZ - maxZ) * (posZ - maxZ);//pos.distanceSquared(maxX,minY,maxZ); } } else { if(posZ > minZ && posZ < maxZ){ return (posX - maxX) * (posX - maxX) + (posY - maxY) * (posY - maxY);//pos.distanceSquared(maxX,maxY,posZ); } else if(Math.abs(posZ - minZ) < Math.abs(posZ - maxZ)){ return (posX - maxX) * (posX - maxX) + (posY - maxY) * (posY - maxY) + (posZ - minZ) * (posZ - minZ);//pos.distanceSquared(maxX,maxY,minZ); } else { return (posX - maxX) * (posX - maxX) + (posY - maxY) * (posY - maxY) + (posZ - maxZ) * (posZ - maxZ);//pos.distanceSquared(maxX,maxY,maxZ); } } } } }