/** * Calculates an intersection with the face of a block defined by 3 points. * * @param blockPos The position of the block to intersect with * @param v0 Point 1 * @param v1 Point 2 * @param v2 Point 3 * @param origin Origin of the intersection ray * @param ray Direction of the intersection ray * @return Ray-face-intersection */ private static RayBoxIntersection rayFaceIntersection( Vector3f blockPos, Vector3f v0, Vector3f v1, Vector3f v2, Vector3f origin, Vector3f ray) { // Calculate the plane to intersect with Vector3f a = Vector3f.sub(v1, v0, null); Vector3f b = Vector3f.sub(v2, v0, null); Vector3f norm = Vector3f.cross(a, b, null); float d = -(norm.x * v0.x + norm.y * v0.y + norm.z * v0.z); /** Calculate the distance on the ray, where the intersection occurs. */ float t = -(norm.x * origin.x + norm.y * origin.y + norm.z * origin.z + d) / (Vector3f.dot(ray, norm)); if (t < 0) { return null; } /** Calc. the point of intersection. */ Vector3f intersectPoint = VectorPool.getVector(ray.x * t, ray.y * t, ray.z * t); Vector3f.add(intersectPoint, origin, intersectPoint); if (intersectPoint.x >= v0.x && intersectPoint.x <= v2.x && intersectPoint.y >= v0.y && intersectPoint.y <= v2.y && intersectPoint.z >= v0.z && intersectPoint.z <= v2.z) { return new RayBoxIntersection(blockPos, v0, v1, v2, d, t, origin, ray, intersectPoint); } return null; }
/** * Returns the vertices of a block at the given position. * * @param x * @param y * @param z * @return */ private static Vector3f[] verticesForBlockAt(int x, int y, int z) { Vector3f[] vertices = new Vector3f[8]; vertices[0] = VectorPool.getVector(x - .5f, y - .5f, z - .5f); vertices[1] = VectorPool.getVector(x + .5f, y - .5f, z - .5f); vertices[2] = VectorPool.getVector(x + .5f, y + .5f, z - .5f); vertices[3] = VectorPool.getVector(x - .5f, y + .5f, z - .5f); vertices[4] = VectorPool.getVector(x - .5f, y - .5f, z + .5f); vertices[5] = VectorPool.getVector(x + .5f, y - .5f, z + .5f); vertices[6] = VectorPool.getVector(x + .5f, y + .5f, z + .5f); vertices[7] = VectorPool.getVector(x - .5f, y + .5f, z + .5f); return vertices; }
/** * Calculates the intersection of a given ray originating from a specified point with a block. * Returns a list of intersections ordered by the distance to the player. * * @param x * @param y * @param z * @param rayOrigin * @param rayDirection * @return Distance-ordered list of ray-face-intersections */ public static FastList<RayBoxIntersection> rayBlockIntersection( World w, int x, int y, int z, Vector3f rayOrigin, Vector3f rayDirection) { /* * Ignore invisible blocks. */ if (Block.getBlockForType(w.getBlock(x, y, z)).isBlockInvisible()) { return null; } FastList<RayBoxIntersection> result = new FastList<RayBoxIntersection>(); /* * Fetch all vertices of the specified block. */ Vector3f[] vertices = verticesForBlockAt(x, y, z); Vector3f blockPos = VectorPool.getVector(x, y, z); /* * Generate a new intersection for each side of the block. */ // Front RayBoxIntersection is = rayFaceIntersection( blockPos, vertices[0], vertices[3], vertices[2], rayOrigin, rayDirection); if (is != null) { result.add(is); } // Back is = rayFaceIntersection( blockPos, vertices[4], vertices[5], vertices[6], rayOrigin, rayDirection); if (is != null) { result.add(is); } // Left is = rayFaceIntersection( blockPos, vertices[0], vertices[4], vertices[7], rayOrigin, rayDirection); if (is != null) { result.add(is); } // Right is = rayFaceIntersection( blockPos, vertices[1], vertices[2], vertices[6], rayOrigin, rayDirection); if (is != null) { result.add(is); } // Top is = rayFaceIntersection( blockPos, vertices[3], vertices[7], vertices[6], rayOrigin, rayDirection); if (is != null) { result.add(is); } // Bottom is = rayFaceIntersection( blockPos, vertices[0], vertices[1], vertices[5], rayOrigin, rayDirection); if (is != null) { result.add(is); } /* * Sort the intersections by distance. */ Collections.sort(result); return result; }