I'm trying to create functionality to take in a 2d screen coordinate and return the block type at that point, as well as the distance to that block. I've tried this function, but it returns a ray in seemingly a random direction. ScreenWidth and ScreenHeight are the Minecraft window size. (I didn't use the built in inverse function because it was giving the wrong result for some reason. I manually verified.)
public static Vec3 GetRay(float screenX, float screenY, Camera cam) {
Matrix4f projectionMatrix = getProjectionMatrix();
Matrix4f viewMatrix = getViewMatrix(cam);
float ndcX = (2.0f * screenX) / ScreenWidth - 1.0f;
float ndcY = 1.0f - (2.0f * screenY) / ScreenHeight;
Vector4f screenVector = new Vector4f(ndcX, ndcY, -1.0f, 1.0f);
Matrix4f inversePM = new Matrix4f(projectionMatrix);
float detPM = inversePM.adjugateAndDet();
inversePM.multiply(1.0f / detPM);
screenVector.transform(inversePM);
screenVector.setZ(-1.0f);
screenVector.setW(0.0f);
Matrix4f inverseVM = new Matrix4f(viewMatrix);
float detVM = inverseVM.adjugateAndDet();
inverseVM.multiply(1.0f / detVM);
screenVector.transform(inverseVM);
Vec3 direction = new Vec3(screenVector.x(), screenVector.y(), screenVector.z());
direction = direction.normalize();
return direction;
}
private static Matrix4f getViewMatrix(Camera cam) {
Vec3 cameraPos = cam.getPosition();
Vector3f camPos = new Vector3f((float) cameraPos.x, (float) cameraPos.y, (float) cameraPos.z);
Vector3f forward = cam.getLookVector();
forward.normalize();
Vector3f up = cam.getUpVector();
up.normalize();
Vector3f right = cam.getLeftVector();
right.mul(-1.0f);
right.normalize();
float[] values = {
right.x(), up.x(), -forward.x(), 0,
right.y(), up.y(), -forward.y(), 0,
right.z(), up.z(), -forward.z(), 0,
-camPos.dot(right), -camPos.dot(up), -camPos.dot(forward), 1.0f
};
Matrix4f viewMatrix = new Matrix4f(values);
return viewMatrix;
}
private static Matrix4f getProjectionMatrix() {
double fov = Math.toRadians(90.0);
double aspectRatio = ScreenWidth / ScreenHeight;
double nearPlane = 0.05f;
double farPlane = 1000.0f;
double yScale = 1.0f / Math.tan(fov / 2.0f);
double xScale = yScale / aspectRatio;
double frustumLength = farPlane - nearPlane;
float[] values = new float[]{
(float) xScale, 0.0f, 0.0f, 0.0f,
0.0f, (float) yScale, 0.0f, 0.0f,
0.0f, 0.0f, (float) -((farPlane + nearPlane) / frustumLength), -1.0f,
0.0f, 0.0f, (float) -((2.0f * nearPlane * farPlane) / frustumLength), 0.0f
};
return new Matrix4f(values);
}