Reduce render event GC pressure

This commit is contained in:
James Seibel
2026-05-30 09:17:21 -05:00
parent 9fe5dcc16e
commit 95e4db2998
12 changed files with 350 additions and 278 deletions
@@ -99,6 +99,11 @@ public class ClientApi
* Only downside is making sure each variable is populated before rendering.
*/
public static final DhRenderState RENDER_STATE = new DhRenderState();
/**
* static variable so we don't have to re-create it each frame,
* reducing GC pressure.
*/
private static final RenderParams RENDER_PARAMS = new RenderParams();
/**
* 50ms = 20 FPS
@@ -148,8 +153,6 @@ public class ClientApi
private Vec3d lastCameraPosForSpeedCheck = new Vec3d();
private long msSinceLastSpeedCheck = 0L;
public static long firstRenderTimeMs = 0;
/**
* keeping track of this is necessary to fix
* out-of-date LODs from rendering when the shading
@@ -570,7 +573,7 @@ public class ClientApi
// render prep and actual rendering into different threads/methods
// this is annoying since it's possible to start a render with only
// partially complete info, but there isn't a better option at the moment
RenderParams renderParams = new RenderParams(renderPass, RENDER_STATE);
RENDER_PARAMS.update(renderPass, RENDER_STATE);
//endregion
@@ -581,12 +584,7 @@ public class ClientApi
//============//
//region
if (firstRenderTimeMs == 0)
{
firstRenderTimeMs = System.currentTimeMillis();
}
String validationMessage = renderParams.getValidationErrorMessage(firstRenderTimeMs);
String validationMessage = RENDER_PARAMS.getValidationErrorMessage();
if (validationMessage != null)
{
// store the error message so it can be seen on the F3 screen
@@ -632,10 +630,10 @@ public class ClientApi
{
if (!renderingDeferredLayer)
{
boolean renderingCancelled = ApiEventInjector.INSTANCE.fireAllEvents(DhApiBeforeRenderEvent.class, renderParams);
boolean renderingCancelled = ApiEventInjector.INSTANCE.fireAllEvents(DhApiBeforeRenderEvent.class, RENDER_PARAMS);
if (!renderingCancelled)
{
LodRenderer.INSTANCE.render(renderParams, profiler);
LodRenderer.INSTANCE.render(RENDER_PARAMS, profiler);
}
if (!DhApi.Delayed.renderProxy.getDeferTransparentRendering())
@@ -645,10 +643,10 @@ public class ClientApi
}
else
{
boolean renderingCancelled = ApiEventInjector.INSTANCE.fireAllEvents(DhApiBeforeDeferredRenderEvent.class, renderParams);
boolean renderingCancelled = ApiEventInjector.INSTANCE.fireAllEvents(DhApiBeforeDeferredRenderEvent.class, RENDER_PARAMS);
if (!renderingCancelled)
{
LodRenderer.INSTANCE.renderDeferred(renderParams, profiler);
LodRenderer.INSTANCE.renderDeferred(RENDER_PARAMS, profiler);
}
@@ -669,11 +667,11 @@ public class ClientApi
{
// meta renderer needed for render state/texture
// for setup on some APIs (IE openGL)
metaRenderer.runRenderPassSetup(renderParams);
metaRenderer.runRenderPassSetup(RENDER_PARAMS);
testRenderer.render(renderParams);
testRenderer.render(RENDER_PARAMS);
metaRenderer.runRenderPassCleanup(renderParams);
metaRenderer.runRenderPassCleanup(RENDER_PARAMS);
}
else
{
@@ -730,8 +728,8 @@ public class ClientApi
// don't fade when Iris shaders are active, otherwise the rendering can get weird
&& !DhApiRenderProxy.INSTANCE.getDeferTransparentRendering())
{
RenderParams renderParams = new RenderParams(EDhApiRenderPass.OPAQUE, RENDER_STATE);
fadeRenderer.render(renderParams);
RENDER_PARAMS.update(EDhApiRenderPass.OPAQUE, RENDER_STATE);
fadeRenderer.render(RENDER_PARAMS);
}
}
/**
@@ -761,8 +759,8 @@ public class ClientApi
&& !DhApiRenderProxy.INSTANCE.getDeferTransparentRendering();
if (renderFade)
{
RenderParams renderParams = new RenderParams(EDhApiRenderPass.TRANSPARENT, RENDER_STATE);
fadeRenderer.render(renderParams);
RENDER_PARAMS.update(EDhApiRenderPass.TRANSPARENT, RENDER_STATE);
fadeRenderer.render(RENDER_PARAMS);
}
}
}
@@ -22,6 +22,7 @@ package com.seibel.distanthorizons.core.render;
import com.seibel.distanthorizons.api.DhApi;
import com.seibel.distanthorizons.api.interfaces.override.rendering.IDhApiCullingFrustum;
import com.seibel.distanthorizons.api.interfaces.override.rendering.IDhApiShadowCullingFrustum;
import com.seibel.distanthorizons.api.objects.math.DhApiMat4f;
import com.seibel.distanthorizons.core.config.Config;
import com.seibel.distanthorizons.core.dataObjects.render.bufferBuilding.LodBufferContainer;
import com.seibel.distanthorizons.core.dependencyInjection.ModAccessorInjector;
@@ -36,9 +37,11 @@ import com.seibel.distanthorizons.core.render.QuadTree.LodRenderSection;
import com.seibel.distanthorizons.core.render.renderer.LodRenderer;
import com.seibel.distanthorizons.core.render.renderer.cullingFrustum.DhFrustumBounds;
import com.seibel.distanthorizons.core.render.renderer.cullingFrustum.NeverCullFrustum;
import com.seibel.distanthorizons.core.util.LodUtil;
import com.seibel.distanthorizons.core.util.objects.SortedArraySet;
import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IMinecraftRenderWrapper;
import com.seibel.distanthorizons.core.wrapperInterfaces.modAccessor.IIrisAccessor;
import com.seibel.distanthorizons.coreapi.ModInfo;
import com.seibel.distanthorizons.coreapi.interfaces.dependencyInjection.IOverrideInjector;
import com.seibel.distanthorizons.core.util.math.Mat4f;
import com.seibel.distanthorizons.core.util.math.Vec3d;
@@ -58,6 +61,13 @@ public class RenderBufferHandler implements AutoCloseable
private static final IIrisAccessor IRIS_ACCESSOR = ModAccessorInjector.INSTANCE.get(IIrisAccessor.class);
// static values for re-use to reduce GC pressure
private static final float[] JOML_TRANSPOSE_ARRAY = new float[16];
private static final Matrix4f WORLD_VIEW_JOML_MATRIX = new Matrix4f();
private static final Matrix4f WORLD_VIEW_PROJ_JOML_MATRIX = new Matrix4f();
private static final Mat4f FRUSTOM_DH_MATRIX = new Mat4f();
/** contains all relevant data */
public final LodQuadTree lodQuadTree;
@@ -123,6 +133,14 @@ public class RenderBufferHandler implements AutoCloseable
*/
public void buildRenderList(RenderParams renderParams)
{
if (ModInfo.IS_DEV_BUILD)
{
if (!RenderThreadTaskHandler.INSTANCE.isCurrentThread())
{
LodUtil.assertNotReach("Should only be run on the render thread");
}
}
// clear the old list so we can start fresh
this.loadedNearToFarBuffers.clear();
@@ -156,18 +174,21 @@ public class RenderBufferHandler implements AutoCloseable
Vec3d cameraPos = MC_RENDER.getCameraExactPosition();
Matrix4fc matWorldView = new Matrix4f()
.setTransposed(renderParams.mcModelViewMatrix.getValuesAsArray())
.translate(
-(float) cameraPos.x,
-(float) cameraPos.y,
-(float) cameraPos.z);
renderParams.mcModelViewMatrix.putValuesInArray(JOML_TRANSPOSE_ARRAY);
WORLD_VIEW_JOML_MATRIX
.setTransposed(JOML_TRANSPOSE_ARRAY)
.translate(
-(float) cameraPos.x,
-(float) cameraPos.y,
-(float) cameraPos.z);
Matrix4fc matWorldViewProjection = new Matrix4f()
.setTransposed(renderParams.dhProjectionMatrix.getValuesAsArray())
.mul(matWorldView);
frustum.update(worldMinY, worldMinY + worldHeight, new Mat4f(matWorldViewProjection));
renderParams.dhProjectionMatrix.putValuesInArray(JOML_TRANSPOSE_ARRAY);
WORLD_VIEW_PROJ_JOML_MATRIX
.setTransposed(JOML_TRANSPOSE_ARRAY)
.mul(WORLD_VIEW_JOML_MATRIX);
FRUSTOM_DH_MATRIX.set(WORLD_VIEW_PROJ_JOML_MATRIX);
frustum.update(worldMinY, worldMinY + worldHeight, FRUSTOM_DH_MATRIX);
}
@@ -175,6 +196,7 @@ public class RenderBufferHandler implements AutoCloseable
//=========================//
// Update the section list //
//=========================//
//region
if (isShadowPass)
{
@@ -251,6 +273,9 @@ public class RenderBufferHandler implements AutoCloseable
{
this.visibleBufferCount = this.loadedNearToFarBuffers.size();
}
//endregion
}
//endregion
@@ -2,22 +2,19 @@ package com.seibel.distanthorizons.core.render;
import com.seibel.distanthorizons.api.enums.rendering.EDhApiRenderPass;
import com.seibel.distanthorizons.api.methods.events.sharedParameterObjects.DhApiRenderParam;
import com.seibel.distanthorizons.api.objects.math.DhApiMat4f;
import com.seibel.distanthorizons.core.api.internal.SharedApi;
import com.seibel.distanthorizons.core.api.internal.rendering.DhRenderState;
import com.seibel.distanthorizons.core.dependencyInjection.ModAccessorInjector;
import com.seibel.distanthorizons.core.dependencyInjection.SingletonInjector;
import com.seibel.distanthorizons.core.jar.EPlatform;
import com.seibel.distanthorizons.core.level.IDhClientLevel;
import com.seibel.distanthorizons.core.util.RenderUtil;
import com.seibel.distanthorizons.core.util.math.Mat4f;
import com.seibel.distanthorizons.core.util.math.Vec3d;
import com.seibel.distanthorizons.core.util.threading.PriorityTaskPicker;
import com.seibel.distanthorizons.core.util.threading.ThreadPoolUtil;
import com.seibel.distanthorizons.core.world.IDhClientWorld;
import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IMinecraftClientWrapper;
import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IMinecraftRenderWrapper;
import com.seibel.distanthorizons.core.wrapperInterfaces.misc.ILightMapWrapper;
import com.seibel.distanthorizons.core.wrapperInterfaces.modAccessor.AbstractOptifineAccessor;
import com.seibel.distanthorizons.core.wrapperInterfaces.modAccessor.IOptifineAccessor;
import com.seibel.distanthorizons.core.wrapperInterfaces.render.renderPass.IDhGenericRenderer;
import com.seibel.distanthorizons.core.wrapperInterfaces.world.IClientLevelWrapper;
@@ -34,8 +31,12 @@ public class RenderParams extends DhApiRenderParam
private static final IOptifineAccessor OPTIFINE_ACCESSOR = ModAccessorInjector.INSTANCE.get(IOptifineAccessor.class);
private static final long TIME_FOR_MAC_TO_FINISH_COMPILING_IN_MS = 10_000;
private static boolean initialLoadingComplete = false;
/**
* Copy used for API events. <br>
* A separate copy is used to prevent API users from accidentally setting values
* that screw up DH's copy of the render parameters.
*/
public final DhApiRenderParam apiCopy = new DhApiRenderParam();
public IDhClientWorld dhClientWorld;
@@ -58,36 +59,27 @@ public class RenderParams extends DhApiRenderParam
//=============//
//region
public RenderParams(EDhApiRenderPass renderPass, DhRenderState renderState)
public void update(EDhApiRenderPass renderPass, DhRenderState renderState)
{
this(renderPass,
renderState.partialTickTime,
renderState.mcProjectionMatrix, renderState.mcModelViewMatrix,
renderState.clientLevelWrapper,
renderState.vanillaFogEnabled
);
}
private RenderParams(
EDhApiRenderPass renderPass,
float newPartialTicks,
Mat4f newMcProjectionMatrix, Mat4f newMcModelViewMatrix,
IClientLevelWrapper clientLevelWrapper,
boolean vanillaFogEnabled
)
{
super(renderPass,
newPartialTicks,
RenderUtil.getNearClipPlaneInBlocks(), RenderUtil.getFarClipPlaneDistanceInBlocks(),
newMcProjectionMatrix, newMcModelViewMatrix,
RenderUtil.createLodProjectionMatrix(newMcProjectionMatrix), RenderUtil.createLodModelViewMatrix(newMcModelViewMatrix),
clientLevelWrapper.getMinHeight(),
clientLevelWrapper);
RenderUtil.setDhProjectionMatrix(this.dhProjectionMatrix, renderState.mcProjectionMatrix);
this.dhModelViewMatrix.set(renderState.mcModelViewMatrix); // DH and MC MVM matrix are the same
super.update(renderPass,
renderState.partialTickTime,
RenderUtil.getNearClipPlaneInBlocks(), RenderUtil.getFarClipPlaneDistanceInBlocks(),
renderState.mcProjectionMatrix, renderState.mcModelViewMatrix,
this.dhProjectionMatrix, this.dhModelViewMatrix,
renderState.clientLevelWrapper.getMinHeight(),
renderState.clientLevelWrapper);
this.clientLevelWrapper = renderState.clientLevelWrapper;
this.dhClientWorld = SharedApi.tryGetDhClientWorld();
if (this.dhClientWorld != null)
{
this.dhClientLevel = (IDhClientLevel) this.dhClientWorld.getLevel(clientLevelWrapper);
this.dhClientLevel = (IDhClientLevel) this.dhClientWorld.getLevel(this.clientLevelWrapper);
if (this.dhClientLevel != null)
{
this.renderBufferHandler = this.dhClientLevel.getRenderBufferHandler();
@@ -95,7 +87,6 @@ public class RenderParams extends DhApiRenderParam
}
}
this.clientLevelWrapper = clientLevelWrapper;
this.lightmap = MC_RENDER.getLightmapWrapper(this.clientLevelWrapper);
if (MC_CLIENT.playerExists())
@@ -103,8 +94,9 @@ public class RenderParams extends DhApiRenderParam
this.exactCameraPosition = MC_RENDER.getCameraExactPosition();
}
this.vanillaFogEnabled = vanillaFogEnabled;
this.vanillaFogEnabled = renderState.vanillaFogEnabled;
this.apiCopy.update(this);
}
//endregion
@@ -120,7 +112,7 @@ public class RenderParams extends DhApiRenderParam
* Should be called before rendering is done.
* @return a message if LODs shouldn't be rendered, null if the LODs can render
*/
public String getValidationErrorMessage(long firstRenderTimeMs)
public String getValidationErrorMessage()
{
// Note: all strings here should be constants to prevent String allocations
@@ -162,12 +154,21 @@ public class RenderParams extends DhApiRenderParam
return "No Generic Renderer Present";
}
if (this.dhModelViewMatrix == null
|| this.mcModelViewMatrix == null)
if (this.dhModelViewMatrix.equals(Mat4f.IDENTITY)
|| this.dhModelViewMatrix.equals(Mat4f.EMPTY))
{
return "No MVM or Proj Matrix Given";
return "No DH MVM Matrix Given";
}
if (this.mcModelViewMatrix.equals(Mat4f.IDENTITY)
|| this.mcModelViewMatrix.equals(Mat4f.EMPTY))
{
return "No MC MVM Matrix Given";
}
// projection matrix not checked since there are some MC versions where
// the MVM and projection matrices are pre-multiplied together
if (OPTIFINE_ACCESSOR != null
&& MC_RENDER.getTargetFramebuffer() == -1)
{
@@ -21,9 +21,18 @@ public class FogRenderParamFactory
{
private static final IMinecraftRenderWrapper MC_RENDER = SingletonInjector.INSTANCE.get(IMinecraftRenderWrapper.class);
/** cached object to reduce GC pressure */
private static final DhApiBeforeFogRenderEvent.EventParam EVENT_PARAM = new DhApiBeforeFogRenderEvent.EventParam();
public static DhApiBeforeFogRenderEvent.EventParam createRenderParam(RenderParams renderParams)
//=========//
// methods //
//=========//
//region
/** returns a cached object to reduce GC pressure */
public static DhApiBeforeFogRenderEvent.EventParam getRenderParam(RenderParams renderParams)
{
Color fogColor = getFogColor(renderParams.partialTicks);
@@ -74,8 +83,8 @@ public class FogRenderParamFactory
heightFogDensity
);
DhApiBeforeFogRenderEvent.EventParam fogRenderEventParam = new DhApiBeforeFogRenderEvent.EventParam(renderParams, fogRenderParam);
return fogRenderEventParam;
EVENT_PARAM.update(renderParams, fogRenderParam);
return EVENT_PARAM;
}
private static Color getFogColor(float partialTicks)
@@ -94,6 +103,8 @@ public class FogRenderParamFactory
return fogColor;
}
//endregion
}
@@ -21,7 +21,6 @@ package com.seibel.distanthorizons.core.render.renderer;
import com.seibel.distanthorizons.api.enums.rendering.EDhApiTransparency;
import com.seibel.distanthorizons.api.methods.events.abstractEvents.*;
import com.seibel.distanthorizons.api.methods.events.sharedParameterObjects.DhApiFogRenderParam;
import com.seibel.distanthorizons.core.config.Config;
import com.seibel.distanthorizons.core.dataObjects.render.bufferBuilding.LodBufferContainer;
import com.seibel.distanthorizons.core.dependencyInjection.ModAccessorInjector;
@@ -119,9 +118,9 @@ public class LodRenderer
private void renderTerrain(RenderParams renderParams, IProfilerWrapper profiler, boolean runningDeferredPass)
{
// validate rendering //
//====================//
//====================//
//===============//
// validate pass //
//===============//
//region
boolean deferTransparentRendering = DhApiRenderProxy.INSTANCE.getDeferTransparentRendering();
@@ -147,7 +146,7 @@ public class LodRenderer
//=================//
//region
ApiEventInjector.INSTANCE.fireAllEvents(DhApiBeforeRenderSetupEvent.class, renderParams);
ApiEventInjector.INSTANCE.fireAllEvents(DhApiBeforeRenderSetupEvent.class, renderParams.apiCopy);
try (IProfilerWrapper.IProfileBlock terrainRender_profile = profiler.push("LOD GL setup")) // starts the new profile block for most DH rendering
{
@@ -203,7 +202,7 @@ public class LodRenderer
renderFog |= renderParams.vanillaFogEnabled;
}
DhApiBeforeFogRenderEvent.EventParam fogRenderEventParam = FogRenderParamFactory.createRenderParam(renderParams);
DhApiBeforeFogRenderEvent.EventParam fogRenderEventParam = FogRenderParamFactory.getRenderParam(renderParams);
//endregion
@@ -216,7 +215,7 @@ public class LodRenderer
if (!runningDeferredPass)
{
// needs to be fired after all the textures have been created/bound
boolean clearTextures = !ApiEventInjector.INSTANCE.fireAllEvents(DhApiBeforeTextureClearEvent.class, renderParams);
boolean clearTextures = !ApiEventInjector.INSTANCE.fireAllEvents(DhApiBeforeTextureClearEvent.class, renderParams.apiCopy);
if (clearTextures)
{
this.metaRenderer.clearDhDepthAndColorTextures(renderParams);
@@ -318,7 +317,7 @@ public class LodRenderer
// Apply to the MC Framebuffer //
//=============================//
boolean cancelApplyShader = ApiEventInjector.INSTANCE.fireAllEvents(DhApiBeforeApplyShaderRenderEvent.class, renderParams);
boolean cancelApplyShader = ApiEventInjector.INSTANCE.fireAllEvents(DhApiBeforeApplyShaderRenderEvent.class, renderParams.apiCopy);
if (!cancelApplyShader)
{
profiler.popPush("Apply to MC");
@@ -356,7 +355,7 @@ public class LodRenderer
//================//
profiler.popPush("LOD cleanup");
ApiEventInjector.INSTANCE.fireAllEvents(DhApiBeforeRenderCleanupEvent.class, renderParams);
ApiEventInjector.INSTANCE.fireAllEvents(DhApiBeforeRenderCleanupEvent.class, renderParams.apiCopy);
this.metaRenderer.runRenderPassCleanup(renderParams);
}
@@ -34,7 +34,6 @@ import com.seibel.distanthorizons.core.wrapperInterfaces.modAccessor.IIrisAccess
import com.seibel.distanthorizons.core.wrapperInterfaces.render.AbstractDhRenderApiDefinition;
import com.seibel.distanthorizons.core.wrapperInterfaces.world.IClientLevelWrapper;
import com.seibel.distanthorizons.coreapi.util.MathUtil;
import com.seibel.distanthorizons.core.util.math.Mat4f;
/**
* This holds miscellaneous helper code
@@ -76,7 +75,7 @@ public class RenderUtil
*
* @param mcProjMat Minecraft's current projection matrix
*/
public static Mat4f createLodProjectionMatrix(DhApiMat4f mcProjMat)
public static void setDhProjectionMatrix(DhApiMat4f updateMatrix, DhApiMat4f mcProjMat)
{
// in James' testing a near clip plane distance of 2 blocks is enough to allow the fragment
// culling to take effect instead of seeing the near clip plane.
@@ -93,28 +92,32 @@ public class RenderUtil
float farClipDist = RenderUtil.getFarClipPlaneDistanceInBlocks();
// Create a copy of the current matrix, so it won't be modified.
Mat4f lodProj = new Mat4f(mcProjMat);
updateMatrix.set(mcProjMat);
// Set new far and near clip plane values.
if (RENDER_API_DEF.getRenderDepth() == EDhRenderDepth.FORWARD_Z)
{
lodProj.setClipPlanes(nearClipDist, farClipDist, false);
setClipPlanes(updateMatrix, nearClipDist, farClipDist, false);
}
else
{
lodProj.setClipPlanes(farClipDist, nearClipDist, true);
setClipPlanes(updateMatrix, farClipDist, nearClipDist, true);
}
return lodProj;
}
/** create and return a new projection matrix based on MC's modelView and projection matrices */
public static Mat4f createLodModelViewMatrix(DhApiMat4f mcModelViewMat)
/**
* Changes the values that store the clipping planes.
* Formula for calculating matrix values is the same that OpenGL uses when making matrices.
*
* @param nearClip New near clipping plane value.
* @param farClip New far clipping plane value.
*/
public static void setClipPlanes(DhApiMat4f matrix, float nearClip, float farClip, boolean zZeroToOne)
{
// nothing beyond copying needs to be done to MC's MVM currently,
// this method is just here in case that changes in the future
return new Mat4f(mcModelViewMat);
// formula copied JOML's implementation to match Minecraft
matrix.m22 = (zZeroToOne ? farClip : farClip + nearClip) / (nearClip - farClip);
matrix.m23 = (zZeroToOne ? farClip : farClip + farClip) * nearClip / (nearClip - farClip);
}
//endregion
@@ -20,8 +20,6 @@
package com.seibel.distanthorizons.core.util.math;
import com.seibel.distanthorizons.api.objects.math.DhApiMat4f;
import com.seibel.distanthorizons.core.dependencyInjection.SingletonInjector;
import com.seibel.distanthorizons.core.wrapperInterfaces.render.AbstractDhRenderApiDefinition;
import org.joml.Matrix4f;
import org.joml.Matrix4fc;
@@ -36,12 +34,33 @@ import java.nio.FloatBuffer;
*/
public class Mat4f extends DhApiMat4f
{
/**
* A matrix containing all 0's. <br><br>
*
* Should not be modified. <br>
* Can be used for comparison testing.
*/
public static final DhApiMat4f EMPTY = new DhApiMat4f();
/**
* The 4x4 identity matrix. <br><br>
*
* Should not be modified. <br>
* Can be used for comparison testing.
*/
public static final DhApiMat4f IDENTITY = new DhApiMat4f();
static
{
IDENTITY.setIdentity();
}
//==============//
// constructors //
//==============//
public Mat4f() { /* all values are 0 */ }
/** all values are 0 */
public Mat4f() { }
public Mat4f(DhApiMat4f sourceMatrix) { super(sourceMatrix); }
@@ -50,56 +69,31 @@ public class Mat4f extends DhApiMat4f
/** Expects the values of the input array to be in row major order (AKA rows then columns) */
public Mat4f(float[] values) { super(values); }
public Mat4f(Matrix4fc sourceMatrix) { this(convertJomlMatrixToArray(sourceMatrix)); }
private static float[] convertJomlMatrixToArray(Matrix4fc sourceMatrix)
public Mat4f(Matrix4fc sourceMatrix) { this.set(sourceMatrix); }
public void set(Matrix4fc sourceMatrix)
{
FloatBuffer buffer = FloatBuffer.allocate(16);
// JOML matricies are stored transposed vs DH's matricies
this.m00 = sourceMatrix.m00();
this.m01 = sourceMatrix.m10();
this.m02 = sourceMatrix.m20();
this.m03 = sourceMatrix.m30();
buffer.put(bufferIndex(0, 0), sourceMatrix.m00());
buffer.put(bufferIndex(0, 1), sourceMatrix.m01());
buffer.put(bufferIndex(0, 2), sourceMatrix.m02());
buffer.put(bufferIndex(0, 3), sourceMatrix.m03());
this.m10 = sourceMatrix.m01();
this.m11 = sourceMatrix.m11();
this.m12 = sourceMatrix.m21();
this.m13 = sourceMatrix.m31();
buffer.put(bufferIndex(1, 0), sourceMatrix.m10());
buffer.put(bufferIndex(1, 1), sourceMatrix.m11());
buffer.put(bufferIndex(1, 2), sourceMatrix.m12());
buffer.put(bufferIndex(1, 3), sourceMatrix.m13());
this.m20 = sourceMatrix.m02();
this.m21 = sourceMatrix.m12();
this.m22 = sourceMatrix.m22();
this.m23 = sourceMatrix.m32();
buffer.put(bufferIndex(2, 0), sourceMatrix.m20());
buffer.put(bufferIndex(2, 1), sourceMatrix.m21());
buffer.put(bufferIndex(2, 2), sourceMatrix.m22());
buffer.put(bufferIndex(2, 3), sourceMatrix.m23());
buffer.put(bufferIndex(3, 0), sourceMatrix.m30());
buffer.put(bufferIndex(3, 1), sourceMatrix.m31());
buffer.put(bufferIndex(3, 2), sourceMatrix.m32());
buffer.put(bufferIndex(3, 3), sourceMatrix.m33());
return buffer.array();
this.m30 = sourceMatrix.m03();
this.m31 = sourceMatrix.m13();
this.m32 = sourceMatrix.m23();
this.m33 = sourceMatrix.m33();
}
private static int bufferIndex(int xIndex, int zIndex) { return (zIndex * 4) + xIndex; }
public void store(FloatBuffer floatBuffer)
{
floatBuffer.put(bufferIndex(0, 0), this.m00);
floatBuffer.put(bufferIndex(0, 1), this.m01);
floatBuffer.put(bufferIndex(0, 2), this.m02);
floatBuffer.put(bufferIndex(0, 3), this.m03);
floatBuffer.put(bufferIndex(1, 0), this.m10);
floatBuffer.put(bufferIndex(1, 1), this.m11);
floatBuffer.put(bufferIndex(1, 2), this.m12);
floatBuffer.put(bufferIndex(1, 3), this.m13);
floatBuffer.put(bufferIndex(2, 0), this.m20);
floatBuffer.put(bufferIndex(2, 1), this.m21);
floatBuffer.put(bufferIndex(2, 2), this.m22);
floatBuffer.put(bufferIndex(2, 3), this.m23);
floatBuffer.put(bufferIndex(3, 0), this.m30);
floatBuffer.put(bufferIndex(3, 1), this.m31);
floatBuffer.put(bufferIndex(3, 2), this.m32);
floatBuffer.put(bufferIndex(3, 3), this.m33);
}
public static Matrix4f createJomlMatrix(DhApiMat4f matrix)
{
@@ -171,26 +165,6 @@ public class Mat4f extends DhApiMat4f
// Forge methods //
//===============//
public void set(DhApiMat4f mat)
{
this.m00 = mat.m00;
this.m01 = mat.m01;
this.m02 = mat.m02;
this.m03 = mat.m03;
this.m10 = mat.m10;
this.m11 = mat.m11;
this.m12 = mat.m12;
this.m13 = mat.m13;
this.m20 = mat.m20;
this.m21 = mat.m21;
this.m22 = mat.m22;
this.m23 = mat.m23;
this.m30 = mat.m30;
this.m31 = mat.m31;
this.m32 = mat.m32;
this.m33 = mat.m33;
}
public void add(DhApiMat4f other)
{
m00 += other.m00;
@@ -229,20 +203,8 @@ public class Mat4f extends DhApiMat4f
this.m23 = z;
}
/**
* Changes the values that store the clipping planes.
* Formula for calculating matrix values is the same that OpenGL uses when making matrices.
*
* @param nearClip New near clipping plane value.
* @param farClip New far clipping plane value.
*/
public void setClipPlanes(float nearClip, float farClip, boolean zZeroToOne)
{
//convert to matrix values, formula copied JOML's implementation to match Minecraft
this.m22 = (zZeroToOne ? farClip : farClip + nearClip) / (nearClip - farClip);
this.m23 = (zZeroToOne ? farClip : farClip + farClip) * nearClip / (nearClip - farClip);
}
public Mat4f copy() { return new Mat4f(this); }
}