From 853c706b774b45df91bb9af6e08d445dd2d2f5bd Mon Sep 17 00:00:00 2001 From: Eric Date: Thu, 28 Oct 2021 22:16:19 -0600 Subject: [PATCH] Add vivecraft support --- .../lod/handlers/ReflectionHandler.java | 101 ++++++++++++------ .../com/seibel/lod/render/LodRenderer.java | 67 +++++++----- 2 files changed, 108 insertions(+), 60 deletions(-) diff --git a/src/main/java/com/seibel/lod/handlers/ReflectionHandler.java b/src/main/java/com/seibel/lod/handlers/ReflectionHandler.java index c62fb4a8b..6a37692c0 100644 --- a/src/main/java/com/seibel/lod/handlers/ReflectionHandler.java +++ b/src/main/java/com/seibel/lod/handlers/ReflectionHandler.java @@ -25,20 +25,21 @@ import java.lang.reflect.Method; import com.seibel.lod.enums.FogQuality; import com.seibel.lod.proxy.ClientProxy; import com.seibel.lod.wrappers.MinecraftWrapper; +import net.minecraft.util.math.vector.Matrix4f; /** * This object is used to get variables from methods * where they are private. Specifically the fog setting * in Optifine. - * + * * @author James Seibel - * @version 9-25-2021 + * @version 9 -25-2021 */ public class ReflectionHandler { public static final ReflectionHandler INSTANCE = new ReflectionHandler(); private final MinecraftWrapper mc = MinecraftWrapper.INSTANCE; - + public Field ofFogField = null; public Method vertexBufferUploadMethod = null; @@ -73,48 +74,82 @@ public class ReflectionHandler // optifine changed the name of the variable ClientProxy.LOGGER.info(ReflectionHandler.class.getSimpleName() + ": unable to find the Optifine fog field. If Optifine isn't installed this can be ignored."); } - - - - + + /** * Get what type of fog optifine is currently set to render. + * + * @return the fog quality */ - public FogQuality getFogQuality() - { - if (ofFogField == null) - { + public FogQuality getFogQuality() { + if (ofFogField == null) { // either optifine isn't installed, // the variable name was changed, or // the setup method wasn't called yet. return FogQuality.FANCY; } - + int returnNum = 0; - - try - { + + try { returnNum = (int) ofFogField.get(mc.getOptions()); - } - catch (IllegalArgumentException | IllegalAccessException e) - { + } catch (IllegalArgumentException | IllegalAccessException e) { e.printStackTrace(); } - - switch (returnNum) - { - default: - case 0: - // optifine's "default" option, - // it should never be called in this case - - // normal options - case 1: - return FogQuality.FAST; - case 2: - return FogQuality.FANCY; - case 3: - return FogQuality.OFF; + + switch (returnNum) { + default: + case 0: + // optifine's "default" option, + // it should never be called in this case + + // normal options + case 1: + return FogQuality.FAST; + case 2: + return FogQuality.FANCY; + case 3: + return FogQuality.OFF; } } + + /** Detect if Vivecraft is present using reflection. Attempts to find the "VRRenderer" class. */ + public boolean detectVivecraft(){ + try { + Class.forName("org.vivecraft.provider.VRRenderer"); + return true; + } catch (ClassNotFoundException ignored){ + System.out.println("Vivecraft not detected."); + } + return false; + } + + /** + * Modifies a projection matrix's clip planes. + * The projection matrix must be in a column-major format. + * + * @param projectionMatrix The projection matrix to be modified. + * @param n the new near clip plane value. + * @param f the new far clip plane value. + * @return The modified matrix. + * + */ + public Matrix4f Matrix4fModifyClipPlanes(Matrix4f projectionMatrix, float n,float f){ + //find the matrix values. + float nMatrixValue = -((f+n)/(f-n)); + float fMatrixValue = -((2*f*n)/(f-n)); + try{ + //get the fields of the projectionMatrix + Field[] fields = projectionMatrix.getClass().getDeclaredFields(); + //bypass the security protections on the fields that encode near and far plane values. + fields[10].setAccessible(true); + fields[11].setAccessible(true); + //Change the values of the near and far plane. + fields[10].set(projectionMatrix, nMatrixValue); + fields[11].set(projectionMatrix, fMatrixValue); + }catch (Exception e){ + e.printStackTrace(); + } + return projectionMatrix; + } } diff --git a/src/main/java/com/seibel/lod/render/LodRenderer.java b/src/main/java/com/seibel/lod/render/LodRenderer.java index 1753b90f6..99fa76136 100644 --- a/src/main/java/com/seibel/lod/render/LodRenderer.java +++ b/src/main/java/com/seibel/lod/render/LodRenderer.java @@ -130,6 +130,8 @@ public class LodRenderer public boolean vanillaRenderedChunksChanged; public boolean vanillaRenderedChunksEmptySkip = false; public int vanillaBlockRenderedDistance; + + boolean vivecraftDetected = ReflectionHandler.INSTANCE.detectVivecraft(); @@ -559,35 +561,46 @@ public class LodRenderer */ private void setupProjectionMatrix(Matrix4f currentProjectionMatrix, float vanillaBlockRenderedDistance, float partialTicks) { - // create the new projection matrix - Matrix4f lodPoj = - Matrix4f.perspective( + Matrix4f lodPoj; + float nearClipPlane = LodConfig.CLIENT.graphics.advancedGraphicsOption.useExtendedNearClipPlane.get() ? vanillaBlockRenderedDistance / 5 : 1; + float farClipPlane = farPlaneBlockDistance * LodUtil.CHUNK_WIDTH / 2; + + if (vivecraftDetected){ + //use modify clip plane method to modify the current projection matrix's clip planes. + lodPoj = ReflectionHandler.INSTANCE.Matrix4fModifyClipPlanes( + currentProjectionMatrix, + nearClipPlane, + farClipPlane); + } else { + // create the new projection matrix + lodPoj = Matrix4f.perspective( getFov(partialTicks, true), (float) this.mc.getWindow().getScreenWidth() / (float) this.mc.getWindow().getScreenHeight(), - LodConfig.CLIENT.graphics.advancedGraphicsOption.useExtendedNearClipPlane.get() ? vanillaBlockRenderedDistance / 5 : 1, - farPlaneBlockDistance * LodUtil.CHUNK_WIDTH / 2); - - // get Minecraft's un-edited projection matrix - // (this is before it is zoomed, distorted, etc.) - Matrix4f defaultMcProj = mc.getGameRenderer().getProjectionMatrix(mc.getGameRenderer().getMainCamera(), partialTicks, true); - // true here means use "use fov setting" (probably) - - - // this logic strips away the defaultMcProj matrix, so we - // can get the distortionMatrix, which represents all - // transformations, zooming, distortions, etc. done - // to Minecraft's Projection matrix - Matrix4f defaultMcProjInv = defaultMcProj.copy(); - defaultMcProjInv.invert(); - - Matrix4f distortionMatrix = defaultMcProjInv.copy(); - distortionMatrix.multiply(currentProjectionMatrix); - - - // edit the lod projection to match Minecraft's - // (so the LODs line up with the real world) - lodPoj.multiply(distortionMatrix); - + nearClipPlane, + farClipPlane); + + // get Minecraft's un-edited projection matrix + // (this is before it is zoomed, distorted, etc.) + Matrix4f defaultMcProj = mc.getGameRenderer().getProjectionMatrix(mc.getGameRenderer().getMainCamera(), partialTicks, true); + // true here means use "use fov setting" (probably) + + + // this logic strips away the defaultMcProj matrix, so we + // can get the distortionMatrix, which represents all + // transformations, zooming, distortions, etc. done + // to Minecraft's Projection matrix + Matrix4f defaultMcProjInv = defaultMcProj.copy(); + defaultMcProjInv.invert(); + + Matrix4f distortionMatrix = defaultMcProjInv.copy(); + distortionMatrix.multiply(currentProjectionMatrix); + + + // edit the lod projection to match Minecraft's + // (so the LODs line up with the real world) + lodPoj.multiply(distortionMatrix); + } + // send the projection over to the GPU gameRender.resetProjectionMatrix(lodPoj); }