idk where I found it but I use a method exactly for this:
public static Vec2 project3Dto2D(Vec3 worldPosition, Matrix4f modelViewMatrix, Matrix4f projectionMatrix, Camera camera) {
Vec3 cameraPosition = camera.getPosition();
Quaternionf cameraRotation = camera.rotation();
Vec3 in3d = worldPosition.subtract(cameraPosition);
var wnd = Minecraft.getInstance().getWindow();
var quaternion = new Quaternionf((float) in3d.x, (float) in3d.y, (float) in3d.z, 1.f);
Matrix4f m = modelViewMatrix.rotate(cameraRotation.invert()); // this
var product = mqProduct(projectionMatrix, mqProduct(m, quaternion));
modelViewMatrix.rotate(cameraRotation); // undo that
if (product.w <= 0f) {
return null;
}
var screenPos = qToScreen(product);
var x = screenPos.x * wnd.getWidth();
var y = screenPos.y * wnd.getHeight();
if (Float.isInfinite(x) || Float.isInfinite(y)) {
return null;
}
return new Vec2(x, wnd.getHeight() - y);
}
private static Quaternionf mqProduct(Matrix4f m, Quaternionf q) {
return new Quaternionf(
m.m00() * q.x + m.m10() * q.y + m.m20() * q.z + m.m30() * q.w,
m.m01() * q.x + m.m11() * q.y + m.m21() * q.z + m.m31() * q.w,
m.m02() * q.x + m.m12() * q.y + m.m22() * q.z + m.m32() * q.w,
m.m03() * q.x + m.m13() * q.y + m.m23() * q.z + m.m33() * q.w);
}
private static Quaternionf qToScreen(Quaternionf q) {
var w = 1f / q.w * 0.5f;
return new Quaternionf(
q.x * w + 0.5f,
q.y * w + 0.5f,
q.z * w + 0.5f,
w);
}
call as project3Dto2D(worldPosition, matrixStack.last().pose(), projectionMatrix, camera);
You might have to translate to yarn as I use mojmap