User: can you extract the FOV from here?
private static void method4175(@OriginalArg(0) float arg0, @OriginalArg(1) float arg1, @OriginalArg(2) float arg2, @OriginalArg(3) float arg3, @OriginalArg(4) float nearClip, @OriginalArg(5) float farClip) {
@Pc(3) float local3 = nearClip * 2.0F;
matrix[0] = local3 / (arg1 - arg0);
matrix[1] = 0.0F;
matrix[2] = 0.0F;
matrix[3] = 0.0F;
matrix[4] = 0.0F;
matrix[5] = local3 / (arg3 - arg2);
matrix[6] = 0.0F;
matrix[7] = 0.0F;
matrix[8] = (arg1 + arg0) / (arg1 - arg0);
matrix[9] = (arg3 + arg2) / (arg3 - arg2);
matrix[10] = aFloat30 = -(farClip + nearClip) / (farClip - nearClip);
matrix[11] = -1.0F;
matrix[12] = 0.0F;
matrix[13] = 0.0F;
matrix[14] = aFloat32 = -(local3 * farClip) / (farClip - nearClip);
matrix[15] = 0.0F;
gl.glLoadMatrixf(matrix, 0);
aFloat33 = 0.0F;
aFloat31 = 0.0F;
}
ChatGPT: The method4175
function you've provided seems to be constructing a perspective projection matrix, just like the createperspectiveprojection
and BuildPerspProjMat
functions we discussed earlier.
Here, arg0
and arg1
would be xmin
and xmax
, respectively, while arg2
and arg3
would be ymin
and ymax
. nearClip
and farClip
represent the near and far clipping planes of the camera.
You can think of xmin
, xmax
, ymin
, and ymax
as defining the extents of the 'camera frustum' in the near plane of the camera. This is the field of view. The specific field of view (FOV) can be calculated based on the following formulas:width = xmax - xmin``````height = ymax - ymin
The horizontal FOV (hFOV) and vertical FOV (vFOV) can then be derived by:hFOV = 2 * atan((xmax - xmin) / (2 * nearClip))``````vFOV = 2 * atan((ymax - ymin) / (2 * nearClip))
Here, atan
is the arctangent function and nearClip
is the distance to the near clipping plane. These formulas use radians, so if you want the result in degrees, you need to convert them accordingly.
This can give you the horizontal and vertical fields of view. Note that this works under the assumption that xmin
and xmax
are symmetric around 0, as well as ymin
and ymax
. If they're not symmetric, you'd need to adjust the formulas accordingly.
User: add those in as debug for me please
ChatGPT: Sure, here is a debug code snippet to calculate and print the horizontal and vertical fields of view.java
private static void method4175(float arg0, float arg1, float arg2, float arg3, float nearClip, float farClip) {
// existing code ...
float width = arg1 - arg0;
float height = arg3 - arg2;
float hFOV = 2 * (float)Math.atan(width / (2 * nearClip));
float vFOV = 2 * (float)Math.atan(height / (2 * nearClip));
// Convert to degrees
hFOV = (float)Math.toDegrees(hFOV);
vFOV = (float)Math.toDegrees(vFOV);
System.out.println("Horizontal FOV: " + hFOV);
System.out.println("Vertical FOV: " + vFOV);
// remaining code ...
}
This should print the horizontal and vertical fields of view every time method4175
is called. Remember to convert radians to degrees if you want to get the FOV in degrees. The Math.toDegrees()
method is used here to achieve that.
User: ok we now have access to vFOV and hFOV inside of the projection code. how can we convert this to use the horizontal and vertical FOV
public static void calculateScreenPosition(int entityX, int entityY, int entityZ) {
// Adjustment for the camera
int elevation = SceneGraph.getTileHeight(plane, entityX, entityZ) - entityY;
entityX -= SceneGraph.cameraX;
elevation -= SceneGraph.cameraY;
entityZ -= SceneGraph.cameraZ;
// Rotation based on camera angles
int sinPitch = MathUtils.sin[Camera.cameraPitch];
int cosPitch = MathUtils.cos[Camera.cameraPitch];
int sinYaw = MathUtils.sin[Camera.cameraYaw];
int cosYaw = MathUtils.cos[Camera.cameraYaw];
int rotatedX = (entityZ * sinYaw + entityX * cosYaw) >> 16;
entityZ = (entityZ * cosYaw - entityX * sinYaw) >> 16;
entityX = rotatedX;
int rotatedY = (elevation * cosPitch - entityZ * sinPitch) >> 16;
entityZ = (elevation * sinPitch + entityZ * cosPitch) >> 16;
elevation = rotatedY;
double originalAspectRatio = 512.0 / 334.0;
double newAspectRatio = (double) GlRenderer.viewportWidth / GlRenderer.viewportHeight;
double newFOV = 2 * Math.atan(newAspectRatio / originalAspectRatio * Math.tan(Math.toRadians(53.13) / 2));
double newViewDist = (GlRenderer.viewportWidth / 2) / Math.tan(newFOV / 2);
// Calculate sprite positions
if (entityZ >= 50) {
if(GetWindowMode() == WindowMode.FIXED) {
ScriptRunner.spriteDrawX = (512/2) + (int)((entityX << 9) / entityZ);
ScriptRunner.spriteDrawY = (334/2) + (int)((elevation << 9) / entityZ);
} else {
ScriptRunner.spriteDrawX = GlRenderer.viewportWidth/2 + (int)((entityX * newViewDist) / entityZ);
ScriptRunner.spriteDrawY = GlRenderer.viewportHeight/2 + (int)((elevation * newViewDist ) / entityZ);
}
} else {
ScriptRunner.spriteDrawX = -1;
ScriptRunner.spriteDrawY = -1;
}
}
ChatGPT: Assuming that vFOV
and hFOV
are accessible and represent the vertical and horizontal fields of view respectively, you can use them directly to calculate newViewDist
as follows:java
public static void calculateScreenPosition(int entityX, int entityY, int entityZ) {
// Adjustment for the camera
int elevation = SceneGraph.getTileHeight(plane, entityX, entityZ) - entityY;
entityX -= SceneGraph.cameraX;
elevation -= SceneGraph.cameraY;
entityZ -= SceneGraph.cameraZ;
// Rotation based on camera angles
int sinPitch = MathUtils.sin[Camera.cameraPitch];
int cosPitch = MathUtils.cos[Camera.cameraPitch];
int sinYaw = MathUtils.sin[Camera.cameraYaw];
int cosYaw = MathUtils.cos[Camera.cameraYaw];
int rotatedX = (entityZ * sinYaw + entityX * cosYaw) >> 16;
entityZ = (entityZ * cosYaw - entityX * sinYaw) >> 16;
entityX = rotatedX;
int rotatedY = (elevation * cosPitch - entityZ * sinPitch) >> 16;
entityZ = (elevation * sinPitch + entityZ * cosPitch) >> 16;
elevation = rotatedY;
// Calculate view distance based on vFOV and hFOV
double newViewDistH = (GlRenderer.viewportWidth / 2) / Math.tan(Math.toRadians(hFOV) / 2);
double newViewDistV = (GlRenderer.viewportHeight / 2) / Math.tan(Math.toRadians(vFOV) / 2);
// Calculate sprite positions
if (entityZ >= 50) {
if(GetWindowMode() == WindowMode.FIXED) {
ScriptRunner.spriteDrawX = (512/2) + (int)((entityX << 9) / entityZ);
ScriptRunner.spriteDrawY = (334/2) + (int)((elevation << 9) / entityZ);
} else {
ScriptRunner.spriteDrawX = GlRenderer.viewportWidth/2 + (int)((entityX * newViewDistH) / entityZ);
ScriptRunner.spriteDrawY = GlRenderer.viewportHeight/2 + (int)((elevation * newViewDistV) / entityZ);
}
} else {
ScriptRunner.spriteDrawX = -1;
ScriptRunner.spriteDrawY = -1;
}
}
This code calculates the view distance horizontally and vertically, using hFOV
and vFOV
respectively, and applies these values for the x and y sprite draw positions.
User: amazing work. works perfect!