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
@@ -59,23 +59,25 @@ public abstract class DhApiBeforeBufferRenderEvent implements IDhApiEvent<DhApiB
* Measured in blocks. * Measured in blocks.
* Should be applied to the model view matrix to move the buffer into its proper place. * Should be applied to the model view matrix to move the buffer into its proper place.
*/ */
public final DhApiVec3f modelPos; public DhApiVec3f modelPos;
public EventParam(DhApiRenderParam parent, DhApiVec3f modelPos)
public EventParam() { }
public void update(DhApiRenderParam parent, DhApiVec3f modelPos)
{ {
super(parent); super.update(parent);
this.modelPos = modelPos; this.modelPos = modelPos;
} }
@Override @Override
public EventParam copy() public boolean getCopyBeforeFire() { return false; }
{
return new EventParam( @Override
this, this.modelPos.copy() public EventParam copy() { return this; }
);
}
} }
} }
@@ -60,9 +60,9 @@ public abstract class DhApiBeforeFogRenderEvent implements IDhApiCancelableEvent
public static class EventParam implements IDhApiEventParam public static class EventParam implements IDhApiEventParam
{ {
private final DhApiRenderParam renderParam; private DhApiRenderParam renderParam;
private final DhApiFogRenderParam originalFogRenderParam; private DhApiFogRenderParam originalFogRenderParam;
private final DhApiMutableFogRenderParam fogRenderParam; private DhApiMutableFogRenderParam fogRenderParam;
@@ -71,7 +71,9 @@ public abstract class DhApiBeforeFogRenderEvent implements IDhApiCancelableEvent
//=============// //=============//
//region //region
public EventParam(DhApiRenderParam renderParam, DhApiFogRenderParam fogRenderParam) public EventParam() {}
public void update(DhApiRenderParam renderParam, DhApiFogRenderParam fogRenderParam)
{ {
this.renderParam = renderParam; this.renderParam = renderParam;
this.originalFogRenderParam = fogRenderParam; this.originalFogRenderParam = fogRenderParam;
@@ -54,44 +54,45 @@ public abstract class DhApiBeforeGenericObjectRenderEvent implements IDhApiCance
public static class EventParam extends DhApiRenderParam implements IDhApiEventParam public static class EventParam extends DhApiRenderParam implements IDhApiEventParam
{ {
public final long boxGroupId; public long boxGroupId;
public final String resourceLocationNamespace; public String resourceLocationNamespace;
public final String resourceLocationPath; public String resourceLocationPath;
public EventParam(
DhApiRenderParam renderParam, //==============//
IDhApiRenderableBoxGroup boxGroup // constructors //
) //==============//
//region
public EventParam() { }
/** internal DH method */
public void update(DhApiRenderParam renderParam, IDhApiRenderableBoxGroup boxGroup)
{ {
super(renderParam); super.update(renderParam);
this.boxGroupId = boxGroup.getId(); this.boxGroupId = boxGroup.getId();
this.resourceLocationNamespace = boxGroup.getResourceLocationNamespace(); this.resourceLocationNamespace = boxGroup.getResourceLocationNamespace();
this.resourceLocationPath = boxGroup.getResourceLocationPath(); this.resourceLocationPath = boxGroup.getResourceLocationPath();
} }
public EventParam(
DhApiRenderParam renderParam,
long boxGroupId, String resourceLocationNamespace, String resourceLocationPath
)
{
super(renderParam);
this.boxGroupId = boxGroupId; //endregion
this.resourceLocationNamespace = resourceLocationNamespace;
this.resourceLocationPath = resourceLocationPath;
}
//================//
// base overrides //
//================//
//region
@Override @Override
public EventParam copy() public EventParam copy() { return this; }
{
return new EventParam( //endregion
this,
this.boxGroupId, this.resourceLocationNamespace, this.resourceLocationPath
);
}
} }
} }
@@ -35,62 +35,69 @@ import com.seibel.distanthorizons.api.objects.math.DhApiMat4f;
public class DhApiRenderParam implements IDhApiEventParam public class DhApiRenderParam implements IDhApiEventParam
{ {
/** Indicates what render pass DH is currently rendering */ /** Indicates what render pass DH is currently rendering */
public final EDhApiRenderPass renderPass; public EDhApiRenderPass renderPass;
/** Indicates how far into this tick the frame is. */ /** Indicates how far into this tick the frame is. */
public final float partialTicks; public float partialTicks;
/** /**
* Indicates DH's near clip plane, measured in blocks. * Indicates DH's near clip plane, measured in blocks.
* Note: this may change based on time, player speed, and other factors. * Note: this may change based on time, player speed, and other factors.
*/ */
public final float nearClipPlane; public float nearClipPlane;
/** /**
* Indicates DH's far clip plane, measured in blocks. * Indicates DH's far clip plane, measured in blocks.
* Note: this may change based on time, player speed, and other factors. * Note: this may change based on time, player speed, and other factors.
*/ */
public final float farClipPlane; public float farClipPlane;
/** The projection matrix Minecraft is using to render this frame. */ /** The projection matrix Minecraft is using to render this frame. */
public final DhApiMat4f mcProjectionMatrix; public final DhApiMat4f mcProjectionMatrix = new DhApiMat4f();
/** The model view matrix Minecraft is using to render this frame. */ /** The model view matrix Minecraft is using to render this frame. */
public final DhApiMat4f mcModelViewMatrix; public final DhApiMat4f mcModelViewMatrix = new DhApiMat4f();
public final DhApiMat4f mcInverseMvmProjectionMatrix = new DhApiMat4f();
/** The projection matrix Distant Horizons is using to render this frame. */ /** The projection matrix Distant Horizons is using to render this frame. */
public final DhApiMat4f dhProjectionMatrix; public final DhApiMat4f dhProjectionMatrix = new DhApiMat4f();
/** The model view matrix Distant Horizons is using to render this frame. */ /** The model view matrix Distant Horizons is using to render this frame. */
public final DhApiMat4f dhModelViewMatrix; public final DhApiMat4f dhModelViewMatrix = new DhApiMat4f();
/** combination of the MVM and projection matrices */ /** combination of the MVM and projection matrices */
public final DhApiMat4f dhMvmProjMatrix; public final DhApiMat4f dhMvmProjMatrix = new DhApiMat4f();
public final DhApiMat4f dhInverseMvmProjectionMatrix = new DhApiMat4f();
public final int worldYOffset; public int worldYOffset;
/** /**
* The level currently being rendered. * The level currently being rendered.
* *
* @since API 5.1.0 * @since API 5.1.0
*/ */
public final IDhApiLevelWrapper clientLevelWrapper; public IDhApiLevelWrapper clientLevelWrapper;
//==============// //==============//
// constructors // // constructors //
//==============// //==============//
//region
public DhApiRenderParam(DhApiRenderParam parent) public DhApiRenderParam() {}
/** Internal DH method */
public void update(DhApiRenderParam param)
{ {
this( this.update(
parent.renderPass, param.renderPass,
parent.partialTicks, param.partialTicks,
parent.nearClipPlane, parent.farClipPlane, param.nearClipPlane, param.farClipPlane,
parent.mcProjectionMatrix.copy(), parent.mcModelViewMatrix.copy(), param.mcProjectionMatrix, param.mcModelViewMatrix,
parent.dhProjectionMatrix.copy(), parent.dhModelViewMatrix.copy(), param.dhProjectionMatrix, param.mcModelViewMatrix,
parent.worldYOffset, param.worldYOffset,
parent.clientLevelWrapper param.clientLevelWrapper
); );
} }
public DhApiRenderParam( /** Internal DH method */
public void update(
EDhApiRenderPass renderPass, EDhApiRenderPass renderPass,
float newPartialTicks, float newPartialTicks,
float nearClipPlane, float farClipPlane, float nearClipPlane, float farClipPlane,
@@ -107,29 +114,51 @@ public class DhApiRenderParam implements IDhApiEventParam
this.farClipPlane = farClipPlane; this.farClipPlane = farClipPlane;
this.nearClipPlane = nearClipPlane; this.nearClipPlane = nearClipPlane;
this.mcProjectionMatrix = newMcProjectionMatrix; // mc matricies
this.mcModelViewMatrix = newMcModelViewMatrix; {
this.mcProjectionMatrix.set(newMcProjectionMatrix);
this.mcModelViewMatrix.set(newMcModelViewMatrix);
this.dhProjectionMatrix = newDhProjectionMatrix; // inverse mvm Proj
this.dhModelViewMatrix = newDhModelViewMatrix; this.mcInverseMvmProjectionMatrix.set(newMcProjectionMatrix);
this.mcInverseMvmProjectionMatrix.invert();
}
DhApiMat4f combinedMatrix = new DhApiMat4f(this.dhProjectionMatrix); // dh matricies
combinedMatrix.multiply(this.dhModelViewMatrix); {
this.dhMvmProjMatrix = combinedMatrix; this.dhProjectionMatrix.set(newDhProjectionMatrix);
this.dhModelViewMatrix.set(newDhModelViewMatrix);
// proj
this.dhMvmProjMatrix.set(this.dhProjectionMatrix);
this.dhMvmProjMatrix.multiply(this.dhModelViewMatrix);
// inverse mvm Proj
this.dhInverseMvmProjectionMatrix.set(this.dhMvmProjMatrix);
this.dhInverseMvmProjectionMatrix.invert();
}
this.worldYOffset = worldYOffset; this.worldYOffset = worldYOffset;
this.clientLevelWrapper = clientLevelWrapper; this.clientLevelWrapper = clientLevelWrapper;
} }
//endregion
//================// //================//
// base overrides // // base overrides //
//================// //================//
//region
@Override @Override
public DhApiRenderParam copy() { return new DhApiRenderParam(this); } public boolean getCopyBeforeFire() { return false; }
@Override
public DhApiRenderParam copy() { return this; }
//endregion
@@ -21,6 +21,8 @@ package com.seibel.distanthorizons.api.objects.math;
import com.seibel.distanthorizons.api.interfaces.util.IDhApiCopyable; import com.seibel.distanthorizons.api.interfaces.util.IDhApiCopyable;
import java.nio.FloatBuffer;
/** /**
* An (almost) exact copy of Minecraft's 1.16.5 * An (almost) exact copy of Minecraft's 1.16.5
* implementation of a 4x4 float matrix. <br><br> * implementation of a 4x4 float matrix. <br><br>
@@ -33,7 +35,7 @@ import com.seibel.distanthorizons.api.interfaces.util.IDhApiCopyable;
* </code> * </code>
* *
* @author James Seibel * @author James Seibel
* @version 2024-6-30 * @version 2026-05-22
*/ */
public class DhApiMat4f implements IDhApiCopyable public class DhApiMat4f implements IDhApiCopyable
{ {
@@ -62,6 +64,7 @@ public class DhApiMat4f implements IDhApiCopyable
//==============// //==============//
// constructors // // constructors //
//==============// //==============//
//region
public DhApiMat4f() { /* all values are 0 */ } public DhApiMat4f() { /* all values are 0 */ }
@@ -71,14 +74,17 @@ public class DhApiMat4f implements IDhApiCopyable
this.m01 = sourceMatrix.m01; this.m01 = sourceMatrix.m01;
this.m02 = sourceMatrix.m02; this.m02 = sourceMatrix.m02;
this.m03 = sourceMatrix.m03; this.m03 = sourceMatrix.m03;
this.m10 = sourceMatrix.m10; this.m10 = sourceMatrix.m10;
this.m11 = sourceMatrix.m11; this.m11 = sourceMatrix.m11;
this.m12 = sourceMatrix.m12; this.m12 = sourceMatrix.m12;
this.m13 = sourceMatrix.m13; this.m13 = sourceMatrix.m13;
this.m20 = sourceMatrix.m20; this.m20 = sourceMatrix.m20;
this.m21 = sourceMatrix.m21; this.m21 = sourceMatrix.m21;
this.m22 = sourceMatrix.m22; this.m22 = sourceMatrix.m22;
this.m23 = sourceMatrix.m23; this.m23 = sourceMatrix.m23;
this.m30 = sourceMatrix.m30; this.m30 = sourceMatrix.m30;
this.m31 = sourceMatrix.m31; this.m31 = sourceMatrix.m31;
this.m32 = sourceMatrix.m32; this.m32 = sourceMatrix.m32;
@@ -109,12 +115,74 @@ public class DhApiMat4f implements IDhApiCopyable
this.m33 = values[15]; this.m33 = values[15];
} }
//endregion
//=========// //=========//
// methods // // methods //
//=========// //=========//
//region
/** Returns the values of this matrix in row major order (AKA rows then columns) */
public float[] getValuesAsArray()
{
float[] array = new float[16];
this.putValuesInArray(array);
return array;
}
/**
* Returns the values of this matrix in row major order (AKA rows then columns)
* @since API 7.0.0
*/
public void putValuesInArray(float[] array)
{
array[0] = this.m00;
array[1] = this.m01;
array[2] = this.m02;
array[3] = this.m03;
array[4] = this.m10;
array[5] = this.m11;
array[6] = this.m12;
array[7] = this.m13;
array[8] = this.m20;
array[9] = this.m21;
array[10] = this.m22;
array[11] = this.m23;
array[12] = this.m30;
array[13] = this.m31;
array[14] = this.m32;
array[15] = this.m33;
}
/** @since API 7.0.0 */
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 setIdentity() public void setIdentity()
{ {
@@ -279,47 +347,14 @@ public class DhApiMat4f implements IDhApiCopyable
this.m33 *= scalar; this.m33 *= scalar;
} }
//endregion
//==================//
// Distant Horizons //
// methods //
//==================//
private static int getArrayIndex(int xIndex, int zIndex) { return (zIndex * 4) + xIndex; }
/** Returns the values of this matrix in row major order (AKA rows then columns) */
public float[] getValuesAsArray()
{
return new float[]{
this.m00,
this.m01,
this.m02,
this.m03,
this.m10,
this.m11,
this.m12,
this.m13,
this.m20,
this.m21,
this.m22,
this.m23,
this.m30,
this.m31,
this.m32,
this.m33,
};
}
//================// //================//
// base overrides // // base overrides //
//================// //================//
//region
@Override @Override
public boolean equals(Object obj) public boolean equals(Object obj)
@@ -388,4 +423,8 @@ public class DhApiMat4f implements IDhApiCopyable
@Override @Override
public DhApiMat4f copy() { return new DhApiMat4f(this); } public DhApiMat4f copy() { return new DhApiMat4f(this); }
//endregion
} }
@@ -99,6 +99,11 @@ public class ClientApi
* Only downside is making sure each variable is populated before rendering. * Only downside is making sure each variable is populated before rendering.
*/ */
public static final DhRenderState RENDER_STATE = new DhRenderState(); 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 * 50ms = 20 FPS
@@ -148,8 +153,6 @@ public class ClientApi
private Vec3d lastCameraPosForSpeedCheck = new Vec3d(); private Vec3d lastCameraPosForSpeedCheck = new Vec3d();
private long msSinceLastSpeedCheck = 0L; private long msSinceLastSpeedCheck = 0L;
public static long firstRenderTimeMs = 0;
/** /**
* keeping track of this is necessary to fix * keeping track of this is necessary to fix
* out-of-date LODs from rendering when the shading * 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 // render prep and actual rendering into different threads/methods
// this is annoying since it's possible to start a render with only // 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 // 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 //endregion
@@ -581,12 +584,7 @@ public class ClientApi
//============// //============//
//region //region
if (firstRenderTimeMs == 0) String validationMessage = RENDER_PARAMS.getValidationErrorMessage();
{
firstRenderTimeMs = System.currentTimeMillis();
}
String validationMessage = renderParams.getValidationErrorMessage(firstRenderTimeMs);
if (validationMessage != null) if (validationMessage != null)
{ {
// store the error message so it can be seen on the F3 screen // store the error message so it can be seen on the F3 screen
@@ -632,10 +630,10 @@ public class ClientApi
{ {
if (!renderingDeferredLayer) if (!renderingDeferredLayer)
{ {
boolean renderingCancelled = ApiEventInjector.INSTANCE.fireAllEvents(DhApiBeforeRenderEvent.class, renderParams); boolean renderingCancelled = ApiEventInjector.INSTANCE.fireAllEvents(DhApiBeforeRenderEvent.class, RENDER_PARAMS);
if (!renderingCancelled) if (!renderingCancelled)
{ {
LodRenderer.INSTANCE.render(renderParams, profiler); LodRenderer.INSTANCE.render(RENDER_PARAMS, profiler);
} }
if (!DhApi.Delayed.renderProxy.getDeferTransparentRendering()) if (!DhApi.Delayed.renderProxy.getDeferTransparentRendering())
@@ -645,10 +643,10 @@ public class ClientApi
} }
else else
{ {
boolean renderingCancelled = ApiEventInjector.INSTANCE.fireAllEvents(DhApiBeforeDeferredRenderEvent.class, renderParams); boolean renderingCancelled = ApiEventInjector.INSTANCE.fireAllEvents(DhApiBeforeDeferredRenderEvent.class, RENDER_PARAMS);
if (!renderingCancelled) 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 // meta renderer needed for render state/texture
// for setup on some APIs (IE openGL) // 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 else
{ {
@@ -730,8 +728,8 @@ public class ClientApi
// don't fade when Iris shaders are active, otherwise the rendering can get weird // don't fade when Iris shaders are active, otherwise the rendering can get weird
&& !DhApiRenderProxy.INSTANCE.getDeferTransparentRendering()) && !DhApiRenderProxy.INSTANCE.getDeferTransparentRendering())
{ {
RenderParams renderParams = new RenderParams(EDhApiRenderPass.OPAQUE, RENDER_STATE); RENDER_PARAMS.update(EDhApiRenderPass.OPAQUE, RENDER_STATE);
fadeRenderer.render(renderParams); fadeRenderer.render(RENDER_PARAMS);
} }
} }
/** /**
@@ -761,8 +759,8 @@ public class ClientApi
&& !DhApiRenderProxy.INSTANCE.getDeferTransparentRendering(); && !DhApiRenderProxy.INSTANCE.getDeferTransparentRendering();
if (renderFade) if (renderFade)
{ {
RenderParams renderParams = new RenderParams(EDhApiRenderPass.TRANSPARENT, RENDER_STATE); RENDER_PARAMS.update(EDhApiRenderPass.TRANSPARENT, RENDER_STATE);
fadeRenderer.render(renderParams); 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.DhApi;
import com.seibel.distanthorizons.api.interfaces.override.rendering.IDhApiCullingFrustum; import com.seibel.distanthorizons.api.interfaces.override.rendering.IDhApiCullingFrustum;
import com.seibel.distanthorizons.api.interfaces.override.rendering.IDhApiShadowCullingFrustum; 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.config.Config;
import com.seibel.distanthorizons.core.dataObjects.render.bufferBuilding.LodBufferContainer; import com.seibel.distanthorizons.core.dataObjects.render.bufferBuilding.LodBufferContainer;
import com.seibel.distanthorizons.core.dependencyInjection.ModAccessorInjector; 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.LodRenderer;
import com.seibel.distanthorizons.core.render.renderer.cullingFrustum.DhFrustumBounds; import com.seibel.distanthorizons.core.render.renderer.cullingFrustum.DhFrustumBounds;
import com.seibel.distanthorizons.core.render.renderer.cullingFrustum.NeverCullFrustum; 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.util.objects.SortedArraySet;
import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IMinecraftRenderWrapper; import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IMinecraftRenderWrapper;
import com.seibel.distanthorizons.core.wrapperInterfaces.modAccessor.IIrisAccessor; 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.coreapi.interfaces.dependencyInjection.IOverrideInjector;
import com.seibel.distanthorizons.core.util.math.Mat4f; import com.seibel.distanthorizons.core.util.math.Mat4f;
import com.seibel.distanthorizons.core.util.math.Vec3d; 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); 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 */ /** contains all relevant data */
public final LodQuadTree lodQuadTree; public final LodQuadTree lodQuadTree;
@@ -123,6 +133,14 @@ public class RenderBufferHandler implements AutoCloseable
*/ */
public void buildRenderList(RenderParams renderParams) 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 // clear the old list so we can start fresh
this.loadedNearToFarBuffers.clear(); this.loadedNearToFarBuffers.clear();
@@ -156,18 +174,21 @@ public class RenderBufferHandler implements AutoCloseable
Vec3d cameraPos = MC_RENDER.getCameraExactPosition(); Vec3d cameraPos = MC_RENDER.getCameraExactPosition();
Matrix4fc matWorldView = new Matrix4f() renderParams.mcModelViewMatrix.putValuesInArray(JOML_TRANSPOSE_ARRAY);
.setTransposed(renderParams.mcModelViewMatrix.getValuesAsArray()) WORLD_VIEW_JOML_MATRIX
.setTransposed(JOML_TRANSPOSE_ARRAY)
.translate( .translate(
-(float) cameraPos.x, -(float) cameraPos.x,
-(float) cameraPos.y, -(float) cameraPos.y,
-(float) cameraPos.z); -(float) cameraPos.z);
Matrix4fc matWorldViewProjection = new Matrix4f() renderParams.dhProjectionMatrix.putValuesInArray(JOML_TRANSPOSE_ARRAY);
.setTransposed(renderParams.dhProjectionMatrix.getValuesAsArray()) WORLD_VIEW_PROJ_JOML_MATRIX
.mul(matWorldView); .setTransposed(JOML_TRANSPOSE_ARRAY)
.mul(WORLD_VIEW_JOML_MATRIX);
frustum.update(worldMinY, worldMinY + worldHeight, new Mat4f(matWorldViewProjection)); 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 // // Update the section list //
//=========================// //=========================//
//region
if (isShadowPass) if (isShadowPass)
{ {
@@ -251,6 +273,9 @@ public class RenderBufferHandler implements AutoCloseable
{ {
this.visibleBufferCount = this.loadedNearToFarBuffers.size(); this.visibleBufferCount = this.loadedNearToFarBuffers.size();
} }
//endregion
} }
//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.enums.rendering.EDhApiRenderPass;
import com.seibel.distanthorizons.api.methods.events.sharedParameterObjects.DhApiRenderParam; 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.SharedApi;
import com.seibel.distanthorizons.core.api.internal.rendering.DhRenderState; import com.seibel.distanthorizons.core.api.internal.rendering.DhRenderState;
import com.seibel.distanthorizons.core.dependencyInjection.ModAccessorInjector; import com.seibel.distanthorizons.core.dependencyInjection.ModAccessorInjector;
import com.seibel.distanthorizons.core.dependencyInjection.SingletonInjector; 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.level.IDhClientLevel;
import com.seibel.distanthorizons.core.util.RenderUtil; import com.seibel.distanthorizons.core.util.RenderUtil;
import com.seibel.distanthorizons.core.util.math.Mat4f; import com.seibel.distanthorizons.core.util.math.Mat4f;
import com.seibel.distanthorizons.core.util.math.Vec3d; 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.world.IDhClientWorld;
import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IMinecraftClientWrapper; import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IMinecraftClientWrapper;
import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IMinecraftRenderWrapper; import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IMinecraftRenderWrapper;
import com.seibel.distanthorizons.core.wrapperInterfaces.misc.ILightMapWrapper; 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.modAccessor.IOptifineAccessor;
import com.seibel.distanthorizons.core.wrapperInterfaces.render.renderPass.IDhGenericRenderer; import com.seibel.distanthorizons.core.wrapperInterfaces.render.renderPass.IDhGenericRenderer;
import com.seibel.distanthorizons.core.wrapperInterfaces.world.IClientLevelWrapper; 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 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; public IDhClientWorld dhClientWorld;
@@ -58,36 +59,27 @@ public class RenderParams extends DhApiRenderParam
//=============// //=============//
//region //region
public RenderParams(EDhApiRenderPass renderPass, DhRenderState renderState) public void update(EDhApiRenderPass renderPass, DhRenderState renderState)
{ {
this(renderPass, RenderUtil.setDhProjectionMatrix(this.dhProjectionMatrix, renderState.mcProjectionMatrix);
renderState.partialTickTime, this.dhModelViewMatrix.set(renderState.mcModelViewMatrix); // DH and MC MVM matrix are the same
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);
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(); this.dhClientWorld = SharedApi.tryGetDhClientWorld();
if (this.dhClientWorld != null) if (this.dhClientWorld != null)
{ {
this.dhClientLevel = (IDhClientLevel) this.dhClientWorld.getLevel(clientLevelWrapper); this.dhClientLevel = (IDhClientLevel) this.dhClientWorld.getLevel(this.clientLevelWrapper);
if (this.dhClientLevel != null) if (this.dhClientLevel != null)
{ {
this.renderBufferHandler = this.dhClientLevel.getRenderBufferHandler(); this.renderBufferHandler = this.dhClientLevel.getRenderBufferHandler();
@@ -95,7 +87,6 @@ public class RenderParams extends DhApiRenderParam
} }
} }
this.clientLevelWrapper = clientLevelWrapper;
this.lightmap = MC_RENDER.getLightmapWrapper(this.clientLevelWrapper); this.lightmap = MC_RENDER.getLightmapWrapper(this.clientLevelWrapper);
if (MC_CLIENT.playerExists()) if (MC_CLIENT.playerExists())
@@ -103,8 +94,9 @@ public class RenderParams extends DhApiRenderParam
this.exactCameraPosition = MC_RENDER.getCameraExactPosition(); this.exactCameraPosition = MC_RENDER.getCameraExactPosition();
} }
this.vanillaFogEnabled = vanillaFogEnabled; this.vanillaFogEnabled = renderState.vanillaFogEnabled;
this.apiCopy.update(this);
} }
//endregion //endregion
@@ -120,7 +112,7 @@ public class RenderParams extends DhApiRenderParam
* Should be called before rendering is done. * Should be called before rendering is done.
* @return a message if LODs shouldn't be rendered, null if the LODs can render * @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 // 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"; return "No Generic Renderer Present";
} }
if (this.dhModelViewMatrix == null if (this.dhModelViewMatrix.equals(Mat4f.IDENTITY)
|| this.mcModelViewMatrix == null) || 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 if (OPTIFINE_ACCESSOR != null
&& MC_RENDER.getTargetFramebuffer() == -1) && MC_RENDER.getTargetFramebuffer() == -1)
{ {
@@ -21,9 +21,18 @@ public class FogRenderParamFactory
{ {
private static final IMinecraftRenderWrapper MC_RENDER = SingletonInjector.INSTANCE.get(IMinecraftRenderWrapper.class); 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); Color fogColor = getFogColor(renderParams.partialTicks);
@@ -74,8 +83,8 @@ public class FogRenderParamFactory
heightFogDensity heightFogDensity
); );
DhApiBeforeFogRenderEvent.EventParam fogRenderEventParam = new DhApiBeforeFogRenderEvent.EventParam(renderParams, fogRenderParam); EVENT_PARAM.update(renderParams, fogRenderParam);
return fogRenderEventParam; return EVENT_PARAM;
} }
private static Color getFogColor(float partialTicks) private static Color getFogColor(float partialTicks)
@@ -94,6 +103,8 @@ public class FogRenderParamFactory
return fogColor; 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.enums.rendering.EDhApiTransparency;
import com.seibel.distanthorizons.api.methods.events.abstractEvents.*; 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.config.Config;
import com.seibel.distanthorizons.core.dataObjects.render.bufferBuilding.LodBufferContainer; import com.seibel.distanthorizons.core.dataObjects.render.bufferBuilding.LodBufferContainer;
import com.seibel.distanthorizons.core.dependencyInjection.ModAccessorInjector; import com.seibel.distanthorizons.core.dependencyInjection.ModAccessorInjector;
@@ -119,9 +118,9 @@ public class LodRenderer
private void renderTerrain(RenderParams renderParams, IProfilerWrapper profiler, boolean runningDeferredPass) private void renderTerrain(RenderParams renderParams, IProfilerWrapper profiler, boolean runningDeferredPass)
{ {
// validate rendering // //===============//
//====================// // validate pass //
//====================// //===============//
//region //region
boolean deferTransparentRendering = DhApiRenderProxy.INSTANCE.getDeferTransparentRendering(); boolean deferTransparentRendering = DhApiRenderProxy.INSTANCE.getDeferTransparentRendering();
@@ -147,7 +146,7 @@ public class LodRenderer
//=================// //=================//
//region //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 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; renderFog |= renderParams.vanillaFogEnabled;
} }
DhApiBeforeFogRenderEvent.EventParam fogRenderEventParam = FogRenderParamFactory.createRenderParam(renderParams); DhApiBeforeFogRenderEvent.EventParam fogRenderEventParam = FogRenderParamFactory.getRenderParam(renderParams);
//endregion //endregion
@@ -216,7 +215,7 @@ public class LodRenderer
if (!runningDeferredPass) if (!runningDeferredPass)
{ {
// needs to be fired after all the textures have been created/bound // 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) if (clearTextures)
{ {
this.metaRenderer.clearDhDepthAndColorTextures(renderParams); this.metaRenderer.clearDhDepthAndColorTextures(renderParams);
@@ -318,7 +317,7 @@ public class LodRenderer
// Apply to the MC Framebuffer // // Apply to the MC Framebuffer //
//=============================// //=============================//
boolean cancelApplyShader = ApiEventInjector.INSTANCE.fireAllEvents(DhApiBeforeApplyShaderRenderEvent.class, renderParams); boolean cancelApplyShader = ApiEventInjector.INSTANCE.fireAllEvents(DhApiBeforeApplyShaderRenderEvent.class, renderParams.apiCopy);
if (!cancelApplyShader) if (!cancelApplyShader)
{ {
profiler.popPush("Apply to MC"); profiler.popPush("Apply to MC");
@@ -356,7 +355,7 @@ public class LodRenderer
//================// //================//
profiler.popPush("LOD cleanup"); profiler.popPush("LOD cleanup");
ApiEventInjector.INSTANCE.fireAllEvents(DhApiBeforeRenderCleanupEvent.class, renderParams); ApiEventInjector.INSTANCE.fireAllEvents(DhApiBeforeRenderCleanupEvent.class, renderParams.apiCopy);
this.metaRenderer.runRenderPassCleanup(renderParams); 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.render.AbstractDhRenderApiDefinition;
import com.seibel.distanthorizons.core.wrapperInterfaces.world.IClientLevelWrapper; import com.seibel.distanthorizons.core.wrapperInterfaces.world.IClientLevelWrapper;
import com.seibel.distanthorizons.coreapi.util.MathUtil; import com.seibel.distanthorizons.coreapi.util.MathUtil;
import com.seibel.distanthorizons.core.util.math.Mat4f;
/** /**
* This holds miscellaneous helper code * This holds miscellaneous helper code
@@ -76,7 +75,7 @@ public class RenderUtil
* *
* @param mcProjMat Minecraft's current projection matrix * @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 // 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. // culling to take effect instead of seeing the near clip plane.
@@ -93,28 +92,32 @@ public class RenderUtil
float farClipDist = RenderUtil.getFarClipPlaneDistanceInBlocks(); float farClipDist = RenderUtil.getFarClipPlaneDistanceInBlocks();
// Create a copy of the current matrix, so it won't be modified. // 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. // Set new far and near clip plane values.
if (RENDER_API_DEF.getRenderDepth() == EDhRenderDepth.FORWARD_Z) if (RENDER_API_DEF.getRenderDepth() == EDhRenderDepth.FORWARD_Z)
{ {
lodProj.setClipPlanes(nearClipDist, farClipDist, false); setClipPlanes(updateMatrix, nearClipDist, farClipDist, false);
} }
else else
{ {
lodProj.setClipPlanes(farClipDist, nearClipDist, true); setClipPlanes(updateMatrix, farClipDist, nearClipDist, true);
}
} }
return lodProj; /**
} * Changes the values that store the clipping planes.
* Formula for calculating matrix values is the same that OpenGL uses when making matrices.
/** create and return a new projection matrix based on MC's modelView and projection matrices */ *
public static Mat4f createLodModelViewMatrix(DhApiMat4f mcModelViewMat) * @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, // formula copied JOML's implementation to match Minecraft
// this method is just here in case that changes in the future matrix.m22 = (zZeroToOne ? farClip : farClip + nearClip) / (nearClip - farClip);
return new Mat4f(mcModelViewMat); matrix.m23 = (zZeroToOne ? farClip : farClip + farClip) * nearClip / (nearClip - farClip);
} }
//endregion //endregion
@@ -20,8 +20,6 @@
package com.seibel.distanthorizons.core.util.math; package com.seibel.distanthorizons.core.util.math;
import com.seibel.distanthorizons.api.objects.math.DhApiMat4f; 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.Matrix4f;
import org.joml.Matrix4fc; import org.joml.Matrix4fc;
@@ -36,12 +34,33 @@ import java.nio.FloatBuffer;
*/ */
public class Mat4f extends DhApiMat4f 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 // // constructors //
//==============// //==============//
public Mat4f() { /* all values are 0 */ } /** all values are 0 */
public Mat4f() { }
public Mat4f(DhApiMat4f sourceMatrix) { super(sourceMatrix); } 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) */ /** 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(float[] values) { super(values); }
public Mat4f(Matrix4fc sourceMatrix) { this(convertJomlMatrixToArray(sourceMatrix)); } public Mat4f(Matrix4fc sourceMatrix) { this.set(sourceMatrix); }
private static float[] convertJomlMatrixToArray(Matrix4fc 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()); this.m10 = sourceMatrix.m01();
buffer.put(bufferIndex(0, 1), sourceMatrix.m01()); this.m11 = sourceMatrix.m11();
buffer.put(bufferIndex(0, 2), sourceMatrix.m02()); this.m12 = sourceMatrix.m21();
buffer.put(bufferIndex(0, 3), sourceMatrix.m03()); this.m13 = sourceMatrix.m31();
buffer.put(bufferIndex(1, 0), sourceMatrix.m10()); this.m20 = sourceMatrix.m02();
buffer.put(bufferIndex(1, 1), sourceMatrix.m11()); this.m21 = sourceMatrix.m12();
buffer.put(bufferIndex(1, 2), sourceMatrix.m12()); this.m22 = sourceMatrix.m22();
buffer.put(bufferIndex(1, 3), sourceMatrix.m13()); this.m23 = sourceMatrix.m32();
buffer.put(bufferIndex(2, 0), sourceMatrix.m20()); this.m30 = sourceMatrix.m03();
buffer.put(bufferIndex(2, 1), sourceMatrix.m21()); this.m31 = sourceMatrix.m13();
buffer.put(bufferIndex(2, 2), sourceMatrix.m22()); this.m32 = sourceMatrix.m23();
buffer.put(bufferIndex(2, 3), sourceMatrix.m23()); this.m33 = sourceMatrix.m33();
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();
} }
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) public static Matrix4f createJomlMatrix(DhApiMat4f matrix)
{ {
@@ -171,26 +165,6 @@ public class Mat4f extends DhApiMat4f
// Forge methods // // 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) public void add(DhApiMat4f other)
{ {
m00 += other.m00; m00 += other.m00;
@@ -229,20 +203,8 @@ public class Mat4f extends DhApiMat4f
this.m23 = z; 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); } public Mat4f copy() { return new Mat4f(this); }
} }