Skip to content

Instantly share code, notes, and snippets.

@downthecrop
Last active June 23, 2023 01:03
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save downthecrop/b9dec2c52e24614131c78b97549e8fba to your computer and use it in GitHub Desktop.
Save downthecrop/b9dec2c52e24614131c78b97549e8fba to your computer and use it in GitHub Desktop.
GPT being insanely good at programming

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!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment